diff --git a/handlers.py b/handlers.py
index 62b22b4..e17f8b3 100644
--- a/handlers.py
+++ b/handlers.py
@@ -58,56 +58,46 @@ class FileServerHandler(BaseHTTPRequestHandler):
def handle_main_page(self):
content = f"""
-
-
-
- SimpliestFS
-
-
-
-
- EN: {CONFIG["ui"]["disclaimer"]}
- RU: {CONFIG["ui"]["disclaimer_ru"]}
- Contact: {CONFIG["ui"]["contact_email"]}
- Contact (prefered): @justuser_31
-
- Register
- Login
- Explore Files
-
-
- Note: NO ENCRYPTION, no external databases. As simple as possible.
-
-
-
+
+
+
+ SimpliestFS
+
+
+
+
+ EN: {CONFIG["ui"]["disclaimer"]}
+ RU: {CONFIG["ui"]["disclaimer_ru"]}
+ Contact: {CONFIG["ui"]["contact_email"]}
+ Contact (prefered): @justuser_31
+
+ Register
+ Login
+ Explore Files
+
+
+ Note: NO ENCRYPTION, no external databases. As simple as possible.
+
+
+
"""
self.send_html(content)
def handle_register_page(self):
content = f"""
-
-
-
- Register - SimpliestFS
-
-
-
-
- Register
- {CONFIG["ui"]["register_info"]}
- Back to Home
-
-
+
+
+
+ Register - SimpliestFS
+
+
+
+
+ Register
+ {CONFIG["ui"]["register_info"]}
+ Back to Home
+
+
"""
self.send_html(content)
@@ -161,31 +151,24 @@ class FileServerHandler(BaseHTTPRequestHandler):
def render_login_form(self, error=""):
content = f"""
-
-
-
- Login - SimpliestFS
-
-
-
-
- Login
- {f'{error}
' if error else ""}
-
- Back to Home
-
-
+
+
+
+ Login - SimpliestFS
+
+
+
+
+ Login
+ {f'{error}
' if error else ""}
+
+ Back to Home
+
+
"""
return content
@@ -227,37 +210,30 @@ class FileServerHandler(BaseHTTPRequestHandler):
"""
content = f"""
-
-
-
- My Files - SimpliestFS
-
-
-
-
- My Files
-
- Quota: {available_mb} MB | Used: {used_mb:.2f} MB
-
-
-
- {files_html if files_html else "No files yet.
"}
-
- Logout
- Back to Home
-
-
-
+
+
+
+ My Files - SimpliestFS
+
+
+
+
+ My Files
+
+ Quota: {available_mb} MB | Used: {used_mb:.2f} MB
+
+
+
+ {files_html if files_html else "No files yet.
"}
+
+ Logout
+ Back to Home
+
+
+
"""
self.send_html(content)
@@ -405,11 +381,7 @@ class FileServerHandler(BaseHTTPRequestHandler):
Explore Files - SimpliestFS
-
+
@@ -448,11 +420,7 @@ class FileServerHandler(BaseHTTPRequestHandler):
{username}'s Files - SimpliestFS
-
+
@@ -573,6 +541,41 @@ class FileServerHandler(BaseHTTPRequestHandler):
database.DB_CONN.commit()
self.send_html("Account deleted
")
+ def handle_static_file(self):
+ if self.path.startswith("/static/"):
+ file_path = self.path[1:] # Remove leading slash
+ try:
+ with open(file_path, "r") as file:
+ content = file.read()
+ if file_path.endswith(".css"):
+ self.send_response(200)
+ self.send_header("Content-type", "text/css")
+ self.end_headers()
+ self.wfile.write(content.encode())
+ else:
+ self.send_error(404)
+ except FileNotFoundError:
+ self.send_error(404)
+ return True
+ return False
+
+ def handle_favicon(self):
+ if self.path == "/favicon.ico":
+ file_path = os.path.join("static", self.path[1:])
+ try:
+ with open(file_path, "rb") as file: # Open in binary mode
+ content = file.read()
+ self.send_response(200)
+ self.send_header(
+ "Content-type", "image/x-icon"
+ ) # Correct MIME type
+ self.end_headers()
+ self.wfile.write(content) # Write bytes directly
+ except FileNotFoundError:
+ self.send_error(404)
+ return True
+ return False
+
def do_GET(self):
parsed_path = urlparse(self.path)
path = parsed_path.path
@@ -597,6 +600,10 @@ class FileServerHandler(BaseHTTPRequestHandler):
else:
username = parts[0]
self.handle_explore_user(username)
+ elif path.startswith("/static/") and not path.endswith("/"):
+ self.handle_static_file()
+ elif path == "/favicon.ico":
+ self.handle_favicon()
else:
self.send_html("Not Found
", 404)
diff --git a/static/favicon.ico b/static/favicon.ico
new file mode 100644
index 0000000..d79f055
Binary files /dev/null and b/static/favicon.ico differ
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..05722c8
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,332 @@
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+body {
+ font-family:
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
+ Arial, sans-serif;
+ margin: 0;
+ padding: 20px;
+ font-size: 16px;
+ line-height: 1.6;
+ color: #2c3e50;
+ background-color: #f8f9fa;
+ min-height: 100vh;
+}
+.container {
+ max-width: 900px;
+ margin: 0 auto;
+}
+h1 {
+ text-align: center;
+ margin: 30px 0;
+ font-size: 32px;
+ font-weight: 600;
+ color: #1a1a1a;
+}
+h1 a {
+ text-decoration: none;
+ color: inherit;
+ transition: color 0.2s;
+}
+h1 a:hover {
+ color: #4a5568;
+}
+h2 {
+ font-size: 24px;
+ font-weight: 500;
+ margin: 20px 0;
+ color: #2d3748;
+ text-align: center;
+}
+p {
+ margin: 12px 0;
+ color: #4a5568;
+}
+a {
+ color: #2c5282;
+ text-decoration: none;
+}
+a:hover {
+ text-decoration: underline;
+}
+hr {
+ border: none;
+ border-top: 1px solid #e2e8f0;
+ margin: 30px 0;
+}
+.btn,
+.back-btn,
+.upload-btn,
+.regular-button,
+button[type="submit"] {
+ display: inline-block;
+ padding: 12px 24px;
+ background: #ffffff;
+ border: 1px solid #cbd5e0;
+ border-radius: 6px;
+ text-decoration: none;
+ color: #2d3748;
+ font-size: 15px;
+ font-weight: 500;
+ text-align: center;
+ cursor: pointer;
+ transition: all 0.2s;
+ font-family: inherit;
+}
+.btn:hover,
+.back-btn:hover,
+.upload-btn:hover,
+.regular-button:hover,
+button[type="submit"]:hover {
+ background: #f7fafc;
+ border-color: #a0aec0;
+ text-decoration: none;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+.back-btn,
+.upload-btn {
+ margin: 5px;
+}
+.main-page {
+ text-align: center;
+ max-width: 700px;
+ margin: 0 auto;
+}
+.main-page h1 {
+ font-size: 40px;
+ margin-bottom: 40px;
+}
+.main-page p {
+ margin: 20px auto;
+ max-width: 600px;
+ font-size: 15px;
+}
+.main-page .btn {
+ font-size: 16px;
+ padding: 14px 32px;
+ margin: 8px;
+ min-width: 160px;
+}
+.main-page .disclaimer {
+ margin-top: 50px;
+ padding: 20px;
+ background-color: #edf2f7;
+ border-radius: 8px;
+ border: 1px solid #cbd5e0;
+ font-size: 14px;
+ color: #4a5568;
+}
+.error {
+ color: #c53030;
+ background-color: #fff5f5;
+ padding: 12px 16px;
+ border-radius: 6px;
+ border: 1px solid #feb2b2;
+ margin: 20px 0;
+ text-align: center;
+}
+.quota-info {
+ margin: 25px 0;
+ padding: 12px 20px;
+ font-size: 14px;
+ color: #4a5568;
+ text-align: center;
+ background-color: #edf2f7;
+ border-radius: 6px;
+ border: 1px solid #cbd5e0;
+}
+.login-form {
+ max-width: 420px;
+ margin: 30px auto;
+ padding: 30px;
+ background-color: #ffffff;
+ border-radius: 8px;
+ border: 1px solid #e2e8f0;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+.login-form input {
+ width: 100%;
+ padding: 14px 16px;
+ margin: 10px 0;
+ font-size: 15px;
+ border: 1px solid #cbd5e0;
+ border-radius: 6px;
+ background-color: #ffffff;
+ font-family: inherit;
+}
+.login-form input:focus {
+ outline: none;
+ border-color: #4299e1;
+ box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.1);
+}
+.login-form button {
+ width: 100%;
+ margin-top: 10px;
+}
+form[action="/upload"] {
+ margin: 25px 0;
+ padding: 20px;
+ background-color: #ffffff;
+ border-radius: 8px;
+ border: 1px solid #e2e8f0;
+ text-align: center;
+}
+input[type="file"] {
+ padding: 10px;
+ margin: 10px;
+ border: 1px solid #cbd5e0;
+ border-radius: 6px;
+ background-color: #ffffff;
+ cursor: pointer;
+}
+.files-list-item,
+div[style*="margin: 5px 0"] {
+ margin: 12px 0 !important;
+ padding: 14px 16px !important;
+ display: flex !important;
+ align-items: center !important;
+ border: 1px solid #e2e8f0 !important;
+ border-radius: 6px !important;
+ background-color: #ffffff !important;
+}
+.files-list-item:hover,
+div[style*="margin: 5px 0"]:hover {
+ background-color: #f7fafc !important;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) !important;
+}
+.files-list-item span,
+div[style*="margin: 5px 0"] span {
+ flex: 1 !important;
+ text-align: left !important;
+}
+.files-list-item a,
+div[style*="margin: 5px 0"] a {
+ font-weight: 500;
+ color: #2c5282;
+ word-break: break-all;
+}
+.files-list-item form,
+div[style*="margin: 5px 0"] form {
+ display: inline !important;
+ margin-left: 10px !important;
+}
+.files-list-item button,
+div[style*="margin: 5px 0"] button {
+ padding: 8px 16px !important;
+ font-size: 14px !important;
+ margin: 0 !important;
+}
+div[style*="margin: 5px 0"] a:only-child {
+ display: block;
+ padding: 12px 16px;
+ font-weight: 500;
+}
+p a.back-btn {
+ display: inline-block;
+ margin: 10px 5px;
+}
+
+@media (max-width: 768px) {
+ body {
+ padding: 15px;
+ font-size: 15px;
+ }
+ h1 {
+ font-size: 28px;
+ margin: 20px 0;
+ }
+ h2 {
+ font-size: 22px;
+ }
+ .main-page h1 {
+ font-size: 32px;
+ }
+ .btn,
+ .back-btn,
+ .upload-btn,
+ button[type="submit"] {
+ padding: 14px 20px;
+ font-size: 15px;
+ }
+ .main-page .btn {
+ width: 100%;
+ max-width: 300px;
+ display: block;
+ margin: 10px auto;
+ }
+ .login-form {
+ padding: 25px 20px;
+ }
+ form[action="/upload"] {
+ padding: 15px;
+ }
+ input[type="file"] {
+ width: 100%;
+ margin: 10px 0;
+ }
+ form[action="/upload"] button {
+ width: 100%;
+ margin-top: 10px;
+ }
+}
+
+@media (max-width: 480px) {
+ body {
+ padding: 10px;
+ }
+ h1 {
+ font-size: 24px;
+ margin: 15px 0;
+ }
+ h2 {
+ font-size: 20px;
+ }
+ .main-page h1 {
+ font-size: 28px;
+ }
+ .main-page p {
+ font-size: 14px;
+ }
+ .btn,
+ .back-btn,
+ .upload-btn,
+ button[type="submit"] {
+ padding: 12px 16px;
+ font-size: 14px;
+ }
+ .main-page .btn {
+ font-size: 15px;
+ padding: 14px 24px;
+ }
+ .login-form {
+ padding: 20px 15px;
+ }
+ .files-list-item,
+ div[style*="margin: 5px 0"] {
+ flex-direction: column !important;
+ align-items: flex-start !important;
+ padding: 12px !important;
+ }
+ .files-list-item span,
+ div[style*="margin: 5px 0"] span {
+ margin-bottom: 10px !important;
+ width: 100% !important;
+ }
+ .files-list-item form,
+ div[style*="margin: 5px 0"] form {
+ width: 100% !important;
+ margin-left: 0 !important;
+ margin-top: 8px !important;
+ }
+ .files-list-item button,
+ div[style*="margin: 5px 0"] button {
+ width: 100% !important;
+ }
+ p a.back-btn {
+ display: block;
+ margin: 8px 0;
+ }
+}