Kaynağa Gözat

Add missing HTML/url encoding (5245-chunk8) (#5253)

* Add missing HTML/url encoding (5245-chunk8)
Was reports that some missing HTML encoding could lead to XSS/javascript injection.

Reviewable chunk of #5245 , which grew too large.

* Fix row ids and item counting

web/templates/pages/list_backup_detail.php
Comment on lines +103 to +104
						<input id="check2<?= tohtml($i) ?>" class="js-unit-checkbox" type="checkbox" name="mail[]" value="<?= tohtml($key) ?>">
						<label for="check2<?= tohtml($i) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
Copilot AI
18 minutes ago
$i is only incremented in the WEB loop, but this MAIL section uses $i to form checkbox id/for. That means every mail row will reuse the same id (e.g. check2N), breaking label targeting and potentially any JS relying on unique ids; it also makes the footer item count inaccurate. Increment $i inside this loop (and the other loops) or use a unique per-row identifier (e.g. derived from $key) for the id/for attributes.

web/templates/pages/list_backup_detail.php
Comment on lines +143 to +144
						<input id="check3<?= tohtml($i) ?>" class="js-unit-checkbox" type="checkbox" name="dns[]" value="<?= tohtml($key) ?>">
						<label for="check3<?= tohtml($i) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
Copilot AI
18 minutes ago
This DNS section also uses $i for id/for, but $i is not incremented in this loop, so multiple DNS rows will end up with duplicate checkbox ids. Increment $i per iteration (or switch the id to a unique value derived from $key) to keep ids unique and keep the footer count correct.

web/templates/pages/list_backup_detail.php
Comment on lines +183 to +184
						<input id="check4<?= tohtml($i) ?>" class="js-unit-checkbox" type="checkbox" name="db[]" value="<?= tohtml($key) ?>">
						<label for="check4<?= tohtml($i) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
Copilot AI
19 minutes ago
In the DB loop, $i is reused for the checkbox id/for without being incremented per database entry, which will generate duplicate ids for multiple DB rows. Increment $i inside this loop (or generate a unique id from $key) to avoid broken label associations and incorrect item counting.

web/templates/pages/list_backup_detail.php
Comment on lines +259 to +260
						<input id="check6<?= tohtml($i) ?>" class="js-unit-checkbox" type="checkbox" name="udir[]" value="<?= tohtml($key) ?>">
						<label for="check6<?= tohtml($i) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
Copilot AI
19 minutes ago
The UDIR loop reuses $i for checkbox id/for but doesn’t increment $i per user-directory row, so ids will be duplicated when there are multiple entries. Increment $i in this loop (or derive a unique id from $key) to keep ids unique and the footer item count accurate.

* unique counter names

so we don't accidentally end up with like "foo1 foo2 foo3 bar4 bar5" but instead "foo1 foo2 foo3 bar1 bar2"
divinity76 3 gün önce
ebeveyn
işleme
ab644d26a8

+ 17 - 17
web/templates/pages/add_dns_rec.php

@@ -2,13 +2,13 @@
 <div class="toolbar">
 	<div class="toolbar-inner">
 		<div class="toolbar-buttons">
-			<a class="button button-secondary button-back js-button-back" href="/list/dns/?domain=<?= htmlentities(trim($v_domain, "'")) ?>&token=<?= $_SESSION["token"] ?>">
-				<i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?>
+				<a class="button button-secondary button-back js-button-back" href="/list/dns/?<?= tohtml(http_build_query(array("domain" => trim($v_domain, "'"), "token" => $_SESSION["token"]))) ?>">
+				<i class="fas fa-arrow-left icon-blue"></i><?= tohtml( _("Back")) ?>
 			</a>
 		</div>
 		<div class="toolbar-buttons">
 			<button type="submit" class="button" form="main-form">
-				<i class="fas fa-floppy-disk icon-purple"></i><?= _("Save") ?>
+				<i class="fas fa-floppy-disk icon-purple"></i><?= tohtml( _("Save")) ?>
 			</button>
 		</div>
 	</div>
@@ -18,24 +18,24 @@
 <div class="container">
 
 	<form id="main-form" name="v_add_dns_rec" method="post">
-		<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
+		<input type="hidden" name="token" value="<?= tohtml($_SESSION["token"]) ?>">
 		<input type="hidden" name="ok_rec" value="add">
 
 		<div class="form-container">
-			<h1 class="u-mb20"><?= _("Add DNS Record") ?></h1>
+			<h1 class="u-mb20"><?= tohtml( _("Add DNS Record")) ?></h1>
 			<?php show_alert_message($_SESSION); ?>
 			<div class="u-mb10">
-				<label for="v_domain" class="form-label"><?= _("Domain") ?></label>
-				<input type="text" class="form-control js-dns-record-domain" name="v_domain" id="v_domain" value="<?= htmlentities(trim($v_domain, "'")) ?>" disabled>
-				<input type="hidden" name="v_domain" value="<?= htmlentities(trim($v_domain, "'")) ?>">
+				<label for="v_domain" class="form-label"><?= tohtml( _("Domain")) ?></label>
+				<input type="text" class="form-control js-dns-record-domain" name="v_domain" id="v_domain" value="<?= tohtml(trim($v_domain, "'")) ?>" disabled>
+				<input type="hidden" name="v_domain" value="<?= tohtml(trim($v_domain, "'")) ?>">
 			</div>
 			<div class="u-mb10">
-				<label for="v_rec" class="form-label"><?= _("Record") ?></label>
-				<input type="text" class="form-control js-dns-record-input" name="v_rec" id="v_rec" value="<?= htmlentities(trim($v_rec, "'")) ?>">
+				<label for="v_rec" class="form-label"><?= tohtml( _("Record")) ?></label>
+				<input type="text" class="form-control js-dns-record-input" name="v_rec" id="v_rec" value="<?= tohtml(trim($v_rec, "'")) ?>">
 				<small class="hint"></small>
 			</div>
 			<div class="u-mb10">
-				<label for="v_type" class="form-label"><?= _("Type") ?></label>
+				<label for="v_type" class="form-label"><?= tohtml( _("Type")) ?></label>
 				<select class="form-select" name="v_type" id="v_type">
 					<option value="A" <?php if ($v_type == 'A') echo "selected"; ?>>A</option>
 					<option value="AAAA" <?php if ($v_type == 'AAAA') echo "selected"; ?>>AAAA</option>
@@ -55,7 +55,7 @@
 				</select>
 			</div>
 			<div class="u-mb10">
-				<label for="v_val" class="form-label"><?= _("IP or Value") ?></label>
+				<label for="v_val" class="form-label"><?= tohtml( _("IP or Value")) ?></label>
 				<div class="u-pos-relative">
 					<select class="form-select" tabindex="-1" onchange="this.nextElementSibling.value=this.value">
 						<option value="">&nbsp;</option>
@@ -66,20 +66,20 @@
 							}
 						?>
 					</select>
