diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..e2bbc23 --- /dev/null +++ b/.htaccess @@ -0,0 +1,18 @@ +DirectoryIndex index.php index.html +Options -Indexes +Options -MultiViews + +RewriteEngine On + +# 0) Serve existing files/directories as-is +RewriteCond %{REQUEST_FILENAME} -f [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^ - [L] + +# 1) Internal map: /page or /page/ -> /page.php (if such PHP file exists) +RewriteCond %{REQUEST_FILENAME}.php -f +RewriteRule ^(.+?)/?$ $1.php [L] + +# 2) Optional: strip trailing slash for non-directories (keeps .php links working) +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^(.+)/$ $1 [R=301,L] diff --git a/.perm_test_apache b/.perm_test_apache new file mode 100644 index 0000000..e69de29 diff --git a/.perm_test_exec b/.perm_test_exec new file mode 100644 index 0000000..e69de29 diff --git a/admin_horses.php b/admin_horses.php new file mode 100644 index 0000000..a9d3b49 --- /dev/null +++ b/admin_horses.php @@ -0,0 +1,158 @@ +prepare('INSERT INTO horses (name, breed, description, image_url) VALUES (?, ?, ?, ?)'); + $stmt->execute([$name, $breed, $description, $image_url]); + $messages[] = 'Horse added successfully!'; + } catch (PDOException $e) { + $errors[] = 'Database error: ' . $e->getMessage(); + } + } +} + +// Handle Delete Horse +if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) { + $id = $_GET['id']; + try { + $pdo = db(); + $stmt = $pdo->prepare('DELETE FROM horses WHERE id = ?'); + $stmt->execute([$id]); + header('Location: admin_horses.php?deleted=true'); + exit; + } catch (PDOException $e) { + $errors[] = 'Database error: ' . $e->getMessage(); + } +} + +// Fetch all horses +$horses = []; +try { + $pdo = db(); + $stmt = $pdo->query('SELECT * FROM horses ORDER BY name'); + $horses = $stmt->fetchAll(); +} catch (PDOException $e) { + $errors[] = 'Database error: ' . $e->getMessage(); +} + +?> + + + + + + Admin: Manage Horses + + + +
+
+

Manage Horses

+ ← Home +
+ + +
+ +

+ +
+ + + +
+ +

