10 Commits

Author SHA1 Message Date
StormyCloud
1a42d0b988 added CSRF 2025-08-17 20:45:38 -05:00
Stormycloud
599e331754 added security updates 2025-08-17 20:06:17 -05:00
5abc6c80ec Update templates/index.html 2025-06-25 09:47:15 -04:00
9ff1e0b0b9 Update templates/index.html 2025-06-25 09:35:06 -04:00
StormyCloud
4b3b8c9013 Merge branch 'main' of https://i2pgit.org/stormycloud/drop.i2p 2025-06-24 16:26:19 -05:00
StormyCloud
d4ae29b5ba Merge branch 'v1.1' 2025-06-24 16:24:37 -05:00
StormyCloud
79d715f3bd fixed syntax and view page issues 2025-06-24 16:22:48 -05:00
9565a2f9b9 Delete wsgi.py 2025-06-21 14:58:32 -04:00
331d2d493a Delete .env 2025-06-21 14:58:20 -04:00
StormyCloud
6d496eb99f nothing 2025-06-21 11:19:22 -05:00
9 changed files with 1357 additions and 1139 deletions

View File

@@ -1,9 +1,2 @@
#i2p-drop # i2pcake
to do:
pastebin increase width
shrink logo
synxtax color not working
add syntax change post?
need owner view pages with Paste Created Successfully and "customer" view pages

1302
app.py

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
/* /*
! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com ! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com
*/ */
/* 1. Preflight (Tailwind's base styles) */ /* 1. Preflight (Tailwind's base styles) */
*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::before,::after{--tw-content:''}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none} *,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::before,::after{--tw-content:''}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}
/* 2. Utility Classes */ /* 2. Utility Classes */
*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: } *,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }
.h-6{height:1.5rem}.h-12{height:3rem}.h-20{height:5rem}.h-24{height:6rem}.w-6{width:1.5rem}.w-12{width:3rem}.w-20{width:5rem}.w-24{width:6rem}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-4xl{max-w:56rem}.flex-shrink-0{flex-shrink:0}.mx-auto{margin-left:auto;margin-right:auto}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.mt-16{margin-top:4rem}.inline-block{display:inline-block}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.list-disc{list-style-type:disc}.list-inside{list-style-position:inside}.min-h-screen{min-height:100vh}.max-h-60vh{max-height:60vh}.object-contain{object-fit:contain}.justify-center{justify-content:center}.items-center{align-items:center}.gap-8{gap:2rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-hidden{overflow:hidden}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99 / var(--tw-border-opacity))}.border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81 / var(--tw-border-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81 / var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246 / var(--tw-bg-opacity))}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-6{padding-top:1.5rem}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}.text-xs{font-size:.75rem;line-height:1rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.font-mono{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}.text-white{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219 / var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128 / var(--tw-text-opacity))}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.ring-blue-500{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246 / var(--tw-ring-opacity))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253 / var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:shadow-outline:focus{box-shadow:0 0 0 3px rgb(96 165 250 / .5);outline:none}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246 / var(--tw-ring-opacity))}@media (min-width: 768px){.md\:grid-cols-3{grid-template-columns:repeat(3, minmax(0, 1fr))}} .h-6{height:1.5rem}.h-12{height:3rem}.h-20{height:5rem}.h-24{height:6rem}.w-6{width:1.5rem}.w-12{width:3rem}.w-20{width:5rem}.w-24{width:6rem}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-4xl{max-w:56rem}.flex-shrink-0{flex-shrink:0}.mx-auto{margin-left:auto;margin-right:auto}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.mt-16{margin-top:4rem}.inline-block{display:inline-block}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.list-disc{list-style-type:disc}.list-inside{list-style-position:inside}.min-h-screen{min-height:100vh}.max-h-60vh{max-height:60vh}.object-contain{object-fit:contain}.justify-center{justify-content:center}.items-center{align-items:center}.gap-8{gap:2rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-hidden{overflow:hidden}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99 / var(--tw-border-opacity))}.border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81 / var(--tw-border-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81 / var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246 / var(--tw-bg-opacity))}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-6{padding-top:1.5rem}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}.text-xs{font-size:.75rem;line-height:1rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.font-mono{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}.text-white{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219 / var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128 / var(--tw-text-opacity))}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.ring-blue-500{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246 / var(--tw-ring-opacity))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253 / var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:shadow-outline:focus{box-shadow:0 0 0 3px rgb(96 165 250 / .5);outline:none}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246 / var(--tw-ring-opacity))}@media (min-width: 768px){.md\:grid-cols-3{grid-template-columns:repeat(3, minmax(0, 1fr))}}

View File