-					<input type="text" class="form-control list-editor" name="v_val" id="v_val" value="<?= htmlentities(trim($v_val, "'")) ?>" required>
+					<input type="text" class="form-control list-editor" name="v_val" id="v_val" value="<?= tohtml(trim($v_val, "'")) ?>" required>
 				</div>
 			</div>
 			<div class="u-mb10">
 				<label for="v_priority" class="form-label">
-					<?= _("Priority") ?> <span class="optional">(<?= _("Optional") ?>)</span>
+					<?= tohtml( _("Priority")) ?> <span class="optional">(<?= tohtml( _("Optional")) ?>)</span>
 				</label>
-				<input type="text" class="form-control" name="v_priority" id="v_priority" value="<?= htmlentities(trim($v_priority, "'")) ?>">
+				<input type="text" class="form-control" name="v_priority" id="v_priority" value="<?= tohtml(trim($v_priority, "'")) ?>">
 			</div>
 			<div class="u-mb10">
 				<label for="v_ttl" class="form-label">
-					<?= _("TTL") ?> <span class="optional">(<?= _("Optional") ?>)</span>
+					<?= tohtml( _("TTL")) ?> <span class="optional">(<?= tohtml( _("Optional")) ?>)</span>
 				</label>
-				<input type="text" class="form-control" name="v_ttl" id="v_ttl" value="<?= htmlentities(trim($v_ttl, "'")) ?>">
+				<input type="text" class="form-control" name="v_ttl" id="v_ttl" value="<?= tohtml(trim($v_ttl, "'")) ?>">
 			</div>
 		</div>
 