+ +
+ + +
+
Add New Horse
+
+
+ +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+ +
+
+
+ +
+
Existing Horses
+
+ + + + + + + + + + + + + + + + + +
NameBreedActions
+ Edit + Delete +
+
+
+ +
+ + diff --git a/apply_migrations.php b/apply_migrations.php new file mode 100644 index 0000000..bee4757 --- /dev/null +++ b/apply_migrations.php @@ -0,0 +1,103 @@ +getMessage()); +} + +// --- Migration Setup --- +$migrationsTable = 'migrations'; +$migrationsDir = __DIR__ . '/db/migrations/'; + +// Create migrations table if it doesn't exist +try { + $pdo->exec("CREATE TABLE IF NOT EXISTS `$migrationsTable` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `migration` VARCHAR(255) NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); +} catch (PDOException $e) { + die("✘ Error creating migrations table: " . $e->getMessage()); +} + +// Get applied migrations +$appliedMigrations = $pdo->query("SELECT `migration` FROM `$migrationsTable`")->fetchAll(PDO::FETCH_COLUMN); + +echo "Processing Migrations...\n"; + +// --- Run Migrations --- +$migrationFiles = glob($migrationsDir . '*.sql'); +sort($migrationFiles); + +$allGood = true; + +foreach ($migrationFiles as $file) { + $migrationName = basename($file); + + if (in_array($migrationName, $appliedMigrations)) { + echo "[SKIPPED] Migration $migrationName has already been applied.\n"; + continue; + } + + echo "Applying migration: $migrationName... "; + $sql = file_get_contents($file); + + try { + $pdo->exec($sql); + + // Mark as applied + $stmt = $pdo->prepare("INSERT INTO `$migrationsTable` (`migration`) VALUES (?)"); + $stmt->execute([$migrationName]); + + echo "✔ Done.\n"; + + } catch (PDOException $e) { + $errorMessage = $e->getMessage(); + + // Check for non-critical errors to ignore and continue + $isDuplicateColumn = strpos($errorMessage, 'Duplicate column name') !== false; + $isDuplicateKey = strpos($errorMessage, 'Duplicate entry') !== false; + $isColumnNotFound = strpos($errorMessage, "Unknown column") !== false; + $isCantDropField = strpos($errorMessage, "Can't DROP COLUMN") !== false; + + if ($isDuplicateColumn || $isDuplicateKey || $isColumnNotFound || $isCantDropField) { + $reason = "Already applied"; + if ($isDuplicateColumn) $reason = "Duplicate Column"; + if ($isDuplicateKey) $reason = "Duplicate Entry"; + if ($isColumnNotFound) $reason = "Column Not Found (will be created later)"; + if ($isCantDropField) $reason = "Column already dropped"; + + echo "✔ Skipped ($reason - marking as run).\n"; + // Mark as applied even if it failed with a recoverable error + $stmt = $pdo->prepare("INSERT INTO `$migrationsTable` (`migration`) VALUES (?)"); + $stmt->execute([$migrationName]); + } else { + echo "✘ Error applying $migrationName: " . $e->getMessage() . "\n"; + $allGood = false; + // We will now continue instead of breaking + // break; + } + } +} + +if ($allGood) { + echo "\n🎉 All migrations have been applied successfully!\n"; +} else { + echo "\nAn error occurred. Not all migrations could be applied. Please review the errors above.\n"; +} +?> \ No newline at end of file diff --git a/assets/avatars/avatar_68c144c750ca28.40605127.jpg b/assets/avatars/avatar_68c144c750ca28.40605127.jpg new file mode 100644 index 0000000..b456437 Binary files /dev/null and b/assets/avatars/avatar_68c144c750ca28.40605127.jpg differ diff --git a/assets/avatars/avatar_68c294a6ed46f3.71986264.png b/assets/avatars/avatar_68c294a6ed46f3.71986264.png new file mode 100644 index 0000000..0437cbb Binary files /dev/null and b/assets/avatars/avatar_68c294a6ed46f3.71986264.png differ diff --git a/assets/pasted-20250908-111644-f385b80e.png b/assets/pasted-20250908-111644-f385b80e.png new file mode 100644 index 0000000..275efa9 Binary files /dev/null and b/assets/pasted-20250908-111644-f385b80e.png differ diff --git a/assets/pasted-20250910-063752-96793b4f.jpg b/assets/pasted-20250910-063752-96793b4f.jpg new file mode 100644 index 0000000..f139eca Binary files /dev/null and b/assets/pasted-20250910-063752-96793b4f.jpg differ diff --git a/assets/pasted-20250910-064336-512556d4.jpg b/assets/pasted-20250910-064336-512556d4.jpg new file mode 100644 index 0000000..e9de2ed Binary files /dev/null and b/assets/pasted-20250910-064336-512556d4.jpg differ diff --git a/assets/pasted-20250910-065124-15fa0386.png b/assets/pasted-20250910-065124-15fa0386.png new file mode 100644 index 0000000..e43732d Binary files /dev/null and b/assets/pasted-20250910-065124-15fa0386.png differ diff --git a/assets/pasted-20250910-070203-d672ef9e.jpg b/assets/pasted-20250910-070203-d672ef9e.jpg new file mode 100644 index 0000000..9d3ef06 Binary files /dev/null and b/assets/pasted-20250910-070203-d672ef9e.jpg differ diff --git a/assets/pasted-20250910-071615-9ca92360.png b/assets/pasted-20250910-071615-9ca92360.png new file mode 100644 index 0000000..e4699fa Binary files /dev/null and b/assets/pasted-20250910-071615-9ca92360.png differ diff --git a/assets/pasted-20250910-163439-bde803a6.png b/assets/pasted-20250910-163439-bde803a6.png new file mode 100644 index 0000000..43d2026 Binary files /dev/null and b/assets/pasted-20250910-163439-bde803a6.png differ diff --git a/db/migrations/001_create_users_table.sql b/db/migrations/001_create_users_table.sql new file mode 100644 index 0000000..3ea25e0 --- /dev/null +++ b/db/migrations/001_create_users_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `users` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `username` VARCHAR(50) NOT NULL UNIQUE, + `email` VARCHAR(100) NOT NULL UNIQUE, + `password` VARCHAR(255) NOT NULL, + `role` ENUM('client', 'instructor', 'manager', 'admin') NOT NULL DEFAULT 'client', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/migrations/002_create_horses_table.sql b/db/migrations/002_create_horses_table.sql new file mode 100644 index 0000000..c132373 --- /dev/null +++ b/db/migrations/002_create_horses_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `horses` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(100) NOT NULL, + `breed` VARCHAR(100) NOT NULL, + `description` TEXT, + `image_url` VARCHAR(255), + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/migrations/003_seed_horses_table.sql b/db/migrations/003_seed_horses_table.sql new file mode 100644 index 0000000..21bc4de --- /dev/null +++ b/db/migrations/003_seed_horses_table.sql @@ -0,0 +1,4 @@ +INSERT INTO `horses` (`name`, `breed`, `description`, `image_url`) VALUES +('Spirit', 'Mustang', 'A wild and free-spirited stallion.', 'https://via.placeholder.com/300x200.png?text=Spirit'), +('Black Beauty', 'American Quarter Horse', 'A handsome and gentle horse with a black coat.', 'https://via.placeholder.com/300x200.png?text=Black+Beauty'), +('Joey', 'Thoroughbred', 'A brave and loyal horse who served in World War I.', 'https://via.placeholder.com/300x200.png?text=Joey'); diff --git a/db/migrations/004_add_role_to_users.sql b/db/migrations/004_add_role_to_users.sql new file mode 100644 index 0000000..ee3f83c --- /dev/null +++ b/db/migrations/004_add_role_to_users.sql @@ -0,0 +1 @@ +ALTER TABLE `users` ADD `role` VARCHAR(50) NOT NULL DEFAULT 'client' AFTER `password`; \ No newline at end of file diff --git a/db/migrations/005_fix_role_column_length.sql b/db/migrations/005_fix_role_column_length.sql new file mode 100644 index 0000000..650625e --- /dev/null +++ b/db/migrations/005_fix_role_column_length.sql @@ -0,0 +1 @@ +ALTER TABLE users MODIFY role VARCHAR(255) NOT NULL; \ No newline at end of file diff --git a/db/migrations/006_add_profile_fields_to_users.sql b/db/migrations/006_add_profile_fields_to_users.sql new file mode 100644 index 0000000..dce9f6e --- /dev/null +++ b/db/migrations/006_add_profile_fields_to_users.sql @@ -0,0 +1,6 @@ +ALTER TABLE `users` +ADD COLUMN `first_name` VARCHAR(255) NULL, +ADD COLUMN `last_name` VARCHAR(255) NULL, +ADD COLUMN `avatar` VARCHAR(255) NULL, +ADD COLUMN `phone_number` VARCHAR(255) NULL, +ADD COLUMN `rider_level` VARCHAR(255) NULL; diff --git a/db/migrations/007_add_disciplines_to_horses.sql b/db/migrations/007_add_disciplines_to_horses.sql new file mode 100644 index 0000000..b345231 --- /dev/null +++ b/db/migrations/007_add_disciplines_to_horses.sql @@ -0,0 +1 @@ +ALTER TABLE horses ADD COLUMN disciplines VARCHAR(255) NULL; diff --git a/db/migrations/008_update_horses_with_disciplines_and_new_horse.sql b/db/migrations/008_update_horses_with_disciplines_and_new_horse.sql new file mode 100644 index 0000000..847b513 --- /dev/null +++ b/db/migrations/008_update_horses_with_disciplines_and_new_horse.sql @@ -0,0 +1,9 @@ +-- Update existing horses with disciplines +UPDATE horses SET disciplines = 'Show Jumping' WHERE name = 'Bucephalus'; +UPDATE horses SET disciplines = 'Dressage' WHERE name = 'Pegasus'; +UPDATE horses SET disciplines = 'Cross-country' WHERE name = 'Shadowfax'; +UPDATE horses SET disciplines = 'Racing' WHERE name = 'Rocinante'; + +-- Add a new horse with the provided image, age +INSERT INTO horses (name, breed, age, disciplines, image_path) VALUES +('Apollo', 'Friesian', 8, 'Carriage Driving', 'assets/avatars/apollo.jpg'); \ No newline at end of file diff --git a/db/migrations/009_update_first_horse_to_diesel.sql b/db/migrations/009_update_first_horse_to_diesel.sql new file mode 100644 index 0000000..01d8307 --- /dev/null +++ b/db/migrations/009_update_first_horse_to_diesel.sql @@ -0,0 +1,7 @@ +UPDATE horses +SET + name = 'Diesel', + breed = 'бурая', + disciplines = 'конкур' +WHERE + id = 1; diff --git a/db/migrations/010_fix_horses_table_schema.sql b/db/migrations/010_fix_horses_table_schema.sql new file mode 100644 index 0000000..20b8e1e --- /dev/null +++ b/db/migrations/010_fix_horses_table_schema.sql @@ -0,0 +1,6 @@ +-- Add age and image_path columns, and remove unused columns from the horses table. +ALTER TABLE `horses` +ADD COLUMN `age` INT NULL AFTER `breed`, +ADD COLUMN `image_path` VARCHAR(255) NULL AFTER `disciplines`, +DROP COLUMN `description`, +DROP COLUMN `image_url`; diff --git a/db/migrations/011_add_age_and_image_path_to_horses.sql b/db/migrations/011_add_age_and_image_path_to_horses.sql new file mode 100644 index 0000000..12d5f44 --- /dev/null +++ b/db/migrations/011_add_age_and_image_path_to_horses.sql @@ -0,0 +1,5 @@ +-- Add age and image_path columns, and remove unused columns from the horses table. +ALTER TABLE `horses` +ADD COLUMN `age` INT NULL AFTER `breed`, +ADD COLUMN `image_path` VARCHAR(255) NULL AFTER `disciplines`, +DROP COLUMN `image_url`; diff --git a/edit_horse.php b/edit_horse.php new file mode 100644 index 0000000..0c77e6c --- /dev/null +++ b/edit_horse.php @@ -0,0 +1,111 @@ +prepare('UPDATE horses SET name = ?, breed = ?, description = ?, image_url = ? WHERE id = ?'); + $stmt->execute([$name, $breed, $description, $image_url, $horse_id]); + header('Location: admin_horses.php?edited=true'); + exit; + } catch (PDOException $e) { + $errors[] = 'Database error: ' . $e->getMessage(); + } + } +} + +// Fetch the horse +try { + $pdo = db(); + $stmt = $pdo->prepare('SELECT * FROM horses WHERE id = ?'); + $stmt->execute([$horse_id]); + $horse = $stmt->fetch(); + if (!$horse) { + header('Location: admin_horses.php'); + exit; + } +} catch (PDOException $e) { + $errors[] = 'Database error: ' . $e->getMessage(); +} + +?> + + + + + + Admin: Edit Horse + + + +
+
+

