PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/mods/event_logging/db.php

https://bitbucket.org/webop/webop-forum
PHP | 508 lines | 309 code | 66 blank | 133 comment | 51 complexity | acbc9aa5c14d9f31fe8944492072064f MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. if(!defined("PHORUM")) return;
  3. // Load the definitions for the constants that we use.
  4. require_once('./mods/event_logging/constants.php');
  5. // The database schema version, which is used to handle
  6. // installation and upgrades directly from the module.
  7. define("EVENT_LOGGING_DB_VERSION", 1);
  8. // The table name for storing event logs.
  9. $GLOBALS["PHORUM"]["event_logging_table"] =
  10. "{$GLOBALS["PHORUM"]["DBCONFIG"]["table_prefix"]}_event_logging";
  11. /**
  12. * This function will check if an upgrade of the database scheme is needed.
  13. * It is generic for all database layers.
  14. */
  15. function event_logging_db_install()
  16. {
  17. $PHORUM = $GLOBALS["PHORUM"];
  18. $version = isset($PHORUM["mod_event_logging_installed"])
  19. ? $PHORUM["mod_event_logging_installed"] : 0;
  20. while ($version < EVENT_LOGGING_DB_VERSION)
  21. {
  22. // Initialize the settings array that we will be saving.
  23. $version++;
  24. $settings = array( "mod_event_logging_installed" => $version );
  25. $sqlfile = "./mods/event_logging/db/" .
  26. $PHORUM["DBCONFIG"]["type"] . "/$version.php";
  27. if (! file_exists($sqlfile)) {
  28. print "<b>Unexpected situation on installing " .
  29. "the Event Logging module</b>: " .
  30. "unable to find the database schema setup script " .
  31. htmlspecialchars($sqlfile);
  32. return false;
  33. }
  34. $sqlqueries = array();
  35. include($sqlfile);
  36. if (count($sqlqueries) == 0) {
  37. print "<b>Unexpected situation on installing " .
  38. "the Event Logging module</b>: could not read any SQL " .
  39. "queries from file " . htmlspecialchars($sqlfile);
  40. return false;
  41. }
  42. $err = phorum_db_run_queries($sqlqueries);
  43. if ($err) {
  44. print "<b>Unexpected situation on installing " .
  45. "the Event Logging module</b>: running the " .
  46. "install queries from file " . htmlspecialchars($sqlfile) .
  47. " failed. The error was " . htmlspecialchars($err);
  48. return false;
  49. }
  50. // Save our settings.
  51. if (!phorum_db_update_settings($settings)) {
  52. print "<b>Unexpected situation on installing " .
  53. "the Event Logging module</b>: updating the " .
  54. "mod_event_logging_installed setting failed";
  55. return false;
  56. }
  57. }
  58. return true;
  59. }
  60. /**
  61. * Write a new message to the event logging table.
  62. *
  63. * This function will automatically fill the log information with
  64. * user_id, ip, hostname (if hostname resolving is enabled for the log module)
  65. * datestamp and vroot information. Other log info can be provided throught
  66. * the $loginfo argument.
  67. *
  68. * @param $loginfo - An array containing logging information. This array
  69. * can contain the following fields:
  70. *
  71. * message A short log message on one line.
  72. * details Details about the log message, which can
  73. * span multiple lines. This could for example
  74. * be used for providing a debug backtrace.
  75. * source The source of the log message. This is a
  76. * free 32 char text field, which can be used
  77. * to specifiy what part of Phorum generated the
  78. * log message (e.g. "mod_smileys"). If no
  79. * source is provided, the "phorum_page"
  80. * constant will be used instead.
  81. * category A high level category for the message.
  82. * Options for this field are:
  83. * EVENTLOG_CAT_APPLICATION (default)
  84. * EVENTLOG_CAT_DATABASE
  85. * EVENTLOG_CAT_SECURITY
  86. * EVENTLOG_CAT_SYSTEM
  87. * EVENTLOG_CAT_MODULE
  88. * loglevel This indicates the severety of the message.
  89. * Options for this field are:
  90. * EVENTLOG_LVL_DEBUG
  91. * Messages that are used by programmers
  92. * for tracking low level Phorum operation.
  93. * EVENTLOG_LVL_INFO
  94. * Messages that provide logging for events
  95. * that occur during normal operation. These
  96. * messages could be harvested for usage
  97. * reporting and other types of reports.
  98. * EVENTLOG_LVL_WARNING
  99. * Warning messages do not indicate errors,
  100. * but they do report events that are not
  101. * considered to belong to normal operation
  102. * (e.g. a user which enters a wrong password
  103. * or a duplicate message being posted).
  104. * EVENTLOG_LVL_ERROR
  105. * Error messages indicate non urgent failures
  106. * in Phorum operation. These should be
  107. * relayed to administrators and/or developers
  108. * to have them solved.
  109. * EVENTLOG_LVL_ALERT
  110. * Alert messages indicate errors which should
  111. * be corrected as soon as possible (e.g. loss
  112. * of network connectivity or a full disk).
  113. * These should be relayed to the system
  114. * administrator).
  115. *
  116. * vroot vroot for which a message is generated.
  117. * forum_id forum_id for which a message is generated.
  118. * thread_id thread_id for which a message is generated
  119. * message_id message_id for which a message is generated
  120. *
  121. * user_id Filled automatically, but can be overridden
  122. * ip Filled automatically, but can be overridden
  123. * hostname Filled automatically, but can be overridden
  124. * datestamp Filled automatically, but can be overridden
  125. */
  126. function event_logging_writelog($loginfo)
  127. {
  128. $PHORUM = $GLOBALS["PHORUM"];
  129. // Check the minimum log level. Only write to the log if the
  130. // log level of the event is at or above the configured minimum.
  131. $lvl = isset($loginfo["loglevel"]) ? (int)$loginfo["loglevel"] : 0;
  132. if ($lvl < $PHORUM["mod_event_logging"]["min_log_level"]) return;
  133. $loginfo = phorum_hook("event_logging_writelog", $loginfo);
  134. // The record that we will insert in the database.
  135. $record = array();
  136. // Handle messages that exceed the maximum message length.
  137. if ($loginfo["message"] !== NULL && strlen($loginfo["message"]) > 255) {
  138. if (!isset($loginfo["details"])) $loginfo["details"] = '';
  139. $loginfo["details"] = "Message:\n\n{$loginfo["message"]}\n\n" .
  140. $loginfo["details"];
  141. $loginfo["message"] = substr($loginfo["message"], 0, 100) . "... (see event details for the full message)\n";
  142. } elseif (isset($loginfo["details"])) {
  143. $loginfo["details"] = "Message:\n\n{$loginfo["message"]}\n\n" .
  144. $loginfo["details"];
  145. }
  146. // Add the fields from the $loginfo argument.
  147. foreach ($loginfo as $key => $val) {
  148. switch ($key)
  149. {
  150. case "datestamp":
  151. case "user_id":
  152. case "vroot":
  153. case "forum_id":
  154. case "thread_id":
  155. case "message_id":
  156. case "category":
  157. case "loglevel":
  158. settype($val, "int");
  159. $record[$key] = $val;
  160. break;
  161. case "message":
  162. case "details":
  163. case "source":
  164. case "ip":
  165. case "hostname":
  166. $record[$key] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $val) . "'";
  167. break;
  168. default: phorum_database_error(
  169. "event_logging_log(): Illegal key " .
  170. "field \"$key\" in the \$loginfo argument"
  171. );
  172. }
  173. }
  174. // Add the message source.
  175. $from_module = FALSE;
  176. if (!isset($record["source"])) {
  177. list($source, $from_module) = event_logging_find_source(1);
  178. $record["source"] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $source) . "'";
  179. }
  180. // Add the category.
  181. if (!isset($record["category"])) {
  182. $record["category"] = $from_module
  183. ? EVENTLOG_CAT_MODULE
  184. : EVENTLOG_CAT_APPLICATION;
  185. }
  186. // Add the datestamp.
  187. if (!isset($record["datestamp"])) {
  188. $record["datestamp"] = time();
  189. }
  190. // Add the IP address for the current visitor.
  191. if (!isset($record["ip"]) && isset($_SERVER["REMOTE_ADDR"])) {
  192. $ip = $_SERVER["REMOTE_ADDR"];
  193. $record["ip"] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $ip) . "'";
  194. }
  195. // Add the hostname for the current visitor.
  196. if (!isset($record["hostname"]) && isset($record["ip"]) &&
  197. $PHORUM["mod_event_logging"]["resolve_hostnames"]) {
  198. $hostname = gethostbyaddr($ip);
  199. if ($hostname != $ip) {
  200. $record["hostname"] = "'" . phorum_db_interact(DB_RETURN_QUOTED, $hostname) . "'";
  201. }
  202. }
  203. // Add the user_id in case the visitor is an authenticated user.
  204. if (!isset($record["user_id"]) &&
  205. isset($PHORUM["user"]["user_id"]) && $PHORUM["user"]["user_id"]) {
  206. $record["user_id"] = $PHORUM["user"]["user_id"];
  207. }
  208. // Add the current vroot.
  209. if (!isset($record["vroot"]) && isset($PHORUM["vroot"])) {
  210. $record["vroot"] = $PHORUM["vroot"];
  211. }
  212. // Insert the logging record in the database.
  213. phorum_db_interact(
  214. DB_RETURN_RES,
  215. "INSERT INTO {$PHORUM["event_logging_table"]}
  216. (".implode(', ', array_keys($record)).")
  217. VALUES (".implode(', ', $record).")",
  218. NULL,
  219. DB_MASTERQUERY
  220. );
  221. }
  222. /**
  223. * This function is used to create a SQL WHERE statement from a filter
  224. * description.
  225. *
  226. * @param $filter - The filter description.
  227. *
  228. * @return $where - A WHERE statement, representing the filter description.
  229. */
  230. function event_logging_create_where($filter)
  231. {
  232. if ($filter === NULL || !is_array($filter)) return '';
  233. $t = $GLOBALS["PHORUM"]["event_logging_table"]; // shorthand
  234. $where_parts = array();
  235. if (isset($filter["loglevels"])) {
  236. $where = '';
  237. if (is_array($filter["loglevels"]) && count($filter["loglevels"]))
  238. {
  239. foreach ($filter["loglevels"] as $id => $l) {
  240. $filter["loglevels"][$id] = (int)$l;
  241. }
  242. $where = count($filter["loglevels"]) == 1
  243. ? "$t.loglevel = " . $filter["loglevels"][0]
  244. : "$t.loglevel IN (".implode(",", $filter["loglevels"]).")";
  245. $where_parts[] = $where;
  246. }
  247. }
  248. if (isset($filter["categories"])) {
  249. $where = '';
  250. if (is_array($filter["categories"]) && count($filter["categories"]))
  251. {
  252. foreach ($filter["categories"] as $id => $l) {
  253. $filter["categories"][$id] = (int)$l;
  254. }
  255. $where = count($filter["categories"]) == 1
  256. ? "$t.category = " . $filter["categories"][0]
  257. : "$t.category IN (".implode(",", $filter["categories"]).")";
  258. $where_parts[] = $where;
  259. }
  260. }
  261. foreach (array(
  262. "source" => "string",
  263. "user_id" => "int",
  264. "username" => "string",
  265. "ip" => "string",
  266. "message" => "string",
  267. "details" => "string",
  268. ) as $field => $type) {
  269. if (isset($filter[$field]) && trim($filter[$field]) != '') {
  270. $val = trim($filter[$field]);
  271. if ($field != 'username') $field = "$t.$field";
  272. if ($type == 'int') {
  273. $where_parts[] = "$field = " . (int) $val;
  274. } else {
  275. if (strstr($val, "*")) {
  276. $val = str_replace('*', '%', $val);
  277. $val = "'" . phorum_db_interact(DB_RETURN_QUOTED, $val) . "'";
  278. $where_parts[] = "$field LIKE $val";
  279. } else {
  280. $val = "'" . phorum_db_interact(DB_RETURN_QUOTED, $val) . "'";
  281. $where_parts[] = "$field = $val";
  282. }
  283. }
  284. }
  285. }
  286. $where = '';
  287. if (count($where_parts) > 0) {
  288. $where = 'WHERE ' . implode(' AND ', $where_parts);
  289. }
  290. return $where;
  291. }
  292. /**
  293. * Return an array of all currently available sources in the event log.
  294. *
  295. * @return $sources - An array of sources. Keys and values are both the
  296. * name of the source.
  297. */
  298. function event_logging_getsources()
  299. {
  300. $PHORUM = $GLOBALS["PHORUM"];
  301. $rows = phorum_db_interact(
  302. DB_RETURN_ASSOCS,
  303. "SELECT DISTINCT(source)
  304. FROM {$PHORUM["event_logging_table"]}
  305. ORDER BY source ASC"
  306. );
  307. $sources = array();
  308. foreach ($rows as $row) {
  309. $sources[$row["source"]] = $row["source"];
  310. }
  311. return $sources;
  312. }
  313. /**
  314. * Count the number of available log lines, either for a filtered or an
  315. * unfiltered view.
  316. *
  317. * @param $filter - The filter to apply or NULL in case there is no filter.
  318. *
  319. * @return $count - The number of log lines.
  320. */
  321. function event_logging_countlogs($filter = NULL)
  322. {
  323. $PHORUM = $GLOBALS["PHORUM"];
  324. $where = event_logging_create_where($filter);
  325. $rows = phorum_db_interact(
  326. DB_RETURN_ASSOCS,
  327. "SELECT count(*) AS count
  328. FROM {$PHORUM["event_logging_table"]}
  329. LEFT JOIN {$PHORUM["user_table"]}
  330. ON {$PHORUM["user_table"]}.user_id = {$PHORUM["event_logging_table"]}.user_id
  331. $where"
  332. );
  333. $count = $rows[0]['count'];
  334. // Limit the maximum number of event logs.
  335. $max = (int)$PHORUM["mod_event_logging"]["max_log_entries"];
  336. if ($max > 0 && $count > $max)
  337. {
  338. // Find the log_id at which we need to chop off old logs.
  339. $rows = phorum_db_interact(
  340. DB_RETURN_ASSOCS,
  341. "SELECT log_id
  342. FROM {$PHORUM["event_logging_table"]}
  343. ORDER BY log_id DESC
  344. LIMIT 1
  345. OFFSET $max"
  346. );
  347. // Delete old logs.
  348. if (isset($rows[0]["log_id"])) {
  349. phorum_db_interact(
  350. DB_RETURN_RES,
  351. "DELETE FROM {$PHORUM["event_logging_table"]}
  352. WHERE log_id <= {$rows[0]["log_id"]}",
  353. NULL,
  354. DB_MASTERQUERY
  355. );
  356. }
  357. $count = $max;
  358. }
  359. return $count;
  360. }
  361. /**
  362. * Retrieve event logs from the database, either for a filtered or an
  363. * unfiltered view.
  364. *
  365. * @param $page - The page number to retrieve logs for.
  366. * @param $pagelength - The number of log messages per page.
  367. * @param $filter - The filter to apply or NULL in case there is no filter.
  368. *
  369. * @return $logs - An array of event logs.
  370. */
  371. function event_logging_getlogs($page = 1, $pagelength = 20, $filter = NULL)
  372. {
  373. $PHORUM = $GLOBALS["PHORUM"];
  374. settype($page, "int");
  375. settype($pagelength, "int");
  376. settype($loglevel, "int");
  377. $offset = ($page-1)*$pagelength;
  378. $where = event_logging_create_where($filter);
  379. $sql = "SELECT {$PHORUM["event_logging_table"]}.log_id AS log_id,
  380. {$PHORUM["event_logging_table"]}.source AS source,
  381. {$PHORUM["event_logging_table"]}.category AS category,
  382. {$PHORUM["event_logging_table"]}.loglevel AS loglevel,
  383. {$PHORUM["event_logging_table"]}.message AS message,
  384. {$PHORUM["event_logging_table"]}.details AS details,
  385. {$PHORUM["event_logging_table"]}.ip AS ip,
  386. {$PHORUM["event_logging_table"]}.hostname AS hostname,
  387. {$PHORUM["event_logging_table"]}.user_id AS user_id,
  388. {$PHORUM["event_logging_table"]}.datestamp AS datestamp,
  389. {$PHORUM["event_logging_table"]}.vroot AS vroot,
  390. {$PHORUM["event_logging_table"]}.forum_id AS forum_id,
  391. {$PHORUM["event_logging_table"]}.thread_id AS thread_id,
  392. {$PHORUM["event_logging_table"]}.message_id AS message_id,
  393. {$PHORUM["user_table"]}.username AS username,
  394. {$PHORUM["user_table"]}.email AS email,
  395. {$PHORUM["forums_table"]}.name AS forum
  396. FROM {$PHORUM["event_logging_table"]}
  397. LEFT JOIN {$PHORUM["user_table"]}
  398. ON {$PHORUM["user_table"]}.user_id = {$PHORUM["event_logging_table"]}.user_id
  399. LEFT JOIN {$PHORUM["forums_table"]}
  400. ON {$PHORUM["forums_table"]}.forum_id = {$PHORUM["event_logging_table"]}.forum_id
  401. $where
  402. ORDER BY log_id DESC";
  403. if ($pagelength > 0) {
  404. $sql .= "
  405. LIMIT $pagelength
  406. OFFSET $offset";
  407. }
  408. return phorum_db_interact(DB_RETURN_ASSOCS, $sql);
  409. }
  410. /**
  411. * Delete logs from the database, possibly using a filter to limit the
  412. * logs that are deleted.
  413. *
  414. * @param $filter - The filter to apply or NULL in case there is no filter.
  415. */
  416. function event_logging_clearlogs($filter = NULL)
  417. {
  418. $PHORUM = $GLOBALS["PHORUM"];
  419. $where = event_logging_create_where($filter);
  420. phorum_db_interact(
  421. DB_RETURN_RES,
  422. "DELETE FROM {$PHORUM["event_logging_table"]} $where",
  423. NULL,
  424. DB_MASTERQUERY
  425. );
  426. }
  427. /**
  428. * Update the forum info for a certain message_id.
  429. */
  430. function event_logging_update_message_id_info($message_id, $forum_id, $thread_id) {
  431. $PHORUM = $GLOBALS["PHORUM"];
  432. phorum_db_interact(
  433. DB_RETURN_RES,
  434. "UPDATE {$PHORUM["event_logging_table"]}
  435. SET forum_id = " . (int)$forum_id . ",
  436. thread_id = " . (int)$thread_id . "
  437. WHERE message_id = " . (int)$message_id,
  438. NULL,
  439. DB_MASTERQUERY
  440. );
  441. }
  442. ?>