From fd752be1145e3960610343f8c46e558d3d5b65a4 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 28 Apr 2020 05:40:23 +0000 Subject: [PATCH 1/4] Issue 8546: Added option to not use prepared statements --- src/Database/Database.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index f86f27996..db906bd01 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -57,6 +57,7 @@ class Database /** @var PDO|mysqli */ protected $connection; protected $driver; + private $emulate_prepares = false; private $error = false; private $errorno = 0; private $affected_rows = 0; @@ -130,6 +131,8 @@ class Database return false; } + $this->emulate_prepares = (bool)$this->configCache->get('database', 'emulate_prepares'); + if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) { $this->driver = 'pdo'; $connect = "mysql:host=" . $server . ";dbname=" . $db; @@ -428,8 +431,10 @@ class Database { $offset = 0; foreach ($args AS $param => $value) { - if (is_int($args[$param]) || is_float($args[$param])) { + if (is_int($args[$param]) || is_float($args[$param]) || is_bool($args[$param])) { $replace = intval($args[$param]); + } elseif (is_null($args[$param])) { + $replace = 'NULL'; } else { $replace = "'" . $this->escape($args[$param]) . "'"; } @@ -515,8 +520,8 @@ class Database switch ($this->driver) { case 'pdo': // If there are no arguments we use "query" - if (count($args) == 0) { - if (!$retval = $this->connection->query($sql)) { + if ($this->emulate_prepares || count($args) == 0) { + if (!$retval = $this->connection->query($this->replaceParameters($sql, $args))) { $errorInfo = $this->connection->errorInfo(); $this->error = $errorInfo[2]; $this->errorno = $errorInfo[1]; @@ -562,7 +567,7 @@ class Database $can_be_prepared = in_array($command, ['select', 'update', 'insert', 'delete']); // The fallback routine is called as well when there are no arguments - if (!$can_be_prepared || (count($args) == 0)) { + if ($this->emulate_prepares || !$can_be_prepared || (count($args) == 0)) { $retval = $this->connection->query($this->replaceParameters($sql, $args)); if ($this->connection->errno) { $this->error = $this->connection->error; From 9ccdbd93490b86bf7e63ecc40e97a8ecfd82a9d9 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 28 Apr 2020 05:55:17 +0000 Subject: [PATCH 2/4] Added forgotten DBA::close --- src/Core/Worker.php | 1 + src/Model/User.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 6fb8bd40f..24febf3bc 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -614,6 +614,7 @@ class Worker } } } + DBA::close($entries); } /** diff --git a/src/Model/User.php b/src/Model/User.php index be71bcf64..89574e760 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -1298,6 +1298,7 @@ class User $statistics['active_users_monthly']++; } } + DBA::close($userStmt); return $statistics; } From f75009c20cf353fa74f20cad4f7697536695ddf5 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 28 Apr 2020 07:10:18 +0000 Subject: [PATCH 3/4] Some more forgotten DBA::close --- mod/msearch.php | 4 +++- src/Model/Contact.php | 2 ++ src/Model/GContact.php | 2 ++ src/Model/Process.php | 2 +- src/Model/Search.php | 2 +- src/Model/UserItem.php | 1 + src/Module/Admin/DBSync.php | 1 + src/Module/Admin/Site.php | 1 + src/Module/Settings/Delegation.php | 1 + src/Protocol/ActivityPub/Transmitter.php | 2 ++ src/Protocol/Diaspora.php | 5 +++++ src/Worker/CronJobs.php | 2 ++ src/Worker/UpdateGContacts.php | 1 + src/Worker/UpdateGServers.php | 1 + 14 files changed, 24 insertions(+), 3 deletions(-) diff --git a/mod/msearch.php b/mod/msearch.php index b02a036ae..14dfd1ef7 100644 --- a/mod/msearch.php +++ b/mod/msearch.php @@ -68,7 +68,7 @@ function msearch_post(App $a) $perpage ); - while($search_result = DBA::fetch($search_stmt)) { + while ($search_result = DBA::fetch($search_stmt)) { $results[] = [ 'name' => $search_result['name'], 'url' => DI::baseUrl() . '/profile/' . $search_result['nickname'], @@ -77,6 +77,8 @@ function msearch_post(App $a) ]; } + DBA::close($search_stmt); + $output = ['total' => $total, 'items_page' => $perpage, 'page' => $page, 'results' => $results]; echo json_encode($output); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 2435b54f9..becc80c0c 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -2057,6 +2057,7 @@ class Contact Worker::add(PRIORITY_HIGH, 'MergeContact', $first, $duplicate['id'], $uid); } + DBA::close($duplicates); Logger::info('Duplicates handled', ['uid' => $uid, 'nurl' => $nurl]); return true; } @@ -2732,6 +2733,7 @@ class Contact ); } } + DBA::close($contacts); } /** diff --git a/src/Model/GContact.php b/src/Model/GContact.php index 553976296..becfd61b0 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -113,6 +113,7 @@ class GContact $gcontacts[] = Contact::getDetailsByURL($result['nurl'], local_user()); } + DBA::close($results); return $gcontacts; } @@ -563,6 +564,7 @@ class GContact PortableContact::loadWorker(0, 0, 0, $base); } } + DBA::close($contacts); } /** diff --git a/src/Model/Process.php b/src/Model/Process.php index 265292968..18b5f785a 100644 --- a/src/Model/Process.php +++ b/src/Model/Process.php @@ -85,7 +85,7 @@ class Process self::deleteByPid($process['pid']); } } - + DBA::close($processes); DBA::commit(); } } diff --git a/src/Model/Search.php b/src/Model/Search.php index 9e00bbe30..ca8960ef3 100644 --- a/src/Model/Search.php +++ b/src/Model/Search.php @@ -44,7 +44,7 @@ class Search while ($term = DBA::fetch($termsStmt)) { $tags[] = trim($term['term'], '#'); } - + DBA::close($termsStmt); return $tags; } } diff --git a/src/Model/UserItem.php b/src/Model/UserItem.php index 6a228c098..72db1005d 100644 --- a/src/Model/UserItem.php +++ b/src/Model/UserItem.php @@ -214,6 +214,7 @@ class UserItem return true; } } + DBA::close($tags); return false; } diff --git a/src/Module/Admin/DBSync.php b/src/Module/Admin/DBSync.php index 8892c2969..dd7febcc5 100644 --- a/src/Module/Admin/DBSync.php +++ b/src/Module/Admin/DBSync.php @@ -102,6 +102,7 @@ class DBSync extends BaseAdmin $failed[] = $upd; } } + DBA::close($configStmt); if (!count($failed)) { $o = Renderer::replaceMacros(Renderer::getMarkupTemplate('admin/dbsync/structure_check.tpl'), [ diff --git a/src/Module/Admin/Site.php b/src/Module/Admin/Site.php index cf3fee31b..f3086856b 100644 --- a/src/Module/Admin/Site.php +++ b/src/Module/Admin/Site.php @@ -121,6 +121,7 @@ class Site extends BaseAdmin while ($user = DBA::fetch($usersStmt)) { Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, $user['uid']); } + DBA::close($usersStmt); info("Relocation started. Could take a while to complete."); diff --git a/src/Module/Settings/Delegation.php b/src/Module/Settings/Delegation.php index e70dee890..e590d6ea7 100644 --- a/src/Module/Settings/Delegation.php +++ b/src/Module/Settings/Delegation.php @@ -125,6 +125,7 @@ class Delegation extends BaseSettings while ($contact = DBA::fetch($contacts)) { $nicknames[] = $contact['nick']; } + DBA::close($contacts); // get user records for all potential page delegates who are not already delegates or managers $potentialDelegateUsers = DBA::selectToArray('user', ['uid', 'username', 'nickname'], ['nickname' => $nicknames]); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index e35d83361..db588ea6d 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -96,6 +96,7 @@ class Transmitter while ($contact = DBA::fetch($contacts)) { $list[] = $contact['url']; } + DBA::close($contacts); if (!empty($list)) { $data['next'] = DI::baseUrl() . '/followers/' . $owner['nickname'] . '?page=' . ($page + 1); @@ -145,6 +146,7 @@ class Transmitter while ($contact = DBA::fetch($contacts)) { $list[] = $contact['url']; } + DBA::close($contacts); if (!empty($list)) { $data['next'] = DI::baseUrl() . '/following/' . $owner['nickname'] . '?page=' . ($page + 1); diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index fe6c328d9..60cb4cf35 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -124,6 +124,7 @@ class Diaspora while ($server = DBA::fetch($servers)) { $serverlist[$server['url']] = $server['url']; } + DBA::close($servers); // All tags of the current post $condition = ['otype' => Term::OBJECT_TYPE_POST, 'type' => Term::HASHTAG, 'oid' => $parent['parent']]; @@ -132,6 +133,7 @@ class Diaspora while ($tag = DBA::fetch($tags)) { $taglist[] = $tag['term']; } + DBA::close($tags); // All servers who wants content with this tag $tagserverlist = []; @@ -140,6 +142,7 @@ class Diaspora while ($server = DBA::fetch($tagserver)) { $tagserverlist[] = $server['gserver-id']; } + DBA::close($tagserver); } // All adresses with the given id @@ -148,6 +151,7 @@ class Diaspora while ($server = DBA::fetch($servers)) { $serverlist[$server['url']] = $server['url']; } + DBA::close($servers); } } @@ -1720,6 +1724,7 @@ class Diaspora while ($contact = DBA::fetch($contacts)) { Contact::remove($contact["id"]); } + DBA::close($contacts); DBA::delete('gcontact', ['addr' => $author]); diff --git a/src/Worker/CronJobs.php b/src/Worker/CronJobs.php index 2a6c97e84..319a369d1 100644 --- a/src/Worker/CronJobs.php +++ b/src/Worker/CronJobs.php @@ -128,6 +128,7 @@ class CronJobs while ($user = DBA::fetch($users)) { User::remove($user['uid']); } + DBA::close($users); // delete user records for recently removed accounts $users = DBA::select('user', ['uid'], ["`account_removed` AND `account_expires_on` < UTC_TIMESTAMP() "]); @@ -140,6 +141,7 @@ class CronJobs DBA::delete('user', ['uid' => $user['uid']]); } + DBA::close($users); } /** diff --git a/src/Worker/UpdateGContacts.php b/src/Worker/UpdateGContacts.php index 80c0ef524..9d9519241 100644 --- a/src/Worker/UpdateGContacts.php +++ b/src/Worker/UpdateGContacts.php @@ -96,5 +96,6 @@ class UpdateGContacts return; } } + DBA::close($contacts); } } diff --git a/src/Worker/UpdateGServers.php b/src/Worker/UpdateGServers.php index 2200d02e9..5a4513846 100644 --- a/src/Worker/UpdateGServers.php +++ b/src/Worker/UpdateGServers.php @@ -52,5 +52,6 @@ class UpdateGServers return; } } + DBA::close($gservers); } } From e52e505a481ed6f7e3766725d709b5f0653b036b Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 28 Apr 2020 08:00:38 +0000 Subject: [PATCH 4/4] Merge --- src/Model/GServer.php | 6 +-- src/Model/Item.php | 4 +- src/Module/Admin/Users.php | 2 +- src/Network/Probe.php | 6 +-- src/Protocol/ActivityPub/Transmitter.php | 4 +- src/Protocol/DFRN.php | 12 ++--- src/Protocol/Diaspora.php | 4 +- src/Util/XML.php | 20 +++++--- view/theme/frio/css/style.css | 62 ++++++------------------ view/theme/frio/templates/jot.tpl | 2 +- view/theme/frio/templates/searchbox.tpl | 2 +- 11 files changed, 51 insertions(+), 73 deletions(-) diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 0f5f55ab6..bc189af9d 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -747,7 +747,7 @@ class GServer return false; } - $xrd = XML::parseString($curlResult->getBody(), false); + $xrd = XML::parseString($curlResult->getBody()); if (!is_object($xrd)) { return false; } @@ -796,13 +796,13 @@ class GServer DBA::close($gcontacts); $apcontacts = DBA::select('apcontact', ['url'], ['baseurl' => [$url, $serverdata['nurl']]]); - while ($gcontact = DBA::fetch($gcontacts)) { + while ($apcontact = DBA::fetch($apcontacts)) { $contacts[Strings::normaliseLink($apcontact['url'])] = $apcontact['url']; } DBA::close($apcontacts); $pcontacts = DBA::select('contact', ['url', 'nurl'], ['uid' => 0, 'baseurl' => [$url, $serverdata['nurl']]]); - while ($gcontact = DBA::fetch($gcontacts)) { + while ($pcontact = DBA::fetch($pcontacts)) { $contacts[$pcontact['nurl']] = $pcontact['url']; } DBA::close($pcontacts); diff --git a/src/Model/Item.php b/src/Model/Item.php index bd8d03359..97c96f674 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1249,8 +1249,8 @@ class Item return; } - $xo = XML::parseString($item["object"], false); - $xt = XML::parseString($item["target"], false); + $xo = XML::parseString($item["object"]); + $xt = XML::parseString($item["target"]); if ($xt->type != Activity\ObjectType::NOTE) { return; diff --git a/src/Module/Admin/Users.php b/src/Module/Admin/Users.php index 002e6c5fe..dca8c9c2e 100644 --- a/src/Module/Admin/Users.php +++ b/src/Module/Admin/Users.php @@ -206,7 +206,7 @@ class Users extends BaseAdmin $e['register_date'] = Temporal::getRelativeDate($e['register_date']); $e['login_date'] = Temporal::getRelativeDate($e['login_date']); - $e['last-item'] = Temporal::getRelativeDate($e['last-item']); + $e['lastitem_date'] = Temporal::getRelativeDate($e['last-item']); $e['is_admin'] = in_array($e['email'], $adminlist); $e['is_deletable'] = (intval($e['uid']) != local_user()); $e['deleted'] = ($e['account_removed'] ? Temporal::getRelativeDate($e['account_expires_on']) : False); diff --git a/src/Network/Probe.php b/src/Network/Probe.php index b5991934b..1e6d8406a 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -160,7 +160,7 @@ class Probe $ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); if ($curlResult->isSuccess()) { $xml = $curlResult->getBody(); - $xrd = XML::parseString($xml, false); + $xrd = XML::parseString($xml, true); if (!empty($url)) { $host_url = 'https://' . $host; } else { @@ -185,7 +185,7 @@ class Probe } $xml = $curlResult->getBody(); - $xrd = XML::parseString($xml, false); + $xrd = XML::parseString($xml, true); $host_url = 'http://'.$host; } if (!is_object($xrd)) { @@ -936,7 +936,7 @@ class Probe } // If it is not JSON, maybe it is XML - $xrd = XML::parseString($data, false); + $xrd = XML::parseString($data, true); if (!is_object($xrd)) { Logger::log("No webfinger data retrievable for ".$url, Logger::DEBUG); return false; diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index db588ea6d..8928b9435 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -1408,8 +1408,8 @@ class Transmitter */ private static function createAddTag($item, $data) { - $object = XML::parseString($item['object'], false); - $target = XML::parseString($item["target"], false); + $object = XML::parseString($item['object']); + $target = XML::parseString($item["target"]); $data['diaspora:guid'] = $item['guid']; $data['actor'] = $item['author-link']; diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index f65a202f4..4e5aac37d 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -805,7 +805,7 @@ class DFRN if ($activity) { $entry = $doc->createElement($element); - $r = XML::parseString($activity, false); + $r = XML::parseString($activity); if (!$r) { return false; } @@ -831,7 +831,7 @@ class DFRN $r->link = preg_replace('/\/', '', $r->link); // XML does need a single element as root element so we add a dummy element here - $data = XML::parseString("" . $r->link . "", false); + $data = XML::parseString("" . $r->link . ""); if (is_object($data)) { foreach ($data->link as $link) { $attributes = []; @@ -2101,7 +2101,7 @@ class DFRN if (!$verb) { return; } - $xo = XML::parseString($item["object"], false); + $xo = XML::parseString($item["object"]); if (($xo->type == Activity\ObjectType::PERSON) && ($xo->id)) { // somebody was poked/prodded. Was it me? @@ -2224,8 +2224,8 @@ class DFRN } if (($item["verb"] == Activity::TAG) && ($item["object-type"] == Activity\ObjectType::TAGTERM)) { - $xo = XML::parseString($item["object"], false); - $xt = XML::parseString($item["target"], false); + $xo = XML::parseString($item["object"]); + $xt = XML::parseString($item["target"]); if ($xt->type == Activity\ObjectType::NOTE) { $item_tag = Item::selectFirst(['id', 'uri-id', 'tag'], ['uri' => $xt->id, 'uid' => $importer["importer_uid"]]); @@ -2413,7 +2413,7 @@ class DFRN $item["object"] = self::transformActivity($xpath, $object, "object"); if (trim($item["object"]) != "") { - $r = XML::parseString($item["object"], false); + $r = XML::parseString($item["object"]); if (isset($r->type)) { $item["object-type"] = $r->type; } diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 60cb4cf35..628229501 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -329,7 +329,7 @@ class Diaspora */ private static function verifyMagicEnvelope($envelope) { - $basedom = XML::parseString($envelope); + $basedom = XML::parseString($envelope, true); if (!is_object($basedom)) { Logger::log("Envelope is no XML file"); @@ -455,7 +455,7 @@ class Diaspora $xml = $raw; } - $basedom = XML::parseString($xml); + $basedom = XML::parseString($xml, true); if (!is_object($basedom)) { Logger::log('Received data does not seem to be an XML. Discarding. '.$xml); diff --git a/src/Util/XML.php b/src/Util/XML.php index 9aba38910..4eed3a85f 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -433,18 +433,26 @@ class XML } } - public static function parseString($s, $strict = true) + /** + * Parse XML string + * + * @param string $s + * @param boolean $suppress_log + * @return Object + */ + public static function parseString(string $s, bool $suppress_log = false) { - // the "strict" parameter is deactivated libxml_use_internal_errors(true); $x = @simplexml_load_string($s); if (!$x) { - Logger::error('Error(s) while parsing XML string.', ['callstack' => System::callstack()]); - foreach (libxml_get_errors() as $err) { - Logger::info('libxml error', ['code' => $err->code, 'position' => $err->line . ":" . $err->column, 'message' => $err->message]); + if (!$suppress_log) { + Logger::error('Error(s) while parsing XML string.', ['callstack' => System::callstack()]); + foreach (libxml_get_errors() as $err) { + Logger::info('libxml error', ['code' => $err->code, 'position' => $err->line . ":" . $err->column, 'message' => $err->message]); + } + Logger::debug('Erroring XML string', ['xml' => $s]); } - Logger::debug('Erroring XML string', ['xml' => $s]); libxml_clear_errors(); } return $x; diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 3dd4b8eb4..88f290ab2 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -56,13 +56,13 @@ body a[name]:not([href]) { visibility: hidden; } -body a:hover, .btn-link:hover, .btn:hover, -body a:focus, .btn-link:focus, .btn:focus, -body a:active, .btn-link:active, .btn:active, -body a.active, .btn-link.active, .btn.active { +body a:hover, .btn-link:hover, +body a:focus, .btn-link:focus, +body a:active, .btn-link:active, +body a.active, .btn-link.active { color: $link_hover_color; + outline-color: $link_hover_color;; text-decoration: none; - outline: none; } .wall-item-container a:hover { @@ -197,8 +197,8 @@ blockquote { padding: 8px 16px; color: inherit; } -a.btn:hover { - color: #333; +.btn:focus { + outline-color: $link_hover_color; } .btn-default { @@ -219,17 +219,17 @@ a.btn:hover { padding: 1px 5px; font-size: 12px; } -.btn-primary { - background: $nav_bg !important; - color: $btn_primary_color !important; +.btn.btn-primary { + background: $nav_bg; + color: $btn_primary_color; } -.btn-primary:hover, .btn-primary:focus { +.btn.btn-primary:hover, .btn.btn-primary:focus { + color: $btn_primary_color; background: $btn_primary_hover_color; text-decoration: none; } -.btn-primary:active, .btn-primary.active { - outline: 0; - background: $btn_primary_hover_color !important; +.btn.btn-primary:active, .btn.btn-primary.active { + background: $btn_primary_hover_color; } .btn-primary.active.focus, .btn-primary.active:focus, .btn-primary.active:hover, @@ -262,31 +262,7 @@ a.btn:hover { .btn-separator { border-left: 1px solid #777; } -/*.btn-info { - background: #6fdbe8; - color: #fff!important; -} -.btn-info:hover, .btn-info:focus { - background: #59d6e4!important; - text-decoration: none; -} -.btn-info:active, .btn-info.active { - outline: 0; - background: #59d6e4; -}*/ -.btn-main { - background: $link_color; - color: #fff!important; -} -.btn-main:hover, .btn-main:focus { - background: $link_hover_color !important; - text-decoration: none; -} -.btn-main:active, .btn-main.active { - outline: 0; - background: $link_hover_color; -} .toggle.btn { border: 1px solid transparent; } @@ -2202,19 +2178,13 @@ ul.dropdown-menu li:hover { box-shadow: none; } .form-control:focus { - /*border: 2px solid #6fdbe8;*/ border: 2px solid $link_color; - outline: 0; box-shadow: none; } - .checkbox input[type="checkbox"]:focus + label::before, -.checkbox input[type="radio"]:focus + label::before { - /*border: 2px solid #6fdbe8;*/ - border: 2px solid $link_color; - outline: 0; - box-shadow: none; +.radio input[type="radio"]:focus + label::before { + outline-color: $link_hover_color; } /* Search form */ diff --git a/view/theme/frio/templates/jot.tpl b/view/theme/frio/templates/jot.tpl index 88130c186..e0c602a28 100644 --- a/view/theme/frio/templates/jot.tpl +++ b/view/theme/frio/templates/jot.tpl @@ -1,5 +1,5 @@ {{* The button to open the jot - in This theme we move the button with js to the second nav bar *}} - +
diff --git a/view/theme/frio/templates/searchbox.tpl b/view/theme/frio/templates/searchbox.tpl index ced6fbbd3..945894252 100644 --- a/view/theme/frio/templates/searchbox.tpl +++ b/view/theme/frio/templates/searchbox.tpl @@ -46,7 +46,7 @@ Some parts of this template will be moved by js to other places (see theme.js) -
{{if $s}} - + {{if $mode == "tag"}} {{else}}