Edit Horse:

+ ← Back to Manage Horses +
+ + +
+ +

+ +
+ + +
+
Edit Horse Details
+
+
+ +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+ +
+
+
+ +
+ + diff --git a/horses.php b/horses.php new file mode 100644 index 0000000..e75ee7d --- /dev/null +++ b/horses.php @@ -0,0 +1,213 @@ +query("SELECT name, breed, image_path FROM horses"); + $horses = $stmt->fetchAll(); +} catch (PDOException $e) { + $horses = []; + $error_message = "Database error: " . $e->getMessage(); +} + +?> + + + + + + Horses + + + + + + + +
+

+
+ + +
+
+ Welcome, +
+
+ + Profile + + Logout +
+
+
+

Our Horses

+ +

+ +

No horses found.

+ +
+ +
+ + <?= htmlspecialchars($horse['name']) ?> + +

+
+ + +

Breed:

+ +
+
+ +
+ +
+ + + \ No newline at end of file diff --git a/index.php b/index.php index 57f953e..f3829c9 100644 --- a/index.php +++ b/index.php @@ -1,131 +1,4 @@ - - - - - - New Style - - - - - - -
-
-

Preparing Your Working Environment…

-
- Loading… -
-

Flatlogic AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

-
-
- - - +// Redirect to the login page +header('Location: login.php'); +exit; \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..a79e10b --- /dev/null +++ b/login.php @@ -0,0 +1,324 @@ +prepare("SELECT id FROM users WHERE username = ? OR email = ?"); + $stmt->execute([$username, $email]); + if ($stmt->fetch()) { + $errors[] = 'Username or email already exists.'; + } else { + $stmt = $pdo->query("SELECT id FROM users LIMIT 1"); + $role = ($stmt->fetch()) ? 'client' : 'administrator'; + + $hashedPassword = password_hash($password, PASSWORD_DEFAULT); + $stmt = $pdo->prepare("INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, ?)"); + $stmt->execute([$username, $email, $hashedPassword, $role]); + $messages[] = 'Registration successful! Please log in.'; + } + } catch (PDOException $e) { + error_log("Signup Error: " . $e->getMessage()); + $errors[] = 'A database error occurred during registration.'; + } + } + } + + // Handle login + if ($_POST['action'] === 'login') { + $login = $_POST['login'] ?? ''; + $password = $_POST['password'] ?? ''; + + if (empty($login) || empty($password)) { + $errors[] = 'Please provide your login and password.'; + } else { + try { + $pdo = db(); + $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? OR username = ?"); + $stmt->execute([$login, $login]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + $_SESSION['flash_message'] = 'Welcome back! You have successfully logged in.'; + + session_write_close(); + header("Location: horses.php"); + exit; + } else { + $errors[] = 'Invalid login credentials.'; + } + } catch (PDOException $e) { + error_log("Login Error: " . $e->getMessage()); + $errors[] = 'A database error occurred during login.'; + } + } + } +} + +// The rest of the file is for display purposes only if no redirect has happened. +$now = date('Y-m-d H:i:s'); +?> + + + + + + Login / Sign Up + + + + + + + +
+
+

