You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

220 lines
7.3 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
use Tiki\File\FileHelper;
function wikiplugin_sql_info()
{
return [
'name' => tra('SQL'),
'documentation' => 'PluginSQL',
'description' => tra('Query a MySQL database and display the results'),
'prefs' => [ 'wikiplugin_sql' ],
'body' => tr('The SQL query goes in the body. Example: ') . '<code>SELECT column1, column2 FROM table</code>',
'validate' => 'all',
'iconname' => 'database',
'introduced' => 1,
'extraparams' => true,
'params' => [
'db' => [
'required' => true,
'name' => tra('DSN Name'),
'description' => tr('DSN name of the database being queried. The DSN name needs to first be defined at
%0', '<code>tiki-admin_dsn.php</code>'),
'since' => '1',
'default' => ''
],
'raw' => [
'required' => false,
'name' => tra('Raw return'),
'description' => tra('Return with table formatting (default) or raw data with no table formatting'),
'since' => '11.0',
'default' => '0',
'filter' => 'digits',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Normal'), 'value' => '0'],
['text' => tra('Raw'), 'value' => '1']
]
],
'delim' => [
'required' => false,
'name' => tra('Delim'),
'description' => tr('The delimiter to be used between data elements (sets %0)', '<code>raw=1</code>'),
'since' => '11.0',
],
'wikiparse' => [
'required' => false,
'name' => tra('Wiki Parse'),
'description' => tr('Turn wiki parsing of select results on and off (default is on)'),
'since' => '11.0',
'default' => '1',
'filter' => 'digits',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Off'), 'value' => '0'],
['text' => tra('On'), 'value' => '1']
]
],
'audit' => [
'required' => false,
'name' => tra('Audit'),
'description' => tr('Create a log entry containing information about the SQL call.'),
'since' => '21.2',
'default' => '0',
],
'audit_csv' => [
'required' => false,
'name' => tra('Audit CSV path'),
'description' => tr('If set, a CSV file will be created or appended with information about the SQL call performed.'),
'since' => '21.2',
'filter' => 'text',
'default' => '',
],
]
];
}
function wikiplugin_sql($data, $params)
{
global $tikilib, $prefs, $user;
extract($params, EXTR_SKIP);
if (! isset($db)) {
return tra('Missing db param');
}
$perms = Perms::get([ 'type' => 'dsn', 'object' => $db ]);
if (! $perms->dsn_query) {
return tra('You do not have the permission that is needed to use this feature');
}
$bindvars = [];
$data = html_entity_decode($data);
if ($nb = preg_match_all("/\?/", $data, $out)) {
foreach ($params as $key => $value) {
if (preg_match('/^[0-9]*$/', $key)) {
if (preg_match('/(.*)\[\$([^\]]*)\](.*)/', $value, $variable)) {
$originalVarValue = $varValue = '{{' . $variable[2] . '}}';
$varName = $variable[2];
TikiLib::lib('parser')->parse_wiki_argvariable($varValue);
if ($originalVarValue !== $varValue) {
$bindvars[$key] = $variable[1] . $varValue . $variable[3];
} else {
global $$varName;
$bindvars[$key] = $variable[1] . $$varName . $variable[3];
}
} elseif (strpos($value, "$") === 0) {
$varName = substr($value, 1);
$originalVarValue = $varValue = '{{' . $varName . '}}';
TikiLib::lib('parser')->parse_wiki_argvariable($varName);
if ($originalVarValue !== $varValue) {
$bindvars[$key] = $varValue;
} else {
global $$varName;
$bindvars[$key] = $$varName;
}
} else {
$bindvars[$key] = $value;
}
}
}
if (count($bindvars) != $nb) {
return tra('Missing db param');
}
}
$ret = '';
$sql_oke = true;
$dbmsg = '';
if ($db = $tikilib->get_db_by_name($db)) {
$result = $db->query($data, $bindvars);
} else {
return '~np~' . tra('Could not obtain valid DSN connection.') . '~/np~';
}
$setup_table = ( isset($raw) or isset($delim) ) ? false : true;
$class = 'even';
while ($result && $res = $result->fetchRow()) {
if ($setup_table) {
$ret .= "<table class='normal'><thead><tr>";
$setup_table = false;
foreach (array_keys($res) as $col) {
$ret .= "<th>$col</th>";
}
$ret .= "</tr></thead>";
}
if (! isset($raw) && ! isset($delim)) {
$ret .= "<tr>";
}
if ($class == 'even') {
$class = 'odd';
} else {
$class = 'even';
}
$first_field = true;
foreach ($res as $name => $val) {
if (isset($delim) && ! $first_field) {
$ret .= $delim;
}
if (isset($raw) || isset($delim)) {
$ret .= "$val";
} else {
$ret .= "<td class=\"$class\">$val</td>";
}
$first_field = false;
}
if (! isset($raw) && ! isset($delim)) {
$ret .= "<tr>";
} elseif (isset($delim)) {
$ret .= "<br>";
}
}
if ($ret && ! isset($raw)) {
$ret .= "</table>";
}
if ($dbmsg) {
$ret .= $dbmsg;
}
if (! empty($params['audit'])) {
TikiLib::lib('logs')->add_log('wikiplugin_sql', "Page - " . $_GET['page'] . "\nParameters - " . print_r($bindvars, true));
}
if (! empty($params['audit_csv'])) {
$headers = ['date', 'user', 'page', 'vars'];
$contentRow[] = [
$tikilib->date_format($prefs['short_date_format'] . ' ' . $prefs['long_time_format'], $tikilib->now),
$user,
isset($_GET['page']) ? $_GET['page'] : '',
$bindvars
];
if (! FileHelper::appendCSV($params['audit_csv'], $headers, $contentRow)) {
Feedback::error(tr('Unable to create or open the file "%0" to log the SQL operation,', $params['audit_csv']));
}
}
if ($wikiparse) {
return $ret;
} else {
return '~np~' . $ret . '~/np~';
}
}