+ 181 - 158
web/templates/pages/list_backup_detail.php

@@ -1,31 +1,35 @@
 <!-- Begin toolbar -->
 <div class="toolbar">
 	<div class="toolbar-inner">
-		<div class="toolbar-buttons">
-			<a class="button button-secondary button-back js-button-back" href="/list/backup/">
-				<i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?>
-			</a>
-			<a href="/schedule/restore/?token=<?= $_SESSION["token"] ?>&backup=<?= htmlentities($_GET["backup"]) ?>" class="button button-secondary">
-				<i class="fas fa-arrow-rotate-left icon-green"></i><?= _("Restore All") ?>
-			</a>
-		</div>
-		<div class="toolbar-right">
-			<form x-data x-bind="BulkEdit" action="/bulk/restore/" method="post">
-				<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
-				<input type="hidden" name="backup" value="<?= htmlentities($_GET["backup"]) ?>">
-				<select class="form-select" name="action">
-					<option value=""><?= _("Apply to selected") ?></option>
-					<option value="restore"><?= _("Restore") ?></option>
-				</select>
-				<button type="submit" class="toolbar-input-submit" title="<?= _("Apply to selected") ?>">
-					<i class="fas fa-arrow-right"></i>
-				</button>
-			</form>
-			<div class="toolbar-search">
+			<div class="toolbar-buttons">
+				<a class="button button-secondary button-back js-button-back" href="/list/backup/">
+					<i class="fas fa-arrow-left icon-blue"></i><?= tohtml( _("Back")) ?>
+				</a>
+				<?php if ($read_only !== "true") { ?>
+					<a href="/schedule/restore/?<?= tohtml(http_build_query(array("token" => $_SESSION["token"], "backup" => $_GET["backup"]))) ?>" class="button button-secondary">
+						<i class="fas fa-arrow-rotate-left icon-green"></i><?= tohtml( _("Restore All")) ?>
+					</a>
+				<?php } ?>
+			</div>
+			<div class="toolbar-right">
+				<?php if ($read_only !== "true") { ?>
+					<form x-data x-bind="BulkEdit" action="/bulk/restore/" method="post">
+						<input type="hidden" name="token" value="<?= tohtml($_SESSION["token"]) ?>">
+						<input type="hidden" name="backup" value="<?= tohtml($_GET["backup"]) ?>">
+						<select class="form-select" name="action">
+							<option value=""><?= tohtml( _("Apply to selected")) ?></option>
+							<option value="restore"><?= tohtml( _("Restore")) ?></option>
+						</select>
+						<button type="submit" class="toolbar-input-submit" title="<?= tohtml( _("Apply to selected")) ?>">
+							<i class="fas fa-arrow-right"></i>
+						</button>
+					</form>
+				<?php } ?>
+				<div class="toolbar-search">
 				<form action="/search/" method="get">
