PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/functions.inc.php

https://github.com/sitracker/sitracker
PHP | 1850 lines | 1442 code | 147 blank | 261 comment | 205 complexity | 396dc7683ca9679654cad2066a3d1801 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. //
  3. // functions.inc.php - Function library and defines for SiT -Support Incident Tracker
  4. //
  5. // SiT (Support Incident Tracker) - Support call tracking system
  6. // Copyright (C) 2010-2014 The Support Incident Tracker Project
  7. // Copyright (C) 2000-2009 Salford Software Ltd. and Contributors
  8. //
  9. // This software may be used and distributed according to the terms
  10. // of the GNU General Public License, incorporated herein by reference.
  11. //
  12. // Authors: Ivan Lucas, <ivan[at]sitracker.org>
  13. // Tom Gerrard, <tomgerrard[at]users.sourceforge.net> - 2001 onwards
  14. // Martin Kilcoyne - 2000
  15. // Paul Heaney, <paul[at]sitracker.org>
  16. // Kieran Hogg, <kieran[at]sitracker.org>
  17. // Many functions here simply extract various snippets of information from
  18. // Most are legacy and can replaced by improving the pages that call them to
  19. // use SQL joins.
  20. // Prevent script from being run directly (ie. it must always be included
  21. if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))
  22. {
  23. exit;
  24. }
  25. include (APPLICATION_LIBPATH . 'classes.inc.php');
  26. include (APPLICATION_LIBPATH . 'group.class.php');
  27. include (APPLICATION_LIBPATH . 'user.class.php');
  28. include (APPLICATION_LIBPATH . 'contact.class.php');
  29. include (APPLICATION_LIBPATH . 'incident.class.php');
  30. include (APPLICATION_LIBPATH . 'status.class.php');
  31. include (APPLICATION_LIBPATH . 'sla.class.php');
  32. include_once (APPLICATION_LIBPATH . 'file.inc.php');
  33. include (APPLICATION_LIBPATH . 'ldap.inc.php');
  34. include (APPLICATION_LIBPATH . 'base.inc.php');
  35. include_once (APPLICATION_LIBPATH . 'array.inc.php');
  36. include_once (APPLICATION_LIBPATH . 'datetime.inc.php');
  37. include_once (APPLICATION_LIBPATH . 'billing.inc.php');
  38. include_once (APPLICATION_LIBPATH . 'billing_unused.inc.php');
  39. include_once (APPLICATION_LIBPATH . 'user.inc.php');
  40. include_once (APPLICATION_LIBPATH . 'sla.inc.php');
  41. include_once (APPLICATION_LIBPATH . 'tags.inc.php');
  42. include_once (APPLICATION_LIBPATH . 'string.inc.php');
  43. include_once (APPLICATION_LIBPATH . 'html_drop_downs.inc.php');
  44. include_once (APPLICATION_LIBPATH . 'html.inc.php');
  45. include_once (APPLICATION_LIBPATH . 'incident_html.inc.php');
  46. include_once (APPLICATION_LIBPATH . 'tasks.inc.php');
  47. include_once (APPLICATION_LIBPATH . 'export.inc.php');
  48. include_once (APPLICATION_LIBPATH . 'contact.inc.php');
  49. include_once (APPLICATION_LIBPATH . 'contract.inc.php');
  50. include_once (APPLICATION_LIBPATH . 'journal.inc.php');
  51. include_once (APPLICATION_LIBPATH . 'kb.inc.php');
  52. include_once (APPLICATION_LIBPATH . 'feedback.inc.php');
  53. include_once (APPLICATION_LIBPATH . 'site.inc.php');
  54. include_once (APPLICATION_LIBPATH . 'configfuncs.inc.php');
  55. include_once (APPLICATION_LIBPATH . 'incident.inc.php');
  56. if (version_compare(PHP_VERSION, "5.1.0", ">="))
  57. {
  58. date_default_timezone_set($CONFIG['timezone']);
  59. }
  60. /**
  61. * Authenticate a user
  62. * @author Lea Anthony
  63. * @param string $username. Username
  64. * @param string $password. Password
  65. * @return an integer to indicate whether the user authenticated against any authentication backends
  66. * @retval bool false the credentials were wrong or the user was not found.
  67. * @retval bool true to indicate user is authenticated and allowed to continue.
  68. */
  69. function authenticate($username, $password)
  70. {
  71. global $CONFIG, $db;
  72. $toReturn = false;
  73. if (!empty($username) AND !empty($password))
  74. {
  75. $sql = "SELECT id, password, status, user_source FROM `{$GLOBALS['dbUsers']}` WHERE username = '{$username}'";
  76. $result = mysqli_query($db, $sql);
  77. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  78. if (mysqli_num_rows($result) == 1)
  79. {
  80. // Exist in SiT DB
  81. $obj = mysqli_fetch_object( $result);
  82. if ($obj->user_source == 'sit')
  83. {
  84. if (md5($password) == $obj->password AND $obj->status != 0) $toReturn = true;
  85. else $toReturn = false;
  86. }
  87. elseif ($obj->user_source == 'ldap')
  88. {
  89. // Auth against LDAP and sync
  90. $toReturn = authenticateLDAP(clean_ldapstring(($username)), $password, $obj->id);
  91. if ($toReturn === -1)
  92. {
  93. // Communication with LDAP server failed
  94. if ($CONFIG['ldap_allow_cached_password'])
  95. {
  96. // Use cached password
  97. if (md5($password) == $obj->password AND $obj->status != 0) $toReturn = true;
  98. else $toReturn = false;
  99. }
  100. else
  101. {
  102. $toReturn = false;
  103. }
  104. }
  105. elseif ($toReturn)
  106. {
  107. $toReturn = true;
  108. }
  109. else
  110. {
  111. $toReturn = false;
  112. }
  113. }
  114. }
  115. elseif (mysqli_num_rows($result) > 1)
  116. {
  117. // Multiple this should NEVER happen
  118. trigger_error("Username not unique", E_USER_ERROR);
  119. $toReturn = false;
  120. }
  121. else
  122. {
  123. // Don't exist, check LDAP etc
  124. if ($CONFIG['use_ldap'])
  125. {
  126. $toReturn = authenticateLDAP($username, $password);
  127. if ($toReturn === -1) $toReturn = false;
  128. }
  129. }
  130. if ($toReturn)
  131. {
  132. journal(CFG_LOGGING_MAX,'User Authenticated',"{$username} authenticated from " . substr($_SERVER['REMOTE_ADDR'], 0, 15), CFG_JOURNAL_LOGIN, 0);
  133. debug_log ("Authenticate: User authenticated",TRUE);
  134. }
  135. else
  136. {
  137. debug_log ("authenticate: User NOT authenticated",TRUE);
  138. }
  139. }
  140. else
  141. {
  142. debug_log ("Blank username or password for user thus denying access");
  143. $toReturn = false;
  144. }
  145. return $toReturn;
  146. }
  147. /**
  148. * Authenticates a contact
  149. * @param string $username
  150. * @param string $password
  151. * @return mixed returns contactID if successful false otherwise
  152. */
  153. function authenticateContact($username, $password)
  154. {
  155. debug_log ("authenticateContact called");
  156. global $CONFIG, $db;
  157. $toReturn = false;
  158. if (!empty($username) AND !empty($password))
  159. {
  160. $sql = "SELECT id, password, contact_source, active, username FROM `{$GLOBALS['dbContacts']}` WHERE (username = '{$username}' OR email = '{$username}')";
  161. $result = mysqli_query($db, $sql);
  162. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  163. if (mysqli_num_rows($result) == 1)
  164. {
  165. debug_log ("Authenticate: Just one contact in db");
  166. // Exists in SiT DB
  167. $obj = mysqli_fetch_object( $result);
  168. if ($obj->contact_source == 'sit')
  169. {
  170. if ((md5($password) == $obj->password OR $password == $obj->password) AND $obj->active == 'true') $toReturn = $obj->id;
  171. else $toReturn = false;
  172. }
  173. elseif ($obj->contact_source == 'ldap')
  174. {
  175. // Auth against LDAP and sync
  176. $toReturn = authenticateLDAP($username, $password, $obj->id, false);
  177. if ($toReturn === -1)
  178. {
  179. // Communication with LDAP server failed
  180. if ($CONFIG['ldap_allow_cached_password'])
  181. {
  182. debug_log ("LDAP connection failed, using cached password");
  183. // Use cached password
  184. if ((md5($password) == $obj->password OR $password == $obj->password) AND $obj->active == 'true') $toReturn = $obj->id;
  185. else $toReturn = false;
  186. debug_log ("Cached contact {$toReturn} {$password}");
  187. }
  188. else
  189. {
  190. debug_log ("Cached passwords are not enabled");
  191. $toReturn = false;
  192. }
  193. }
  194. elseif ($toReturn)
  195. {
  196. $toReturn = $obj->id;
  197. }
  198. else
  199. {
  200. $toReturn = false;
  201. }
  202. }
  203. else
  204. {
  205. debug_log ("Source SOMETHING ELSE this shouldn't happen'");
  206. $toReturn = false;
  207. }
  208. }
  209. elseif (mysqli_num_rows($result) > 1)
  210. {
  211. debug_log ("Multiple");
  212. // Multiple this should NEVER happen
  213. trigger_error($GLOBALS['strUsernameNotUnique'], E_USER_ERROR);
  214. $toReturn = false;
  215. }
  216. else
  217. {
  218. debug_log ("Authenticate: No matching contact '{$username}' found in db");
  219. // Don't exist, check LDAP etc
  220. if ($CONFIG['use_ldap'] AND !empty($CONFIG['ldap_customer_group']))
  221. {
  222. $toReturn = authenticateLDAP($username, $password, 0, false);
  223. if ($toReturn === -1) $toReturn = false;
  224. }
  225. }
  226. }
  227. else
  228. {
  229. debug_log ("Blank username or password for user thus denying access");
  230. $toReturn = false;
  231. }
  232. debug_log ("authenticateContact returning {$toReturn}");
  233. return $toReturn;
  234. }
  235. /**
  236. * Authenticates a user when trusted server mode is enabled
  237. * @author Paul Heaney
  238. * @return mixed username if valid, false otherwise
  239. */
  240. function authenticateTrustedServerMode()
  241. {
  242. global $CONFIG, $db;
  243. $toReturn = false;
  244. if ($CONFIG['trusted_server'])
  245. {
  246. if (trustedServerValidateBasicAuth())
  247. {
  248. $username = $_SERVER["HTTP_".strtoupper($CONFIG['trusted_server_username_header'])];
  249. debug_log("Headers received ".print_r($_SERVER, true));
  250. $sql = "SELECT id, password, status, user_source, username FROM `{$GLOBALS['dbUsers']}` WHERE username = '{$username}'";
  251. $result = mysqli_query($db, $sql);
  252. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  253. if (mysqli_num_rows($result) == 1)
  254. {
  255. // Exists in SiT DB
  256. $obj = mysqli_fetch_object( $result);
  257. $toReturn = $obj->username;
  258. }
  259. if ($toReturn)
  260. {
  261. debug_log ("authenticateTrustedServerMode: User authenticated via trusted server", TRUE);
  262. }
  263. else
  264. {
  265. debug_log ("authenticateTrustedServerMode: User NOT authenticated via trusted server", TRUE);
  266. }
  267. }
  268. else
  269. {
  270. debug_log("authenticateTrustedServerMode: credentials used to identify trusted server invalid");
  271. $toReturn = false;
  272. }
  273. }
  274. else
  275. {
  276. debug_log("authenticateTrustedServerModeContact called and trusted_server mode disabled");
  277. $toReturn = false;
  278. }
  279. return $toReturn;
  280. }
  281. /**
  282. * Authenticates a contact when trusted server mode is enabled
  283. * @author Paul Heaney
  284. * @return mixed contact id if valid, false otherwise
  285. */
  286. function authenticateTrustedServerModeContact()
  287. {
  288. global $CONFIG, $db;
  289. $toReturn = false;
  290. if ($CONFIG['trusted_server'])
  291. {
  292. if (trustedServerValidateBasicAuth())
  293. {
  294. $username = $_SERVER["HTTP_".strtoupper($CONFIG['trusted_server_username_header'])];
  295. $sql = "SELECT id, password, contact_source, active, username FROM `{$GLOBALS['dbContacts']}` WHERE (username = '{$username}' OR email = '{$username}')";
  296. $result = mysqli_query($db, $sql);
  297. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  298. if (mysqli_num_rows($result) == 1)
  299. {
  300. // Exists in SiT DB
  301. $obj = mysqli_fetch_object( $result);
  302. $toReturn = $obj->id;
  303. if ($CONFIG['contact_jit_provision'])
  304. {
  305. // Then we need to update
  306. $contact = new Contact($toReturn);
  307. foreach ($CONFIG['contact_jit_mapping'] AS $header => $field)
  308. {
  309. $value = $_SERVER["HTTP_".strtoupper($header)];
  310. debug_log("Setting field '" . $field . "' to '" . $value . "'");
  311. $contact->$field = $value;
  312. }
  313. // Don't need to ensure valid fields as contact class does that
  314. debug_log("Updating contact '" . $toReturn . "'");
  315. $contact->edit();
  316. }
  317. }
  318. else if (mysqli_num_rows($result) == 0 AND $CONFIG['contact_jit_provision'])
  319. {
  320. // we can create
  321. debug_log("Contact mapping headers are: " . print_r($CONFIG['contact_jit_mapping'], true));
  322. $contracts = null;
  323. $contact = new Contact();
  324. foreach ($CONFIG['contact_jit_mapping'] AS $header => $field)
  325. {
  326. $value = $_SERVER["HTTP_".strtoupper($header)];
  327. debug_log("Setting field '" . $field . "' to '" . $value . "'");
  328. if ($header == 'contractids') $contracts = $value;
  329. else $contact->$field = $value;
  330. }
  331. $contact->source = "jit";
  332. // Don't need to ensure valid fields as contact class does that
  333. debug_log("Adding contact");
  334. $toReturn = $contact->add();
  335. if (!empty($contracts) AND !empty($toReturn))
  336. {
  337. $contractids = explode(",", $contracts);
  338. foreach ($contractids AS $id)
  339. {
  340. $id = clean_int($id);
  341. $sql = "INSERT INTO `{$GLOBALS['dbSupportContacts']}` (maintenanceid, contactid) VALUES ({$id}, {$toReturn})";
  342. $result = mysqli_query($db, $sql);
  343. if (mysqli_error($db)) trigger_error("MySQL Query Error ".mysqli_error($db), E_USER_ERROR);
  344. }
  345. }
  346. }
  347. if ($toReturn)
  348. {
  349. journal(CFG_LOGGING_MAX,'Contact Authenticated',"{$username} authenticated from " . substr($_SERVER['REMOTE_ADDR']." via trusted server", 0, 15), CFG_JOURNAL_LOGIN, 0);
  350. debug_log ("authenticateTrustedServerModeContact: User authenticated via trusted server", TRUE);
  351. }
  352. else
  353. {
  354. debug_log ("authenticateTrustedServerModeContact: Contact NOT authenticated via trusted server", TRUE);
  355. }
  356. }
  357. else
  358. {
  359. debug_log("authenticateTrustedServerModeContact: credentials used to identify trusted server invalid");
  360. $toReturn = false;
  361. }
  362. }
  363. else
  364. {
  365. debug_log("authenticateTrustedServerModeContact called and trusted_server mode disabled");
  366. $toReturn = false;
  367. }
  368. return $toReturn;
  369. }
  370. /**
  371. * Creates valid user session within SiT!
  372. * @param string $username The username to create a session for
  373. */
  374. function createUserSession($username)
  375. {
  376. global $CONFIG, $db;
  377. $_SESSION['auth'] = TRUE;
  378. // Retrieve users profile
  379. $sql = "SELECT id, username, realname, email, groupid, user_source FROM `{$GLOBALS['dbUsers']}` WHERE username='{$username}' LIMIT 1";
  380. $result = mysqli_query($db, $sql);
  381. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  382. if (mysqli_num_rows($result) < 1)
  383. {
  384. $_SESSION['auth'] = FALSE;
  385. trigger_error("No such user", E_USER_ERROR);
  386. }
  387. $user = mysqli_fetch_object( $result);
  388. // Profile
  389. $_SESSION['userid'] = $user->id;
  390. $_SESSION['username'] = $user->username;
  391. $_SESSION['realname'] = $user->realname;
  392. $_SESSION['email'] = $user->email;
  393. $_SESSION['groupid'] = is_null($user->groupid) ? 0 : $user->groupid;
  394. $_SESSION['portalauth'] = FALSE;
  395. $_SESSION['user_source'] = $user->user_source;
  396. if (!is_null($_SESSION['startdate'])) $_SESSION['startdate'] = $user->user_startdate;
  397. // Read user config from database
  398. $_SESSION['userconfig'] = get_user_config_vars($user->id);
  399. // Make sure utc_offset cannot be blank
  400. if ($_SESSION['userconfig']['utc_offset'] == '')
  401. {
  402. $_SESSION['userconfig']['utc_offset'] == 0;
  403. }
  404. // Defaults
  405. if (empty($_SESSION['userconfig']['theme']))
  406. {
  407. $_SESSION['userconfig']['theme'] = $CONFIG['default_interface_style'];
  408. }
  409. if (empty($_SESSION['userconfig']['iconset']))
  410. {
  411. $_SESSION['userconfig']['iconset'] = $CONFIG['default_iconset'];
  412. }
  413. // Delete any old session user notices
  414. $sql = "DELETE FROM `{$GLOBALS['dbNotices']}` WHERE durability='session' AND userid = {$_SESSION['userid']}";
  415. mysqli_query($db, $sql);
  416. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_ERROR);
  417. //check if the session lang is different the their profiles
  418. if ($_SESSION['lang'] != '' AND !empty($_SESSION['userconfig']['language']) AND
  419. $_SESSION['lang'] != $_SESSION['userconfig']['language'])
  420. {
  421. $t = new TriggerEvent('TRIGGER_LANGUAGE_DIFFERS', array('profilelang' => $_SESSION['userconfig']['language'],
  422. 'currentlang' => $_SESSION['lang'], 'user' => $_SESSION['userid']));
  423. }
  424. if ($_SESSION['userconfig']['language'] != $CONFIG['default_i18n'] AND $_SESSION['lang'] == '')
  425. {
  426. $_SESSION['lang'] = is_null($_SESSION['userconfig']['language']) ? '' : $_SESSION['userconfig']['language'];
  427. }
  428. // Make an array full of users permissions
  429. // The zero permission is added to all users, zero means everybody can access
  430. $userpermissions[] = 0;
  431. // First lookup the role permissions
  432. $sql = "SELECT * FROM `{$GLOBALS['dbUsers']}` AS u, `{$GLOBALS['dbRolePermissions']}` AS rp WHERE u.roleid = rp.roleid ";
  433. $sql .= "AND u.id = '{$_SESSION['userid']}' AND granted='true'";
  434. $result = mysqli_query($db, $sql);
  435. if (mysqli_error($db))
  436. {
  437. $_SESSION['auth'] = FALSE;
  438. trigger_error(mysqli_error($db), E_USER_ERROR);
  439. }
  440. if (mysqli_num_rows($result) >= 1)
  441. {
  442. while ($perm = mysqli_fetch_object( $result))
  443. {
  444. $userpermissions[] = $perm->permissionid;
  445. }
  446. }
  447. // Next lookup the individual users permissions
  448. $sql = "SELECT * FROM `{$GLOBALS['dbUserPermissions']}` WHERE userid = '{$_SESSION['userid']}' AND granted='true' ";
  449. $result = mysqli_query($db, $sql);
  450. if (mysqli_error($db))
  451. {
  452. $_SESSION['auth'] = FALSE;
  453. trigger_error(mysqli_error($db), E_USER_ERROR);
  454. }
  455. if (mysqli_num_rows($result) >= 1)
  456. {
  457. while ($perm = mysqli_fetch_object( $result))
  458. {
  459. $userpermissions[] = $perm->permissionid;
  460. }
  461. }
  462. $_SESSION['permissions'] = array_unique($userpermissions);
  463. }
  464. /**
  465. * Creates valid contact session within SiT!
  466. * @param int $contactid The ID of the contact
  467. */
  468. function createContactSession($contactid)
  469. {
  470. global $CONFIG, $db;
  471. debug_log("PORTAL AUTH SUCESSFUL");
  472. $_SESSION['portalauth'] = TRUE;
  473. $sql = "SELECT * FROM `{$GLOBALS['dbContacts']}` WHERE id = '{$contactid}'";
  474. $result = mysqli_query($db, $sql);
  475. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  476. if (mysqli_num_rows($result) < 1)
  477. {
  478. $_SESSION['portalauth'] = FALSE;
  479. trigger_error("No such user", E_USER_ERROR);
  480. }
  481. $contact = mysqli_fetch_object( $result);
  482. // Customer session
  483. // Valid user
  484. $_SESSION['contactid'] = $contact->id;
  485. $_SESSION['siteid'] = $contact->siteid;
  486. $_SESSION['userconfig']['theme'] = $CONFIG['portal_interface_style'];
  487. $_SESSION['userconfig']['iconset'] = $CONFIG['portal_iconset'];
  488. $_SESSION['contracts'] = array();
  489. $_SESSION['auth'] = FALSE;
  490. $_SESSION['contact_source'] = $contact->contact_source;
  491. //get admin contracts
  492. if (admin_contact_contracts($_SESSION['contactid'], $_SESSION['siteid']) != NULL)
  493. {
  494. $admincontracts = admin_contact_contracts($_SESSION['contactid'], $_SESSION['siteid']);
  495. $_SESSION['usertype'] = 'admin';
  496. }
  497. //get named contact contracts
  498. if (contact_contracts($_SESSION['contactid'], $_SESSION['siteid'], false) != NULL)
  499. {
  500. $contactcontracts = contact_contracts($_SESSION['contactid'], $_SESSION['siteid'], false);
  501. if (!isset($_SESSION['usertype']))
  502. {
  503. $_SESSION['usertype'] = 'contact';
  504. }
  505. }
  506. //get other contracts
  507. if (all_contact_contracts($_SESSION['siteid']) != NULL)
  508. {
  509. $allcontracts = all_contact_contracts($_SESSION['siteid']);
  510. if (!isset($_SESSION['usertype']))
  511. {
  512. $_SESSION['usertype'] = 'user';
  513. }
  514. }
  515. $_SESSION['contracts'] = array_merge((array)$admincontracts, (array)$contactcontracts, (array)$allcontracts);
  516. load_entitlements($_SESSION['contactid'], $_SESSION['siteid']);
  517. header("Location: portal/");
  518. }
  519. /**
  520. * Validates the credentials password when doing a basic authentication for trusted server mode
  521. * @author Paul Heaney
  522. * @return boolean - True if successful, false otherwise
  523. */
  524. function trustedServerValidateBasicAuth()
  525. {
  526. global $CONFIG;
  527. $username = $_SERVER['PHP_AUTH_USER'];
  528. $secret = $_SERVER['PHP_AUTH_PW'];
  529. if (isset($CONFIG['trusted_server_client_id']))
  530. {
  531. if ($username == $CONFIG['trusted_server_client_id'] AND $secret == $CONFIG['trusted_server_client_secret'])
  532. {
  533. return true;
  534. }
  535. }
  536. else
  537. {
  538. // We don't have basic auth enabled
  539. return true;
  540. }
  541. return false;
  542. }
  543. /**
  544. * Returns a specified column from a specified table in the database given an ID primary key
  545. * @author Ivan Lucas
  546. * @param string $column a database column
  547. * @param string $table a database table
  548. * @param int $id the primary key / id column
  549. * @return A column from the database
  550. * @note it's not always efficient to read a single column at a time, but when you only need
  551. * one column, this is handy
  552. */
  553. function db_read_column($column, $table, $id)
  554. {
  555. global $db;
  556. $sql = "SELECT `{$column}` FROM `{$table}` WHERE id ='$id' LIMIT 1";
  557. $result = mysqli_query($db, $sql);
  558. if (mysqli_error($db)) trigger_error("MySQL Query Error ".mysqli_error($db), E_USER_WARNING);
  559. if (mysqli_num_rows($result) == 0)
  560. {
  561. $column = FALSE;
  562. }
  563. else
  564. {
  565. list($column) = mysqli_fetch_row($result);
  566. }
  567. return $column;
  568. }
  569. /**
  570. * @author Ivan Lucas
  571. * @note: Requires permission names to be i18n strings in the database table
  572. */
  573. function permission_name($permissionid)
  574. {
  575. global $dbPermissions;
  576. $name = db_read_column('name', $dbPermissions, $permissionid);
  577. if (empty($name)) $name = $GLOBALS['strUnknown'];
  578. else $name = $GLOBALS["{$name}"];
  579. return $name;
  580. }
  581. /**
  582. * Get the name associated with software ID / skill ID
  583. * @author Ivan Lucas
  584. * @param int $softwareid
  585. * @return string. Skill/Software Name
  586. * @note Software was renamed skills for v3.30
  587. */
  588. function software_name($softwareid)
  589. {
  590. global $now, $dbSoftware, $strEOL, $strEndOfLife, $db;
  591. $sql = "SELECT * FROM `{$dbSoftware}` WHERE id = '{$softwareid}'";
  592. $result = mysqli_query($db, $sql);
  593. if (mysqli_num_rows($result) >= 1)
  594. {
  595. $software = mysqli_fetch_object($result);
  596. $lifetime_end = mysql2date($software->lifetime_end);
  597. if ($lifetime_end > 0 AND $lifetime_end < $now)
  598. {
  599. $name = "<span class='deleted'>{$software->name}</span> (<abbr title='{$strEndOfLife}'>{$strEOL}</abbr>)";
  600. }
  601. else
  602. {
  603. $name = $software->name;
  604. }
  605. }
  606. else
  607. {
  608. $name = $GLOBALS['strUnknown'];
  609. }
  610. return $name;
  611. }
  612. /**
  613. * Returns a string representing the name of the given product.
  614. * @return Returns an empty string if the product does not exist.
  615. */
  616. function product_name($id)
  617. {
  618. return db_read_column('name', $GLOBALS['dbProducts'], $id);
  619. }
  620. /**
  621. * Handle a PHP triggered error
  622. * @author Ivan Lucas
  623. * @note Not called directly but triggered by PHP's own error handling
  624. * and the trigger_error function.
  625. * @note Parameters as per http://www.php.net/set_error_handler
  626. * @note This function is not internationalised in order that bugs can
  627. * be reported to developers and still be sure that they will be
  628. * understood
  629. */
  630. function sit_error_handler($errno, $errstr, $errfile, $errline, $errcontext)
  631. {
  632. global $CONFIG, $sit, $siterrors;
  633. // if error has been supressed with an @
  634. if (error_reporting() == 0)
  635. {
  636. return;
  637. }
  638. $errortype = array(
  639. E_ERROR => 'Fatal Error',
  640. E_WARNING => 'Warning',
  641. E_PARSE => 'Parse Error',
  642. E_NOTICE => 'Notice',
  643. E_CORE_ERROR => 'Core Error',
  644. E_CORE_WARNING => 'Core Warning',
  645. E_COMPILE_ERROR => 'Compile Error',
  646. E_COMPILE_WARNING => 'Compile Warning',
  647. E_USER_ERROR => 'Application Error',
  648. E_USER_WARNING => 'Application Warning',
  649. E_USER_NOTICE => 'Application Notice');
  650. if (defined('E_STRICT')) $errortype[E_STRICT] = 'Strict Runtime notice';
  651. $trace_errors = array(E_ERROR, E_USER_ERROR);
  652. if ($CONFIG['debug'] != TRUE)
  653. {
  654. $errfile = basename($errfile);
  655. }
  656. $user_errors = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE;
  657. $system_errors = E_ERROR | E_WARNING | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING;
  658. $warnings = E_WARNING | E_USER_WARNING | E_CORE_WARNING | E_COMPILE_WARNING;
  659. $notices = E_NOTICE | E_USER_NOTICE;
  660. if (($errno & $user_errors) OR ($errno & $system_errors))
  661. {
  662. if (empty($CONFIG['error_logfile']) === FALSE AND is_writable($CONFIG['error_logfile']) === TRUE)
  663. {
  664. $displayerrors = FALSE;
  665. }
  666. else
  667. {
  668. $displayerrors = TRUE;
  669. }
  670. if ($errno & $notices) $class = 'info';
  671. elseif ($errno & $warnings) $class = 'warning';
  672. else $class = 'error';
  673. $backtrace = debug_backtrace();
  674. if (php_sapi_name() != 'cli')
  675. {
  676. $tracelog = '';
  677. if ($displayerrors)
  678. {
  679. echo "<p class='{$class}'><strong>{$errortype[$errno]} [{$errno}]</strong><br />";
  680. if ($errno != E_USER_NOTICE)
  681. {
  682. echo "{$errstr} in {$errfile} @ line {$errline}";
  683. }
  684. else
  685. {
  686. echo "{$errstr}";
  687. }
  688. if ($CONFIG['debug']) echo "<br /><strong>Backtrace</strong>:";
  689. }
  690. foreach ($backtrace AS $trace)
  691. {
  692. if (!empty($trace['file']))
  693. {
  694. if ($CONFIG['debug'] AND $displayerrors)
  695. {
  696. echo "<br />{$trace['file']} @ line {$trace['line']}";
  697. }
  698. $tracelog .= "{$trace['file']} @ line {$trace['line']}";
  699. if (!empty($trace['function']))
  700. {
  701. $tracelog .= " {$trace['function']}()";
  702. if ($displayerrors) echo " {$trace['function']}() ";
  703. // foreach ($trace['args'] AS $arg)
  704. // {
  705. // echo "$arg &bull; ";
  706. // }
  707. }
  708. $tracelog .= "\n";
  709. }
  710. }
  711. if ($errno != E_NOTICE)
  712. {
  713. $logentry = " {$errortype[$errno]} [{$errno}] {$errstr} (in line {$errline} of file {$errfile})\n";
  714. }
  715. if ($errno == E_ERROR
  716. || $errno == E_USER_ERROR
  717. || $errno == E_CORE_ERROR
  718. || $errno == E_CORE_WARNING
  719. || $errno == E_COMPILE_ERROR
  720. || $errno == E_COMPILE_WARNING)
  721. {
  722. $logentry .= "\n[CONTEXT-BEGIN]\n".print_r($errcontext, TRUE)."\n[CONTEXT-END]\n----------\n\n";
  723. $siterrors++;
  724. }
  725. debug_log($logentry);
  726. if ($displayerrors)
  727. {
  728. echo "</p>";
  729. // Tips, to help diagnose errors
  730. if (strpos($errstr, 'Unknown column') !== FALSE OR
  731. preg_match("/Table '(.*)' doesn't exist/", $errstr))
  732. {
  733. echo "<p class='tip'>The SiT schema may need updating to fix this problem.";
  734. if (user_permission($sit[2], PERM_ADMIN)) echo "Visit <a href='setup.php'>Setup</a>"; // Only show this to admin
  735. echo "</p>";
  736. }
  737. if (strpos($errstr, 'headers already sent') !== FALSE)
  738. {
  739. echo "<p class='tip'>This warning may be caused by a problem that occurred before the ";
  740. echo "page was displayed, or sometimes by a syntax error or ";
  741. echo "extra whitespace in your config file.</p>";
  742. }
  743. if (strpos($errstr, 'You have an error in your SQL syntax') !== FALSE OR
  744. strpos($errstr, 'Query Error Incorrect table name') !== FALSE)
  745. {
  746. echo "<p class='tip'>You may have found a bug in SiT, please <a href=\"{$CONFIG['bugtracker_url']}\">report it</a>.</p>";
  747. }
  748. }
  749. }
  750. else
  751. {
  752. debug_log("ERROR: {$errortype[$errno]} {$errstr} in {$errfile} at line {$errline}\n");
  753. if (!empty($tracelog)) debug_log("ERROR: Backtrace:\n{$tracelog}\n");
  754. }
  755. }
  756. }
  757. /**
  758. * Write an entry to the configured error logfile
  759. * @author Ivan Lucas
  760. * @param string $logentry. A line, or lines to write to the log file
  761. * (with newlines \n)
  762. * @param bool $debugmodeonly. Only write an entry if debug mode is TRUE
  763. * @retval bool TRUE log entry written
  764. * @retval bool FALSE log entry not written
  765. */
  766. function debug_log($logentry, $debugmodeonly = FALSE)
  767. {
  768. global $CONFIG;
  769. if ($debugmodeonly === FALSE
  770. OR ($debugmodeonly === TRUE AND $CONFIG['debug'] == TRUE))
  771. {
  772. if ($CONFIG['debug'] == TRUE)
  773. {
  774. $scriptname = $_SERVER["SCRIPT_NAME"];
  775. }
  776. else
  777. {
  778. $scriptname = basename($_SERVER["SCRIPT_NAME"]);
  779. }
  780. $logentry = $scriptname . ' ' .$logentry;
  781. if (substr($logentry, -1) != "\n") $logentry .= "\n";
  782. if (!empty($CONFIG['error_logfile']))
  783. {
  784. if (file_exists($CONFIG['error_logfile']))
  785. {
  786. if (is_writable($CONFIG['error_logfile']))
  787. {
  788. $fp = fopen(clean_fspath($CONFIG['error_logfile']), 'a+');
  789. if ($fp)
  790. {
  791. fwrite($fp, date('c').' '.$logentry);
  792. fclose($fp);
  793. }
  794. else
  795. {
  796. echo "<p class='error'>Could not log message to error_logfile</p>";
  797. trigger_error("Could not log message to error_logfile", E_USER_NOTICE);
  798. return FALSE;
  799. }
  800. return TRUE;
  801. }
  802. else
  803. {
  804. trigger_error("Debug log file (error_logfile) [{$CONFIG['error_logfile']}] not writable", E_USER_WARNING);
  805. }
  806. }
  807. else
  808. {
  809. trigger_error("Debug log file (error_logfile) [{$CONFIG['error_logfile']}] not found", E_USER_WARNING);
  810. }
  811. }
  812. else
  813. {
  814. return FALSE;
  815. }
  816. }
  817. else return TRUE;
  818. }
  819. /**
  820. * Send an email from SiT
  821. * @param string $to. Destination email address
  822. * @param string $from. Source email address
  823. * @param string $subject. Email subject line
  824. * @param string $body. Email body text
  825. * @param string $replyto. (optional) Address to send reply to
  826. * @param string $cc. (optional) Carbon copy address
  827. * @param string $bcc. (optional) Blind carbon copy address
  828. * @return The return value from PHP mail() function or TRUE when in Demo mode
  829. * @note Returns TRUE but does not actually send mail when SiT is in Demo mode
  830. */
  831. function send_email($to, $from, $subject, $body, $replyto='', $cc='', $bcc='')
  832. {
  833. global $CONFIG, $application_version_string;
  834. if ($CONFIG['outbound_email_newline'] == 'CRLF')
  835. {
  836. $crlf = "\r\n";
  837. }
  838. else
  839. {
  840. $crlf = "\n";
  841. }
  842. if (empty($to)) trigger_error('Empty TO address in email', E_USER_WARNING);
  843. $extra_headers = '';
  844. if (!empty($replyto)) $extra_headers .= "Reply-To: {$replyto}" . $crlf;
  845. if (!empty($cc))
  846. {
  847. $extra_headers .= "CC: {$cc}" . $crlf;
  848. }
  849. if (!empty($bcc))
  850. {
  851. $extra_headers .= "BCC: {$bcc}" . $crlf;
  852. }
  853. if (!empty($CONFIG['support_email']))
  854. {
  855. $extra_headers .= "Errors-To: {$CONFIG['support_email']}" . $crlf;
  856. }
  857. $extra_headers .= "X-Mailer: {$CONFIG['application_shortname']} {$application_version_string}/PHP " . phpversion() . $crlf;
  858. if ($CONFIG['outbound_email_send_xoriginatingip']) $extra_headers .= "X-Originating-IP: " . substr($_SERVER['REMOTE_ADDR'], 0, 15) . $crlf;
  859. // $extra_headers .= "\r\n";
  860. if ($CONFIG['demo'])
  861. {
  862. $rtnvalue = TRUE;
  863. }
  864. elseif ($CONFIG['enable_outbound_email'] == false)
  865. {
  866. $rtnvalue = TRUE;
  867. debug_log("Outgoing email disabled, no mail is sent");
  868. }
  869. else
  870. {
  871. // $rtnvalue = mail($to, $subject, $body, $extra_headers);
  872. $mime = new MIME_mail($from, $to, html_entity_decode($subject), '', $extra_headers, $mailerror);
  873. $mime -> attach($body, '', "text/plain; charset={$GLOBALS['i18ncharset']}", $CONFIG['outbound_email_encoding'], 'inline');
  874. // actually send the email
  875. $rtnvalue = $mime -> send_mail();
  876. if (!empty($mailerror)) debug_log("Outoing email error: {$mailerror}");
  877. }
  878. return $rtnvalue;
  879. }
  880. /**
  881. * Return a global signature chosen at random
  882. *
  883. * @author Ivan Lucas
  884. * @note This is inefficient SQL but shouldn't be too much of a problem since
  885. * there are usually a low number records in this table.
  886. */
  887. function global_signature()
  888. {
  889. global $db;
  890. $sql = "SELECT signature FROM `{$GLOBALS['dbEmailSig']}` ORDER BY RAND() LIMIT 1";
  891. $result = mysqli_query($db, $sql);
  892. list($signature) = mysqli_fetch_row($result);
  893. mysqli_free_result($result);
  894. return $signature;
  895. }
  896. /**
  897. * Wrapper function to call dashboard_*_do() within a dashlet plugin
  898. * See dashlet() for more information
  899. * @author Ivan Lucas
  900. * @param string $context
  901. * @param string $row
  902. * @param string $dashboardid
  903. */
  904. function dashboard_do($context, $row=0, $dashboardid=0)
  905. {
  906. global $DASHBOARDCOMP;
  907. $dashletid = "{$row}-{$dashboardid}";
  908. $action = $DASHBOARDCOMP[$context];
  909. if ($action != NULL || $action != '')
  910. {
  911. if (function_exists($action)) $action($dashletid);
  912. }
  913. }
  914. /**
  915. * Output a dashboard component
  916. * @author Ivan Lucas
  917. * @param string $row
  918. * @param string $dashboardid
  919. */
  920. function show_dashboard_component($row, $dashboardid)
  921. {
  922. global $dbDashboard, $db;
  923. $sql = "SELECT name FROM `{$dbDashboard}` WHERE enabled = 'true' AND id = '$dashboardid'";
  924. $result = mysqli_query($db, $sql);
  925. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  926. if (mysqli_num_rows($result) == 1)
  927. {
  928. $obj = mysqli_fetch_object($result);
  929. dashboard_do("dashboard_".$obj->name, 'db_'.$row, $dashboardid);
  930. }
  931. }
  932. /**
  933. * Checks to see if a dashlet is installed
  934. * @author Paul Heaney
  935. * @param String $dashlet The name of the dashlet
  936. * @retval bool TRUE installed
  937. * @retval bool FALSE not installed
  938. */
  939. function is_dashlet_installed($dashlet)
  940. {
  941. global $db;
  942. $sql = "SELECT id FROM `{$GLOBALS['dbDashboard']}` WHERE name = '{$dashlet}'";
  943. $result = mysqli_query($db, $sql);
  944. if (mysqli_error($db)) trigger_error("MySQL Query Error ".mysqli_error($db), E_USER_WARNING);
  945. if (mysqli_num_rows($result) == 1)
  946. {
  947. return TRUE;
  948. }
  949. else
  950. {
  951. return FALSE;
  952. }
  953. }
  954. /**
  955. * Shows errors from a form, if any
  956. * @author Kieran Hogg
  957. * @return string. HTML of the form errors stored in the users session
  958. */
  959. function show_form_errors($formname)
  960. {
  961. if ($_SESSION['formerrors'][$formname])
  962. {
  963. foreach ($_SESSION['formerrors'][$formname] as $error)
  964. {
  965. if (mb_substr(trim($error), 0, 1) != "<")
  966. {
  967. $html .= user_alert($error, E_USER_ERROR);
  968. }
  969. else
  970. {
  971. $html .= $error;
  972. }
  973. }
  974. }
  975. return $html;
  976. }
  977. /**
  978. * Cleans form errors by clearing the formerrors array in the users session
  979. * @author Kieran Hogg
  980. * @param string $formname. The form name to clear.
  981. * @return nothing
  982. */
  983. function clear_form_errors($formname)
  984. {
  985. unset($_SESSION['formerrors'][$formname]);
  986. }
  987. /**
  988. * Cleans form data by clearing the formdata array in the users session
  989. * @author Kieran Hogg
  990. * @param string $formname. The form name to clear.
  991. * @return nothing
  992. */
  993. function clear_form_data($formname)
  994. {
  995. unset($_SESSION['formdata'][$formname]);
  996. }
  997. /**
  998. * Returns the value for a form returned from either the session or the default value
  999. * Useful in conjunction with show_form_errors where you wish to restore values from the session to aid data input
  1000. * @author Paul Heaney
  1001. * @param String $formname form name from _SESSION['formdata'][FORMNAME]
  1002. * @param String $fieldvalue The field in the form to show the value for
  1003. * @param String $defaultvalue The default avlue to show if not set
  1004. * @return String - The String to display
  1005. */
  1006. function show_form_value($formname, $fieldvalue, $defaultvalue='')
  1007. {
  1008. if (isset($_SESSION['formdata'][$formname][$fieldvalue]))
  1009. {
  1010. return $_SESSION['formdata'][$formname][$fieldvalue];
  1011. }
  1012. else
  1013. {
  1014. return $defaultvalue;
  1015. }
  1016. }
  1017. /**
  1018. * Generates a form token and timeout value and stores them in the session
  1019. * @author Ivan Lucas
  1020. * @retval string MD5 form token
  1021. */
  1022. function gen_form_token()
  1023. {
  1024. $formtoken = sha1(uniqid(rand(), true));
  1025. $_SESSION['formtoken'] = $formtoken;
  1026. $_SESSION['formtime'] = time();
  1027. return $formtoken;
  1028. }
  1029. /**
  1030. * Checks a form token matches the one stored in the session and that the form
  1031. * hasn't timed out
  1032. * @author Ivan Lucas
  1033. * @param string a SHA1 form token
  1034. * @retval bool TRUE - Form token is valid
  1035. * @retval bool FALSE - Form token is invalid
  1036. * @see gen_form_token()
  1037. * @note Also clears the form token and timeout stored in the session
  1038. */
  1039. function check_form_token($formtoken)
  1040. {
  1041. // Time allowed to complete the form (in seconds)
  1042. $min_time = 3;
  1043. $max_time = 120;
  1044. $val = FALSE;
  1045. if ($formtoken != $_SESSION['formtoken'])
  1046. {
  1047. trigger_error('Invalid form token', E_USER_WARNING);
  1048. }
  1049. else
  1050. {
  1051. $val = TRUE;
  1052. }
  1053. if ($val === TRUE AND (time() - $_SESSION['formtime']) < $min_time)
  1054. {
  1055. trigger_error('Invalid form. Submitted too quickly', E_USER_WARNING);
  1056. $val = FALSE;
  1057. }
  1058. if ($val === TRUE AND (time() - $_SESSION['formtime']) > $max_time)
  1059. {
  1060. trigger_error('Invalid form. Form expired before submission', E_USER_WARNING);
  1061. $val = FALSE;
  1062. }
  1063. unset($_SESSION['formtoken']);
  1064. unset($_SESSION['formtime']);
  1065. return $val;
  1066. }
  1067. /**
  1068. * Finds out which scheduled tasks should be run right now
  1069. * Ensures that a task cannot start until the previous iteration has completed
  1070. * @author Ivan Lucas, Paul Heaney
  1071. * @return array
  1072. */
  1073. function schedule_actions_due()
  1074. {
  1075. global $dbScheduler, $now, $db;
  1076. $actions = FALSE;
  1077. // Interval
  1078. $sql = "SELECT * FROM `{$dbScheduler}` WHERE `status` = 'enabled' AND type = 'interval' ";
  1079. $sql .= "AND UNIX_TIMESTAMP(start) <= {$now} AND (UNIX_TIMESTAMP(end) >= {$now} OR UNIX_TIMESTAMP(end) = 0 OR UNIX_TIMESTAMP(end) is NULL) ";
  1080. $sql .= "AND IF(UNIX_TIMESTAMP(lastran) > 0, UNIX_TIMESTAMP(lastran) + `interval`, 0) <= {$now} ";
  1081. $sql .= "AND IF(UNIX_TIMESTAMP(laststarted) > 0, UNIX_TIMESTAMP(lastran), -1) <= IF(UNIX_TIMESTAMP(laststarted) > 0, UNIX_TIMESTAMP(laststarted), 0)";
  1082. $result = mysqli_query($db, $sql);
  1083. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  1084. if (mysqli_num_rows($result) > 0)
  1085. {
  1086. while ($action = mysqli_fetch_object($result))
  1087. {
  1088. $actions[$action->action] = $actions->params;
  1089. }
  1090. }
  1091. // Month
  1092. $sql = "SELECT * FROM `{$dbScheduler}` WHERE `status` = 'enabled' AND type = 'date' ";
  1093. $sql .= "AND UNIX_TIMESTAMP(start) <= {$now} AND (UNIX_TIMESTAMP(end) >= {$now} OR UNIX_TIMESTAMP(end) = 0 OR UNIX_TIMESTAMP(end) is NULL) ";
  1094. $sql .= "AND ((date_type = 'month' AND (DAYOFMONTH(CURDATE()) > date_offset OR (DAYOFMONTH(CURDATE()) = date_offset AND CURTIME() >= date_time)) ";
  1095. $sql .= "AND DATE_FORMAT(CURDATE(), '%Y-%m') != DATE_FORMAT(lastran, '%Y-%m') ) ) "; // not run this month
  1096. $sql .= "AND IF(UNIX_TIMESTAMP(lastran) > 0, UNIX_TIMESTAMP(lastran) + `interval`, 0) <= {$now} ";
  1097. $sql .= "AND IF(UNIX_TIMESTAMP(laststarted) > 0, UNIX_TIMESTAMP(lastran), -1) <= IF(UNIX_TIMESTAMP(laststarted) > 0, UNIX_TIMESTAMP(laststarted), 0)";
  1098. $result = mysqli_query($db, $sql);
  1099. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  1100. if (mysqli_num_rows($result) > 0)
  1101. {
  1102. while ($action = mysqli_fetch_object($result))
  1103. {
  1104. $actions[$action->action] = $actions->params;
  1105. }
  1106. }
  1107. // Year TODO CHECK
  1108. $sql = "SELECT * FROM `{$dbScheduler}` WHERE `status` = 'enabled' ";
  1109. $sql .= "AND type = 'date' AND UNIX_TIMESTAMP(start) <= {$now} ";
  1110. $sql .= "AND (UNIX_TIMESTAMP(end) >= {$now} OR UNIX_TIMESTAMP(end) = 0 OR UNIX_TIMESTAMP(end) is NULL) ";
  1111. $sql .= "AND ((date_type = 'year' AND (DAYOFYEAR(CURDATE()) > date_offset ";
  1112. $sql .= "OR (DAYOFYEAR(CURDATE()) = date_offset AND CURTIME() >= date_time)) ";
  1113. $sql .= "AND DATE_FORMAT(CURDATE(), '%Y') != DATE_FORMAT(lastran, '%Y') ) ) "; // not run this year
  1114. $sql .= "AND IF(UNIX_TIMESTAMP(lastran) > 0, UNIX_TIMESTAMP(lastran) + `interval`, 0) <= {$now} ";
  1115. $sql .= "AND IF(UNIX_TIMESTAMP(laststarted) > 0, UNIX_TIMESTAMP(lastran), -1) <= IF(UNIX_TIMESTAMP(laststarted) > 0, UNIX_TIMESTAMP(laststarted), 0)";
  1116. $result = mysqli_query($db, $sql);
  1117. if (mysqli_error($db)) trigger_error(mysqli_error($db), E_USER_WARNING);
  1118. if (mysqli_num_rows($result) > 0)
  1119. {
  1120. while ($action = mysqli_fetch_object($result))
  1121. {
  1122. $actions[$action->action] = $actions->params;
  1123. }
  1124. }
  1125. if (is_array($actions)) debug_log('Scheduler actions due: '.implode(', ', array_keys($actions)));
  1126. return $actions;
  1127. }
  1128. /**
  1129. * Marks a schedule action as started
  1130. * @author Paul Heaney
  1131. * @param string $action. Name of scheduled action
  1132. * @return boolean Success of update
  1133. */
  1134. function schedule_action_started($action)
  1135. {
  1136. global $now, $db;
  1137. $nowdate = date('Y-m-d H:i:s', $now);
  1138. $sql = "UPDATE `{$GLOBALS['dbScheduler']}` SET laststarted = '{$nowdate}' ";
  1139. $sql .= "WHERE action = '{$action}'";
  1140. mysqli_query($db, $sql);
  1141. if (mysqli_error($db))
  1142. {
  1143. trigger_error(mysqli_error($db), E_USER_ERROR);
  1144. return FALSE;
  1145. }
  1146. if (mysqli_affected_rows($db) > 0) return TRUE;
  1147. else return FALSE;
  1148. }
  1149. /**
  1150. * Mark a schedule action as done
  1151. * @author Ivan Lucas
  1152. * @param string $doneaction. Name of scheduled action
  1153. * @param bool $success. Was the run successful, TRUE = Yes, FALSE = No
  1154. */
  1155. function schedule_action_done($doneaction, $success = TRUE)
  1156. {
  1157. global $dbScheduler, $now, $db;
  1158. if ($success != TRUE)
  1159. {
  1160. $t = new TriggerEvent('TRIGGER_SCHEDULER_TASK_FAILED', array('schedulertask' => $doneaction));
  1161. }
  1162. $nowdate = date('Y-m-d H:i:s', $now);
  1163. $sql = "UPDATE `{$dbScheduler}` SET lastran = '{$nowdate}' ";
  1164. if ($success == FALSE) $sql .= ", success=0, status='disabled' ";
  1165. else $sql .= ", success=1 ";
  1166. $sql .= "WHERE action = '{$doneaction}'";
  1167. mysqli_query($db, $sql);
  1168. if (mysqli_error($db))
  1169. {
  1170. trigger_error(mysqli_error($db), E_USER_ERROR);
  1171. return FALSE;
  1172. }
  1173. if (mysqli_affected_rows($db) > 0) return TRUE;
  1174. else return FALSE;
  1175. }
  1176. /**
  1177. * Update the current session id with a newly generated one
  1178. * @author Ivan Lucas
  1179. * @note Wrap the php function for different versions of php
  1180. */
  1181. function session_regenerate()
  1182. {
  1183. if (function_exists('session_regenerate_id'))
  1184. {
  1185. if (!version_compare(phpversion(), "5.1.0", ">=")) session_regenerate_id(FALSE);
  1186. else session_regenerate_id();
  1187. }
  1188. }
  1189. /**
  1190. * Outputs the full base url of the install, e.g. http://www.example.com/
  1191. *
  1192. * @return string base url of the install
  1193. * @author Kieran Hogg
  1194. */
  1195. function application_url()
  1196. {
  1197. global $CONFIG;
  1198. if (empty($CONFIG['application_uriprefix']))
  1199. {
  1200. $url = parse_url($_SERVER['HTTP_REFERER']);
  1201. if ($_SERVER['HTTPS'] == 'off' OR empty($_SERVER['HTTPS']))
  1202. {
  1203. $baseurl = "http://";
  1204. }
  1205. else
  1206. {
  1207. $baseurl = "https://";
  1208. }
  1209. $baseurl .= htmlspecialchars(substr($_SERVER['HTTP_HOST'], 0, 255), ENT_QUOTES, 'utf-8');
  1210. }
  1211. else
  1212. {
  1213. $baseurl = "{$CONFIG['application_uriprefix']}";
  1214. }
  1215. $baseurl .= "{$CONFIG['application_webpath']}";
  1216. return $baseurl;
  1217. }
  1218. /**
  1219. * Sets up default triggers for new users or upgraded users
  1220. *
  1221. * @param int $userid ID of the user
  1222. * @return bool TRUE on success, FALSE if not
  1223. * @author Kieran Hogg
  1224. */
  1225. function setup_user_triggers($userid)
  1226. {
  1227. global $db;
  1228. $return = TRUE;
  1229. $userid = intval($userid);
  1230. if ($userid != 0)
  1231. {
  1232. $sqls[] = "INSERT INTO `{$GLOBALS['dbTriggers']}` (`triggerid`, `userid`, `action`, `template`, `parameters`, `checks`)
  1233. VALUES('TRIGGER_INCIDENT_ASSIGNED', {$userid}, 'ACTION_NOTICE', 'NOTICE_INCIDENT_ASSIGNED', '', '{userid} == {$userid}');";
  1234. $sqls[] = "INSERT INTO `{$GLOBALS['dbTriggers']}` (`triggerid`, `userid`, `action`, `template`, `parameters`, `checks`)
  1235. VALUES('TRIGGER_SIT_UPGRADED', {$userid}, 'ACTION_NOTICE', 'NOTICE_SIT_UPGRADED', '', '');";
  1236. $sqls[] = "INSERT INTO `{$GLOBALS['dbTriggers']}` (`triggerid`, `userid`, `action`, `template`, `parameters`, `checks`)
  1237. VALUES('TRIGGER_INCIDENT_CLOSED', {$userid}, 'ACTION_NOTICE', 'NOTICE_INCIDENT_CLOSED', '', '{userid} == {$userid}');";
  1238. $sqls[] = "INSERT INTO `{$GLOBALS['dbTriggers']}` (`triggerid`, `userid`, `action`, `template`, `parameters`, `checks`)
  1239. VALUES('TRIGGER_INCIDENT_NEARING_SLA', {$userid}, 'ACTION_NOTICE', 'NOTICE_INCIDENT_NEARING_SLA', '',
  1240. '{ownerid} == {$userid} OR {townerid} == {$userid}');";
  1241. $sqls[] = "INSERT INTO `{$GLOBALS['dbTriggers']}` (`triggerid`, `userid`, `action`, `template`, `parameters`, `checks`)
  1242. VALUES('TRIGGER_LANGUAGE_DIFFERS', {$userid}, 'ACTION_NOTICE', 'NOTICE_LANGUAGE_DIFFERS', '', '');";
  1243. foreach ($sqls AS $sql)
  1244. {
  1245. mysqli_query($db, $sql);
  1246. if (mysqli_error($db))
  1247. {
  1248. trigger_error("MySQL Query Error ".mysqli_error($db), E_USER_ERROR);
  1249. $return = FALSE;
  1250. }
  1251. }
  1252. }
  1253. else
  1254. {
  1255. trigger_error("setup_user_triggers() Invalid userid '{$userid}' specified", E_USER_NOTICE);
  1256. $return = FALSE;
  1257. }
  1258. return $return;
  1259. }
  1260. /**
  1261. * Function to return currently running SiT! version
  1262. * @return String - Currently running application version
  1263. */
  1264. function application_version_string()
  1265. {
  1266. global $application_version_string;
  1267. return $application_version_string;
  1268. }
  1269. /**
  1270. * Returns the currently running schema version
  1271. * @author Paul Heaney
  1272. * @return String - currently running schema version
  1273. */
  1274. function database_schema_version()
  1275. {
  1276. global $db;
  1277. $return = '';
  1278. $sql = "SELECT `schemaversion` FROM `{$GLOBALS['dbSystem']}` WHERE id = 0";
  1279. $result = mysqli_query($db, $sql);
  1280. if (mysqli_error($db))
  1281. {
  1282. trigger_error("MySQL Query Error ".mysqli_error($db), E_USER_WARNING);
  1283. $return = FALSE;
  1284. }
  1285. if (mysqli_num_rows($result) > 0)
  1286. {
  1287. list($return) = mysqli_fetch_row($result);
  1288. }
  1289. return $return;
  1290. }
  1291. /**
  1292. * Populates $_SESSION['syslang], system language strings
  1293. *
  1294. * @author Kieran Hogg
  1295. * @sa See also populate_syslang2() which is a copy of this function
  1296. */
  1297. function populate_syslang()
  1298. {
  1299. global $CONFIG;
  1300. // Populate $SYSLANG with first the native lang and then the system lang
  1301. // This is so that we have a complete language file
  1302. $nativefile = APPLICATION_I18NPATH . "en-GB.inc.php";
  1303. $file = APPLICATION_I18NPATH . "{$CONFIG['default_i18n']}.inc.php";
  1304. if (file_exists($nativefile))
  1305. {
  1306. $nativefile = clean_fspath($nativefile);
  1307. $fh = fopen($nativefile, "r");
  1308. $theData = fread($fh, filesize($nativefile));
  1309. fclose($fh);
  1310. $nativelines = explode("\n", $theData);
  1311. if (file_exists($file))
  1312. {
  1313. $file = clean_fspath($file);
  1314. $fh = fopen($file, "r");
  1315. $theData = fread($fh, filesize($file));
  1316. fclose($fh);
  1317. $lines = explode("\n", $theData);
  1318. }
  1319. else
  1320. {
  1321. trigger_error("Language file specified in \$CONFIG['default_i18n'] can't be found", E_USER_ERROR);
  1322. $lines = $nativelines;
  1323. }
  1324. foreach ($nativelines as $values)
  1325. {
  1326. $badchars = array("$", "\"…

Large files files are truncated, but you can click here to view the full file