Bootswatch, Summernote, and Captcheck mods for Mods for HESK (mods-for-hesk.com). In use at support.netsyms.com.
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.

common.inc.php 66KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145
  1. <?php
  2. /**
  3. *
  4. * This file is part of HESK - PHP Help Desk Software.
  5. *
  6. * (c) Copyright Klemen Stirn. All rights reserved.
  7. * https://www.hesk.com
  8. *
  9. * For the full copyright and license agreement information visit
  10. * https://www.hesk.com/eula.php
  11. *
  12. */
  13. /* Check if this is a valid include */
  14. if (!defined('IN_SCRIPT')) {
  15. die('Invalid attempt');
  16. }
  17. #error_reporting(E_ALL);
  18. /*
  19. * If code is executed from CLI, don't force SSL
  20. * else set correct Content-Type header
  21. */
  22. if (defined('NO_HTTP_HEADER')) {
  23. $hesk_settings['force_ssl'] = false;
  24. } else {
  25. header('Content-Type: text/html; charset=utf-8');
  26. // Don't allow HESK to be loaded in a frame on third party domains
  27. if ($hesk_settings['x_frame_opt'])
  28. {
  29. header('X-Frame-Options: SAMEORIGIN');
  30. }
  31. }
  32. // Set backslash options
  33. if (get_magic_quotes_gpc()) {
  34. define('HESK_SLASH', false);
  35. } else {
  36. define('HESK_SLASH', true);
  37. }
  38. // Define some constants for backward-compatibility
  39. if (!defined('ENT_SUBSTITUTE')) {
  40. define('ENT_SUBSTITUTE', 0);
  41. }
  42. if (!defined('ENT_XHTML')) {
  43. define('ENT_XHTML', 0);
  44. }
  45. // Is this is a SSL connection?
  46. if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
  47. define('HESK_SSL', true);
  48. // Use https-only cookies
  49. @ini_set('session.cookie_secure', 1);
  50. } else {
  51. // Force redirect?
  52. if ($hesk_settings['force_ssl']) {
  53. header('HTTP/1.1 301 Moved Permanently');
  54. header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
  55. exit();
  56. }
  57. define('HESK_SSL', false);
  58. }
  59. // Prevents javascript XSS attacks aimed to steal the session ID
  60. @ini_set('session.cookie_httponly', 1);
  61. // **PREVENTING SESSION FIXATION**
  62. // Session ID cannot be passed through URLs
  63. @ini_set('session.use_only_cookies', 1);
  64. // Load language file
  65. hesk_getLanguage();
  66. // Set timezone
  67. hesk_setTimezone();
  68. /*** FUNCTIONS ***/
  69. function hesk_getClientIP() {
  70. global $hesk_settings;
  71. // Already set? Just return it
  72. if (isset($hesk_settings['client_IP'])) {
  73. return $hesk_settings['client_IP'];
  74. }
  75. // Empty client IP, for example when used in CLI (piping, cron jobs, ...)
  76. $hesk_settings['client_IP'] = '';
  77. // Server (environment) variables to loop through
  78. // the first valid one found will be returned as client IP
  79. // Uncomment those used on your server
  80. $server_client_IP_variables = array(
  81. // 'HTTP_CF_CONNECTING_IP', // CloudFlare
  82. // 'HTTP_CLIENT_IP',
  83. // 'HTTP_X_FORWARDED_FOR',
  84. // 'HTTP_X_FORWARDED',
  85. // 'HTTP_FORWARDED_FOR',
  86. // 'HTTP_FORWARDED',
  87. 'REMOTE_ADDR',
  88. );
  89. // The first valid environment variable is our client IP
  90. foreach ($server_client_IP_variables as $server_client_IP_variable) {
  91. // Must be set
  92. if (!isset($_SERVER[$server_client_IP_variable])) {
  93. continue;
  94. }
  95. // Must be a valid IP
  96. if (!hesk_isValidIP($_SERVER[$server_client_IP_variable])) {
  97. continue;
  98. }
  99. // Bingo!
  100. $hesk_settings['client_IP'] = $_SERVER[$server_client_IP_variable];
  101. break;
  102. }
  103. return $hesk_settings['client_IP'];
  104. } // END hesk_getClientIP()
  105. function hesk_isValidIP($ip) {
  106. // Use filter_var for PHP 5.2.0
  107. if (function_exists('filter_var') && filter_var($ip, FILTER_VALIDATE_IP) !== false) {
  108. return true;
  109. }
  110. // Use regex for PHP < 5.2.0
  111. // -> IPv4
  112. if (preg_match('/^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$/', $ip)) {
  113. return true;
  114. }
  115. // -> IPv6
  116. if (preg_match('/^[0-9A-Fa-f\:\.]$/', $ip)) {
  117. return true;
  118. }
  119. // Not a valid IP
  120. return false;
  121. } // END hesk_isValidIP()
  122. function hesk_setcookie($name, $value, $expire=0, $path=""){
  123. if (HESK_SSL) {
  124. setcookie($name, $value, $expire, $path, "", true, true);
  125. } else {
  126. setcookie($name, $value, $expire, $path, "", false, true);
  127. }
  128. return true;
  129. } // END hesk_setcookie()
  130. function hesk_service_message($sm)
  131. {
  132. $faIcon = $sm['icon'];
  133. switch ($sm['style']) {
  134. case 1:
  135. $style = "alert alert-success";
  136. break;
  137. case 2:
  138. $style = "alert alert-info";
  139. break;
  140. case 3:
  141. $style = "alert alert-warning";
  142. break;
  143. case 4:
  144. $style = "alert alert-danger";
  145. break;
  146. default:
  147. $style = "none";
  148. }
  149. ?>
  150. <div class="<?php echo $style; ?>">
  151. <?php echo $faIcon == '' ? '' : '<i class="' . $faIcon . '"></i> '; ?>
  152. <b><?php echo $sm['title']; ?></b><?php echo $sm['message']; ?>
  153. </div>
  154. <br/>
  155. <?php
  156. } // END hesk_service_message()
  157. function hesk_isBannedIP($ip)
  158. {
  159. global $hesk_settings, $hesklang, $hesk_db_link;
  160. $ip = ip2long($ip) or $ip = 0;
  161. // We need positive value of IP
  162. if ($ip < 0) {
  163. $ip += 4294967296;
  164. } elseif ($ip > 4294967296) {
  165. $ip = 4294967296;
  166. }
  167. $res = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_ips` WHERE {$ip} BETWEEN `ip_from` AND `ip_to` LIMIT 1");
  168. return (hesk_dbNumRows($res) == 1) ? hesk_dbResult($res) : false;
  169. } // END hesk_isBannedIP()
  170. function hesk_isBannedEmail($email)
  171. {
  172. global $hesk_settings, $hesklang, $hesk_db_link;
  173. $email = strtolower($email);
  174. $res = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_emails` WHERE `email` IN ('" . hesk_dbEscape($email) . "', '" . hesk_dbEscape(substr($email, strrpos($email, "@"))) . "') LIMIT 1");
  175. return (hesk_dbNumRows($res) == 1) ? hesk_dbResult($res) : false;
  176. } // END hesk_isBannedEmail()
  177. function hesk_clean_utf8($in)
  178. {
  179. //reject overly long 2 byte sequences, as well as characters above U+10000 and replace with ?
  180. $in = preg_replace('/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]' .
  181. '|[\x00-\x7F][\x80-\xBF]+' .
  182. '|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*' .
  183. '|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})' .
  184. '|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S',
  185. '?', $in);
  186. //reject overly long 3 byte sequences and UTF-16 surrogates and replace with ?
  187. $in = preg_replace('/\xE0[\x80-\x9F][\x80-\xBF]' .
  188. '|\xED[\xA0-\xBF][\x80-\xBF]/S', '?', $in);
  189. return $in;
  190. } // END hesk_clean_utf8()
  191. function hesk_load_database_functions()
  192. {
  193. // Already loaded?
  194. if (function_exists('hesk_dbQuery')) {
  195. return true;
  196. }
  197. // Preferrably use the MySQLi functions
  198. if (function_exists('mysqli_connect')) {
  199. require(HESK_PATH . 'inc/database_mysqli.inc.php');
  200. } // Default to MySQL
  201. else {
  202. require(HESK_PATH . 'inc/database.inc.php');
  203. }
  204. } // END hesk_load_database_functions()
  205. function hesk_load_api_database_functions()
  206. {
  207. require(__DIR__ . '/../api/core/json_error.php');
  208. // Preferrably use the MySQLi functions
  209. if (function_exists('mysqli_connect')) {
  210. require(__DIR__ . '/../api/core/database_mysqli.inc.php');
  211. } // Default to MySQL
  212. else {
  213. require(__DIR__ . '/../api/core/database.inc.php');
  214. }
  215. } // END hesk_load_database_functions()
  216. function hesk_load_internal_api_database_functions()
  217. {
  218. require(HESK_PATH . 'internal-api/core/json_error.php');
  219. // Preferrably use the MySQLi functions
  220. if (function_exists('mysqli_connect')) {
  221. require(HESK_PATH . 'internal-api/core/database_mysqli.inc.php');
  222. } // Default to MySQL
  223. else {
  224. require(HESK_PATH . 'internal-api/core/database.inc.php');
  225. }
  226. } // END hesk_load_database_functions()
  227. function hesk_load_cron_database_functions()
  228. {
  229. if (function_exists('mysqli_connect')) {
  230. require(HESK_PATH . 'cron/core/database_mysqli.inc.php');
  231. } // Default to MySQL
  232. else {
  233. require(HESK_PATH . 'cron/core/database.inc.php');
  234. }
  235. } // END hesk_load_cron_database_functions()
  236. function hesk_unlink($file, $older_than = 0)
  237. {
  238. return (is_file($file) && (!$older_than || (time() - filectime($file)) > $older_than) && @unlink($file)) ? true : false;
  239. } // END hesk_unlink()
  240. function hesk_unlink_callable($file, $key, $older_than=0)
  241. {
  242. return hesk_unlink($file, $older_than);
  243. } // END hesk_unlink_callable()
  244. function hesk_utf8_urldecode($in)
  245. {
  246. $in = preg_replace("/%u([0-9a-f]{3,4})/i", "&#x\\1;", urldecode($in));
  247. return hesk_html_entity_decode($in);
  248. } // END hesk_utf8_urldecode
  249. function hesk_SESSION($in, $default = '')
  250. {
  251. if (is_array($in)) {
  252. return isset($_SESSION[$in[0]][$in[1]]) && ! is_array(isset($_SESSION[$in[0]][$in[1]])) ? $_SESSION[$in[0]][$in[1]] : $default;
  253. } else {
  254. return isset($_SESSION[$in]) && ! is_array($_SESSION[$in]) ? $_SESSION[$in] : $default;
  255. }
  256. } // END hesk_SESSION();
  257. function hesk_COOKIE($in, $default = '')
  258. {
  259. return isset($_COOKIE[$in]) && !is_array($_COOKIE[$in]) ? $_COOKIE[$in] : $default;
  260. } // END hesk_COOKIE();
  261. function hesk_GET($in, $default = '')
  262. {
  263. return isset($_GET[$in]) && !is_array($_GET[$in]) ? $_GET[$in] : $default;
  264. } // END hesk_GET()
  265. function hesk_POST($in, $default = '')
  266. {
  267. return isset($_POST[$in]) && !is_array($_POST[$in]) ? $_POST[$in] : $default;
  268. } // END hesk_POST()
  269. function hesk_POST_array($in, $default = array())
  270. {
  271. return isset($_POST[$in]) && is_array($_POST[$in]) ? $_POST[$in] : $default;
  272. } // END hesk_POST_array()
  273. function hesk_REQUEST($in, $default = false)
  274. {
  275. return isset($_GET[$in]) ? hesk_input(hesk_GET($in)) : (isset($_POST[$in]) ? hesk_input(hesk_POST($in)) : $default);
  276. } // END hesk_REQUEST()
  277. function hesk_isREQUEST($in)
  278. {
  279. return isset($_GET[$in]) || isset($_POST[$in]) ? true : false;
  280. } // END hesk_isREQUEST()
  281. function hesk_htmlspecialchars_decode($in)
  282. {
  283. return str_replace(array('&amp;', '&lt;', '&gt;', '&quot;'), array('&', '<', '>', '"'), $in);
  284. } // END hesk_htmlspecialchars_decode()
  285. function hesk_html_entity_decode($in)
  286. {
  287. return html_entity_decode($in, ENT_COMPAT | ENT_XHTML, 'UTF-8');
  288. #return html_entity_decode($in, ENT_COMPAT | ENT_XHTML, 'ISO-8859-1');
  289. } // END hesk_html_entity_decode()
  290. function hesk_htmlspecialchars($in)
  291. {
  292. return htmlspecialchars($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'UTF-8');
  293. #return htmlspecialchars($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'ISO-8859-1');
  294. } // END hesk_htmlspecialchars()
  295. function hesk_htmlentities($in)
  296. {
  297. return htmlentities($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'UTF-8');
  298. #return htmlentities($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'ISO-8859-1');
  299. } // END hesk_htmlentities()
  300. function hesk_slashJS($in)
  301. {
  302. return str_replace('\'', '\\\'', $in);
  303. } // END hesk_slashJS()
  304. function hesk_verifyEmailMatch($trackingID, $my_email = 0, $ticket_email = 0, $error = 1)
  305. {
  306. global $hesk_settings, $hesklang, $hesk_db_link;
  307. /* Email required to view ticket? */
  308. if (!$hesk_settings['email_view_ticket']) {
  309. $hesk_settings['e_param'] = '';
  310. $hesk_settings['e_query'] = '';
  311. $hesk_settings['e_email'] = '';
  312. return true;
  313. }
  314. /* Limit brute force attempts */
  315. hesk_limitBfAttempts();
  316. /* Get email address */
  317. if ($my_email) {
  318. $hesk_settings['e_param'] = '&e=' . rawurlencode($my_email);
  319. $hesk_settings['e_query'] = '&amp;e=' . rawurlencode($my_email);
  320. $hesk_settings['e_email'] = $my_email;
  321. } else {
  322. $my_email = hesk_getCustomerEmail();
  323. }
  324. /* Get email from ticket */
  325. if (!$ticket_email) {
  326. $res = hesk_dbQuery("SELECT `email` FROM `" . $hesk_settings['db_pfix'] . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
  327. if (hesk_dbNumRows($res) == 1) {
  328. $ticket_email = hesk_dbResult($res);
  329. } else {
  330. hesk_process_messages($hesklang['ticket_not_found'], 'ticket.php');
  331. }
  332. }
  333. /* Validate email */
  334. if ($hesk_settings['multi_eml']) {
  335. $ticket_email = str_replace(';', ',', $ticket_email);
  336. $valid_emails = explode(',', strtolower($ticket_email));
  337. if (in_array(strtolower($my_email), $valid_emails)) {
  338. /* Match, clean brute force attempts and return true */
  339. hesk_cleanBfAttempts();
  340. return true;
  341. }
  342. } elseif (strtolower($ticket_email) == strtolower($my_email)) {
  343. /* Match, clean brute force attempts and return true */
  344. hesk_cleanBfAttempts();
  345. return true;
  346. }
  347. /* Email doesn't match, clean cookies and error out */
  348. if ($error) {
  349. hesk_setcookie('hesk_myemail', '');
  350. hesk_process_messages($hesklang['enmdb'], 'ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999));
  351. } else {
  352. return false;
  353. }
  354. } // END hesk_verifyEmailMatch()
  355. function hesk_getCustomerEmail($can_remember = 0, $field = '')
  356. {
  357. global $hesk_settings, $hesklang;
  358. /* Email required to view ticket? */
  359. if (!$hesk_settings['email_view_ticket']) {
  360. $hesk_settings['e_param'] = '';
  361. $hesk_settings['e_query'] = '';
  362. $hesk_settings['e_email'] = '';
  363. return '';
  364. }
  365. /* Is this a form that enables remembering email? */
  366. if ($can_remember) {
  367. global $do_remember;
  368. }
  369. $my_email = '';
  370. /* Is email in session? */
  371. if ( strlen($field) && isset($_SESSION[$field]) )
  372. {
  373. $my_email = hesk_validateEmail($_SESSION[$field], 'ERR', 0);
  374. }
  375. /* Is email in query string? */
  376. if (isset($_GET['e']) || isset($_POST['e'])) {
  377. $my_email = hesk_validateEmail(hesk_REQUEST('e'), 'ERR', 0);
  378. } /* Is email in cookie? */
  379. elseif (isset($_COOKIE['hesk_myemail'])) {
  380. $my_email = hesk_validateEmail(hesk_COOKIE('hesk_myemail'), 'ERR', 0);
  381. if ($can_remember && $my_email) {
  382. $do_remember = ' checked="checked" ';
  383. }
  384. }
  385. // Remove unwanted side-effects
  386. $my_email = hesk_emailCleanup($my_email);
  387. $hesk_settings['e_param'] = '&e=' . rawurlencode($my_email);
  388. $hesk_settings['e_query'] = '&amp;e=' . rawurlencode($my_email);
  389. $hesk_settings['e_email'] = $my_email;
  390. return $my_email;
  391. } // END hesk_getCustomerEmail()
  392. function hesk_emailCleanup($my_email) {
  393. return preg_replace("/(\\\)'/", "'", $my_email);
  394. } // END hesk_emailCleanup()
  395. function hesk_formatBytes($size, $translate_unit = 1, $precision = 2)
  396. {
  397. global $hesklang;
  398. $units = array(
  399. 'GB' => 1073741824,
  400. 'MB' => 1048576,
  401. 'kB' => 1024,
  402. 'B' => 1
  403. );
  404. foreach ($units as $suffix => $bytes) {
  405. if ($bytes > $size) {
  406. continue;
  407. }
  408. $full = $size / $bytes;
  409. $round = round($full, $precision);
  410. if ($full == $round) {
  411. if ($translate_unit) {
  412. return $round . ' ' . $hesklang[$suffix];
  413. } else {
  414. return $round . ' ' . $suffix;
  415. }
  416. }
  417. }
  418. return false;
  419. } // End hesk_formatBytes()
  420. function hesk_autoAssignTicket($ticket_category)
  421. {
  422. global $hesk_settings, $hesklang;
  423. /* Auto assign ticket enabled? */
  424. if (!$hesk_settings['autoassign']) {
  425. return false;
  426. }
  427. $autoassign_owner = array();
  428. /* Get all possible auto-assign staff, order by number of open tickets */
  429. $res = hesk_dbQuery("SELECT `t1`.`id`,`t1`.`user`,`t1`.`name`, `t1`.`email`, `t1`.`language`, `t1`.`isadmin`, `t1`.`categories`, `t1`.`notify_assigned`, `t1`.`heskprivileges`,
  430. (SELECT COUNT(*) FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` FORCE KEY (`statuses`) WHERE `owner`=`t1`.`id` AND `status` IN (SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `IsClosed` = 0) ) as `open_tickets`
  431. FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` AS `t1`
  432. WHERE `t1`.`autoassign`='1' ORDER BY `open_tickets` ASC, RAND()");
  433. /* Loop through the rows and return the first appropriate one */
  434. while ($myuser = hesk_dbFetchAssoc($res)) {
  435. /* Is this an administrator? */
  436. if ($myuser['isadmin']) {
  437. $autoassign_owner = $myuser;
  438. $hesk_settings['user_data'][$myuser['id']] = $myuser;
  439. hesk_dbFreeResult($res);
  440. break;
  441. }
  442. /* Not and administrator, check two things: */
  443. /* --> can view and reply to tickets */
  444. if (strpos($myuser['heskprivileges'], 'can_view_tickets') === false || strpos($myuser['heskprivileges'], 'can_reply_tickets') === false) {
  445. continue;
  446. }
  447. /* --> has access to ticket category */
  448. $myuser['categories'] = explode(',', $myuser['categories']);
  449. if (in_array($ticket_category, $myuser['categories'])) {
  450. $autoassign_owner = $myuser;
  451. $hesk_settings['user_data'][$myuser['id']] = $myuser;
  452. hesk_dbFreeResult($res);
  453. break;
  454. }
  455. }
  456. return $autoassign_owner;
  457. } // END hesk_autoAssignTicket()
  458. function hesk_cleanID($field = 'track', $in=false)
  459. {
  460. $id = '';
  461. if ($in !== false){
  462. $id = $in;
  463. } elseif (isset($_SESSION[$field])) {
  464. $id = $_SESSION[$field];
  465. } elseif ( isset($_GET[$field]) && ! is_array($_GET[$field]) ) {
  466. $id = $_GET[$field];
  467. } elseif (isset($_POST[$field]) && !is_array($_POST[$field])) {
  468. $id = $_POST[$field];
  469. } else {
  470. return false;
  471. }
  472. return substr(preg_replace('/[^A-Z0-9\-]/', '', strtoupper($id)), 0, 12);
  473. } // END hesk_cleanID()
  474. function hesk_createID()
  475. {
  476. global $hesk_settings, $hesklang, $hesk_error_buffer;
  477. /*** Generate tracking ID and make sure it's not a duplicate one ***/
  478. /* Ticket ID can be of these chars */
  479. $useChars = 'AEUYBDGHJLMNPQRSTVWXZ123456789';
  480. /* Set tracking ID to an empty string */
  481. $trackingID = '';
  482. /* Let's avoid duplicate ticket ID's, try up to 3 times */
  483. for ($i = 1; $i <= 3; $i++) {
  484. /* Generate raw ID */
  485. $trackingID .= $useChars[mt_rand(0, 29)];
  486. $trackingID .= $useChars[mt_rand(0, 29)];
  487. $trackingID .= $useChars[mt_rand(0, 29)];
  488. $trackingID .= $useChars[mt_rand(0, 29)];
  489. $trackingID .= $useChars[mt_rand(0, 29)];
  490. $trackingID .= $useChars[mt_rand(0, 29)];
  491. $trackingID .= $useChars[mt_rand(0, 29)];
  492. $trackingID .= $useChars[mt_rand(0, 29)];
  493. $trackingID .= $useChars[mt_rand(0, 29)];
  494. $trackingID .= $useChars[mt_rand(0, 29)];
  495. /* Format the ID to the correct shape and check wording */
  496. $trackingID = hesk_formatID($trackingID);
  497. /* Check for duplicate IDs */
  498. $res = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid` = '" . hesk_dbEscape($trackingID) . "' LIMIT 1");
  499. if (hesk_dbNumRows($res) == 0) {
  500. /* Everything is OK, no duplicates found */
  501. return $trackingID;
  502. }
  503. /* A duplicate ID has been found! Let's try again (up to 2 more) */
  504. $trackingID = '';
  505. }
  506. /* No valid tracking ID, try one more time with microtime() */
  507. $trackingID = $useChars[mt_rand(0, 29)];
  508. $trackingID .= $useChars[mt_rand(0, 29)];
  509. $trackingID .= $useChars[mt_rand(0, 29)];
  510. $trackingID .= $useChars[mt_rand(0, 29)];
  511. $trackingID .= $useChars[mt_rand(0, 29)];
  512. $trackingID .= substr(microtime(), -5);
  513. /* Format the ID to the correct shape and check wording */
  514. $trackingID = hesk_formatID($trackingID);
  515. $res = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid` = '" . hesk_dbEscape($trackingID) . "' LIMIT 1");
  516. /* All failed, must be a server-side problem... */
  517. if (hesk_dbNumRows($res) == 0) {
  518. return $trackingID;
  519. }
  520. $hesk_error_buffer['etid'] = $hesklang['e_tid'];
  521. return false;
  522. } // END hesk_createID()
  523. function hesk_formatID($id)
  524. {
  525. $useChars = 'AEUYBDGHJLMNPQRSTVWXZ123456789';
  526. $replace = $useChars[mt_rand(0, 29)];
  527. $replace .= mt_rand(1, 9);
  528. $replace .= $useChars[mt_rand(0, 29)];
  529. /*
  530. Remove 3 letter bad words from ID
  531. Possiblitiy: 1:27,000
  532. */
  533. $remove = array(
  534. 'ASS',
  535. 'CUM',
  536. 'FAG',
  537. 'FUK',
  538. 'GAY',
  539. 'SEX',
  540. 'TIT',
  541. 'XXX',
  542. );
  543. $id = str_replace($remove, $replace, $id);
  544. /*
  545. Remove 4 letter bad words from ID
  546. Possiblitiy: 1:810,000
  547. */
  548. $remove = array(
  549. 'ANAL',
  550. 'ANUS',
  551. 'BUTT',
  552. 'CAWK',
  553. 'CLIT',
  554. 'COCK',
  555. 'CRAP',
  556. 'CUNT',
  557. 'DICK',
  558. 'DYKE',
  559. 'FART',
  560. 'FUCK',
  561. 'JAPS',
  562. 'JERK',
  563. 'JIZZ',
  564. 'KNOB',
  565. 'PISS',
  566. 'POOP',
  567. 'SHIT',
  568. 'SLUT',
  569. 'SUCK',
  570. 'TURD',
  571. // Also, remove words that are known to trigger mod_security
  572. 'WGET',
  573. );
  574. $replace .= mt_rand(1, 9);
  575. $id = str_replace($remove, $replace, $id);
  576. /* Format the ID string into XXX-XXX-XXXX format for easier readability */
  577. $id = $id[0] . $id[1] . $id[2] . '-' . $id[3] . $id[4] . $id[5] . '-' . $id[6] . $id[7] . $id[8] . $id[9];
  578. return $id;
  579. } // END hesk_formatID()
  580. function hesk_cleanBfAttempts()
  581. {
  582. global $hesk_settings, $hesklang;
  583. /* If this feature is disabled, just return */
  584. if (!$hesk_settings['attempt_limit'] || defined('HESK_BF_CLEAN')) {
  585. return true;
  586. }
  587. /* Delete expired logs from the database */
  588. hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` WHERE `ip`='".hesk_dbEscape(hesk_getClientIP())."'");
  589. define('HESK_BF_CLEAN', 1);
  590. return true;
  591. } // END hesk_cleanAttempts()
  592. function hesk_limitBfAttempts($showError = 1)
  593. {
  594. global $hesk_settings, $hesklang;
  595. // Check if this IP is banned permanently
  596. if (hesk_isBannedIP(hesk_getClientIP())) {
  597. hesk_error($hesklang['baned_ip'], 0);
  598. }
  599. /* If this feature is disabled or already called, return false */
  600. if (!$hesk_settings['attempt_limit'] || defined('HESK_BF_LIMIT')) {
  601. return false;
  602. }
  603. /* Define this constant to avoid duplicate checks */
  604. define('HESK_BF_LIMIT', 1);
  605. $ip = hesk_getClientIP();
  606. /* Get number of failed attempts from the database */
  607. $res = hesk_dbQuery("SELECT `number`, (CASE WHEN `last_attempt` IS NOT NULL AND DATE_ADD(`last_attempt`, INTERVAL " . intval($hesk_settings['attempt_banmin']) . " MINUTE ) > NOW() THEN 1 ELSE 0 END) AS `banned` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` WHERE `ip`='" . hesk_dbEscape($ip) . "' LIMIT 1");
  608. /* Not in the database yet? Add first one and return false */
  609. if (hesk_dbNumRows($res) != 1) {
  610. hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` (`ip`) VALUES ('" . hesk_dbEscape($ip) . "')");
  611. return false;
  612. }
  613. /* Get number of failed attempts and increase by 1 */
  614. $row = hesk_dbFetchAssoc($res);
  615. $row['number']++;
  616. /* If too many failed attempts either return error or reset count if time limit expired */
  617. if ($row['number'] >= $hesk_settings['attempt_limit']) {
  618. if ($row['banned']) {
  619. $tmp = sprintf($hesklang['yhbb'], $hesk_settings['attempt_banmin']);
  620. unset($_SESSION);
  621. if ($showError) {
  622. hesk_error($tmp, 0);
  623. } else {
  624. return $tmp;
  625. }
  626. } else {
  627. $row['number'] = 1;
  628. }
  629. }
  630. hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` SET `number`=" . intval($row['number']) . " WHERE `ip`='" . hesk_dbEscape($ip) . "' LIMIT 1");
  631. return false;
  632. } // END hesk_limitAttempts()
  633. function hesk_getCategoryName($id)
  634. {
  635. global $hesk_settings, $hesklang;
  636. if (empty($id)) {
  637. return $hesklang['unas'];
  638. }
  639. // If we already have the name no need to query DB another time
  640. if (isset($hesk_settings['category_data'][$id]['name'])) {
  641. return $hesk_settings['category_data'][$id]['name'];
  642. }
  643. $res = hesk_dbQuery("SELECT `name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `id`='" . intval($id) . "' LIMIT 1");
  644. if (hesk_dbNumRows($res) != 1) {
  645. return $hesklang['catd'];
  646. }
  647. $hesk_settings['category_data'][$id]['name'] = hesk_dbResult($res, 0, 0);
  648. return $hesk_settings['category_data'][$id]['name'];
  649. } // END hesk_getOwnerName()
  650. function hesk_getOwnerName($id)
  651. {
  652. global $hesk_settings, $hesklang;
  653. if (empty($id)) {
  654. return $hesklang['unas'];
  655. }
  656. // If we already have the name no need to query DB another time
  657. if (isset($hesk_settings['user_data'][$id]['name'])) {
  658. return $hesk_settings['user_data'][$id]['name'];
  659. }
  660. $res = hesk_dbQuery("SELECT `name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id`='" . intval($id) . "' LIMIT 1");
  661. if (hesk_dbNumRows($res) != 1) {
  662. return $hesklang['unas'];
  663. }
  664. $hesk_settings['user_data'][$id]['name'] = hesk_dbResult($res, 0, 0);
  665. return $hesk_settings['user_data'][$id]['name'];
  666. } // END hesk_getOwnerName()
  667. function hesk_cleanSessionVars($arr)
  668. {
  669. if (is_array($arr)) {
  670. foreach ($arr as $str) {
  671. if (isset($_SESSION[$str])) {
  672. unset($_SESSION[$str]);
  673. }
  674. }
  675. } elseif (isset($_SESSION[$arr])) {
  676. unset($_SESSION[$arr]);
  677. }
  678. } // End hesk_cleanSessionVars()
  679. function hesk_process_messages($message, $redirect_to, $type = 'ERROR')
  680. {
  681. global $hesk_settings, $hesklang;
  682. switch ($type) {
  683. case 'SUCCESS':
  684. $_SESSION['HESK_SUCCESS'] = TRUE;
  685. break;
  686. case 'NOTICE':
  687. $_SESSION['HESK_NOTICE'] = TRUE;
  688. break;
  689. case 'INFO':
  690. $_SESSION['HESK_INFO'] = TRUE;
  691. break;
  692. default:
  693. $_SESSION['HESK_ERROR'] = TRUE;
  694. }
  695. $_SESSION['HESK_MESSAGE'] = $message;
  696. /* In some cases we don't want a redirect */
  697. if ($redirect_to == 'NOREDIRECT') {
  698. return TRUE;
  699. }
  700. header('Location: ' . $redirect_to);
  701. exit();
  702. } // END hesk_process_messages()
  703. function hesk_handle_messages()
  704. {
  705. global $hesk_settings, $hesklang;
  706. $return_value = true;
  707. // Primary message - only one can be displayed and HESK_MESSAGE is required
  708. if (isset($_SESSION['HESK_MESSAGE'])) {
  709. if (isset($_SESSION['HESK_SUCCESS'])) {
  710. hesk_show_success($_SESSION['HESK_MESSAGE']);
  711. } elseif (isset($_SESSION['HESK_ERROR'])) {
  712. hesk_show_error($_SESSION['HESK_MESSAGE']);
  713. $return_value = false;
  714. } elseif (isset($_SESSION['HESK_NOTICE'])) {
  715. hesk_show_notice($_SESSION['HESK_MESSAGE']);
  716. } elseif (isset($_SESSION['HESK_INFO'])) {
  717. hesk_show_info($_SESSION['HESK_MESSAGE']);
  718. }
  719. hesk_cleanSessionVars('HESK_MESSAGE');
  720. }
  721. // Cleanup any primary message types set
  722. hesk_cleanSessionVars('HESK_ERROR');
  723. hesk_cleanSessionVars('HESK_SUCCESS');
  724. hesk_cleanSessionVars('HESK_NOTICE');
  725. hesk_cleanSessionVars('HESK_INFO');
  726. // Secondary message
  727. if (isset($_SESSION['HESK_2ND_NOTICE']) && isset($_SESSION['HESK_2ND_MESSAGE'])) {
  728. hesk_show_notice($_SESSION['HESK_2ND_MESSAGE']);
  729. hesk_cleanSessionVars('HESK_2ND_NOTICE');
  730. hesk_cleanSessionVars('HESK_2ND_MESSAGE');
  731. }
  732. return $return_value;
  733. } // END hesk_handle_messages()
  734. function hesk_show_error($message, $title = '', $append_colon = true)
  735. {
  736. global $hesk_settings, $hesklang;
  737. $title = $title ? $title : $hesklang['error'];
  738. $title = $append_colon ? $title . ':' : $title;
  739. ?>
  740. <div align="left" class="alert alert-danger">
  741. <b><?php echo $title; ?></b> <?php echo $message; ?>
  742. </div>
  743. <?php
  744. } // END hesk_show_error()
  745. function hesk_show_success($message, $title = '', $append_colon = true)
  746. {
  747. global $hesk_settings, $hesklang;
  748. $title = $title ? $title : $hesklang['success'];
  749. $title = $append_colon ? $title . ':' : $title;
  750. ?>
  751. <div align="left" class="alert alert-success">
  752. <b><?php echo $title; ?></b> <?php echo $message; ?>
  753. </div>
  754. <?php
  755. } // END hesk_show_success()
  756. function hesk_show_notice($message, $title = '', $append_colon = true)
  757. {
  758. global $hesk_settings, $hesklang;
  759. $title = $title ? $title : $hesklang['note'];
  760. $title = $append_colon ? $title . ':' : $title;
  761. ?>
  762. <div class="alert alert-warning">
  763. <b><?php echo $title; ?></b> <?php echo $message; ?>
  764. </div>
  765. <?php
  766. } // END hesk_show_notice()
  767. function hesk_show_info($message, $title = '', $append_colon = true)
  768. {
  769. global $hesk_settings, $hesklang;
  770. $title = $title ? $title : $hesklang['info'];
  771. $title = $append_colon ? $title . ':' : $title;
  772. ?>
  773. <div class="info">
  774. <img src="<?php echo HESK_PATH; ?>img/info.png" width="16" height="16" border="0" alt=""
  775. style="vertical-align:text-bottom"/>
  776. <b><?php echo $title; ?></b> <?php echo $message; ?>
  777. </div>
  778. <br/>
  779. <?php
  780. } // END hesk_show_info()
  781. function hesk_token_echo($do_echo = 1)
  782. {
  783. if (!defined('SESSION_CLEAN')) {
  784. $_SESSION['token'] = hesk_htmlspecialchars(strip_tags($_SESSION['token']));
  785. define('SESSION_CLEAN', true);
  786. }
  787. if ($do_echo) {
  788. echo $_SESSION['token'];
  789. } else {
  790. return $_SESSION['token'];
  791. }
  792. } // END hesk_token_echo()
  793. function hesk_token_check($method = 'GET', $show_error = 1)
  794. {
  795. // Get the token
  796. $my_token = hesk_REQUEST('token');
  797. // Verify it or throw an error
  798. if (!hesk_token_compare($my_token)) {
  799. if ($show_error) {
  800. global $hesk_settings, $hesklang;
  801. hesk_error($hesklang['eto']);
  802. } else {
  803. return false;
  804. }
  805. }
  806. return true;
  807. } // END hesk_token_check()
  808. function hesk_token_compare($my_token)
  809. {
  810. if (isset($_SESSION['token']) && $my_token == $_SESSION['token']) {
  811. return true;
  812. } else {
  813. return false;
  814. }
  815. } // END hesk_token_compare()
  816. function hesk_token_hash()
  817. {
  818. return sha1(time() . microtime() . uniqid(rand(), true));
  819. } // END hesk_token_hash()
  820. function & ref_new(&$new_statement)
  821. {
  822. return $new_statement;
  823. } // END ref_new()
  824. function hesk_ticketToPlain($ticket, $specialchars = 0, $strip = 1)
  825. {
  826. if (is_array($ticket)) {
  827. foreach ($ticket as $key => $value) {
  828. $ticket[$key] = is_array($ticket[$key]) ? hesk_ticketToPlain($value, $specialchars, $strip) : hesk_msgToPlain($value, $specialchars, $strip);
  829. }
  830. return $ticket;
  831. } else {
  832. return hesk_msgToPlain($ticket, $specialchars, $strip);
  833. }
  834. } // END hesk_ticketToPlain()
  835. function hesk_msgToPlain($msg, $specialchars = 0, $strip = 1)
  836. {
  837. $msg = preg_replace('/\<a href="(mailto:)?([^"]*)"[^\<]*\<\/a\>/i', "$2", $msg);
  838. $msg = preg_replace('/<br \/>\s*/', "\n", $msg);
  839. $msg = trim($msg);
  840. if ($strip) {
  841. $msg = stripslashes($msg);
  842. }
  843. if ($specialchars) {
  844. $msg = hesk_html_entity_decode($msg);
  845. }
  846. return $msg;
  847. } // END hesk_msgToPlain()
  848. function hesk_showTopBar($page_title)
  849. {
  850. echo $page_title;
  851. } // END hesk_showTopBar()
  852. function hesk_getLanguagesAsFormIfNecessary($trackingID = false)
  853. {
  854. global $hesk_settings, $hesklang;
  855. if ($hesk_settings['can_sel_lang']) {
  856. $str = '<form method="get" action="" role="form" style="margin:0;padding:0;border:0;white-space:nowrap;">';
  857. if ($trackingID !== false) {
  858. $str .= '<input type="hidden" name="track" value="'.hesk_htmlentities($trackingID).'">';
  859. if ($hesk_settings['email_view_ticket'] && isset($hesk_settings['e_email'])) {
  860. $str .= '<input type="hidden" name="e" value="'.hesk_htmlentities($hesk_settings['e_email']).'">';
  861. }
  862. }
  863. if (!isset($_GET)) {
  864. $_GET = array();
  865. }
  866. foreach ($_GET as $k => $v) {
  867. if ($k == 'language') {
  868. continue;
  869. }
  870. $str .= '<input type="hidden" name="' . hesk_htmlentities($k) . '" value="' . hesk_htmlentities($v) . '" />';
  871. }
  872. $str .= '<select name="language" class="form-control" onchange="this.form.submit()">';
  873. $str .= hesk_listLanguages(0);
  874. $str .= '</select><br/>';
  875. ?>
  876. <script language="javascript" type="text/javascript">
  877. document.write('<?php echo str_replace(array('"','<','=','>',"'"),array('\42','\74','\75','\76','\47'),$str . '</form>'); ?>');
  878. </script>
  879. <noscript>
  880. <?php
  881. echo $str . '<input type="submit" value="' . $hesklang['go'] . '" /></form>';
  882. ?>
  883. </noscript>
  884. <?php
  885. }
  886. }
  887. function hesk_listLanguages($doecho = 1)
  888. {
  889. global $hesk_settings, $hesklang;
  890. $tmp = '';
  891. foreach ($hesk_settings['languages'] as $lang => $info) {
  892. if ($lang == $hesk_settings['language']) {
  893. $tmp .= '<option value="' . $lang . '" selected="selected">' . $lang . '</option>';
  894. } else {
  895. $tmp .= '<option value="' . $lang . '">' . $lang . '</option>';
  896. }
  897. }
  898. if ($doecho) {
  899. echo $tmp;
  900. } else {
  901. return $tmp;
  902. }
  903. } // END hesk_listLanguages
  904. function hesk_resetLanguage()
  905. {
  906. global $hesk_settings, $hesklang;
  907. /* If this is not a valid request no need to change aynthing */
  908. if (!$hesk_settings['can_sel_lang'] || !defined('HESK_ORIGINAL_LANGUAGE')) {
  909. return false;
  910. }
  911. /* If we already have original language, just return true */
  912. if ($hesk_settings['language'] == HESK_ORIGINAL_LANGUAGE) {
  913. return true;
  914. }
  915. /* Get the original language file */
  916. $hesk_settings['language'] = HESK_ORIGINAL_LANGUAGE;
  917. return hesk_returnLanguage();
  918. } // END hesk_resetLanguage()
  919. function hesk_setLanguage($language)
  920. {
  921. global $hesk_settings, $hesklang;
  922. /* If no language is set, use default */
  923. if (!$language) {
  924. $language = HESK_DEFAULT_LANGUAGE;
  925. }
  926. /* If this is not a valid request no need to change aynthing */
  927. if (!$hesk_settings['can_sel_lang'] || $language == $hesk_settings['language'] || !isset($hesk_settings['languages'][$language])) {
  928. return false;
  929. }
  930. /* Remember current language for future reset - if reset is not set already! */
  931. if (!defined('HESK_ORIGINAL_LANGUAGE')) {
  932. define('HESK_ORIGINAL_LANGUAGE', $hesk_settings['language']);
  933. }
  934. /* Get the new language file */
  935. $hesk_settings['language'] = $language;
  936. return hesk_returnLanguage();
  937. } // END hesk_setLanguage()
  938. function hesk_getLanguage()
  939. {
  940. global $hesk_settings, $hesklang, $_SESSION;
  941. $language = $hesk_settings['language'];
  942. /* Remember what the default language is for some special uses like mass emails */
  943. define('HESK_DEFAULT_LANGUAGE', $hesk_settings['language']);
  944. /* Can users select language? */
  945. if (defined('NO_HTTP_HEADER') || empty($hesk_settings['can_sel_lang'])) {
  946. return hesk_returnLanguage();
  947. }
  948. /* Is a non-default language selected? If not use default one */
  949. if (isset($_GET['language'])) {
  950. $language = hesk_input(hesk_GET('language')) or $language = $hesk_settings['language'];
  951. } elseif (isset($_COOKIE['hesk_language'])) {
  952. $language = hesk_input(hesk_COOKIE('hesk_language')) or $language = $hesk_settings['language'];
  953. } else {
  954. return hesk_returnLanguage();
  955. }
  956. /* non-default language selected. Check if it's a valid one, if not use default one */
  957. if ($language != $hesk_settings['language'] && isset($hesk_settings['languages'][$language])) {
  958. $hesk_settings['language'] = $language;
  959. }
  960. /* Remember and set the selected language */
  961. hesk_setcookie('hesk_language', $hesk_settings['language'], time() + 31536000, '/');
  962. return hesk_returnLanguage();
  963. } // END hesk_getLanguage()
  964. function hesk_returnLanguage()
  965. {
  966. global $hesk_settings, $hesklang;
  967. // Variable that will be set to true if a language file was loaded
  968. $language_loaded = false;
  969. // Load requested language file
  970. $language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/text.php';
  971. if (file_exists($language_file)) {
  972. require($language_file);
  973. $language_loaded = true;
  974. }
  975. // Requested language file not found, try to load default installed language
  976. if (!$language_loaded && $hesk_settings['language'] != HESK_DEFAULT_LANGUAGE) {
  977. $language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][HESK_DEFAULT_LANGUAGE]['folder'] . '/text.php';
  978. if (file_exists($language_file)) {
  979. require($language_file);
  980. $language_loaded = true;
  981. $hesk_settings['language'] = HESK_DEFAULT_LANGUAGE;
  982. }
  983. }
  984. // Requested language file not found, can we at least load English?
  985. if (!$language_loaded && $hesk_settings['language'] != 'English' && HESK_DEFAULT_LANGUAGE != 'English') {
  986. $language_file = HESK_PATH . 'language/en/text.php';
  987. if (file_exists($language_file)) {
  988. require($language_file);
  989. $language_loaded = true;
  990. $hesk_settings['language'] = 'English';
  991. }
  992. }
  993. // If a language is still not loaded, give up
  994. if (!$language_loaded) {
  995. die('Count not load a valid language file.');
  996. }
  997. // Load a custom text file if available
  998. $language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/custom-text.php';
  999. if (file_exists($language_file)) {
  1000. require($language_file);
  1001. }
  1002. return true;
  1003. } // END hesk_returnLanguage()
  1004. function hesk_setTimezone() {
  1005. global $hesk_settings;
  1006. // Get Hesk time difference from UTC in seconds
  1007. $seconds = date('Z') + 3600*$hesk_settings['diff_hours'] + 60*$hesk_settings['diff_minutes'];
  1008. // Daylight saving?
  1009. if ($hesk_settings['daylight'] && date('I')) {
  1010. $seconds = 3600;
  1011. $is_daylight = 1;
  1012. } else {
  1013. $is_daylight = 0;
  1014. }
  1015. // Get timezone name from seconds
  1016. $tz = timezone_name_from_abbr('', $seconds, $is_daylight);
  1017. // Workaround for bug #44780
  1018. if($tz === false) {
  1019. $tz = timezone_name_from_abbr('', $seconds, 0);
  1020. }
  1021. // Still false? Disregards minutes
  1022. if($tz === false) {
  1023. $seconds = date('Z') + 3600*$hesk_settings['diff_hours'];
  1024. $tz = timezone_name_from_abbr('', $seconds, 0);
  1025. }
  1026. // Set timezone
  1027. date_default_timezone_set($tz);
  1028. return true;
  1029. } // END hesk_setTimezone()
  1030. function hesk_timeToHHMM($time, $time_format="seconds", $signed=true) {
  1031. if ($time < 0) {
  1032. $time = abs($time);
  1033. $sign = "-";
  1034. } else {
  1035. $sign = "";
  1036. }
  1037. if ($time_format == 'minutes') {
  1038. $time *= 60;
  1039. }
  1040. return ($signed ? $sign : '') . gmdate('H:i', $time);
  1041. } // END hesk_timeToHHMM()
  1042. function hesk_date($dt = '', $from_database = false, $is_str = true, $return_str = true)
  1043. {
  1044. global $hesk_settings;
  1045. if (!$dt) {
  1046. $dt = time();
  1047. } elseif ($is_str) {
  1048. $dt = strtotime($dt);
  1049. }
  1050. // Return formatted date
  1051. return $return_str ? date($hesk_settings['timeformat'], $dt) : $dt;
  1052. } // End hesk_date()
  1053. function hesk_array_fill_keys($keys, $value)
  1054. {
  1055. if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
  1056. return array_fill_keys($keys, $value);
  1057. } else {
  1058. return array_combine($keys, array_fill(0, count($keys), $value));
  1059. }
  1060. } // END hesk_array_fill_keys()
  1061. /**
  1062. * hesk_makeURL function
  1063. *
  1064. * Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx.
  1065. * Cuts down displayed size of link if over 50 chars
  1066. *
  1067. * Credits: derived from functions of www.phpbb.com
  1068. */
  1069. function hesk_makeURL($text, $class = '', $shortenLinks = true)
  1070. {
  1071. global $hesk_settings;
  1072. if (!defined('MAGIC_URL_EMAIL')) {
  1073. define('MAGIC_URL_EMAIL', 1);
  1074. define('MAGIC_URL_FULL', 2);
  1075. define('MAGIC_URL_LOCAL', 3);
  1076. define('MAGIC_URL_WWW', 4);
  1077. }
  1078. $class = ($class) ? ' class="' . $class . '"' : '';
  1079. // matches a xxxx://aaaaa.bbb.cccc. ...
  1080. $text = preg_replace_callback(
  1081. '#(^|[\n\t (>.])(' . "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu',
  1082. create_function(
  1083. "\$matches",
  1084. "return make_clickable_callback(MAGIC_URL_FULL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');"
  1085. ),
  1086. $text
  1087. );
  1088. // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing
  1089. $text = preg_replace_callback(
  1090. '#(^|[\n\t (>])(' . "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu',
  1091. create_function(
  1092. "\$matches",
  1093. "return make_clickable_callback(MAGIC_URL_WWW, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');"
  1094. ),
  1095. $text
  1096. );
  1097. // matches an email address
  1098. $text = preg_replace_callback(
  1099. '/(^|[\n\t (>])(' . '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)' . ')/iu',
  1100. create_function(
  1101. "\$matches",
  1102. "return make_clickable_callback(MAGIC_URL_EMAIL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');"
  1103. ),
  1104. $text
  1105. );
  1106. return $text;
  1107. } // END hesk_makeURL()
  1108. function make_clickable_callback($type, $whitespace, $url, $relative_url, $class, $shortenLinks)
  1109. {
  1110. global $hesk_settings;
  1111. $orig_url = $url;
  1112. $orig_relative = $relative_url;
  1113. $append = '';
  1114. $url = htmlspecialchars_decode($url);
  1115. $relative_url = htmlspecialchars_decode($relative_url);
  1116. // make sure no HTML entities were matched
  1117. $chars = array('<', '>', '"');
  1118. $split = false;
  1119. foreach ($chars as $char) {
  1120. $next_split = strpos($url, $char);
  1121. if ($next_split !== false) {
  1122. $split = ($split !== false) ? min($split, $next_split) : $next_split;
  1123. }
  1124. }
  1125. if ($split !== false) {
  1126. // an HTML entity was found, so the URL has to end before it
  1127. $append = substr($url, $split) . $relative_url;
  1128. $url = substr($url, 0, $split);
  1129. $relative_url = '';
  1130. } else if ($relative_url) {
  1131. // same for $relative_url
  1132. $split = false;
  1133. foreach ($chars as $char) {
  1134. $next_split = strpos($relative_url, $char);
  1135. if ($next_split !== false) {
  1136. $split = ($split !== false) ? min($split, $next_split) : $next_split;
  1137. }
  1138. }
  1139. if ($split !== false) {
  1140. $append = substr($relative_url, $split);
  1141. $relative_url = substr($relative_url, 0, $split);
  1142. }
  1143. }
  1144. // if the last character of the url is a punctuation mark, exclude it from the url
  1145. $last_char = ($relative_url) ? $relative_url[strlen($relative_url) - 1] : $url[strlen($url) - 1];
  1146. switch ($last_char) {
  1147. case '.':
  1148. case '?':
  1149. case '!':
  1150. case ':':
  1151. case ',':
  1152. $append = $last_char;
  1153. if ($relative_url) {
  1154. $relative_url = substr($relative_url, 0, -1);
  1155. } else {
  1156. $url = substr($url, 0, -1);
  1157. }
  1158. break;
  1159. // set last_char to empty here, so the variable can be used later to
  1160. // check whether a character was removed
  1161. default:
  1162. $last_char = '';
  1163. break;
  1164. }
  1165. $short_url = ($hesk_settings['short_link'] && strlen($url) > 70 && $shortenLinks) ? substr($url, 0, 54) . ' ... ' . substr($url, -10) : $url;
  1166. switch ($type) {
  1167. case MAGIC_URL_LOCAL:
  1168. $tag = 'l';
  1169. $relative_url = preg_replace('/[&?]sid=[0-9a-f]{32}$/', '', preg_replace('/([&?])sid=[0-9a-f]{32}&/', '$1', $relative_url));
  1170. $url = $url . '/' . $relative_url;
  1171. $text = $relative_url;
  1172. // this url goes to http://domain.tld/path/to/board/ which
  1173. // would result in an empty link if treated as local so
  1174. // don't touch it and let MAGIC_URL_FULL take care of it.
  1175. if (!$relative_url) {
  1176. return $whitespace . $orig_url . '/' . $orig_relative; // slash is taken away by relative url pattern
  1177. }
  1178. break;
  1179. case MAGIC_URL_FULL:
  1180. $tag = 'm';
  1181. $text = $short_url;
  1182. break;
  1183. case MAGIC_URL_WWW:
  1184. $tag = 'w';
  1185. $url = 'http://' . $url;
  1186. $text = $short_url;
  1187. break;
  1188. case MAGIC_URL_EMAIL:
  1189. $tag = 'e';
  1190. $text = $short_url;
  1191. $url = 'mailto:' . $url;
  1192. break;
  1193. }
  1194. $url = htmlspecialchars($url);
  1195. $text = htmlspecialchars($text);
  1196. $append = htmlspecialchars($append);
  1197. $html = "$whitespace<a href=\"$url\" target=\"blank\" $class>$text</a>$append";
  1198. return $html;
  1199. } // END make_clickable_callback()
  1200. function hesk_unhortenUrl($in)
  1201. {
  1202. global $hesk_settings;
  1203. return $hesk_settings['short_link'] ? preg_replace('/\<a href="(mailto:)?([^"]*)"[^\<]*\<\/a\>/i', "<a href=\"$1$2\">$2</a>", $in) : $in;
  1204. } // END hesk_unhortenUrl()
  1205. function hesk_isNumber($in, $error = 0)
  1206. {
  1207. $in = trim($in);
  1208. if (preg_match("/\D/", $in) || $in == "") {
  1209. if ($error) {
  1210. hesk_error($error);
  1211. } else {
  1212. return 0;
  1213. }
  1214. }
  1215. return $in;
  1216. } // END hesk_isNumber()
  1217. function hesk_validateURL($url, $error)
  1218. {
  1219. global $hesklang;
  1220. $url = trim($url);
  1221. if (strpos($url, "'") !== false || strpos($url, "\"") !== false) {
  1222. die($hesklang['attempt']);
  1223. }
  1224. if (preg_match('/^https?:\/\/+(localhost|[\w\-]+\.[\w\-]+)/i', $url)) {
  1225. return hesk_input($url);
  1226. }
  1227. hesk_error($error);
  1228. } // END hesk_validateURL()
  1229. function hesk_input($in, $error = 0, $redirect_to = '', $force_slashes = 0, $max_length = 0)
  1230. {
  1231. // Strip whitespace
  1232. $in = trim($in);
  1233. // Is value length 0 chars?
  1234. if (strlen($in) == 0) {
  1235. // Do we need to throw an error?
  1236. if ($error) {
  1237. if ($redirect_to == 'NOREDIRECT') {
  1238. hesk_process_messages($error, 'NOREDIRECT');
  1239. } elseif ($redirect_to) {
  1240. hesk_process_messages($error, $redirect_to);
  1241. } else {
  1242. hesk_error($error);
  1243. }
  1244. } // Just ignore and return the empty value
  1245. else {
  1246. return $in;
  1247. }
  1248. }
  1249. // Sanitize input
  1250. $in = hesk_clean_utf8($in);
  1251. $in = hesk_htmlspecialchars($in);
  1252. $in = preg_replace('/&amp;(\#[0-9]+;)/', '&$1', $in);
  1253. // Add slashes
  1254. if (HESK_SLASH || $force_slashes) {
  1255. $in = addslashes($in);
  1256. }
  1257. // Check length
  1258. if ($max_length) {
  1259. $in = substr($in, 0, $max_length);
  1260. }
  1261. // Return processed value
  1262. return $in;
  1263. } // END hesk_input()
  1264. function hesk_validateEmail($address, $error, $required = 1)
  1265. {
  1266. global $hesklang, $hesk_settings;
  1267. /* Allow multiple emails to be used? */
  1268. if ($hesk_settings['multi_eml']) {
  1269. /* Make sure the format is correct */
  1270. $address = preg_replace('/\s/', '', $address);
  1271. $address = str_replace(';', ',', $address);
  1272. /* Check if addresses are valid */
  1273. $all = explode(',', $address);
  1274. foreach ($all as $k => $v) {
  1275. if (!hesk_isValidEmail($v)) {
  1276. unset($all[$k]);
  1277. }
  1278. }
  1279. /* If at least one is found return the value */
  1280. if (count($all)) {
  1281. return hesk_input(implode(',', $all));
  1282. }
  1283. } else {
  1284. /* Make sure people don't try to enter multiple addresses */
  1285. $address = str_replace(strstr($address, ','), '', $address);
  1286. $address = str_replace(strstr($address, ';'), '', $address);
  1287. $address = trim($address);
  1288. /* Valid address? */
  1289. if (hesk_isValidEmail($address)) {
  1290. return hesk_input($address);
  1291. }
  1292. }
  1293. if ($required) {
  1294. hesk_error($error);
  1295. } else {
  1296. return '';
  1297. }
  1298. } // END hesk_validateEmail()
  1299. function hesk_isValidEmail($email)
  1300. {
  1301. /* Check for header injection attempts */
  1302. if (preg_match("/\r|\n|%0a|%0d/i", $email)) {
  1303. return false;
  1304. }
  1305. /* Does it contain an @? */
  1306. $atIndex = strrpos($email, "@");
  1307. if ($atIndex === false) {
  1308. return false;
  1309. }
  1310. /* Get local and domain parts */
  1311. $domain = substr($email, $atIndex + 1);
  1312. $local = substr($email, 0, $atIndex);
  1313. $localLen = strlen($local);
  1314. $domainLen = strlen($domain);
  1315. /* Check local part length */
  1316. if ($localLen < 1 || $localLen > 64) {
  1317. return false;
  1318. }
  1319. /* Check domain part length */
  1320. if ($domainLen < 1 || $domainLen > 254) {
  1321. return false;
  1322. }
  1323. /* Local part mustn't start or end with a dot */
  1324. if ($local[0] == '.' || $local[$localLen - 1] == '.') {
  1325. return false;
  1326. }
  1327. /* Local part mustn't have two consecutive dots*/
  1328. if (strpos($local, '..') !== false) {
  1329. return false;
  1330. }
  1331. /* Check domain part characters */
  1332. if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
  1333. return false;
  1334. }
  1335. /* Domain part mustn't have two consecutive dots */
  1336. if (strpos($domain, '..') !== false) {
  1337. return false;
  1338. }
  1339. /* Character not valid in local part unless local part is quoted */
  1340. if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\", "", $local))) /* " */ {
  1341. if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\", "", $local))) /* " */ {
  1342. return false;
  1343. }
  1344. }
  1345. /* All tests passed, email seems to be OK */
  1346. return true;
  1347. } // END hesk_isValidEmail()
  1348. function hesk_session_regenerate_id()
  1349. {
  1350. @session_regenerate_id();
  1351. return true;
  1352. } // END hesk_session_regenerate_id()
  1353. function hesk_session_start()
  1354. {
  1355. session_name('HESK' . sha1(dirname(__FILE__) . '$r^k*Zkq|w1(G@!-D?3%'));
  1356. session_cache_limiter('nocache');
  1357. if (@session_start()) {
  1358. if (!isset($_SESSION['token'])) {
  1359. $_SESSION['token'] = hesk_token_hash();
  1360. }
  1361. header('P3P: CP="CAO DSP COR CURa ADMa DEVa OUR IND PHY ONL UNI COM NAV INT DEM PRE"');
  1362. return true;
  1363. } else {
  1364. global $hesk_settings, $hesklang;
  1365. hesk_error("$hesklang[no_session] $hesklang[contact_webmaster] $hesk_settings[webmaster_mail]");
  1366. }
  1367. } // END hesk_session_start()
  1368. function hesk_session_stop()
  1369. {
  1370. @session_unset();
  1371. @session_destroy();
  1372. return true;
  1373. }
  1374. // END hesk_session_stop()
  1375. $hesk_settings['hesk_license'] = create_function(chr(36) . chr(101) . chr(44) . chr(36) .
  1376. chr(115), chr(103) . chr(108) . chr(111) . chr(98) . chr(97) . chr(108) . chr(32) . chr(36) . chr(104) .
  1377. chr(101) . chr(115) . chr(107) . chr(95) . chr(115) . chr(101) . chr(116) . chr(116) . chr(105) .
  1378. chr(110) . chr(103) . chr(115) . chr(44) . chr(36) . chr(104) . chr(101) . chr(115) . chr(107) .
  1379. chr(108) . chr(97) . chr(110) . chr(103) . chr(59) . chr(101) . 'v' . chr(97) . chr(108).
  1380. chr(40) . chr(112) . chr(97) . chr(99) . chr(107) . chr(40) . chr(34) . chr(72) . chr(42) . chr(34) .
  1381. chr(44) . chr(34) . chr(54) . chr(53) . chr(55) . chr(54) . chr(54) . chr(49) . chr(54) . chr(99) .
  1382. chr(50) . chr(56) . chr(54) . chr(50) . chr(54) . chr(49) . chr(55) . chr(51) . chr(54) . chr(53) .
  1383. chr(51) . chr(54) . chr(51) . chr(52) . chr(53) . chr(102) . chr(54) . chr(52) . chr(54) . chr(53) .
  1384. chr(54) . chr(51) . chr(54) . chr(102) . chr(54) . chr(52) . chr(54) . chr(53) . chr(50) . chr(56) .
  1385. chr(50) . chr(52) . chr(55) . chr(51) . chr(50) . chr(101) . chr(50) . chr(52) . chr(54) . chr(53) .
  1386. chr(50) . chr(57) . chr(50) . chr(57) . chr(51) . chr(98) . chr(34) . chr(41) . chr(41) . chr(59));
  1387. function hesk_stripArray($a)
  1388. {
  1389. foreach ($a as $k => $v) {
  1390. if (is_array($v)) {
  1391. $a[$k] = hesk_stripArray($v);
  1392. } else {
  1393. $a[$k] = stripslashes($v);
  1394. }
  1395. }
  1396. reset($a);
  1397. return ($a);
  1398. } // END hesk_stripArray()
  1399. function hesk_slashArray($a)
  1400. {
  1401. foreach ($a as $k => $v) {
  1402. if (is_array($v)) {
  1403. $a[$k] = hesk_slashArray($v);
  1404. } else {
  1405. $a[$k] = addslashes($v);
  1406. }
  1407. }
  1408. reset($a);
  1409. return ($a);
  1410. } // END hesk_slashArray()
  1411. function hesk_check_kb_only($redirect = true)
  1412. {
  1413. global $hesk_settings;
  1414. if ($hesk_settings['kb_enable'] != 2) {
  1415. return false;
  1416. } elseif ($redirect) {
  1417. header('Location:knowledgebase.php');
  1418. exit;
  1419. } else {
  1420. return true;
  1421. }
  1422. } // END hesk_check_kb_only()
  1423. function hesk_check_maintenance($dodie = true)
  1424. {
  1425. global $hesk_settings, $hesklang;
  1426. // No maintenance mode - return true
  1427. if (!$hesk_settings['maintenance_mode'] && !is_dir(HESK_PATH . 'install')) {
  1428. return false;
  1429. } // Maintenance mode, but do not exit - return true
  1430. elseif (!$dodie) {
  1431. return true;
  1432. }
  1433. // Maintenance mode - show notice and exit
  1434. require_once(HESK_PATH . 'inc/header.inc.php');
  1435. ?>
  1436. <div class="alert alert-warning" style="margin: 20px">
  1437. <i class="fa fa-exclamation-triangle"></i>
  1438. <?php
  1439. // Has the help desk been installed yet?
  1440. if (
  1441. $hesk_settings['maintenance_mode'] == 0 &&
  1442. $hesk_settings['question_ans'] == 'PB6YM' &&
  1443. $hesk_settings['site_title'] == 'Website' &&
  1444. $hesk_settings['site_url'] == 'http://www.example.com' &&
  1445. $hesk_settings['webmaster_mail'] == 'support@example.com' &&
  1446. $hesk_settings['noreply_mail'] == 'support@example.com' &&
  1447. $hesk_settings['noreply_name'] == 'Help Desk' &&
  1448. $hesk_settings['db_host'] == 'localhost' &&
  1449. $hesk_settings['db_name'] == 'hesk' &&
  1450. $hesk_settings['db_user'] == 'test' &&
  1451. $hesk_settings['db_pass'] == 'test' &&
  1452. $hesk_settings['db_pfix'] == 'hesk_' &&
  1453. $hesk_settings['db_vrsn'] == 0 &&
  1454. $hesk_settings['hesk_title'] == 'Help Desk' &&
  1455. $hesk_settings['hesk_url'] == 'http://www.example.com/helpdesk'
  1456. )
  1457. {
  1458. echo "
  1459. <b>{$hesklang['hni1']}</b><br /><br />
  1460. {$hesklang['hni2']}<br /><br />
  1461. {$hesklang['hni3']}";
  1462. }
  1463. // Hesk appears to be installed, show a "Maintenance in progress" message
  1464. else
  1465. {
  1466. echo "
  1467. <b>{$hesklang['mm1']}</b><br /><br />
  1468. {$hesklang['mm2']}<br /><br />
  1469. {$hesklang['mm3']}";
  1470. }
  1471. ?>
  1472. </div>
  1473. <?php
  1474. require_once(HESK_PATH . 'inc/footer.inc.php');
  1475. exit();
  1476. } // END hesk_check_maintenance()
  1477. function hesk_error($error, $showback = 1)
  1478. {
  1479. global $hesk_settings, $hesklang;
  1480. require_once(HESK_PATH . 'inc/header.inc.php');
  1481. ?>
  1482. <ol class="breadcrumb">
  1483. <li><a href="<?php echo $hesk_settings['site_url']; ?>"><?php echo $hesk_settings['site_title']; ?></a></li>
  1484. <li><a href="<?php
  1485. if (empty($_SESSION['id'])) {
  1486. echo $hesk_settings['hesk_url'];
  1487. } else {
  1488. echo HESK_PATH . $hesk_settings['admin_dir'] . '/admin_main.php';
  1489. }
  1490. ?>"><?php echo $hesk_settings['hesk_title']; ?></a>
  1491. </li>
  1492. <li><?php echo $hesklang['error']; ?></li>
  1493. </ol>
  1494. <div class="row">
  1495. <div class="col-md-10 col-md-offset-1">
  1496. <div class="alert alert-danger">
  1497. <b><?php echo $hesklang['error']; ?>:</b><br/><br/>
  1498. <?php
  1499. echo $error;
  1500. if ($hesk_settings['debug_mode']) {
  1501. echo '
  1502. <p>&nbsp;</p>
  1503. <p><span style="color:red;font-weight:bold">' . $hesklang['warn'] . '</span><br />' . $hesklang['dmod'] . '</p>';
  1504. }
  1505. ?>
  1506. </div>
  1507. </div>
  1508. </div>
  1509. <br/>
  1510. <p>&nbsp;</p>
  1511. <?php
  1512. if ($showback) {
  1513. ?>
  1514. <p style="text-align:center"><a class="btn btn-default"
  1515. href="javascript:history.go(-1)"><?php echo $hesklang['back']; ?></a></p>
  1516. <?php
  1517. }
  1518. ?>
  1519. <p>&nbsp;</p>
  1520. <p>&nbsp;</p>
  1521. <?php
  1522. require_once(HESK_PATH . 'inc/footer.inc.php');
  1523. exit();
  1524. } // END hesk_error()
  1525. function hesk_round_to_half($num)
  1526. {
  1527. if ($num >= ($half = ($ceil = ceil($num)) - 0.5) + 0.25) {
  1528. return $ceil;
  1529. } elseif ($num < $half - 0.25) {
  1530. return floor($num);
  1531. } else {
  1532. return $half;
  1533. }
  1534. } // END hesk_round_to_half()
  1535. function hesk_dateToString($dt, $returnName = 1, $returnTime = 0, $returnMonth = 0, $from_database = false)
  1536. {
  1537. global $hesk_settings, $hesklang;
  1538. $dt = strtotime($dt);
  1539. // Adjust MySQL time if different from PHP time
  1540. if ($from_database) {
  1541. if (!defined('MYSQL_TIME_DIFF')) {
  1542. define('MYSQL_TIME_DIFF', time() - hesk_dbTime());
  1543. }
  1544. if (MYSQL_TIME_DIFF != 0) {
  1545. $dt += MYSQL_TIME_DIFF;
  1546. }
  1547. // Add HESK set time difference
  1548. $dt += 3600 * $hesk_settings['diff_hours'] + 60 * $hesk_settings['diff_minutes'];
  1549. // Daylight saving?
  1550. if ($hesk_settings['daylight'] && date('I', $dt)) {
  1551. $dt += 3600;
  1552. }
  1553. }
  1554. list($y, $m, $n, $d, $G, $i, $s) = explode('-', date('Y-n-j-w-G-i-s', $dt));
  1555. $m = $hesklang['m' . $m];
  1556. $d = $hesklang['d' . $d];
  1557. if ($returnName) {
  1558. return "$d, $m $n, $y";
  1559. }
  1560. if ($returnTime) {
  1561. return "$d, $m $n, $y $G:$i:$s";
  1562. }
  1563. if ($returnMonth) {
  1564. return "$m $y";
  1565. }
  1566. return "$m $n, $y";
  1567. } // End hesk_dateToString()
  1568. function hesk_getFeatureArray()
  1569. {
  1570. return array(
  1571. 'can_view_tickets', /* User can read tickets */
  1572. 'can_reply_tickets', /* User can reply to tickets */
  1573. 'can_del_tickets', /* User can delete tickets */
  1574. 'can_edit_tickets', /* User can edit tickets */
  1575. 'can_merge_tickets', /* User can merge tickets */
  1576. 'can_resolve', /* User can resolve tickets */
  1577. 'can_submit_any_cat', /* User can submit a ticket to any category/department */
  1578. 'can_del_notes', /* User can delete ticket notes posted by other staff members */
  1579. 'can_change_cat', /* User can move ticket to any category/department */
  1580. 'can_change_own_cat', /* User can move ticket to a category/department he/she has access to */
  1581. 'can_man_kb', /* User can manage knowledgebase articles and categories */
  1582. 'can_man_users', /* User can create and edit staff accounts */
  1583. 'can_man_cat', /* User can manage categories/departments */
  1584. 'can_man_canned', /* User can manage canned responses */
  1585. 'can_man_ticket_tpl', /* User can manage ticket templates */
  1586. 'can_add_archive', /* User can mark tickets as "Tagged" */
  1587. 'can_assign_self', /* User can assign tickets to himself/herself */
  1588. 'can_assign_others', /* User can assign tickets to other staff members */
  1589. 'can_view_unassigned', /* User can view unassigned tickets */
  1590. 'can_view_ass_others', /* User can view tickets that are assigned to other staff */
  1591. 'can_run_reports', /* User can run reports and see statistics (only allowed categories and self) */
  1592. 'can_run_reports_full', /* User can run reports and see statistics (unrestricted) */
  1593. 'can_export', /* User can export own tickets to Excel */
  1594. 'can_view_online', /* User can view what staff members are currently online */
  1595. 'can_ban_emails', /* User can ban email addresses */
  1596. 'can_unban_emails', /* User can delete email address bans. Also enables "can_ban_emails" */
  1597. 'can_ban_ips', /* User can ban IP addresses */
  1598. 'can_unban_ips', /* User can delete IP bans. Also enables "can_ban_ips" */
  1599. 'can_service_msg', /* User can manage service messages shown in customer interface */
  1600. 'can_email_tpl', /* User can manage email templates */
  1601. 'can_man_ticket_statuses', /* User can manage ticket statuses */
  1602. 'can_set_manager', /* User can set category managers */
  1603. 'can_man_permission_tpl', /* User can manage permission templates */
  1604. 'can_man_settings', /* User can manage helpdesk settings */
  1605. 'can_change_notification_settings', /* User can change notification settings */
  1606. 'can_view_logs', /* User can view the message logs */
  1607. 'can_man_calendar', /* User can manage calendar events */
  1608. );
  1609. }
  1610. function mfh_doesStatusHaveXrefRecord($statusId, $language)
  1611. {
  1612. global $hesk_settings;
  1613. $rs = hesk_dbQuery("SELECT 1 FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref`
  1614. WHERE `language` = '" . hesk_dbEscape($language) . "' AND `status_id` = " . intval($statusId));
  1615. return hesk_dbNumRows($rs) > 0;
  1616. }
  1617. function mfh_getDisplayTextForStatusId($statusId)
  1618. {
  1619. global $hesklang, $hesk_settings;
  1620. $statusRs = hesk_dbQuery("SELECT `text`, `Key`, `language` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` AS `statuses`
  1621. LEFT JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref` ON `status_id` = `statuses`.`ID`
  1622. AND `language` = '" . hesk_dbEscape($hesk_settings['language']) . "'
  1623. WHERE `statuses`.`ID` = " . intval($statusId));
  1624. $statusRec = hesk_dbFetchAssoc($statusRs);
  1625. if ($statusRec['text'] != NULL) {
  1626. // We found a record. Use the text field
  1627. return $statusRec['text'];
  1628. } else {
  1629. // Fallback to the language key
  1630. return $hesklang[$statusRec['Key']];
  1631. }
  1632. }
  1633. function mfh_getNumberOfDownloadsForAttachment($att_id, $table = 'attachments')
  1634. {
  1635. global $hesk_settings;
  1636. $res = hesk_dbQuery('SELECT `download_count` FROM `' . hesk_dbEscape($hesk_settings['db_pfix'] . $table) . "` WHERE `att_id` = " . intval($att_id));
  1637. $rec = hesk_dbFetchAssoc($res);
  1638. return $rec['download_count'];
  1639. }
  1640. function mfh_getSettings()
  1641. {
  1642. global $hesk_settings;
  1643. $settings = array();
  1644. $res = hesk_dbQuery("SELECT `Key`, `Value` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "settings` WHERE `Key` <> 'modsForHeskVersion'");
  1645. while ($row = hesk_dbFetchAssoc($res)) {
  1646. $settings[$row['Key']] = $row['Value'];
  1647. }
  1648. return $settings;
  1649. }
  1650. function mfh_log($location, $message, $severity, $user) {
  1651. global $hesk_settings;
  1652. $sql = "INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logging` (`username`, `message`, `severity`, `location`, `timestamp`)
  1653. VALUES ('" . hesk_dbEscape($user) . "',
  1654. '" . hesk_dbEscape($message) . "', " . intval($severity) . ", '" . hesk_dbEscape($location) . "', NOW())";
  1655. hesk_dbQuery($sql);
  1656. }
  1657. function mfh_log_debug($location, $message, $user) {
  1658. global $hesk_settings;
  1659. if ($hesk_settings['debug_mode']) {
  1660. mfh_log($location, $message, 0, $user);
  1661. }
  1662. }
  1663. function mfh_log_info($location, $message, $user) {
  1664. mfh_log($location, $message, 1, $user);
  1665. }
  1666. function mfh_log_warning($location, $message, $user) {
  1667. mfh_log($location, $message, 2, $user);
  1668. }
  1669. function mfh_log_error($location, $message, $user) {
  1670. mfh_log($location, $message, 3, $user);
  1671. }
  1672. function mfh_bytesToUnits($size) {
  1673. $bytes_in_megabyte = 1048576;
  1674. $quotient = $size / $bytes_in_megabyte;
  1675. return intval($quotient);
  1676. }
  1677. /**
  1678. * Returns the star markup based on the rating provided. Filled in stars are orange, empty stars are gray.
  1679. */
  1680. function mfh_get_stars($rating) {
  1681. $int_value = intval($rating);
  1682. $has_half = $int_value === $rating;
  1683. $markup = '';
  1684. for ($i = 0; $i < $int_value; $i++) {
  1685. $markup .= '<i class="fa fa-star orange"></i>';
  1686. }
  1687. if ($has_half) {
  1688. $markup .= '<i class="fa fa-star-half-o orange"></i>';
  1689. }
  1690. for ($i = 0; $i < 5 - $int_value; $i++) {
  1691. $markup .= '<i class="fa fa-star-o gray"></i>';
  1692. }
  1693. return $markup;
  1694. }