-					<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
-					<input type="search" class="form-control js-search-input" name="q" value="<? echo isset($_POST['q']) ? htmlspecialchars($_POST['q']) : '' ?>" title="<?= _("Search") ?>">
-					<button type="submit" class="toolbar-input-submit" title="<?= _("Search") ?>">
+					<input type="hidden" name="token" value="<?= tohtml($_SESSION["token"]) ?>">
+						<input type="search" class="form-control js-search-input" name="q" value="<?= tohtml($_GET['q'] ?? '') ?>" title="<?= tohtml( _("Search")) ?>">
+					<button type="submit" class="toolbar-input-submit" title="<?= tohtml( _("Search")) ?>">
 						<i class="fas fa-magnifying-glass"></i>
 					</button>
 				</form>
@@ -37,53 +41,56 @@
 
 <div class="container">
 
-	<h1 class="u-text-center u-hide-desktop u-mt20 u-pr30 u-mb20 u-pl30"><?= _("Backup Details") ?></h1>
+	<h1 class="u-text-center u-hide-desktop u-mt20 u-pr30 u-mb20 u-pl30"><?= tohtml( _("Backup Details")) ?></h1>
 
 	<div class="units-table js-units-container">
 		<div class="units-table-header">
 			<div class="units-table-cell">
-				<input type="checkbox" class="js-toggle-all-checkbox" title="<?= _("Select all") ?>" <?= $display_mode ?>>
+				<input type="checkbox" class="js-toggle-all-checkbox" title="<?= tohtml( _("Select all")) ?>" <?= tohtml($display_mode) ?>>
 			</div>
-			<div class="units-table-cell"><?= _("Type") ?></div>
-			<div class="units-table-cell"><?= _("Details") ?></div>
-			<div class="units-table-cell"><?= _("Restore") ?></div>
+			<div class="units-table-cell"><?= tohtml( _("Type")) ?></div>
+			<div class="units-table-cell"><?= tohtml( _("Details")) ?></div>
+			<div class="units-table-cell"><?= tohtml( _("Restore")) ?></div>
 		</div>
 