@@ -1,73 +1,73 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg <svg
version="1.1" version="1.1"
id="Layer_1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" x="0px" y="0px"
viewBox="0 135 1500 636" viewBox="0 135 1500 636"
style="enable-background:new 0 135 1500 636;" style="enable-background:new 0 135 1500 636;"
xml:space="preserve" xml:space="preserve"
> >
<style type="text/css"> <style type="text/css">
.st0{fill:#FFFFFF;} .st0{fill:#FFFFFF;}
.st1{fill:url(#SVGID_1_);} .st1{fill:url(#SVGID_1_);}
.st2{fill:url(#SVGID_2_);} .st2{fill:url(#SVGID_2_);}
.st3{fill:url(#SVGID_3_);} .st3{fill:url(#SVGID_3_);}
.st4{fill:url(#SVGID_4_);} .st4{fill:url(#SVGID_4_);}
.st5{fill:url(#SVGID_5_);} .st5{fill:url(#SVGID_5_);}
.st6{fill:#006BCC;} .st6{fill:#006BCC;}
</style> </style>
<g> <g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="378.2952" y1="456.0995" x2="378.2952" y2="131.6513"> <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="378.2952" y1="456.0995" x2="378.2952" y2="131.6513">
<stop offset="0" style="stop-color:#006FCD"/> <stop offset="0" style="stop-color:#006FCD"/>
<stop offset="1" style="stop-color:#00A9F2"/> <stop offset="1" style="stop-color:#00A9F2"/>
</linearGradient> </linearGradient>
<path class="st1" d="M600.3,324.7c-11.5-34.2-45.1-41.5-45.1-41.5c-13.7-62-73.4-64.4-73.4-64.4c-31.4-91.3-119.5-87.1-119.5-87.1 <path class="st1" d="M600.3,324.7c-11.5-34.2-45.1-41.5-45.1-41.5c-13.7-62-73.4-64.4-73.4-64.4c-31.4-91.3-119.5-87.1-119.5-87.1
C260.2,135,242.6,223,242.6,223c-92.5,15.4-90.1,94.4-90.1,94.4c3.5,93,81.8,100.3,81.8,100.3h33.5c1,18.1,8.6,27.7,15.9,32.8 C260.2,135,242.6,223,242.6,223c-92.5,15.4-90.1,94.4-90.1,94.4c3.5,93,81.8,100.3,81.8,100.3h33.5c1,18.1,8.6,27.7,15.9,32.8
c5.4,3.8,11.9,5.6,18.5,5.6h162c3.5,0,7-0.3,10.4-1.2c27.6-7.2,26.7-37.2,26.7-37.2h39.4c24.4-3.3,39.5-14.9,48.7-27 c5.4,3.8,11.9,5.6,18.5,5.6h162c3.5,0,7-0.3,10.4-1.2c27.6-7.2,26.7-37.2,26.7-37.2h39.4c24.4-3.3,39.5-14.9,48.7-27
C604,372,607.9,347.1,600.3,324.7z M489.4,415.4c0,15.4-12.5,27.8-27.8,27.8H304.2c-12.1,0-21.9-9.8-21.9-21.9V228.7 C604,372,607.9,347.1,600.3,324.7z M489.4,415.4c0,15.4-12.5,27.8-27.8,27.8H304.2c-12.1,0-21.9-9.8-21.9-21.9V228.7
c0-15.5,12.6-28.1,28.1-28.1H405c9.8,0,19.2,3.7,26.4,10.4l43.8,40.9c9.1,8.5,14.3,20.4,14.3,32.8V415.4z"/> c0-15.5,12.6-28.1,28.1-28.1H405c9.8,0,19.2,3.7,26.4,10.4l43.8,40.9c9.1,8.5,14.3,20.4,14.3,32.8V415.4z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="432.1597" y1="283.199" x2="432.1597" y2="227.7854"> <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="432.1597" y1="283.199" x2="432.1597" y2="227.7854">
<stop offset="0" style="stop-color:#008CE2"/> <stop offset="0" style="stop-color:#008CE2"/>
<stop offset="0.9017" style="stop-color:#0098E8"/> <stop offset="0.9017" style="stop-color:#0098E8"/>
</linearGradient> </linearGradient>
<path class="st2" d="M414.1,229.4l43.6,40.8c5,4.7,1.7,13.1-5.2,13.1h-39.4c-4.9,0-8.9-4-8.9-8.9v-40.6 <path class="st2" d="M414.1,229.4l43.6,40.8c5,4.7,1.7,13.1-5.2,13.1h-39.4c-4.9,0-8.9-4-8.9-8.9v-40.6
C404.2,228.5,410.4,225.9,414.1,229.4z"/> C404.2,228.5,410.4,225.9,414.1,229.4z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="380.3181" y1="417.6981" x2="380.3181" y2="294.9461"> <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="380.3181" y1="417.6981" x2="380.3181" y2="294.9461">
<stop offset="0" style="stop-color:#006FCE"/> <stop offset="0" style="stop-color:#006FCE"/>
<stop offset="0.9017" style="stop-color:#0082D9"/> <stop offset="0.9017" style="stop-color:#0082D9"/>
</linearGradient> </linearGradient>
<path class="st3" d="M425.9,376.3L385,415.6c-1.4,1.3-3.2,2.1-5.2,2.1c-2,0-3.9-0.8-5.3-2.2l-39.9-40.1c-1.8-1.8-2.6-4.1-2.6-6.4 <path class="st3" d="M425.9,376.3L385,415.6c-1.4,1.3-3.2,2.1-5.2,2.1c-2,0-3.9-0.8-5.3-2.2l-39.9-40.1c-1.8-1.8-2.6-4.1-2.6-6.4
c0-2.7,1.2-5.4,3.5-7.2c3.7-2.9,8.9-2.5,12.2,0.9l23.6,24.6v-82.7c0-5.3,4.3-9.6,9.6-9.6h0c5.3,0,9.6,4.3,9.6,9.6v80.6l23-22 c0-2.7,1.2-5.4,3.5-7.2c3.7-2.9,8.9-2.5,12.2,0.9l23.6,24.6v-82.7c0-5.3,4.3-9.6,9.6-9.6h0c5.3,0,9.6,4.3,9.6,9.6v80.6l23-22
c1.8-1.7,4-2.5,6.3-2.5c2.5,0,5,1,6.8,3C429.6,367.4,429.4,372.9,425.9,376.3z"/> c1.8-1.7,4-2.5,6.3-2.5c2.5,0,5,1,6.8,3C429.6,367.4,429.4,372.9,425.9,376.3z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="490.3123" y1="553.3344" x2="490.3123" y2="461.3674"> <linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="490.3123" y1="553.3344" x2="490.3123" y2="461.3674">
<stop offset="4.469245e-02" style="stop-color:#007BD8"/> <stop offset="4.469245e-02" style="stop-color:#007BD8"/>
<stop offset="1" style="stop-color:#007DD8"/> <stop offset="1" style="stop-color:#007DD8"/>
</linearGradient> </linearGradient>
<path class="st4" d="M468.5,520.7l34.1-37.2c0.6-0.7,1.4-1.3,2.2-1.8c5.7-3.4,29.9-17.6,39.9-20.4c0,0-50,86.7-108.6,92 <path class="st4" d="M468.5,520.7l34.1-37.2c0.6-0.7,1.4-1.3,2.2-1.8c5.7-3.4,29.9-17.6,39.9-20.4c0,0-50,86.7-108.6,92
c0,0,21.3-5,30.6-29.4C467,522.7,467.7,521.6,468.5,520.7z"/> c0,0,21.3-5,30.6-29.4C467,522.7,467.7,521.6,468.5,520.7z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="327.0562" y1="771.1231" x2="327.0562" y2="426.3489"> <linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="327.0562" y1="771.1231" x2="327.0562" y2="426.3489">
<stop offset="0.1117" style="stop-color:#0067C7"/> <stop offset="0.1117" style="stop-color:#0067C7"/>
<stop offset="1" style="stop-color:#0082DA"/> <stop offset="1" style="stop-color:#0082DA"/>
</linearGradient> </linearGradient>
<path class="st5" d="M40.5,692.5c0,0,89.9,15,139.8,78.6c0,0,22.9-70.8,57.5-100.4c1.5-1.3,2.9-2.6,4.3-3.9 <path class="st5" d="M40.5,692.5c0,0,89.9,15,139.8,78.6c0,0,22.9-70.8,57.5-100.4c1.5-1.3,2.9-2.6,4.3-3.9
c5.8-5.6,27.6-22,79.3-17.5c0,0,121.1,15.3,198.9-60c2.6-2.6,5.4-5.1,8.1-7.5c9.3-8.3,33.6-32.7,54.2-76.2l29.8-61 c5.8-5.6,27.6-22,79.3-17.5c0,0,121.1,15.3,198.9-60c2.6-2.6,5.4-5.1,8.1-7.5c9.3-8.3,33.6-32.7,54.2-76.2l29.8-61
c2.6-5.3,0.8-11.7-4.2-14.9l0,0c-7.5-4.8-17.1-4.6-24.3,0.4c-8.1,5.6-19.1,16.2-32.6,36.3c-1.8,2.7-3.6,5.5-5.2,8.4 c2.6-5.3,0.8-11.7-4.2-14.9l0,0c-7.5-4.8-17.1-4.6-24.3,0.4c-8.1,5.6-19.1,16.2-32.6,36.3c-1.8,2.7-3.6,5.5-5.2,8.4
c-7.3,12.4-35.7,57.5-71.6,76.5c0,0-54.2,34-162.2-0.4H390c0,0,37.9,1.6,54.4-15.1c11-11,6.6-29.5-8.3-33.9 c-7.3,12.4-35.7,57.5-71.6,76.5c0,0-54.2,34-162.2-0.4H390c0,0,37.9,1.6,54.4-15.1c11-11,6.6-29.5-8.3-33.9
c-3-0.9-6.5-1.5-10.7-1.6l-55.7,0.9c-13.6,0.2-27.2-1.8-40-6.4c-2.5-0.9-5-1.9-7.4-3c-5.4-2.5-10.9-4.7-16.6-6.3 c-3-0.9-6.5-1.5-10.7-1.6l-55.7,0.9c-13.6,0.2-27.2-1.8-40-6.4c-2.5-0.9-5-1.9-7.4-3c-5.4-2.5-10.9-4.7-16.6-6.3
c-29-8.5-104.6-22.6-157.3,39.4c0,0-22.8,27.8-39.6,75.3C108.8,600.3,85.4,664.8,40.5,692.5z"/> c-29-8.5-104.6-22.6-157.3,39.4c0,0-22.8,27.8-39.6,75.3C108.8,600.3,85.4,664.8,40.5,692.5z"/>
<path class="st6" d="M758.1,315h-90.7v270H737c3.1,0,6.3,0,9.4,0.1c19.9,0.3,139.1-3.4,139.1-141.8 <path class="st6" d="M758.1,315h-90.7v270H737c3.1,0,6.3,0,9.4,0.1c19.9,0.3,139.1-3.4,139.1-141.8
C885.5,443.2,890.6,317.9,758.1,315z M827.7,461.1c0,41.1-33.3,74.5-74.5,74.5h-29.3V361.8h29.3c41.1,0,74.5,33.3,74.5,74.5V461.1z"/> C885.5,443.2,890.6,317.9,758.1,315z M827.7,461.1c0,41.1-33.3,74.5-74.5,74.5h-29.3V361.8h29.3c41.1,0,74.5,33.3,74.5,74.5V461.1z"/>
<path class="st6" d="M911.9,384.8v198.4h54.3v-98.1c0-11,2.8-21.9,8.6-31.3c8.2-13.3,23.6-26.4,51.6-19.3l8.5-49.7 <path class="st6" d="M911.9,384.8v198.4h54.3v-98.1c0-11,2.8-21.9,8.6-31.3c8.2-13.3,23.6-26.4,51.6-19.3l8.5-49.7
c0,0-44.1-15.5-68.7,29.7v-29.7H911.9z"/> c0,0-44.1-15.5-68.7,29.7v-29.7H911.9z"/>
<path class="st6" d="M1152.2,381.1c-8.3-1.3-16.7-1.4-24.9-0.4c-86.2,10.5-87.8,93-87.8,93c-3.4,117.7,94.8,115,94.8,115 <path class="st6" d="M1152.2,381.1c-8.3-1.3-16.7-1.4-24.9-0.4c-86.2,10.5-87.8,93-87.8,93c-3.4,117.7,94.8,115,94.8,115
c101.9-0.6,101.9-96.1,101.9-96.1C1240,405.4,1180.4,385.6,1152.2,381.1z M1137.4,545.1c-24.9,0-45.1-27.2-45.1-60.6 c101.9-0.6,101.9-96.1,101.9-96.1C1240,405.4,1180.4,385.6,1152.2,381.1z M1137.4,545.1c-24.9,0-45.1-27.2-45.1-60.6
c0-33.5,20.2-60.6,45.1-60.6s45.1,27.1,45.1,60.6C1182.5,518,1162.3,545.1,1137.4,545.1z"/> c0-33.5,20.2-60.6,45.1-60.6s45.1,27.1,45.1,60.6C1182.5,518,1162.3,545.1,1137.4,545.1z"/>
<path class="st6" d="M1441.8,431.3c0,0-12.4-40.5-60.7-49.6c-11.9-2.2-24.2-1.7-35.8,2c-10.5,3.3-23.4,9.6-33.8,21.3l-0.3-20.6 <path class="st6" d="M1441.8,431.3c0,0-12.4-40.5-60.7-49.6c-11.9-2.2-24.2-1.7-35.8,2c-10.5,3.3-23.4,9.6-33.8,21.3l-0.3-20.6
l-52.2,0.6l-0.6,262.3h53.5v-83.5c0,0,45.6,50.3,104.7,6.3C1416.5,570.2,1472.8,530.3,1441.8,431.3z M1363.4,543.6 l-52.2,0.6l-0.6,262.3h53.5v-83.5c0,0,45.6,50.3,104.7,6.3C1416.5,570.2,1472.8,530.3,1441.8,431.3z M1363.4,543.6
c-20.6,3.3-33.6-5.1-41.6-14.8c-7.7-9.3-11.5-21.2-11.5-33.2V470c0-7.3,1.4-14.5,4.3-21.1c12.1-27.1,35.9-25.1,35.9-25.1 c-20.6,3.3-33.6-5.1-41.6-14.8c-7.7-9.3-11.5-21.2-11.5-33.2V470c0-7.3,1.4-14.5,4.3-21.1c12.1-27.1,35.9-25.1,35.9-25.1
c43.7-2.7,47.5,48.3,47.5,48.3C1403.6,537.3,1363.4,543.6,1363.4,543.6z"/> c43.7-2.7,47.5,48.3,47.5,48.3C1403.6,537.3,1363.4,543.6,1363.4,543.6z"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -1,151 +1,152 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard - I2P Secure Share</title> <title>Admin Dashboard - I2P Secure Share</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwind.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/tailwind.css') }}">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<style> <style>
body { background-color: #1a202c; color: #cbd5e0; } body { background-color: #1a202c; color: #cbd5e0; }
.content-container { background-color: #2d3748; border: 1px solid #4a5568; } .content-container { background-color: #2d3748; border: 1px solid #4a5568; }
.btn { background-color: #4299e1; transition: background-color 0.3s ease; } .btn { background-color: #4299e1; transition: background-color 0.3s ease; }
.btn:hover { background-color: #3182ce; } .btn:hover { background-color: #3182ce; }
.btn-danger { background-color: #e53e3e; } .btn-danger { background-color: #e53e3e; }
.btn-danger:hover { background-color: #c53030; } .btn-danger:hover { background-color: #c53030; }
input { background-color: #4a5568; border: 1px solid #718096; } input { background-color: #4a5568; border: 1px solid #718096; }
table { width: 100%; border-collapse: collapse; } table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #4a5568; padding: 0.75rem; text-align: left; } th, td { border: 1px solid #4a5568; padding: 0.75rem; text-align: left; }
th { background-color: #1a202c; } th { background-color: #1a202c; }
tr:nth-child(even) { background-color: #2d3748; } tr:nth-child(even) { background-color: #2d3748; }
.alert-error { background-color: #e53e3e; } .alert-error { background-color: #e53e3e; }
.announcement-bar { background-color: #2563eb; border-bottom: 1px solid #1e3a8a; } .announcement-bar { background-color: #2563eb; border-bottom: 1px solid #1e3a8a; }
</style> </style>
</head> </head>
<body class="font-sans"> <body class="font-sans">
{% if announcement_enabled and announcement_message %} {% if announcement_enabled and announcement_message %}
<div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg"> <div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg">
<span>{{ announcement_message }}</span> <span>{{ announcement_message }}</span>
<button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button> <button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button>
</div> </div>
{% endif %} {% endif %}
<div class="flex items-center justify-center min-h-screen py-8"> <div class="flex items-center justify-center min-h-screen py-8">
<div class="w-full max-w-4xl mx-auto p-4"> <a href="/" class="inline-block mb-4">
<header class="text-center mb-8"> <img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
<a href="/" class="inline-block mb-4"> </a>
<img src="{{ url_for('static', filename='images/stormycloud.svg') }}" alt="StormyCloud Logo" style="width: 550px; max-width: 100%;" class="mx-auto"> <h1 class="text-4xl font-bold text-white">Admin Dashboard</h1>
</a> </header>
<h1 class="text-4xl font-bold text-white">Admin Dashboard</h1>
</header> <main class="content-container rounded-lg p-8 shadow-lg">
{% if auth_success %}
<main class="content-container rounded-lg p-8 shadow-lg"> <h2 class="text-2xl font-semibold text-white mb-6">Active Images</h2>
{% if auth_success %} {% if images %}
<h2 class="text-2xl font-semibold text-white mb-6">Active Images</h2> <div class="overflow-x-auto">
{% if images %} <table>
<div class="overflow-x-auto"> <thead>
<table> <tr>
<thead> <th>Filename</th>
<tr> <th>Expires On (UTC)</th>
<th>Filename</th> <th>Time Left</th>
<th>Expires On (UTC)</th> <th>Action</th>
<th>Time Left</th> </tr>
<th>Action</th> </thead>
</tr> <tbody>
</thead> {% for image in images %}
<tbody> <tr>
{% for image in images %} <td class="font-mono text-sm break-all">{{ image[0] }}</td>
<tr> <td class="font-mono text-sm">{{ image[1] }}</td>
<td class="font-mono text-sm break-all">{{ image[0] }}</td> <td class="font-mono text-sm">{{ image[2] }}</td>
<td class="font-mono text-sm">{{ image[1] }}</td> <td>
<td class="font-mono text-sm">{{ image[2] }}</td> <form action="{{ url_for('delete_image', filename=image[0]) }}" method="POST" onsubmit="return confirm('Are you sure you want to delete this image?');">
<td> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<form action="{{ url_for('delete_image', filename=image[0]) }}" method="POST" onsubmit="return confirm('Are you sure you want to delete this image?');"> <button type="submit" class="btn-danger text-white font-bold py-1 px-3 rounded text-sm">Delete</button>
<button type="submit" class="btn-danger text-white font-bold py-1 px-3 rounded text-sm">Delete</button> </form>
</form> </td>
</td> </tr>
</tr> {% endfor %}
{% endfor %} </tbody>
</tbody> </table>
</table> </div>
</div> {% else %}
{% else %} <p class="text-gray-400">No active images.</p>
<p class="text-gray-400">No active images.</p> {% endif %}
{% endif %}
<h2 class="text-2xl font-semibold text-white mt-12 mb-6">Active Pastes</h2>
<h2 class="text-2xl font-semibold text-white mt-12 mb-6">Active Pastes</h2> {% if pastes %}
{% if pastes %} <div class="overflow-x-auto">
<div class="overflow-x-auto"> <table>
<table> <thead>
<thead> <tr>
<tr> <th>ID</th>
<th>ID</th> <th>Language</th>
<th>Language</th> <th>Expires On (UTC)</th>
<th>Expires On (UTC)</th> <th>Time Left</th>
<th>Time Left</th> <th>Action</th>
<th>Action</th> </tr>
</tr> </thead>
</thead> <tbody>
<tbody> {% for paste in pastes %}
{% for paste in pastes %} <tr>
<tr> <td class="font-mono text-sm break-all">{{ paste[0] }}</td>
<td class="font-mono text-sm break-all">{{ paste[0] }}</td> <td class="font-mono text-sm">{{ paste[1] }}</td>
<td class="font-mono text-sm">{{ paste[1] }}</td> <td class="font-mono text-sm">{{ paste[2] }}</td>
<td class="font-mono text-sm">{{ paste[2] }}</td> <td class="font-mono text-sm">{{ paste[3] }}</td>
<td class="font-mono text-sm">{{ paste[3] }}</td> <td>
<td> <form action="{{ url_for('delete_paste', paste_id=paste[0]) }}" method="POST" onsubmit="return confirm('Are you sure you want to delete this paste?');">
<form action="{{ url_for('delete_paste', paste_id=paste[0]) }}" method="POST" onsubmit="return confirm('Are you sure you want to delete this paste?');"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<button type="submit" class="btn-danger text-white font-bold py-1 px-3 rounded text-sm">Delete</button> <button type="submit" class="btn-danger text-white font-bold py-1 px-3 rounded text-sm">Delete</button>
</form> </form>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
{% else %} {% else %}
<p class="text-gray-400">No active pastes.</p> <p class="text-gray-400">No active pastes.</p>
{% endif %} {% endif %}
{% else %} {% else %}
<h2 class="text-2xl font-semibold text-white mb-6">Admin Login</h2> <h2 class="text-2xl font-semibold text-white mb-6">Admin Login</h2>
{% with messages = get_flashed_messages(with_categories=true) %} {% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %} {% if messages %}
<div class="mb-4"> <div class="mb-4">
{% for category, message in messages %} {% for category, message in messages %}
<div class="alert-{{ category }} text-white p-3 rounded-md shadow-lg" role="alert"> <div class="alert-{{ category }} text-white p-3 rounded-md shadow-lg" role="alert">
{{ message }} {{ message }}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<form method="POST" action="{{ url_for('admin_dashboard') }}"> <form method="POST" action="{{ url_for('admin_dashboard') }}">
<div class="mb-6"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<label for="password" class="block text-gray-300 text-sm font-bold mb-2">Password:</label> <div class="mb-6">
<input type="password" name="password" id="password" class="w-full p-2 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-blue-500" required> <label for="password" class="block text-gray-300 text-sm font-bold mb-2">Password:</label>
</div> <input type="password" name="password" id="password" class="w-full p-2 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-blue-500" required>
<div><button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md focus:shadow-outline">Login</button></div> </div>
</form> <div><button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md focus:shadow-outline">Login</button></div>
{% endif %} </form>
<div class="text-center mt-8 border-t border-gray-700 pt-6"> {% endif %}
<a href="{{ url_for('index') }}" class="text-blue-400 hover:text-blue-300">Back to Homepage</a> <div class="text-center mt-8 border-t border-gray-700 pt-6">
</div> <a href="{{ url_for('index') }}" class="text-blue-400 hover:text-blue-300">Back to Homepage</a>
</main> </div>
<footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8"> </main>
<a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a> <footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8">
</footer> <a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a>
</div> </footer>
</div> </div>
<script> </div>
const announcementBar = document.getElementById('announcement-bar'); <script>
const closeButton = document.getElementById('close-announcement'); const announcementBar = document.getElementById('announcement-bar');
if (closeButton) { const closeButton = document.getElementById('close-announcement');
closeButton.addEventListener('click', () => { if (closeButton) {
announcementBar.style.display = 'none'; closeButton.addEventListener('click', () => {
}); announcementBar.style.display = 'none';
} });
</script> }
</body> </script>
</html> </body>
</html>

View File

@@ -1,66 +1,66 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Support the Project - I2P Secure Share</title> <title>Support the Project - I2P Secure Share</title>
<link rel="stylesheet" href="/static/css/tailwind.css"> <link rel="stylesheet" href="/static/css/tailwind.css">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<style> <style>
body { background-color: #1a202c; color: #cbd5e0; } body { background-color: #1a202c; color: #cbd5e0; }
.content-container { background-color: #2d3748; border: 1px solid #4a5568; } .content-container { background-color: #2d3748; border: 1px solid #4a5568; }
.announcement-bar { background-color: #2563eb; border-bottom: 1px solid #1e3a8a; } .announcement-bar { background-color: #2563eb; border-bottom: 1px solid #1e3a8a; }
.address-box { background-color: #1a202c; padding: 1rem; border-radius: 0.5rem; word-break: break-all; } .address-box { background-color: #1a202c; padding: 1rem; border-radius: 0.5rem; word-break: break-all; }
</style> </style>
</head> </head>
<body class="font-sans"> <body class="font-sans">
{% if announcement_enabled and announcement_message %} {% if announcement_enabled and announcement_message %}
<div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg"> <div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg">
<span>{{ announcement_message }}</span> <span>{{ announcement_message }}</span>
<button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button> <button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button>
</div> </div>
{% endif %} {% endif %}
<div class="flex items-center justify-center min-h-screen py-8"> <div class="flex items-center justify-center min-h-screen py-8">
<div class="w-full max-w-2xl mx-auto p-4"> <div class="w-full max-w-2xl mx-auto p-4">
<header class="text-center mb-8"> <header class="text-center mb-8">
<a href="/" class="inline-block mb-4"> <a href="/" class="inline-block mb-4">
<img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width: 550px; max-width: 100%;" class="mx-auto"> <img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
</a> </a>
<h1 class="text-3xl font-bold text-white">Support the Service</h1> <h1 class="text-3xl font-bold text-white">Support the Service</h1>
</header> </header>
<main class="content-container rounded-lg p-8 shadow-lg"> <main class="content-container rounded-lg p-8 shadow-lg">
<p class="text-center text-gray-400 mb-6">This service is developed and maintained for the I2P community free of charge. If you find it valuable, please consider a small donation to help cover server costs and support future development.</p> <p class="text-center text-gray-400 mb-6">This service is developed and maintained for the I2P community free of charge. If you find it valuable, please consider a small donation to help cover server costs and support future development.</p>
<div class="text-center"> <div class="text-center">
<h2 class="text-2xl font-semibold text-white mb-2">Monero (XMR)</h2> <h2 class="text-2xl font-semibold text-white mb-2">Monero (XMR)</h2>
<div class="address-box font-mono text-sm"> <div class="address-box font-mono text-sm">
45Gtj5tkhs4EsbnV7kkhMCRpbZUdqCQqR5qmLFVLAvbFCYaPL4pFbBkEBLJ7beHqkiJxdTBkPwFsT5EMu5jDrYBHPjQzPuv 45Gtj5tkhs4EsbnV7kkhMCRpbZUdqCQqR5qmLFVLAvbFCYaPL4pFbBkEBLJ7beHqkiJxdTBkPwFsT5EMu5jDrYBHPjQzPuv
</div> </div>
</div> </div>
<div class="text-center mt-12 border-t border-gray-700 pt-6"> <div class="text-center mt-12 border-t border-gray-700 pt-6">
<a href="/" class="text-blue-400 hover:text-blue-300">Back to Uploader</a> <a href="/" class="text-blue-400 hover:text-blue-300">Back to Uploader</a>
</div> </div>
</main> </main>
<footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8"> <footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8">
<a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a> <a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a>
<span class="mx-2">|</span> <span class="mx-2">|</span>
<a href="/donate" class="hover:text-gray-400">Donate</a> <a href="/donate" class="hover:text-gray-400">Donate</a>
</footer> </footer>
</div> </div>
</div> </div>
<script> <script>
const announcementBar = document.getElementById('announcement-bar'); const announcementBar = document.getElementById('announcement-bar');
const closeButton = document.getElementById('close-announcement'); const closeButton = document.getElementById('close-announcement');
if (closeButton) { if (closeButton) {
closeButton.addEventListener('click', () => { closeButton.addEventListener('click', () => {
announcementBar.style.display = 'none'; announcementBar.style.display = 'none';
}); });
} }
</script> </script>
</body> </body>
</html> </html>

View File

@@ -100,12 +100,9 @@
<div class="flex items-center justify-center min-h-screen py-8"> <div class="flex items-center justify-center min-h-screen py-8">
<div id="main-container" class="w-full max-w-2xl mx-auto p-4"> <div id="main-container" class="w-full max-w-2xl mx-auto p-4">
<header class="text-center mb-8"> <header class="text-center mb-8">
<a href="/" class="inline-block mb-4"> <a href="/" class="inline-block mb-4">
<img src="/static/images/stormycloud.svg" <img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
alt="StormyCloud Logo" </a>
style="width:550px;max-width:100%;"
class="mx-auto"/>
</a>
<h1 class="text-4xl font-bold text-white">I2P Secure Share</h1> <h1 class="text-4xl font-bold text-white">I2P Secure Share</h1>
<p class="text-gray-400">Anonymously share images and text pastes.</p> <p class="text-gray-400">Anonymously share images and text pastes.</p>
</header> </header>
@@ -141,9 +138,9 @@
</div> </div>
<div class="noscript-forms-container"> <div class="noscript-forms-container">
<!-- IMAGE FORM -->
<div id="image-form" class="content-container rounded-lg p-8 shadow-lg tab-content"> <div id="image-form" class="content-container rounded-lg p-8 shadow-lg tab-content">
<form action="/upload/image" method="POST" enctype="multipart/form-data"> <form action="/upload/image" method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<h2 class="text-2xl font-semibold mb-6 text-white">Upload an Image</h2> <h2 class="text-2xl font-semibold mb-6 text-white">Upload an Image</h2>
<div class="mb-6"> <div class="mb-6">
@@ -197,9 +194,9 @@
</form> </form>
</div> </div>
<!-- PASTE FORM -->
<div id="paste-form" class="content-container rounded-lg p-8 shadow-lg hidden tab-content"> <div id="paste-form" class="content-container rounded-lg p-8 shadow-lg hidden tab-content">
<form action="/upload/paste" method="POST"> <form action="/upload/paste" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<h2 class="text-2xl font-semibold mb-6 text-white">Create a Paste</h2> <h2 class="text-2xl font-semibold mb-6 text-white">Create a Paste</h2>
<div class="mb-6"> <div class="mb-6">
<label for="paste-content" class="block text-gray-300 text-sm font-bold mb-2">Paste Content:</label> <label for="paste-content" class="block text-gray-300 text-sm font-bold mb-2">Paste Content:</label>
@@ -251,7 +248,6 @@
</form> </form>
</div> </div>
<!-- API DOCS -->
<div id="api-docs" class="content-container docs-container rounded-lg p-8 shadow-lg hidden tab-content"> <div id="api-docs" class="content-container docs-container rounded-lg p-8 shadow-lg hidden tab-content">
<h3>Introduction</h3> <h3>Introduction</h3>
<p>The API allows programmatic uploads. All endpoints are rate-limited. No API key is required.</p> <p>The API allows programmatic uploads. All endpoints are rate-limited. No API key is required.</p>
@@ -282,7 +278,6 @@
http://{{ request.host }}/api/upload/paste</pre> http://{{ request.host }}/api/upload/paste</pre>
</div> </div>
<!-- STATS -->
<div id="stats-content" class="content-container rounded-lg p-8 shadow-lg hidden tab-content"> <div id="stats-content" class="content-container rounded-lg p-8 shadow-lg hidden tab-content">
<h2 class="text-3xl font-bold text-white text-center mb-8">Service Statistics</h2> <h2 class="text-3xl font-bold text-white text-center mb-8">Service Statistics</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@@ -301,7 +296,6 @@ http://{{ request.host }}/api/upload/paste</pre>
</div> </div>
</div> </div>
<!-- TERMS OF SERVICE -->
<div id="tos-content" class="content-container tos-container rounded-lg p-8 shadow-lg hidden tab-content"> <div id="tos-content" class="content-container tos-container rounded-lg p-8 shadow-lg hidden tab-content">
<h2 class="text-3xl font-bold text-white mb-4">Terms of Service</h2> <h2 class="text-3xl font-bold text-white mb-4">Terms of Service</h2>
<p><strong>Last Updated: June 20, 2025</strong></p> <p><strong>Last Updated: June 20, 2025</strong></p>
@@ -320,14 +314,12 @@ http://{{ request.host }}/api/upload/paste</pre>
</div> </div>
</div> </div>
<!-- Version Info (Moved outside the tabbed content) -->
<div class="text-center text-xs text-gray-500 mt-6 mb-8"> <div class="text-center text-xs text-gray-500 mt-6 mb-8">
<a href="https://github.com/your-username/your-repo-name" target="_blank" rel="noopener noreferrer" class="hover:text-gray-400 transition-colors"> <a href="http://git.idk.i2p/stormycloud/drop.i2p/releases/tag/v1.1" target="_blank" rel="noopener noreferrer" class="hover:text-gray-400 transition-colors">
Version 1.1 Version 1.1
</a> </a>
</div> </div>
<!-- FEATURES -->
<section class="text-center features-section"> <section class="text-center features-section">
<h2 class="text-3xl font-bold text-white mb-8">Features</h2> <h2 class="text-3xl font-bold text-white mb-8">Features</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8"> <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
@@ -416,4 +408,4 @@ http://{{ request.host }}/api/upload/paste</pre>
}); });
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,108 +1,121 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Image Uploaded - I2P Secure Share</title> <title>View Image - I2P Secure Share</title>
<link rel="stylesheet" href="/static/css/tailwind.css"/> <link rel="stylesheet" href="/static/css/tailwind.css"/>
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<style> <style>
body { background-color: #1a202c; color: #cbd5e0; } body { background-color: #1a202c; color: #cbd5e0; }
.link-box { background-color: #2d3748; border:1px solid #4a5568; word-break:break-all; } .content-container { background-color: #2d3748; border: 1px solid #4a5568; }
.btn { background-color:#4299e1; transition:background-color .3s ease; } .link-box { background-color: #2d3748; border:1px solid #4a5568; word-break:break-all; }
.btn:hover { background-color:#3182ce; } .btn { background-color:#4299e1; transition:background-color .3s ease; }
.thumbnail-container { border:2px dashed #4a5568; max-width:100%; } .btn:hover { background-color:#3182ce; }
.thumbnail { max-width:100%; max-height:60vh; object-fit:contain; } .thumbnail-container { border:2px dashed #4a5568; max-width:100%; }
.announcement-bar { background-color:#2563eb; border-bottom:1px solid #1e3a8a; } .thumbnail { max-width:100%; max-height:60vh; object-fit:contain; }
</style> .announcement-bar { background-color:#2563eb; border-bottom:1px solid #1e3a8a; }
</head> .alert-success { background-color:#38a169; }
<body class="font-sans"> .alert-error { background-color:#e53e3e; }
</style>
{% if announcement_enabled and announcement_message %} </head>
<div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg"> <body class="font-sans">
<span>{{ announcement_message }}</span>
<button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button> {% if announcement_enabled and announcement_message %}
</div> <div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg">
{% endif %} <span>{{ announcement_message }}</span>
<button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button>
<div class="flex items-center justify-center min-h-screen py-8"> </div>
<div class="w-full max-w-2xl mx-auto p-4"> {% endif %}
{% if password_required %}
<div class="content-container rounded-lg p-8 shadow-lg"> <div class="flex items-center justify-center min-h-screen py-8">
<h2 class="text-2xl font-semibold text-white mb-6">Enter Password to View Image</h2> <div class="w-full max-w-2xl mx-auto p-4">
<form method="POST"> {% if password_required %}
<div class="mb-6"> <div class="content-container rounded-lg p-8 shadow-lg">
<label for="password" class="block text-gray-300 text-sm font-bold mb-2">Password:</label> <h2 class="text-2xl font-semibold text-white mb-6">Enter Password to View Image</h2>
<input type="password" name="password" id="password" <form method="POST">
class="w-full p-2 rounded-md text-white bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
required> <div class="mb-6">
</div> <label for="password" class="block text-gray-300 text-sm font-bold mb-2">Password:</label>
<button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md">Unlock Image</button> <input type="password" name="password" id="password"
</form> class="w-full p-2 rounded-md text-white bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
</div> required>
{% else %} </div>
<header class="text-center mb-8"> <button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md">Unlock Image</button>
<a href="/" class="inline-block mb-4"> </form>
<img src="/static/images/stormycloud.svg" </div>
alt="StormyCloud Logo" {% else %}
style="width:550px; max-width:100%;" class="mx-auto"/> <header class="text-center mb-8">
</a> <a href="/" class="inline-block mb-4">
<h1 class="text-3xl font-bold text-white">Image Uploaded Successfully</h1> <img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
<p class="text-gray-400 mt-2 text-xl">Expires in: {{ time_left }}</p> </a>
</header> <h1 class="text-3xl font-bold text-white">View Image</h1>
<p class="text-gray-400 mt-2 text-xl">Expires in: {{ time_left }}</p>
<main> </header>
<div class="thumbnail-container rounded-lg p-4 mb-6 flex justify-center items-center">
<img src="/uploads/{{ filename }}" <main>
alt="Uploaded Image" class="thumbnail rounded-md"/> {% with messages = get_flashed_messages(with_categories=true) %}
</div> {% if messages %}
<div class="mb-4">
<div class="link-box rounded-lg p-4 mb-4"> {% for category, message in messages %}
<label for="share-link" class="block text-gray-300 text-sm font-bold mb-2">Direct Image Link:</label> <div class="alert-{{category}} text-white p-3 rounded-md shadow-lg"
<div class="flex items-center space-x-2"> role="alert">{{ message }}</div>
<input type="text" id="share-link" {% endfor %}
class="bg-gray-700 text-white w-full p-2 border border-gray-600 rounded-md" </div>
value="{{ request.host_url }}uploads/{{ filename }}" readonly> {% endif %}
<button id="copy-button" {% endwith %}
class="btn whitespace-nowrap flex-shrink-0 text-white font-bold py-3 px-5 rounded-md">
Copy <div class="thumbnail-container rounded-lg p-4 mb-6 flex justify-center items-center">
</button> <img src="/uploads/{{ filename }}"
</div> alt="Uploaded Image" class="thumbnail rounded-md"/>
</div> </div>
<div class="text-center mt-8"> <div class="link-box rounded-lg p-4 mb-4">
<a href="/" class="text-blue-400 hover:text-blue-300">Upload another file</a> <label for="share-link" class="block text-gray-300 text-sm font-bold mb-2">Direct Image Link:</label>
</div> <div class="flex items-center space-x-2">
<div class="text-center mt-4 text-sm"> <input type="text" id="share-link"
<p class="text-gray-500">Find this service useful? <a href="/donate" class="text-blue-400 hover:underline">Consider supporting its future.</a></p> class="bg-gray-700 text-white w-full p-2 border border-gray-600 rounded-md"
</div> value="{{ request.host_url }}uploads/{{ filename }}" readonly>
<button id="copy-button"
</main> class="btn whitespace-nowrap flex-shrink-0 text-white font-bold py-3 px-5 rounded-md">
{% endif %} Copy
</button>
<footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8"> </div>
<a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a> </div>
<span class="mx-2">|</span>
<a href="/donate" class="hover:text-gray-400">Donate</a> <div class="text-center mt-8">
</footer> <a href="/" class="text-blue-400 hover:text-blue-300">Upload another file</a>
</div> </div>
</div> <div class="text-center mt-4 text-sm">
<p class="text-gray-500">Find this service useful? <a href="/donate" class="text-blue-400 hover:underline">Consider supporting its future.</a></p>
<script> </div>
const copyBtn = document.getElementById('copy-button');
if (copyBtn) { </main>
copyBtn.addEventListener('click', () => { {% endif %}
const inp = document.getElementById('share-link');
inp.select(); document.execCommand('copy'); <footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8">
copyBtn.textContent = 'Copied!'; <a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a>
setTimeout(() => copyBtn.textContent = 'Copy', 2000); <span class="mx-2">|</span>
}); <a href="/donate" class="hover:text-gray-400">Donate</a>
} </footer>
const closeBtn = document.getElementById('close-announcement'); </div>
if (closeBtn) closeBtn.addEventListener('click', () => </div>
document.getElementById('announcement-bar').style.display = 'none'
); <script>
</script> const copyBtn = document.getElementById('copy-button');
</body> if (copyBtn) {
</html> copyBtn.addEventListener('click', () => {
const inp = document.getElementById('share-link');
inp.select(); document.execCommand('copy');
copyBtn.textContent = 'Copied!';
setTimeout(() => copyBtn.textContent = 'Copy', 2000);
});
}
const closeBtn = document.getElementById('close-announcement');
if (closeBtn) closeBtn.addEventListener('click', () =>
document.getElementById('announcement-bar').style.display = 'none'
);
</script>
</body>
</html>

View File

@@ -1,118 +1,215 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Paste Created - I2P Secure Share</title> <title>View Paste - I2P Secure Share</title>
<link rel="stylesheet" href="/static/css/tailwind.css"/> <link rel="stylesheet" href="/static/css/tailwind.css"/>
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<style> <style>
body { background-color: #1a202c; color: #cbd5e0; } body { background-color: #1a202c; color: #cbd5e0; }
.link-box { background-color: #2d3748; border:1px solid #4a5568; word-break:break-all; } .link-box { background-color: #2d3748; border:1px solid #4a5568; word-break:break-all; }
.btn { background-color:#4299e1; transition:background-color .3s ease; } .btn { background-color:#4299e1; transition:background-color .3s ease; }
.btn:hover { background-color:#3182ce; } .btn:hover { background-color:#3182ce; }
.code-container { .code-container {
background-color:#2d3748; border-radius:0.5rem; border:1px solid #4a5568; overflow:hidden; background-color:#2d3748; border-radius:0.5rem; border:1px solid #4a5568; overflow:hidden;
} }
.syntax pre { .syntax pre {
margin:0; padding:1rem; white-space:pre-wrap; word-wrap:break-word; margin:0; padding:1rem; white-space:pre-wrap; word-wrap:break-word;
} }
.announcement-bar { background-color:#2563eb; border-bottom:1px solid #1e3a8a; } .announcement-bar { background-color:#2563eb; border-bottom:1px solid #1e3a8a; }
.wide-container { max-width: 85rem; } .wide-container { max-width: 85rem; }
.alert-success { background-color:#38a169; }
</style> .alert-error { background-color:#e53e3e; }
</head>
<body class="font-sans"> /* Pygments 'monokai' theme CSS */
.syntax .hll { background-color: #49483e }
{% if announcement_enabled and announcement_message %} .syntax { background: #272822; color: #f8f8f2 }
<div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg"> .syntax .c { color: #75715e } /* Comment */
<span>{{ announcement_message }}</span> .syntax .err { color: #960050; background-color: #1e0010 } /* Error */
<button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button> .syntax .k { color: #66d9ef } /* Keyword */
</div> .syntax .l { color: #ae81ff } /* Literal */
{% endif %} .syntax .n { color: #f8f8f2 } /* Name */
.syntax .o { color: #f92672 } /* Operator */
<div class="flex items-center justify-center min-h-screen py-8"> .syntax .p { color: #f8f8f2 } /* Punctuation */
<div class="w-full wide-container mx-auto p-6"> .syntax .ch { color: #75715e } /* Comment.Hashbang */
{% if password_required %} .syntax .cm { color: #75715e } /* Comment.Multiline */
<div class="content-container rounded-lg p-10 shadow-lg"></div> .syntax .cp { color: #75715e } /* Comment.Preproc */
<h2 class="text-2xl font-semibold text-white mb-6">Enter Password to View Paste</h2> .syntax .cpf { color: #75715e } /* Comment.PreprocFile */
<form method="POST"> .syntax .c1 { color: #75715e } /* Comment.Single */
<div class="mb-6"> .syntax .cs { color: #75715e } /* Comment.Special */
<label for="password" class="block text-gray-300 text-sm font-bold mb-2">Password:</label> .syntax .gd { color: #f92672 } /* Generic.Deleted */
<input type="password" name="password" id="password" .syntax .ge { font-style: italic } /* Generic.Emph */
class="w-full p-2 rounded-md text-white bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" .syntax .gi { color: #a6e22e } /* Generic.Inserted */
required> .syntax .gs { font-weight: bold } /* Generic.Strong */
</div> .syntax .gu { color: #75715e } /* Generic.Subheading */
<button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md">Unlock Paste</button> .syntax .kc { color: #66d9ef } /* Keyword.Constant */
</form> .syntax .kd { color: #66d9ef } /* Keyword.Declaration */
</div> .syntax .kn { color: #f92672 } /* Keyword.Namespace */
{% else %} .syntax .kp { color: #66d9ef } /* Keyword.Pseudo */
<header class="text-center mb-8"> .syntax .kr { color: #66d9ef } /* Keyword.Reserved */
<a href="/" class="inline-block mb-4"> .syntax .kt { color: #66d9ef } /* Keyword.Type */
<img src="/static/images/stormycloud.svg" .syntax .ld { color: #e6db74 } /* Literal.Date */
alt="StormyCloud Logo" .syntax .m { color: #ae81ff } /* Literal.Number */
style="width:550px; max-width:100%;" class="mx-auto"/> .syntax .s { color: #e6db74 } /* Literal.String */
</a> .syntax .na { color: #a6e22e } /* Name.Attribute */
<h1 class="text-3xl font-bold text-white">Paste Created Successfully</h1> .syntax .nb { color: #f8f8f2 } /* Name.Builtin */
<p class="text-gray-400 mt-2 text-xl">Expires in: {{ time_left }}</p> .syntax .nc { color: #a6e22e } /* Name.Class */
</header> .syntax .no { color: #66d9ef } /* Name.Constant */
.syntax .nd { color: #a6e22e } /* Name.Decorator */
<main> .syntax .ni { color: #f8f8f2 } /* Name.Entity */
<div class="code-container mb-6 syntax"> .syntax .ne { color: #a6e22e } /* Name.Exception */
{{ highlighted_content|safe }} .syntax .nf { color: #a6e22e } /* Name.Function */
</div> .syntax .nl { color: #f8f8f2 } /* Name.Label */
.syntax .nn { color: #f8f8f2 } /* Name.Namespace */
<div class="link-box rounded-lg p-4 mb-4"> .syntax .nx { color: #a6e22e } /* Name.Other */
<label for="share-link" class="block text-gray-300 text-sm font-bold mb-2">Shareable Link:</label> .syntax .py { color: #f8f8f2 } /* Name.Property */
<div class="flex items-center space-x-2"> .syntax .nt { color: #f92672 } /* Name.Tag */
<input type="text" id="share-link" .syntax .nv { color: #f8f8f2 } /* Name.Variable */
class="bg-gray-700 text-white w-full p-2 border border-gray-600 rounded-md" .syntax .ow { color: #f92672 } /* Operator.Word */
value="{{ request.url }}" readonly> .syntax .w { color: #f8f8f2 } /* Text.Whitespace */
<button id="copy-button" .syntax .mb { color: #ae81ff } /* Literal.Number.Bin */
class="btn whitespace-nowrap flex-shrink-0 text-white font-bold py-3 px-5 rounded-md"> .syntax .mf { color: #ae81ff } /* Literal.Number.Float */
Copy .syntax .mh { color: #ae81ff } /* Literal.Number.Hex */
</button> .syntax .mi { color: #ae81ff } /* Literal.Number.Integer */
<a href="/paste/{{ paste_id }}/raw" .syntax .mo { color: #ae81ff } /* Literal.Number.Oct */
target="_blank" .syntax .sa { color: #e6db74 } /* Literal.String.Affix */
class="btn whitespace-nowrap flex-shrink-0 text-white font-bold py-3 px-5 rounded-md"> .syntax .sb { color: #e6db74 } /* Literal.String.Backtick */
Raw .syntax .sc { color: #e6db74 } /* Literal.String.Char */
</a> .syntax .dl { color: #e6db74 } /* Literal.String.Delimiter */
</div> .syntax .sd { color: #e6db74 } /* Literal.String.Doc */
</div> .syntax .s2 { color: #e6db74 } /* Literal.String.Double */
.syntax .se { color: #ae81ff } /* Literal.String.Escape */
<div class="text-center mt-8"> .syntax .sh { color: #e6db74 } /* Literal.String.Heredoc */
<a href="/" class="text-blue-400 hover:text-blue-300">Create another paste</a> .syntax .si { color: #e6db74 } /* Literal.String.Interpol */
</div> .syntax .sx { color: #e6db74 } /* Literal.String.Other */
<div class="text-center mt-4 text-sm"> .syntax .sr { color: #e6db74 } /* Literal.String.Regex */
<p class="text-gray-500">Find this service useful? <a href="/donate" class="text-blue-400 hover:underline">Consider supporting its future.</a></p> .syntax .s1 { color: #e6db74 } /* Literal.String.Single */
</div> .syntax .ss { color: #e6db74 } /* Literal.String.Symbol */
.syntax .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
</main> .syntax .fm { color: #a6e22e } /* Name.Function.Magic */
{% endif %} .syntax .vc { color: #f8f8f2 } /* Name.Variable.Class */
.syntax .vg { color: #f8f8f2 } /* Name.Variable.Global */
<footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8"> .syntax .vi { color: #f8f8f2 } /* Name.Variable.Instance */
<a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a> .syntax .vm { color: #f8f8f2 } /* Name.Variable.Magic */
<span class="mx-2">|</span> .syntax .il { color: #ae81ff } /* Literal.Number.Integer.Long */
<a href="/donate" class="hover:text-gray-400">Donate</a> </style>
</footer> </head>
</div> <body class="font-sans">
</div>
{% if announcement_enabled and announcement_message %}
<script> <div id="announcement-bar" class="announcement-bar text-white text-center p-2 relative shadow-lg">
const copyBtn = document.getElementById('copy-button'); <span>{{ announcement_message }}</span>
if (copyBtn) { <button id="close-announcement" class="absolute top-0 right-0 mt-2 mr-4 text-white hover:text-gray-200 text-2xl leading-none">&times;</button>
copyBtn.addEventListener('click', () => { </div>
const inp = document.getElementById('share-link'); {% endif %}
inp.select(); document.execCommand('copy');
copyBtn.textContent = 'Copied!'; <div class="flex items-center justify-center min-h-screen py-8">
setTimeout(() => copyBtn.textContent = 'Copy', 2000); <div class="w-full wide-container mx-auto p-6">
}); {% if password_required %}
} <div class="content-container rounded-lg p-10 shadow-lg"></div>
const closeBtn = document.getElementById('close-announcement'); <h2 class="text-2xl font-semibold text-white mb-6">Enter Password to View Paste</h2>
if (closeBtn) closeBtn.addEventListener('click', () => <form method="POST">
document.getElementById('announcement-bar').style.display = 'none' <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
); <div class="mb-6">
</script> <label for="password" class="block text-gray-300 text-sm font-bold mb-2">Password:</label>
</body> <input type="password" name="password" id="password"
</html> class="w-full p-2 rounded-md text-white bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
required>
</div>
<button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md">Unlock Paste</button>
</form>
</div>
{% else %}
<header class="text-center mb-8">
<a href="/" class="inline-block mb-4">
<img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
</a>
<h1 class="text-3xl font-bold text-white">View Paste</h1>
<p class="text-gray-400 mt-2 text-xl">Expires in: {{ time_left }}</p>
</header>
<main>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="mb-4">
{% for category, message in messages %}
<div class="alert-{{category}} text-white p-3 rounded-md shadow-lg"
role="alert">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<div class="flex justify-end mb-2">
<form method="GET" action="" class="flex items-center space-x-2">
<label for="language-switcher" class="text-sm text-gray-400">Syntax:</label>
<select name="lang" id="language-switcher" onchange="this.form.submit()" class="text-sm rounded-md p-1 bg-gray-700 border border-gray-600 focus:outline-none focus:ring-1 focus:ring-blue-500 cursor-pointer">
{% for lang in languages %}
<option value="{{ lang }}" {% if lang == selected_language %}selected{% endif %}>
{{ lang|capitalize }}
</option>
{% endfor %}
</select>
<noscript><button type="submit" class="btn text-sm py-1 px-3">Update</button></noscript>
</form>
</div>
<div class="code-container mb-6 syntax">
{{ highlighted_content|safe }}
</div>
<div class="link-box rounded-lg p-4 mb-4">
<label for="share-link" class="block text-gray-300 text-sm font-bold mb-2">Shareable Link:</label>
<div class="flex items-center space-x-2">
<input type="text" id="share-link"
class="bg-gray-700 text-white w-full p-2 border border-gray-600 rounded-md"
value="{{ request.url }}" readonly>
<button id="copy-button"
class="btn whitespace-nowrap flex-shrink-0 text-white font-bold py-3 px-5 rounded-md">
Copy
</button>
<a href="/paste/{{ paste_id }}/raw"
target="_blank"
class="btn whitespace-nowrap flex-shrink-0 text-white font-bold py-3 px-5 rounded-md">
Raw
</a>
</div>
</div>
<div class="text-center mt-8">
<a href="/" class="text-blue-400 hover:text-blue-300">Create another paste</a>
</div>
<div class="text-center mt-4 text-sm">
<p class="text-gray-500">Find this service useful? <a href="/donate" class="text-blue-400 hover:underline">Consider supporting its future.</a></p>
</div>
</main>
{% endif %}
<footer class="text-center text-gray-500 mt-16 border-t border-gray-700 pt-8 pb-8">
<a href="http://stormycloud.i2p" class="hover:text-gray-400">StormyCloud</a>
<span class="mx-2">|</span>
<a href="/donate" class="hover:text-gray-400">Donate</a>
</footer>
</div>
</div>
<script>
const copyBtn = document.getElementById('copy-button');
if (copyBtn) {
copyBtn.addEventListener('click', () => {
const inp = document.getElementById('share-link');
inp.select(); document.execCommand('copy');
copyBtn.textContent = 'Copied!';
setTimeout(() => copyBtn.textContent = 'Copy', 2000);
});
}
const closeBtn = document.getElementById('close-announcement');
if (closeBtn) closeBtn.addEventListener('click', () =>
document.getElementById('announcement-bar').style.display = 'none'
);
</script>
</body>
</html>