diff --git a/admin/index.php b/admin/index.php
index 50ff63d..5dbd114 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -153,7 +153,7 @@ if ($isAjax) {
-
Questions? Call or text (817) 555-0199 or reply to this email β we're happy to help.
+
Questions? Call or text (817) 266-2022 or reply to this email β we're happy to help.
diff --git a/db.php b/db.php
index b353beb..188e7d7 100644
--- a/db.php
+++ b/db.php
@@ -1,5 +1,5 @@
βοΈ
diff --git a/upload-docs.php b/upload-docs.php
new file mode 100644
index 0000000..9307999
--- /dev/null
+++ b/upload-docs.php
@@ -0,0 +1,189 @@
+prepare("SELECT id, name, email, booking_ref, rental_date, status FROM bookings WHERE booking_ref=?");
+ $stmt->execute([$ref]);
+ $booking = $stmt->fetch();
+ if (!$booking) $error = 'Booking not found. Please check your confirmation email.';
+ elseif ($booking['status'] === 'cancelled') $error = 'This booking has been cancelled.';
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && $booking && !$error) {
+ $file = $_FILES['doc'] ?? null;
+ if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
+ $error = 'Upload failed β please try again or check file size.';
+ } else {
+ $finfo = new finfo(FILEINFO_MIME_TYPE);
+ $mime = $finfo->file($file['tmp_name']);
+ $allowed = ['image/jpeg','image/png','application/pdf'];
+ if (!in_array($mime, $allowed)) {
+ $error = 'Only JPG, PNG, or PDF files are accepted.';
+ } elseif ($file['size'] > 10 * 1024 * 1024) {
+ $error = 'File must be under 10 MB.';
+ } else {
+ $ext = ['image/jpeg'=>'jpg','image/png'=>'png','application/pdf'=>'pdf'][$mime];
+ $dir = __DIR__ . '/uploads/' . $ref;
+ if (!is_dir($dir)) mkdir($dir, 0750, true);
+ $fname = $type . '_' . date('YmdHis') . '.' . $ext;
+ $dest = $dir . '/' . $fname;
+ if (move_uploaded_file($file['tmp_name'], $dest)) {
+ $col = $type === 'license' ? 'license_file' : 'insurance_file';
+ $rel = 'uploads/' . $ref . '/' . $fname;
+ db()->prepare("UPDATE bookings SET {$col}=? WHERE booking_ref=?")->execute([$rel, $ref]);
+
+ $typeLabel = $type === 'license' ? "Driver's License" : 'Proof of Insurance';
+ $dateLabel = date('F j, Y', strtotime($booking['rental_date']));
+ $adminHtml = "
+
+
{$typeLabel} Uploaded β {$booking['booking_ref']}
+
+
+
" . htmlspecialchars($booking['name']) . " uploaded their {$typeLabel} for booking {$booking['booking_ref']} (rental: {$dateLabel}).
+
View it in the admin panel under their booking detail.
+
+
+
";
+ sendEmail(ADMIN_EMAIL, 'Parker Slingshot Admin', "{$typeLabel} Uploaded β {$booking['booking_ref']}: " . $booking['name'], $adminHtml);
+ $done = true;
+ } else {
+ $error = 'Could not save file. Please try again.';
+ }
+ }
+ }
+}
+
+$typeLabel = $type === 'license' ? "Driver's License" : ($type === 'insurance' ? 'Proof of Insurance' : '');
+$dateLabel = $booking ? date('F j, Y', strtotime($booking['rental_date'])) : '';
+?>
+
+
+
+
+
Upload Document β Parker County Slingshot Rentals
+
+
+
+
+
+
+
+
+
+
+
+
Upload Document
+
Invalid or missing upload link. Please use the link from your email or contact us.
+
+
+
+
+
= htmlspecialchars($error) ?>
+
Need help? Call or text (817) 266-2022 .
+
+
+
+
+
β
+
+
Upload Received!
+
Thanks, = htmlspecialchars($booking['name']) ?>! Your = htmlspecialchars($typeLabel) ?> has been submitted for booking = htmlspecialchars($booking['booking_ref']) ?> .
+
We'll review it and still do a quick visual check at pickup. See you on = htmlspecialchars($dateLabel) ?>!
+
+
+
+
+
= htmlspecialchars($error) ?>
+
+
Upload = htmlspecialchars($typeLabel) ?>
+
+
= htmlspecialchars($booking['booking_ref']) ?>
+
= htmlspecialchars($booking['name']) ?> — = htmlspecialchars($dateLabel) ?>
+
+
+
+ Please upload a photo or scan of your current auto insurance card. JPG, PNG, or PDF accepted (max 10 MB).
+
+ Please upload a photo or scan of the front of your driver's license. JPG, PNG, or PDF accepted (max 10 MB).
+
+
+
We'll still do a visual check at pickup β this is just for our records.
+
+
Your document is stored securely and only visible to Parker County Slingshot Rentals staff.
+
+
+
+
+
+
+
diff --git a/view-doc.php b/view-doc.php
new file mode 100644
index 0000000..b82c898
--- /dev/null
+++ b/view-doc.php
@@ -0,0 +1,61 @@
+prepare("SELECT token FROM admin_tokens WHERE token=? AND expires_at > NOW()");
+ $stmt->execute([$token]);
+ return (bool)$stmt->fetch();
+}
+
+$token = preg_replace('/[^a-f0-9]/', '', $_GET['_t'] ?? '');
+if (!_verifyToken($token)) {
+ http_response_code(403);
+ header('Content-Type: text/plain');
+ exit('Unauthorized β please log in to the admin panel first.');
+}
+
+$ref = strtoupper(preg_replace('/[^A-Z0-9\-]/', '', $_GET['ref'] ?? ''));
+$type = in_array($_GET['type'] ?? '', ['license','insurance']) ? $_GET['type'] : '';
+if (!$ref || !$type) {
+ http_response_code(400);
+ header('Content-Type: text/plain');
+ exit('Missing parameters.');
+}
+
+$col = $type === 'license' ? 'license_file' : 'insurance_file';
+$stmt = db()->prepare("SELECT {$col} AS file_path FROM bookings WHERE booking_ref=?");
+$stmt->execute([$ref]);
+$row = $stmt->fetch();
+
+if (!$row || !$row['file_path']) {
+ http_response_code(404);
+ header('Content-Type: text/plain');
+ exit('Document not found.');
+}
+
+$base = realpath(__DIR__ . '/uploads');
+$path = realpath(__DIR__ . '/' . $row['file_path']);
+
+if (!$path || !$base || strpos($path, $base . DIRECTORY_SEPARATOR) !== 0) {
+ http_response_code(404);
+ header('Content-Type: text/plain');
+ exit('File not found.');
+}
+
+$finfo = new finfo(FILEINFO_MIME_TYPE);
+$mime = $finfo->file($path);
+$allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'application/pdf' => 'pdf'];
+if (!isset($allowed[$mime])) {
+ http_response_code(403);
+ header('Content-Type: text/plain');
+ exit('Invalid file type.');
+}
+
+$fname = $type . '-' . $ref . '.' . $allowed[$mime];
+header('Content-Type: ' . $mime);
+header('Content-Disposition: inline; filename="' . $fname . '"');
+header('Content-Length: ' . filesize($path));
+header('Cache-Control: private, max-age=3600');
+readfile($path);
+exit;