-		<!-- List web domains -->
-		<?php
-			$backup = htmlentities($_GET['backup']);
-			$web = explode(',',$data[$backup]['WEB']);
-			foreach ($web as $key) {
-				if (!empty($key)) {
-					++$i;
-			?>
-			<div class="units-table-row js-unit">
-				<div class="units-table-cell">
-					<div>
-						<input id="check<?= $i ?>" class="js-unit-checkbox" type="checkbox" name="web[]" value="<?= $key ?>">
-						<label for="check<?= $i ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+			<!-- List web domains -->
+			<?php
+				$item_count = 0;
+				$backup = $_GET['backup'];
+				$web_index = 0;
+				$web = explode(',',$data[$backup]['WEB']);
+				foreach ($web as $key) {
+					if (!empty($key)) {
+						++$web_index;
+						++$item_count;
+				?>
+				<div class="units-table-row js-unit">
+					<div class="units-table-cell">
+						<div>
+							<input id="check-web<?= tohtml($web_index) ?>" class="js-unit-checkbox" type="checkbox" name="web[]" value="<?= tohtml($key) ?>">
+							<label for="check-web<?= tohtml($web_index) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
+						</div>
 					</div>
-				</div>
 				<div class="units-table-cell units-table-heading-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("Type") ?>:</span>
-					<?= _("Web Domain") ?>
+					<span class="u-hide-desktop u-text-bold"><?= tohtml( _("Type")) ?>:</span>
+					<?= tohtml( _("Web Domain")) ?>
 				</div>
 				<div class="units-table-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Details") ?>:</span>
-					<?= $key ?>
+					<span class="u-hide-desktop"><?= tohtml( _("Details")) ?>:</span>
+					<?= tohtml($key) ?>
 				</div>
 				<div class="units-table-cell">
 					<ul class="units-table-row-actions">
 						<li class="units-table-row-action shortcut-enter" data-key-action="href">
 							<a
 								class="units-table-row-action-link data-controls js-confirm-action"
-								href="/schedule/restore/?backup=<?= $backup ?>&type=web&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>"
-								title="<?= _("Restore") ?>"
-								data-confirm-title="<?= _("Restore") ?>"
-								data-confirm-message="<?= sprintf(_("Are you sure you want to restore %s?"), $key) ?>"
+								href="/schedule/restore/?<?= tohtml(http_build_query(array("backup" => $backup, "type" => "web", "object" => $key, "token" => $_SESSION["token"]))) ?>"
+								title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-message="<?= tohtml(sprintf(_("Are you sure you want to restore %s?"), $key)) ?>"
 							>
 								<i class="fas fa-arrow-rotate-left icon-green"></i>
-								<span class="u-hide-desktop"><?= _("Restore") ?></span>
+								<span class="u-hide-desktop"><?= tohtml( _("Restore")) ?></span>
 							</a>
 						</li>
 					</ul>
@@ -92,38 +99,41 @@
 		<?php }} ?>
 
 		<!-- List mail domains -->
-		<?php
-			$mail = explode(',',$data[$backup]['MAIL']);
-			foreach ($mail as $key) {
-				if (!empty($key)) {
-			?>
-			<div class="units-table-row js-unit">
-				<div class="units-table-cell">
-					<div>
-						<input id="check2<?= $i ?>" class="js-unit-checkbox" type="checkbox" name="mail[]" value="<?= $key ?>">
-						<label for="check2<?= $i ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+			<?php
+				$mail_index = 0;
+				$mail = explode(',',$data[$backup]['MAIL']);
+				foreach ($mail as $key) {
+					if (!empty($key)) {
+						++$mail_index;
+						++$item_count;
+				?>
+				<div class="units-table-row js-unit">
+					<div class="units-table-cell">
+						<div>
+							<input id="check-mail<?= tohtml($mail_index) ?>" class="js-unit-checkbox" type="checkbox" name="mail[]" value="<?= tohtml($key) ?>">
+							<label for="check-mail<?= tohtml($mail_index) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
+						</div>
 					</div>
-				</div>
 				<div class="units-table-cell units-table-heading-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("Type") ?>:</span>
-					<?= _("Mail Domain") ?>
+					<span class="u-hide-desktop u-text-bold"><?= tohtml( _("Type")) ?>:</span>
+					<?= tohtml( _("Mail Domain")) ?>
 				</div>
 				<div class="units-table-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Details") ?>:</span>
-					<?= $key ?>
+					<span class="u-hide-desktop"><?= tohtml( _("Details")) ?>:</span>
+					<?= tohtml($key) ?>
 				</div>
 				<div class="units-table-cell">
 					<ul class="units-table-row-actions">
 						<li class="units-table-row-action shortcut-enter" data-key-action="href">
 							<a
 								class="units-table-row-action-link data-controls js-confirm-action"
-								href="/schedule/restore/?backup=<?= $backup ?>&type=mail&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>"
-								title="<?= _("Restore") ?>"
-								data-confirm-title="<?= _("Restore") ?>"
-								data-confirm-message="<?= sprintf(_("Are you sure you want to restore %s?"), $key) ?>"
+								href="/schedule/restore/?<?= tohtml(http_build_query(array("backup" => $backup, "type" => "mail", "object" => $key, "token" => $_SESSION["token"]))) ?>"
+								title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-message="<?= tohtml(sprintf(_("Are you sure you want to restore %s?"), $key)) ?>"
 							>
 								<i class="fas fa-arrow-rotate-left icon-green"></i>
-								<span class="u-hide-desktop"><?= _("Restore") ?></span>
+								<span class="u-hide-desktop"><?= tohtml( _("Restore")) ?></span>
 							</a>
 						</li>
 					</ul>
@@ -132,38 +142,41 @@
 		<?php }} ?>
 
 		<!-- List DNS zones -->
-		<?php
-			$dns = explode(',',$data[$backup]['DNS']);
-			foreach ($dns as $key) {
-				if (!empty($key)) {
-			?>
-			<div class="units-table-row js-unit">
-				<div class="units-table-cell">
-					<div>
-						<input id="check3<?= $i ?>" class="js-unit-checkbox" type="checkbox" name="dns[]" value="<?= $key ?>">
-						<label for="check3<?= $i ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+			<?php
+				$dns_index = 0;
+				$dns = explode(',',$data[$backup]['DNS']);
+				foreach ($dns as $key) {
+					if (!empty($key)) {
+						++$dns_index;
+						++$item_count;
+				?>
+				<div class="units-table-row js-unit">
+					<div class="units-table-cell">
+						<div>
+							<input id="check-dns<?= tohtml($dns_index) ?>" class="js-unit-checkbox" type="checkbox" name="dns[]" value="<?= tohtml($key) ?>">
+							<label for="check-dns<?= tohtml($dns_index) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
+						</div>
 					</div>
-				</div>
 				<div class="units-table-cell units-table-heading-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("Type") ?>:</span>
-					<?= _("DNS Zone") ?>
+					<span class="u-hide-desktop u-text-bold"><?= tohtml( _("Type")) ?>:</span>
+					<?= tohtml( _("DNS Zone")) ?>
 				</div>
 				<div class="units-table-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Details") ?>:</span>
-					<?= $key ?>
+					<span class="u-hide-desktop"><?= tohtml( _("Details")) ?>:</span>
+					<?= tohtml($key) ?>
 				</div>
 				<div class="units-table-cell">
 					<ul class="units-table-row-actions">
 						<li class="units-table-row-action shortcut-enter" data-key-action="href">
 							<a
 								class="units-table-row-action-link data-controls js-confirm-action"
-								href="/schedule/restore/?backup=<?= $backup ?>&type=dns&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>"
-								title="<?= _("Restore") ?>"
-								data-confirm-title="<?= _("Restore") ?>"
-								data-confirm-message="<?= sprintf(_("Are you sure you want to restore %s?"), $key) ?>"
+								href="/schedule/restore/?<?= tohtml(http_build_query(array("backup" => $backup, "type" => "dns", "object" => $key, "token" => $_SESSION["token"]))) ?>"
+								title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-message="<?= tohtml(sprintf(_("Are you sure you want to restore %s?"), $key)) ?>"
 							>
 								<i class="fas fa-arrow-rotate-left icon-green"></i>
-								<span class="u-hide-desktop"><?= _("Restore") ?></span>
+								<span class="u-hide-desktop"><?= tohtml( _("Restore")) ?></span>
 							</a>
 						</li>
 					</ul>
@@ -172,38 +185,41 @@
 		<?php }} ?>
 
 		<!-- List Databases -->
-		<?php
-			$db = explode(',',$data[$backup]['DB']);
-			foreach ($db as $key) {
-				if (!empty($key)) {
-			?>
-			<div class="units-table-row js-unit">
-				<div class="units-table-cell">
-					<div>
-						<input id="check4<?= $i ?>" class="js-unit-checkbox" type="checkbox" name="db[]" value="<?= $key ?>">
-						<label for="check4<?= $i ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+			<?php
+				$db_index = 0;
+				$db = explode(',',$data[$backup]['DB']);
+				foreach ($db as $key) {
+					if (!empty($key)) {
+						++$db_index;
+						++$item_count;
+				?>
+				<div class="units-table-row js-unit">
+					<div class="units-table-cell">
+						<div>
+							<input id="check-db<?= tohtml($db_index) ?>" class="js-unit-checkbox" type="checkbox" name="db[]" value="<?= tohtml($key) ?>">
+							<label for="check-db<?= tohtml($db_index) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
+						</div>
 					</div>
-				</div>
 				<div class="units-table-cell units-table-heading-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("Type") ?>:</span>
-					<?= _("Database") ?>
+					<span class="u-hide-desktop u-text-bold"><?= tohtml( _("Type")) ?>:</span>
+					<?= tohtml( _("Database")) ?>
 				</div>
 				<div class="units-table-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Details") ?>:</span>
-					<?= $key ?>
+					<span class="u-hide-desktop"><?= tohtml( _("Details")) ?>:</span>
+					<?= tohtml($key) ?>
 				</div>
 				<div class="units-table-cell">
 					<ul class="units-table-row-actions">
 						<li class="units-table-row-action shortcut-enter" data-key-action="href">
 							<a
 								class="units-table-row-action-link data-controls js-confirm-action"
-								href="/schedule/restore/?backup=<?= $backup ?>&type=db&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>"
-								title="<?= _("Restore") ?>"
-								data-confirm-title="<?= _("Restore") ?>"
-								data-confirm-message="<?= sprintf(_("Are you sure you want to restore %s?"), $key) ?>"
+								href="/schedule/restore/?<?= tohtml(http_build_query(array("backup" => $backup, "type" => "db", "object" => $key, "token" => $_SESSION["token"]))) ?>"
+								title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-message="<?= tohtml(sprintf(_("Are you sure you want to restore %s?"), $key)) ?>"
 							>
 								<i class="fas fa-arrow-rotate-left icon-green"></i>
-								<span class="u-hide-desktop"><?= _("Restore") ?></span>
+								<span class="u-hide-desktop"><?= tohtml( _("Restore")) ?></span>
 							</a>
 						</li>
 					</ul>
@@ -211,76 +227,83 @@
 			</div>
 		<?php }} ?>
 
-		<!-- List Cron Jobs -->
-		<?php if (!empty($data[$backup]["CRON"])) {
-		if (!empty($key)) { ?>
-			<div class="units-table-row js-unit">
-				<div class="units-table-cell">
-					<div>
-						<input id="check5<?= $i ?>" class="js-unit-checkbox" type="checkbox" name="check" value="<?= $key ?>">
-						<label for="check5<?= $i ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+			<!-- List Cron Jobs -->
+			<?php
+				$cron_index = 0;
+				if (!empty($data[$backup]["CRON"])) {
+					++$cron_index;
+					++$item_count;
+			?>
+				<div class="units-table-row js-unit">
+					<div class="units-table-cell">
+						<div>
+							<input id="check-cron<?= tohtml($cron_index) ?>" class="js-unit-checkbox" type="checkbox" name="cron" value="yes">
+							<label for="check-cron<?= tohtml($cron_index) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
+						</div>
 					</div>
-				</div>
 				<div class="units-table-cell units-table-heading-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("Type") ?>:</span>
-					<?= _("Cron Jobs") ?>
+					<span class="u-hide-desktop u-text-bold"><?= tohtml( _("Type")) ?>:</span>
+					<?= tohtml( _("Cron Jobs")) ?>
 				</div>
 				<div class="units-table-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Details") ?>:</span>
-					<?= _("Jobs") ?>
+					<span class="u-hide-desktop"><?= tohtml( _("Details")) ?>:</span>
+					<?= tohtml( _("Jobs")) ?>
 				</div>
 				<div class="units-table-cell">
 					<ul class="units-table-row-actions">
 						<li class="units-table-row-action shortcut-enter" data-key-action="href">
-							<a
-								class="units-table-row-action-link data-controls js-confirm-action"
-								href="/schedule/restore/?backup=<?= $backup ?>&type=cron&object=records&token=<?= $_SESSION["token"] ?>"
-								title="<?= _("Restore") ?>"
-								data-confirm-title="<?= _("Restore") ?>"
-								data-confirm-message="<?= sprintf(_("Are you sure you want to restore %s?"), $key) ?>"
-							>
-								<i class="fas fa-arrow-rotate-left icon-green"></i>
-								<span class="u-hide-desktop"><?= _("Restore") ?></span>
+								<a
+									class="units-table-row-action-link data-controls js-confirm-action"
+									href="/schedule/restore/?<?= tohtml(http_build_query(array("backup" => $backup, "type" => "cron", "object" => "records", "token" => $_SESSION["token"]))) ?>"
+									title="<?= tohtml( _("Restore")) ?>"
+									data-confirm-title="<?= tohtml( _("Restore")) ?>"
+									data-confirm-message="<?= tohtml( _("Are you sure you want to restore cron jobs?")) ?>"
+								>
+									<i class="fas fa-arrow-rotate-left icon-green"></i>
+									<span class="u-hide-desktop"><?= tohtml( _("Restore")) ?></span>
 							</a>
 						</li>
 					</ul>
 				</div>
 			</div>
-		<?php }} ?>
+			<?php } ?>
 
 		<!-- List user directories -->
-		<?php
-			$udir = explode(',',$data[$backup]['UDIR']);
-			foreach ($udir as $key) {
-				if (!empty($key)) {
-			?>
-			<div class="units-table-row js-unit">
-				<div class="units-table-cell">
-					<div>
-						<input id="check6<?= $i ?>" class="js-unit-checkbox" type="checkbox" name="udir[]" value="<?= $key ?>">
-						<label for="check6<?= $i ?>" class="u-hide-desktop"><?= _("Select") ?></label>
+			<?php
+				$udir_index = 0;
+				$udir = explode(',',$data[$backup]['UDIR']);
+				foreach ($udir as $key) {
+					if (!empty($key)) {
+						++$udir_index;
+						++$item_count;
+				?>
+				<div class="units-table-row js-unit">
+					<div class="units-table-cell">
+						<div>
+							<input id="check-udir<?= tohtml($udir_index) ?>" class="js-unit-checkbox" type="checkbox" name="udir[]" value="<?= tohtml($key) ?>">
+							<label for="check-udir<?= tohtml($udir_index) ?>" class="u-hide-desktop"><?= tohtml( _("Select")) ?></label>
+						</div>
 					</div>
-				</div>
 				<div class="units-table-cell units-table-heading-cell">
-					<span class="u-hide-desktop u-text-bold"><?= _("Type") ?>:</span>
-					<?= _("User Directory") ?>
+					<span class="u-hide-desktop u-text-bold"><?= tohtml( _("Type")) ?>:</span>
+					<?= tohtml( _("User Directory")) ?>
 				</div>
 				<div class="units-table-cell u-text-bold">
-					<span class="u-hide-desktop"><?= _("Details") ?>:</span>
-					<?= $key ?>
+					<span class="u-hide-desktop"><?= tohtml( _("Details")) ?>:</span>
+					<?= tohtml($key) ?>
 				</div>
 				<div class="units-table-cell">
 					<ul class="units-table-row-actions">
 						<li class="units-table-row-action shortcut-enter" data-key-action="href">
 							<a
 								class="units-table-row-action-link data-controls js-confirm-action"
-								href="/schedule/restore/?backup=<?= $backup ?>&type=udir&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>"
-								title="<?= _("Restore") ?>"
-								data-confirm-title="<?= _("Restore") ?>"
-								data-confirm-message="<?= sprintf(_("Are you sure you want to restore %s?"), $key) ?>"
+								href="/schedule/restore/?<?= tohtml(http_build_query(array("backup" => $backup, "type" => "udir", "object" => $key, "token" => $_SESSION["token"]))) ?>"
+								title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-title="<?= tohtml( _("Restore")) ?>"
+								data-confirm-message="<?= tohtml(sprintf(_("Are you sure you want to restore %s?"), $key)) ?>"
 							>
 								<i class="fas fa-arrow-rotate-left icon-green"></i>
-								<span class="u-hide-desktop"><?= _("Restore") ?></span>
+								<span class="u-hide-desktop"><?= tohtml( _("Restore")) ?></span>
 							</a>
 						</li>
 					</ul>
@@ -291,8 +314,8 @@
 
 	<div class="units-table-footer">
 		<p>
-			<?php printf(ngettext("%d item", "%d items", $i), $i); ?>
-		</p>
-	</div>
+				<?php printf(ngettext("%d item", "%d items", $item_count), $item_count); ?>
+			</p>
+		</div>
 
 </div>