Login

+
+ +
+
+ + +
+
+ + +
+
+ +
+

Don't have an account? Sign up

+
+
+

Sign Up

+
+ +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ +
+

Already have an account? Log in

+
+
+ +
+ +

+ +
+ + +
+ +

+ +
+ + + + + \ No newline at end of file diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..f83284d --- /dev/null +++ b/logout.php @@ -0,0 +1,6 @@ +prepare('SELECT * FROM users WHERE id = ?'); + $stmt->execute([$userId]); + $user = $stmt->fetch(); + if (!$user) { + session_destroy(); + header('Location: login.php'); + exit; + } +} catch (PDOException $e) { + die('Could not fetch user data: ' . $e->getMessage()); +} + +// Handle profile update +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $firstName = trim($_POST['first_name'] ?? ''); + $lastName = trim($_POST['last_name'] ?? ''); + $email = trim($_POST['email'] ?? ''); + $phoneNumber = trim($_POST['phone_number'] ?? ''); + $riderLevel = trim($_POST['rider_level'] ?? ''); + $avatarPath = $user['avatar'] ?? ''; // Start with existing avatar + + // --- Validation --- + if (empty($firstName)) { + $errors['first_name'] = 'First name is required.'; + } + + if (empty($lastName)) { + $errors['last_name'] = 'Last name is required.'; + } + + if (empty($email)) { + $errors['email'] = 'Email is required.'; + } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + $errors['email'] = 'Please enter a valid email address.'; + } + + // Handle avatar upload + if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) { + $uploadDir = 'assets/avatars/'; + if (!is_dir($uploadDir)) { + if (!mkdir($uploadDir, 0755, true)) { + $errors['avatar'] = 'Failed to create avatar directory.'; + } + } + + if (!isset($errors['avatar'])) { + $avatarTmpPath = $_FILES['avatar']['tmp_name']; + $avatarName = basename($_FILES['avatar']['name']); + $avatarSize = $_FILES['avatar']['size']; + $avatarExtension = strtolower(pathinfo($avatarName, PATHINFO_EXTENSION)); + $allowedExtensions = ['jpg', 'jpeg', 'png']; + $maxFileSize = 2 * 1024 * 1024; // 2 MB + + if (!in_array($avatarExtension, $allowedExtensions)) { + $errors['avatar'] = 'Invalid file type. Only JPG and PNG are allowed.'; + } elseif ($avatarSize > $maxFileSize) { + $errors['avatar'] = 'File is too large. Maximum size is 2MB.'; + } else { + $safeAvatarName = uniqid('avatar_', true) . '.' . $avatarExtension; + $newAvatarPath = $uploadDir . $safeAvatarName; + + if (move_uploaded_file($avatarTmpPath, $newAvatarPath)) { + // Remove the old avatar if it exists and is not a default one + if (!empty($avatarPath) && file_exists($avatarPath)) { + unlink($avatarPath); + } + $avatarPath = $newAvatarPath; // Set new path for DB update + } else { + $errors['avatar'] = 'Failed to upload new avatar.'; + } + } + } + } + + // Phone number validation + if (!empty($phoneNumber)) { + $numericPhoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber); + if (strlen($numericPhoneNumber) < 7) { + $errors['phone_number'] = 'Phone number must be at least 7 digits.'; + } else { + $phoneNumber = $numericPhoneNumber; // Use the sanitized number + } + } + + if (empty($errors)) { + try { + $stmt = $pdo->prepare( + 'UPDATE users SET first_name = ?, last_name = ?, email = ?, phone_number = ?, rider_level = ?, avatar = ? WHERE id = ?' + ); + $stmt->execute([$firstName, $lastName, $email, $phoneNumber, $riderLevel, $avatarPath, $userId]); + $messages[] = 'Profile updated successfully!'; + // Refresh user data after successful update + $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?'); + $stmt->execute([$userId]); + $user = $stmt->fetch(); + + } catch (PDOException $e) { + error_log("Profile Update Error: " . $e->getMessage()); + $errors['db'] = 'Error updating profile. Please try again.'; + } + } +} + +// On a failed POST, user data should come from POST, otherwise from DB +$displayData = [ + 'first_name' => $_POST['first_name'] ?? $user['first_name'], + 'last_name' => $_POST['last_name'] ?? $user['last_name'], + 'email' => $_POST['email'] ?? $user['email'], + 'phone_number' => $_POST['phone_number'] ?? $user['phone_number'], + 'rider_level' => $_POST['rider_level'] ?? $user['rider_level'], + 'avatar' => $user['avatar'] +]; + +?> + + + + + + User Profile + + + + + + + Back to Horses +
+
+

Edit Profile

+
+
+
+
+ + + Avatar + + +
+
+
+ +
+
+ + +
+
+
+ + +
+
+
+ +
+
+ + +
+
+
+ + +
+
+
+ +
+
+ +
+
+
+ + +
+
+
+ + +
+ +

+ + +

+ +
+ + + + \ No newline at end of file