summaryrefslogtreecommitdiffstats
path: root/modules-available/syslog
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/syslog')
-rw-r--r--modules-available/syslog/api.inc.php22
-rw-r--r--modules-available/syslog/inc/clientlog.inc.php47
-rw-r--r--modules-available/syslog/lang/de/template-tags.json1
-rw-r--r--modules-available/syslog/lang/en/template-tags.json1
-rw-r--r--modules-available/syslog/page.inc.php84
-rw-r--r--modules-available/syslog/templates/page-syslog.html18
6 files changed, 116 insertions, 57 deletions
diff --git a/modules-available/syslog/api.inc.php b/modules-available/syslog/api.inc.php
index a8a8b0da..cc64b31c 100644
--- a/modules-available/syslog/api.inc.php
+++ b/modules-available/syslog/api.inc.php
@@ -25,7 +25,7 @@ if (($user = Request::post('export-user', false, 'string')) !== false) {
unset($best);
foreach ($srcs as &$src) {
if (!isset($src['row'])) {
- $src['row'] = $src['res']->fetch(PDO::FETCH_ASSOC);
+ $src['row'] = $src['res']->fetch();
}
if ($src['row'] !== false && (!isset($best) || $src['row']['dateline'] < $best['dateline'])) {
$best =& $src['row'];
@@ -64,25 +64,17 @@ $longdesc = '';
if (isset($_POST['longdesc'])) $longdesc = $_POST['longdesc'];
$longdesc = Request::post('longdesc', '', 'string');
-if ($type{0} !== '.' && $type{0} !== '~') {
+if (preg_match('/^[a-z0-9\-]+$/', $type)) {
- // Spam from IP
- $row = Database::queryFirst('SELECT Count(*) AS cnt FROM clientlog WHERE clientip = :client AND dateline + 1800 > UNIX_TIMESTAMP()', array(':client' => $ip));
+ // Spam from IP?
+ $row = Database::queryFirst('SELECT Count(*) AS cnt FROM clientlog
+ WHERE clientip = :client AND dateline + 1800 > UNIX_TIMESTAMP()',
+ [':client' => $ip]);
if ($row !== false && $row['cnt'] > 250) {
exit(0);
}
- $ret = Database::exec('INSERT INTO clientlog (dateline, logtypeid, clientip, machineuuid, description, extra) VALUES (UNIX_TIMESTAMP(), :type, :client, :uuid, :description, :longdesc)', array(
- 'type' => $type,
- 'client' => $ip,
- 'description' => $description,
- 'longdesc' => $longdesc,
- 'uuid' => $uuid,
- ), true);
- if ($ret === false) {
- error_log("Constraint failed for client log from $uuid for $type : $description");
- die("NOPE.\n");
- }
+ ClientLog::write(['machineuuid' => $uuid, 'clientip' => $ip], $type, $description, $longdesc);
}
diff --git a/modules-available/syslog/inc/clientlog.inc.php b/modules-available/syslog/inc/clientlog.inc.php
new file mode 100644
index 00000000..b38c29fe
--- /dev/null
+++ b/modules-available/syslog/inc/clientlog.inc.php
@@ -0,0 +1,47 @@
+<?php
+
+class ClientLog
+{
+
+ public static function write(array $client, string $type, string $description, string $longDesc = ''): bool
+ {
+ if (!isset($client['machineuuid']) && !isset($client['clientip'])) {
+ error_log("Bad clientlog write call: " . json_encode($client));
+ return false;
+ }
+ if (!isset($client['machineuuid'])) {
+ $res = Database::queryFirst("SELECT machineuuid FROM machine WHERE clientip = :ip
+ ORDER BY lastseen DESC LIMIT 1", ['ip' => $client['clientip']]);
+ if ($res === false) {
+ error_log("Invalid client IP for client log: " . $client['clientip']);
+ return false;
+ }
+ $client['machineuuid'] = $res['machineuuid'];
+ }
+ if (!isset($client['clientip'])) {
+ $res = Database::queryFirst("SELECT clientip FROM machine WHERE machineuuid = :uuid",
+ ['uuid' => $client['machineuuid']]);
+ if ($res === false) {
+ error_log("Invalid machine uuid for client log: " . $client['machineuuid']);
+ return false;
+ }
+ $client['clientip'] = $res['clientip'];
+ }
+ $data = [
+ 'type' => $type,
+ 'clientip' => $client['clientip'],
+ 'description' => $description,
+ 'extra' => $longDesc,
+ 'machineuuid' => $client['machineuuid'],
+ ];
+ $res = Database::exec('INSERT INTO clientlog (dateline, logtypeid, clientip, machineuuid, description, extra)
+ VALUES (UNIX_TIMESTAMP(), :type, :clientip, :machineuuid, :description, :extra)', $data, true);
+ if ($res === false) {
+ error_log("Constraint failed for client log from {$client['machineuuid']} for $type : $description");
+ return false;
+ }
+ EventLog::applyFilterRules($type, $data + $client);
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/syslog/lang/de/template-tags.json b/modules-available/syslog/lang/de/template-tags.json
index c00d619a..90d0a294 100644
--- a/modules-available/syslog/lang/de/template-tags.json
+++ b/modules-available/syslog/lang/de/template-tags.json
@@ -9,6 +9,7 @@
"lang_exportUserDesc": "Mit dieser Funktion k\u00f6nnen Sie alle in der Datenbank vorhandenen Datens\u00e4tze zu einem bestimmten Benutzer exportieren. Bitte geben Sie den Benutzernamen genau so ein, wie ihn der Nutzer beim Login am Client angeben muss.",
"lang_filter": "Filter",
"lang_not": "not",
+ "lang_searchString": "Suchbegriff",
"lang_settings": "Einstellungen",
"lang_userExport": "Nutzer-Export",
"lang_userLogin": "Benutzer-Login",
diff --git a/modules-available/syslog/lang/en/template-tags.json b/modules-available/syslog/lang/en/template-tags.json
index 24e9aaa1..725f7e94 100644
--- a/modules-available/syslog/lang/en/template-tags.json
+++ b/modules-available/syslog/lang/en/template-tags.json
@@ -9,6 +9,7 @@
"lang_exportUserDesc": "This exports all data from the database relating to the given user login. Please specify the user name exactly the way they would provide it when logging in on a client.",
"lang_filter": "Filter",
"lang_not": "not",
+ "lang_searchString": "Search term",
"lang_settings": "Settings",
"lang_userExport": "User export",
"lang_userLogin": "User login",
diff --git a/modules-available/syslog/page.inc.php b/modules-available/syslog/page.inc.php
index 6c1a0a16..401d9dd8 100644
--- a/modules-available/syslog/page.inc.php
+++ b/modules-available/syslog/page.inc.php
@@ -25,6 +25,20 @@ class Page_SysLog extends Page
}
Util::redirect('?do=syslog');
}
+ if (Request::isPost()) {
+ $pairs = [];
+ foreach (['search', 'filter', 'not', 'machineuuid'] as $key) {
+ $val = Request::any($key, false, 'string');
+ if (!empty($val)) {
+ if ($key === 'not') {
+ $val = (bool)$val;
+ }
+ $pairs[$key] = $val;
+ }
+ Session::set('log_' . $key, $pairs[$key] ?? false, false);
+ }
+ Util::redirect('?do=syslog&' . http_build_query($pairs));
+ }
User::assertPermission('*');
}
@@ -40,64 +54,63 @@ class Page_SysLog extends Page
}
$cutoff = strtotime('-1 month');
- $res = Database::simpleQuery("SELECT logtypeid, Count(*) AS counter FROM clientlog WHERE dateline > $cutoff GROUP BY logtypeid ORDER BY counter ASC");
+ $res = Database::simpleQuery("SELECT logtypeid, Count(*) AS counter
+ FROM clientlog
+ WHERE dateline > $cutoff
+ GROUP BY logtypeid ORDER BY counter ASC");
$types = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$types[$row['logtypeid']] = $row;
}
- if (Request::get('filter') !== false) {
+ if (Request::get('filter') !== false || Request::get('search') !== false) {
+ $search = Request::get('search');
$filter = Request::get('filter');
- $not = Request::get('not') ? 'NOT' : '';
- } elseif (Request::post('filter') !== false) {
- $filter = Request::post('filter');
- $not = Request::post('not') ? 'NOT' : '';
-
- Session::set('log_filter', $filter);
- Session::set('log_not', $not);
- Session::save();
+ $not = Request::get('not', false, 'bool');
} else {
+ $search = Session::get('log_search');
$filter = Session::get('log_filter');
- $not = Session::get('log_not') ? 'NOT' : '';
+ $not = (bool)Session::get('log_not');
}
+ $qArgs = [];
+ $whereClause = '1';
if (!empty($filter)) {
- $filterList = explode(',', $filter);
- $whereClause = array();
+ $whereClause .= ' AND ( ';
+ if ($not) {
+ $whereClause .= 'NOT ';
+ }
+ $filterList = array_unique(explode(',', $filter));
foreach ($filterList as $filterItem) {
- $filterItem = preg_replace('/[^a-z0-9_\-]/', '', trim($filterItem));
- if (empty($filterItem) || in_array($filterItem, $whereClause)) continue;
- $whereClause[] = "'$filterItem'";
if (!isset($types[$filterItem])) {
$types[$filterItem] = ['logtypeid' => $filterItem, 'counter' => ''];
}
}
- if (!empty($whereClause)) $whereClause = ' WHERE logtypeid ' . $not . ' IN (' . implode(', ', $whereClause) . ')';
+ $whereClause .= "logtypeid IN (:typeids) )";
+ $qArgs['typeids'] = $filterList;
+ }
+ if (!empty($search)) {
+ $qArgs['search'] = '%' . str_replace(array('=', '_', '%', '*', '?'), array('==', '=_', '=%', '%', '_'), $search) . '%';
+ $whereClause .= " AND description LIKE :search ESCAPE '='";
}
- if (!isset($whereClause) || empty($whereClause)) $whereClause = '';
if (Request::get('machineuuid')) {
- if (empty($whereClause))
- $whereClause .= ' WHERE ';
- else
- $whereClause .= ' AND ';
-
- $whereClause .= "machineuuid='" . preg_replace('/[^0-9a-zA-Z\-]/', '', Request::get('machineuuid', '', 'string')) . "'";
+ $whereClause .= " AND machineuuid = :uuid";
+ $qArgs['uuid'] = Request::get('machineuuid', '', 'string');
}
$allowedLocations = User::getAllowedLocations("view");
$joinClause = "";
if (!in_array(0, $allowedLocations)) {
$joinClause = "INNER JOIN machine USING (machineuuid)";
- if (empty($whereClause))
- $whereClause .= ' WHERE ';
- else
- $whereClause .= ' AND ';
-
- $whereClause .= 'locationid IN (:allowedLocations)';
+ $whereClause .= ' AND locationid IN (:allowedLocations)';
+ $qArgs['allowedLocations'] = $allowedLocations;
}
$lines = array();
- $paginate = new Paginate("SELECT logid, dateline, logtypeid, clientlog.clientip, clientlog.machineuuid, description, extra FROM clientlog $joinClause $whereClause ORDER BY logid DESC", 50);
- $res = $paginate->exec(array("allowedLocations" => $allowedLocations));
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $paginate = new Paginate("SELECT logid, dateline, logtypeid, clientlog.clientip, clientlog.machineuuid, description, extra
+ FROM clientlog $joinClause
+ WHERE $whereClause
+ ORDER BY logid DESC", 50);
+ $res = $paginate->exec($qArgs);
+ foreach ($res as $row) {
$row['date'] = Util::prettyTime($row['dateline']);
$row['icon'] = $this->eventToIconName($row['logtypeid']);
$lines[] = $row;
@@ -105,6 +118,7 @@ class Page_SysLog extends Page
$paginate->render('page-syslog', array(
'filter' => $filter,
+ 'search' => $search,
'not' => $not,
'list' => $lines,
'types' => json_encode(array_values($types)),
@@ -112,7 +126,7 @@ class Page_SysLog extends Page
));
}
- private function eventToIconName($event)
+ private function eventToIconName(string $event): string
{
switch ($event) {
case 'session-open':
diff --git a/modules-available/syslog/templates/page-syslog.html b/modules-available/syslog/templates/page-syslog.html
index 9d05d434..2b7c1439 100644
--- a/modules-available/syslog/templates/page-syslog.html
+++ b/modules-available/syslog/templates/page-syslog.html
@@ -3,8 +3,9 @@
max-width: 500px;
}
</style>
-<form method="post" action="?do=SysLog{{#machineuuid}}&machineuuid={{machineuuid}}{{/machineuuid}}">
+<form method="post" action="?do=syslog">
<input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="machineuuid" value="{{machineuuid}}">
<div class="pull-left">
<label for="filterstring">{{lang_filter}}</label>
</div>
@@ -12,6 +13,11 @@
<div class="row">
+ <div class="col-sm-11">
+ <div>
+ <input class="form-control" id="filterstring" placeholder="id" value="{{filter}}" name="filter">
+ </div>
+ </div>
<div class="col-sm-1">
<div class="checkbox">
<input id="notbox" type="checkbox" name="not" {{#not}}checked="checked"{{/not}}>
@@ -19,12 +25,10 @@
</div>
</div>
<div class="col-sm-11">
- <div class="input-group">
- <input id="filterstring" placeholder="id" value="{{filter}}" name="filter">
- <span style="padding-bottom: 5px;" class="input-group-btn">
- <button class="btn btn-primary" type="submit">{{lang_applyFilter}}</button>
- </span>
- </div>
+ <input class="form-control" placeholder="{{lang_searchString}}" value="{{search}}" name="search">
+ </div>
+ <div class="col-sm-1">
+ <button class="btn btn-primary" type="submit">{{lang_applyFilter}}</button>
</div>
</div>
</form>