cleanup. Improve homepage semantics. Add .htaccess files to blocked directories.
This commit is contained in:
		
							parent
							
								
									77ec1bbb3b
								
							
						
					
					
						commit
						f72896892b
					
				
							
								
								
									
										49
									
								
								.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								.htaccess
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path | ||||
| # on shared hosting via .htaccess | ||||
| # | ||||
| # e.g. http://www.my-domain.com/tkr | ||||
| # | ||||
| # This should work without modification if you extract the app | ||||
| # to /tkr from your web document root | ||||
| 
 | ||||
| # Enable mod_rewrite | ||||
| RewriteEngine On | ||||
| 
 | ||||
| # Security headers | ||||
| Header always set X-Frame-Options "SAMEORIGIN" | ||||
| Header always set X-XSS-Protection "1; mode=block" | ||||
| Header always set X-Content-Type-Options "nosniff" | ||||
| 
 | ||||
| # Directory index | ||||
| DirectoryIndex public/index.php | ||||
| 
 | ||||
| # Security: Block direct access to .php files (except through rewrites) | ||||
| RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
| RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
| # Security: Block access to sensitive directories | ||||
| RewriteRule ^(storage|src|templates|examples|config)(/.*)?$ - [F,L] | ||||
| 
 | ||||
| # Security: Block access to hidden files | ||||
| RewriteRule ^\..*$ - [F,L] | ||||
| 
 | ||||
| # Cache CSS files for 1 hour | ||||
| <FilesMatch "\.css$"> | ||||
|     Header set Cache-Control "public, max-age=3600" | ||||
| </FilesMatch> | ||||
| 
 | ||||
| # Serve the one static file that exists: css/tkr.css | ||||
| # (Pass requests to css/custom/ through to the PHP app) | ||||
| RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
| RewriteRule ^css/tkr\.css$ public/css/tkr.css [L] | ||||
| 
 | ||||
| # 404 all other static files (images, js, fonts, etc.) | ||||
| # so those requests don't hit the PHP app  | ||||
| # (this is to reduce load on the PHP app from bots and scanners) | ||||
| RewriteRule \.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$ - [R=404,L] | ||||
| 
 | ||||
| # Everything else goes to the front controller | ||||
| RewriteCond %{REQUEST_FILENAME} !-f | ||||
| RewriteCond %{REQUEST_FILENAME} !-d | ||||
| RewriteRule ^(.*)$ public/index.php [L] | ||||
							
								
								
									
										6
									
								
								config/.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								config/.htaccess
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # Deny all access to this directory | ||||
| Require all denied | ||||
| 
 | ||||
| # Fallback for Apache 2.2 | ||||
| Order deny,allow | ||||
| Deny from all | ||||
| @ -41,7 +41,7 @@ function handle_setup_exception(SetupException $e){ | ||||
|             // Show error message and exit
 | ||||
|             http_response_code(500); | ||||
|             echo "<h1>Configuration Error</h1>"; | ||||
|             echo "<p>" . htmlspecialchars($setupError['message']) . "</p>"; | ||||
|             echo "<p>" . Util::escape_html($setupError['message']) . "</p>"; | ||||
|             exit; | ||||
|         case 'table_contents': | ||||
|             // Recoverable error.
 | ||||
|  | ||||
							
								
								
									
										6
									
								
								examples/.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								examples/.htaccess
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # Deny all access to this directory | ||||
| Require all denied | ||||
| 
 | ||||
| # Fallback for Apache 2.2 | ||||
| Order deny,allow | ||||
| Deny from all | ||||
| @ -95,7 +95,7 @@ fieldset.emoji-group { | ||||
| } | ||||
| 
 | ||||
| h1.site-description { | ||||
|     font-size: 1.3em; | ||||
|     font-size: 1.5em; | ||||
| } | ||||
| 
 | ||||
| .delete-emoji-fieldset .fieldset-items { | ||||
| @ -310,19 +310,85 @@ label.description { | ||||
| } | ||||
| 
 | ||||
| .home-sidebar{ | ||||
|     padding-top: 1em; | ||||
|     padding-bottom: 1em; | ||||
| } | ||||
| 
 | ||||
| .site-description { | ||||
|     font-size: 1.2rem; | ||||
|     color: var(--color-text-dark); | ||||
|     margin-bottom: 0.5rem; | ||||
|     margin-bottom: 1.2rem; | ||||
| } | ||||
| 
 | ||||
| .profile-row { | ||||
| .profile-data { | ||||
|   display: grid; | ||||
|   gap: 1rem; | ||||
|   margin: 0; | ||||
|   margin-bottom: 1rem; | ||||
| } | ||||
| 
 | ||||
| /* Description list: description */ | ||||
| .profile-data dd { | ||||
|   margin: 0; | ||||
| } | ||||
| 
 | ||||
| /* Description list: term */ | ||||
| /* Hidden from visual display - screen reader only class */ | ||||
| .profile-data dt { | ||||
|   position: absolute; | ||||
|   width: 1px; | ||||
|   height: 1px; | ||||
|   padding: 0; | ||||
|   margin: -1px; | ||||
|   overflow: hidden; | ||||
|   clip: rect(0, 0, 0, 0); | ||||
|   white-space: nowrap; | ||||
|   border: 0; | ||||
| } | ||||
| 
 | ||||
| /* | ||||
|     Left-justify the greeting text, | ||||
|     right-justify the Change Mood link | ||||
| */ | ||||
| 
 | ||||
| /* greeting text */ | ||||
| .profile-greeting { | ||||
|     display: flex; | ||||
|     width: 100%; | ||||
|     gap: 0.5em; | ||||
|     justify-content: space-between; | ||||
|     align-items: center; | ||||
|     gap: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| /* add a small gap between the greeting and the mood emoji */ | ||||
| .greeting-content { | ||||
|     display: flex; | ||||
|     align-items: baseline; | ||||
|     gap: 0.4em; | ||||
| } | ||||
| 
 | ||||
| /* define the profile "greeting" style */ | ||||
| .greeting-text { | ||||
|     font-weight: 600; | ||||
|     font-size: 1.1em; | ||||
|     color: var(--color-text-primary); | ||||
| } | ||||
| 
 | ||||
| /* Adjust emoji positioning */ | ||||
| .greeting-emoji { | ||||
|     vertical-align: middle; | ||||
| } | ||||
| 
 | ||||
| /* Style the Change Mood link */ | ||||
| .change-mood { | ||||
|     font-size: 0.9em; | ||||
|     white-space: nowrap; | ||||
| } | ||||
| 
 | ||||
| /* define the profile "about" style */ | ||||
| .profile-about { | ||||
|     font-style: italic; | ||||
|     font-size: 0.95em; | ||||
|     color: var(--color-text-muted); | ||||
| } | ||||
| 
 | ||||
| .tick-form { | ||||
| @ -332,20 +398,13 @@ label.description { | ||||
|     gap: 0.5em; | ||||
| } | ||||
| 
 | ||||
| .mood-bar { | ||||
|     display: flex; | ||||
|     width: 100%; | ||||
|     justify-content: space-between; | ||||
|     align-items: center; | ||||
|     gap: 0.5em; | ||||
| } | ||||
| 
 | ||||
| /* Styling for flash messages */ | ||||
| .flash-messages { | ||||
|     background: white; | ||||
|     background: var(--color-bg-white);  | ||||
|     margin-top: 10px; | ||||
|     padding: 15px; | ||||
|     border-radius: 8px; | ||||
|     box-shadow: 0 2px 10px rgba(0,0,0,0.1); | ||||
|     box-shadow: 0 2px 10px var(--shadow-primary); | ||||
| } | ||||
|          | ||||
| .flash-message { | ||||
| @ -436,18 +495,28 @@ label.description { | ||||
|     color: var(--color-required); | ||||
| } | ||||
| 
 | ||||
| .tick-feed { | ||||
|     list-style: none; | ||||
|     padding: 0; | ||||
|     margin: 0; | ||||
|     margin-top: 0.5em; | ||||
| } | ||||
| 
 | ||||
| .tick { | ||||
|     margin-bottom: 1em; | ||||
|     padding-left: 0.5em; | ||||
| } | ||||
| 
 | ||||
| .tick-time { | ||||
|     color: var(--color-text-muted);  | ||||
|     font-size: 0.8em; | ||||
|     margin-bottom: 0.4em; | ||||
| } | ||||
| 
 | ||||
| .tick-text { | ||||
|     color: var(--color-text-black); | ||||
|     font-size: 1.0em; | ||||
|     display: block; | ||||
| } | ||||
| 
 | ||||
| .tick-pagination a {  | ||||
|  | ||||
							
								
								
									
										6
									
								
								src/.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/.htaccess
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # Deny all access to this directory | ||||
| Require all denied | ||||
| 
 | ||||
| # Fallback for Apache 2.2 | ||||
| Order deny,allow | ||||
| Deny from all | ||||
| @ -16,8 +16,6 @@ class AuthController extends Controller { | ||||
|     function handleLogin(){ | ||||
|         global $config; | ||||
| 
 | ||||
|         $error = ''; | ||||
| 
 | ||||
|         if ($_SERVER['REQUEST_METHOD'] === 'POST') { | ||||
|             $username = $_POST['username'] ?? ''; | ||||
|             $password = $_POST['password'] ?? ''; | ||||
| @ -37,7 +35,10 @@ class AuthController extends Controller { | ||||
|                 header('Location: ' . $config->basePath); | ||||
|                 exit; | ||||
|             } else { | ||||
|                 $error = 'Invalid username or password'; | ||||
|                 // Set a flash message and reload the login page
 | ||||
|                 Session::setFlashMessage('error', 'Invalid username or password'); | ||||
|                 header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|                 exit; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -9,7 +9,7 @@ class FlashView { | ||||
|             <?php foreach ($flashMessages as $type => $messages): ?>
 | ||||
|                 <?php foreach ($messages as $message): ?>
 | ||||
|                     <div class="flash-message flash-<?php echo $type; ?>"> | ||||
|                         <?php echo htmlspecialchars($message); ?>
 | ||||
|                         <?php echo Util::escape_html($message); ?>
 | ||||
|                     </div> | ||||
|                 <?php endforeach; ?>
 | ||||
|             <?php endforeach; ?>
 | ||||
|  | ||||
| @ -4,15 +4,14 @@ class HomeView { | ||||
|         ob_start(); | ||||
|         ?>
 | ||||
| 
 | ||||
|         <main id="ticks" class="home-main"> | ||||
|             <div class="tick-feed"> | ||||
|             <ul class="tick-feed"> | ||||
|             <?php foreach ($ticks as $tick): ?>
 | ||||
|                 <article class="tick"> | ||||
|                 <li class="tick"> | ||||
|                     <div class="tick-time"><?= Util::escape_html(Util::relative_time($tick['timestamp'])) ?></div>
 | ||||
|                     <span class="tick-text"><?= Util::linkify(Util::escape_html($tick['tick'])) ?></span>
 | ||||
|                 </article> | ||||
|                 </li> | ||||
|             <?php endforeach; ?>
 | ||||
|             </div> | ||||
|             </ul> | ||||
|             <div class="tick-pagination"> | ||||
|             <?php if ($page > 1): ?>
 | ||||
|                 <a href="?page=<?= $page - 1 ?>">« Newer</a> | ||||
| @ -21,7 +20,6 @@ class HomeView { | ||||
|                 <a href="?page=<?= $page + 1 ?>">Older »</a> | ||||
|             <?php endif; ?>
 | ||||
|             </div> | ||||
|         </main> | ||||
| 
 | ||||
|         <?php return ob_get_clean(); | ||||
|     } | ||||
|  | ||||
| @ -7,18 +7,18 @@ class MoodView { | ||||
|         ?>
 | ||||
| 
 | ||||
|         <?php foreach ($emojiGroups as $group => $emojis): ?>
 | ||||
|             <fieldset id="<?= htmlspecialchars($group) ?>" class="emoji-group"> | ||||
|             <fieldset id="<?= Util::escape_html($group) ?>" class="emoji-group"> | ||||
|                 <legend><?= ucfirst($group) ?></legend>
 | ||||
|             <?php foreach ($emojis as [$emoji, $description]): ?>
 | ||||
|                 <label class="emoji-option"> | ||||
|                     <input | ||||
|                         type="radio" | ||||
|                         name="mood" | ||||
|                         value="<?= htmlspecialchars($emoji) ?>" | ||||
|                         aria-label="<?=htmlspecialchars($description ?? 'emoji') ?>" | ||||
|                         value="<?= Util::escape_html($emoji) ?>" | ||||
|                         aria-label="<?=Util::escape_html($description ?? 'emoji') ?>" | ||||
|                         <?= $emoji === $selected_emoji ? 'checked' : '' ?>
 | ||||
|                     > | ||||
|                     <span><?= htmlspecialchars($emoji) ?></span>
 | ||||
|                     <span><?= Util::escape_html($emoji) ?></span>
 | ||||
|                 </label> | ||||
|             <?php endforeach; ?>
 | ||||
|             </fieldset> | ||||
| @ -31,7 +31,7 @@ class MoodView { | ||||
|         ob_start(); | ||||
|         ?>
 | ||||
|         <form method="post" class="emoji-form"> | ||||
|             <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|             <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|             <?= $this->render_emoji_groups($emojiGroups, $currentMood) ?>
 | ||||
|             <div class="button-group"> | ||||
|                 <button type="submit" name="action" value="set">Set the mood</button> | ||||
|  | ||||
							
								
								
									
										6
									
								
								storage/.htaccess
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								storage/.htaccess
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # Deny all access to this directory | ||||
| Require all denied | ||||
| 
 | ||||
| # Fallback for Apache 2.2 | ||||
| Order deny,allow | ||||
| Deny from all | ||||
							
								
								
									
										6
									
								
								templates/.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								templates/.htaccess
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # Deny all access to this directory | ||||
| Require all denied | ||||
| 
 | ||||
| # Fallback for Apache 2.2 | ||||
| Order deny,allow | ||||
| Deny from all | ||||
| @ -10,19 +10,19 @@ | ||||
|         <meta charset="UTF-8"> | ||||
|         <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|         <link rel="stylesheet" | ||||
|               href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css"> | ||||
|               href="<?= Util::escape_html($config->basePath) ?>css/tkr.css"> | ||||
| <?php if (!empty($config->cssId)): ?>
 | ||||
|         <link rel="stylesheet" | ||||
|               href="<?= htmlspecialchars($config->basePath) ?>css/custom/<?= htmlspecialchars($config->customCssFilename()) ?>"> | ||||
|               href="<?= Util::escape_html($config->basePath) ?>css/custom/<?= Util::escape_html($config->customCssFilename()) ?>"> | ||||
| <?php endif; ?>
 | ||||
|         <link rel="alternate" | ||||
|               type="application/rss+xml" | ||||
|               title="<?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed" | ||||
|               href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/rss/">    | ||||
|               title="<?php echo Util::escape_html($config->siteTitle) ?> RSS Feed" | ||||
|               href="<?php echo Util::escape_html($config->baseUrl . $config->basePath)?>feed/rss/">    | ||||
|         <link rel="alternate" | ||||
|               type="application/atom+xml" | ||||
|               title="<?php echo htmlspecialchars($config->siteTitle) ?> Atom Feed" | ||||
|               href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/atom/">    | ||||
|               title="<?php echo Util::escape_html($config->siteTitle) ?> Atom Feed" | ||||
|               href="<?php echo Util::escape_html($config->baseUrl . $config->basePath)?>feed/atom/">    | ||||
|     </head> | ||||
|     <body> | ||||
| <?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | ||||
|  | ||||
| @ -6,28 +6,28 @@ | ||||
|             <form | ||||
|                 action="<?php echo $config->basePath . ($isSetup ? 'setup' : 'admin') ?>"   | ||||
|                 method="post"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|                 <fieldset> | ||||
|                     <legend>User settings</legend> | ||||
|                     <div class="fieldset-items"> | ||||
|                         <label>Username <span class=required>*</span></label> | ||||
|                         <input type="text" | ||||
|                             name="username" | ||||
|                             value="<?= $user->username ?>" | ||||
|                             value="<?= Util::escape_html($user->username) ?>" | ||||
|                             required> | ||||
|                         <label>Display name <span class=required>*</span></label> | ||||
|                         <input type="text"  | ||||
|                                name="display_name" | ||||
|                                value="<?= $user->displayName ?>" | ||||
|                                value="<?= Util::escape_html($user->displayName) ?>" | ||||
|                                required> | ||||
|                         <label>About </label> | ||||
|                         <input type="text" | ||||
|                             name="about" | ||||
|                             value="<?= $user->about ?>"> | ||||
|                             value="<?= Util::escape_html($user->about) ?>"> | ||||
|                         <label>Website </label> | ||||
|                         <input type="text" | ||||
|                             name="website" | ||||
|                             value="<?= $user->website ?>"> | ||||
|                             value="<?= Util::escape_html($user->website) ?>"> | ||||
|                     </div> | ||||
|                 </fieldset> | ||||
|                 <fieldset> | ||||
| @ -36,21 +36,21 @@ | ||||
|                         <label>Title <span class=required>*</span></label> | ||||
|                         <input type="text" | ||||
|                             name="site_title" | ||||
|                             value="<?= $config->siteTitle ?>"  | ||||
|                             value="<?= Util::escape_html($config->siteTitle) ?>"  | ||||
|                             required> | ||||
|                         <label>Description <span class=required>*</span></label> | ||||
|                         <input type="text" | ||||
|                             name="site_description" | ||||
|                             value="<?= $config->siteDescription ?>"> | ||||
|                             value="<?= Util::escape_html($config->siteDescription) ?>"> | ||||
|                         <label>Base URL <span class=required>*</span></label> | ||||
|                         <input type="text" | ||||
|                             name="base_url" | ||||
|                             value="<?= $config->baseUrl ?>" | ||||
|                             value="<?= Util::escape_html($config->baseUrl) ?>" | ||||
|                             required> | ||||
|                         <label>Base path <span class=required>*</span></label>  | ||||
|                         <input type="text" | ||||
|                             name="base_path" | ||||
|                             value="<?= $config->basePath ?>" | ||||
|                             value="<?= Util::escape_html($config->basePath) ?>" | ||||
|                             required> | ||||
|                         <label>Items per page (max 50) <span class=required>*</span></label> | ||||
|                         <input type="number" | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <h1>CSS Management</h1> | ||||
|         <div> | ||||
|             <form action="<?= $config->basePath ?>admin/css" method="post" enctype="multipart/form-data"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|                 <fieldset> | ||||
|                     <legend>Manage</legend> | ||||
|                     <div class="fieldset-items"> | ||||
| @ -20,13 +20,13 @@ | ||||
| 
 | ||||
|                             <option value=<?= $cssFile['id'] ?> 
 | ||||
|                                     <?= isset($selected) ? $selected : ""?>>
 | ||||
|                                     <?=$cssFile['filename']?>
 | ||||
|                                     <?=Util::escape_html($cssFile['filename'])?>
 | ||||
|                             </option> | ||||
| <?php endforeach; ?>
 | ||||
|                         </select> | ||||
| <?php if (isset($cssDescription) && $cssDescription): ?>
 | ||||
|                         <label>Description</label> | ||||
|                         <label class="description"><?= $cssDescription ?></label>
 | ||||
|                         <label class="description"><?= Util::escape_html($cssDescription) ?></label>
 | ||||
| <?php endif; ?>
 | ||||
|                         <div></div> | ||||
|                         <div> | ||||
| @ -38,7 +38,7 @@ | ||||
|                 <fieldset> | ||||
|                     <legend>Upload</legend> | ||||
|                     <div class="fieldset-items"> | ||||
|                         <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|                         <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|                         <label for="uploadCssFile">Select File to Upload</label> | ||||
|                         <input type="file"  | ||||
|                                id="uploadCssFile"  | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <h1>Emoji Management</h1> | ||||
|         <div> | ||||
|             <form action="<?= $config->basePath ?>admin/emoji" method="post" enctype="multipart/form-data"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|                 <fieldset> | ||||
|                     <legend>Add Emoji</legend> | ||||
|                     <div class="fieldset-items"> | ||||
| @ -25,19 +25,19 @@ | ||||
|             </form> | ||||
| <?php if (!empty($emojiList)): ?>
 | ||||
|             <form action="<?= $config->basePath ?>admin/emoji" method="post" enctype="multipart/form-data"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|                 <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|                 <fieldset class="delete-emoji-fieldset"> | ||||
|                     <legend>Delete Emoji</legend> | ||||
|                     <div class="fieldset-items"> | ||||
|                         <?php foreach ($emojiList as $emojiItem): ?>
 | ||||
|                             <div class="emoji-checkbox-item"> | ||||
|                                 <input type="checkbox"  | ||||
|                                        id="delete_emoji_<?= htmlspecialchars($emojiItem['id']) ?>"  | ||||
|                                        id="delete_emoji_<?= Util::escape_html($emojiItem['id']) ?>"  | ||||
|                                        name="delete_emoji_ids[]"  | ||||
|                                        value="<?= htmlspecialchars($emojiItem['id']) ?>"> | ||||
|                                 <label for="delete_emoji_<?= htmlspecialchars($emojiItem['id']) ?>"> | ||||
|                                     <span class="emoji-display"><?= htmlspecialchars($emojiItem['emoji']) ?></span>
 | ||||
|                                     <span class="emoji-description"><?= htmlspecialchars($emojiItem['description']) ?></span>
 | ||||
|                                        value="<?= Util::escape_html($emojiItem['id']) ?>"> | ||||
|                                 <label for="delete_emoji_<?= Util::escape_html($emojiItem['id']) ?>"> | ||||
|                                     <span class="emoji-display"><?= Util::escape_html($emojiItem['emoji']) ?></span>
 | ||||
|                                     <span class="emoji-description"><?= Util::escape_html($emojiItem['description']) ?></span>
 | ||||
|                                 </label> | ||||
|                             </div> | ||||
|                         <?php endforeach; ?>
 | ||||
|  | ||||
| @ -3,36 +3,50 @@ | ||||
| <?php /** @var UserModel $user */ ?>
 | ||||
| <?php /** @var string $tickList */ ?>
 | ||||
|         <div class="home-container"> | ||||
|             <section id="sidebar" class="home-sidebar"> | ||||
|                 <div class="home-header"> | ||||
|                     <h1 class="site-description"><?= $config->siteDescription ?></h1>
 | ||||
|                 </div> | ||||
|             <aside id="sidebar" class="home-sidebar"> | ||||
|                 <dl class="profile-data"> | ||||
|                     <dt>Current Status</dt> | ||||
|                     <dd class="profile-greeting"> | ||||
|                         <span class="greeting-content"> | ||||
|                             <span class="greeting-text">Hi, I'm <?php echo Util::escape_html($user->displayName) ?></span>
 | ||||
|                             <span class="greeting-mood"><?php echo Util::escape_html($user->mood) ?></span>
 | ||||
|                         </span> | ||||
| <?php if (Session::isLoggedIn()): ?>
 | ||||
|                         <a href="<?= $config->basePath ?>mood" class="change-mood">Change mood</a> | ||||
| <?php endif ?>
 | ||||
|                     </dd> | ||||
| <?php if (!empty($user->about)): ?>
 | ||||
|                 <p>About: <?= $user->about ?></p>
 | ||||
|                     <dt>About</dt> | ||||
|                     <dd class="profile-about"> | ||||
|                         <?php echo Util::escape_html($user->about) ?>
 | ||||
|                     </dd> | ||||
| <?php endif ?>
 | ||||
| <?php if (!empty($user->website)): ?>
 | ||||
|                 <p>Website: <?= Util::linkify(Util::escape_html($user->website)) ?></p>
 | ||||
|                     <dt>Website</dt> | ||||
|                     <dd class="profile-website"> | ||||
|                         <?php echo Util::linkify(Util::escape_html($user->website)) ?>
 | ||||
|                     </dd> | ||||
| <?php endif ?>
 | ||||
| <?php if (!empty($user->mood) || Session::isLoggedIn()): ?>
 | ||||
|                 <div class="profile-row"> | ||||
|                     <div class="mood-bar"> | ||||
|                         <span>Current mood: <?= $user->mood ?></span>
 | ||||
|                 </dl> | ||||
| <?php if (Session::isLoggedIn()): ?>
 | ||||
|                         <a href="<?= $config->basePath ?>mood">Change</a> | ||||
| <?php endif; ?>
 | ||||
|                     </div> | ||||
|                 </div> | ||||
| <?php endif; ?>
 | ||||
| <?php if (Session::isLoggedIn()): ?>
 | ||||
|                 <hr/> | ||||
|                 <div class="profile-row"> | ||||
|                 <div class="profile-tick"> | ||||
|                     <form class="tick-form" method="post"> | ||||
|                         <input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>"> | ||||
|                         <textarea name="tick" placeholder="What's ticking?" rows="3"></textarea> | ||||
|                         <textarea name="tick" | ||||
|                                   placeholder="What's ticking?" | ||||
|                                   minlength="1"  | ||||
|                                   maxlength="200" | ||||
|                                   rows="3"></textarea> | ||||
|                         <button type="submit" class="submit-btn">Tick</button> | ||||
|                     </form> | ||||
|                 </div> | ||||
| <?php endif; ?>
 | ||||
|             </section> | ||||
|             <?php echo $tickList ?>
 | ||||
|             </aside> | ||||
|             <main id="ticks" class="home-main"> | ||||
|                 <div class="home-header"> | ||||
|                     <h1 class="site-description"><?= $config->siteDescription ?></h1>
 | ||||
|                 </div> | ||||
|                 <?php echo $tickList ?>
 | ||||
|             </main> | ||||
| 
 | ||||
|         </div> | ||||
|  | ||||
| @ -2,12 +2,9 @@ | ||||
| <?php /** @var string $csrf_token */ ?>
 | ||||
| <?php /** @var string $error */ ?>
 | ||||
|     <h2>Login</h2> | ||||
| <?php if ($error): ?>
 | ||||
|     <p style="color:red"><?=  htmlspecialchars($error) ?></p>
 | ||||
| <?php endif; ?>
 | ||||
|     <form method="post" action="<?= $config->basePath ?>login"> | ||||
|         <div class="fieldset-items"> | ||||
|             <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf_token) ?>"> | ||||
|             <input type="hidden" name="csrf_token" value="<?= Util::escape_html($csrf_token) ?>"> | ||||
|             <label for="username">Username:</label> | ||||
|             <input type="text" id="username" name="username" required> | ||||
|             <label for="password">Password:</label> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user