PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/magirc/Magirc.class.php

https://github.com/CerberusStyle/magirc
PHP | 259 lines | 179 code | 21 blank | 59 comment | 51 complexity | 5032b3887562b3f391063f3fe98acbb3 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. <?php
  2. // Root path
  3. define('PATH_ROOT', __DIR__ . '/../../');
  4. // Database configuration
  5. class Magirc_DB extends DB {
  6. private static $instance = NULL;
  7. public static function getInstance() {
  8. if (is_null(self::$instance) === true) {
  9. $db = null;
  10. $error = false;
  11. if (file_exists(PATH_ROOT.'conf/magirc.cfg.php')) {
  12. include(PATH_ROOT.'conf/magirc.cfg.php');
  13. } else {
  14. $error = true;
  15. }
  16. if (!is_array($db)) {
  17. $error = true;
  18. }
  19. if ($error) {
  20. die ('<strong>MagIRC</strong> is not configured<br />Please run <a href="setup/">Setup</a>');
  21. }
  22. $dsn = "mysql:dbname={$db['database']};host={$db['hostname']}";
  23. $args = array();
  24. if (isset($db['ssl']) && $db['ssl_key']) $args[PDO::MYSQL_ATTR_SSL_KEY] = $db['ssl_key'];
  25. if (isset($db['ssl']) && $db['ssl_cert']) $args[PDO::MYSQL_ATTR_SSL_CERT] = $db['ssl_cert'];
  26. if (isset($db['ssl']) && $db['ssl_ca']) $args[PDO::MYSQL_ATTR_SSL_CA] = $db['ssl_ca'];
  27. self::$instance = new DB($dsn, $db['username'], $db['password'], $args);
  28. if (self::$instance->error) die('Error opening the MagIRC database<br />' . self::$instance->error);
  29. }
  30. return self::$instance;
  31. }
  32. }
  33. class Magirc {
  34. public $db;
  35. public $cfg;
  36. public $tpl;
  37. public $slim;
  38. public $denora;
  39. /**
  40. * Magirc Class Constructor
  41. * @param type $api_mode ('web': frontend, 'denora': Denora API)
  42. */
  43. function __construct($api_mode = "web") {
  44. // Setup the Slim framework
  45. $this->slim = new \Slim\Slim();
  46. if ($api_mode == "web") {
  47. // Setup the template engine
  48. $this->tpl = new Smarty;
  49. $this->tpl->template_dir = 'theme/default/tpl';
  50. $this->tpl->config_dir = 'theme/default/cfg';
  51. $this->tpl->compile_dir = 'tmp';
  52. $this->tpl->cache_dir = 'tmp';
  53. $this->tpl->autoload_filters = array('pre' => array('jsmin'));
  54. $this->tpl->addPluginsDir('lib/smarty-plugins/');
  55. }
  56. // Setup the database
  57. $this->db = Magirc_DB::getInstance();
  58. $query = "SHOW TABLES LIKE 'magirc_config'";
  59. $this->db->query($query, SQL_INIT);
  60. if (!$this->db->record) {
  61. $this->displayError('Database table missing. Please run setup.', $api_mode);
  62. }
  63. // Get the configuration
  64. $this->cfg = new Config();
  65. // Initialize modules
  66. define('IRCD', $this->cfg->ircd_type);
  67. if ($api_mode == "web" || $api_mode == "denora") {
  68. $this->denora = new Denora();
  69. }
  70. // Set the locale
  71. $locales = $this->getLocales();
  72. if (isset($_GET['locale']) && in_array($_GET['locale'], $locales)) {
  73. setcookie('magirc_locale', $_GET['locale'], time()+60*60*24*30, '/');
  74. $locale = $_GET['locale'];
  75. } elseif (isset($_COOKIE['magirc_locale']) && in_array($_COOKIE['magirc_locale'], $locales)) {
  76. $locale = $_COOKIE['magirc_locale'];
  77. } else {
  78. $locale = $this->detectLocale($locales);
  79. }
  80. // Configure gettext
  81. require_once(PATH_ROOT.'lib/gettext/gettext.inc');
  82. $domain = "messages";
  83. T_setlocale(LC_ALL, $locale.'.UTF-8', $locale);
  84. T_bindtextdomain($domain, PATH_ROOT.'locale/');
  85. T_bind_textdomain_codeset($domain, 'UTF-8');
  86. T_textdomain($domain);
  87. if (!ini_get("safe_mode")) {
  88. @putenv("LC_ALL={$locale}.utf8");
  89. }
  90. define('LOCALE', $locale);
  91. define('LANG', substr($locale, 0, 2));
  92. }
  93. /**
  94. * Gets a list of available locales
  95. * @return array
  96. */
  97. private function getLocales() {
  98. $locales = array();
  99. foreach (glob(PATH_ROOT."locale/*") as $filename) {
  100. if (is_dir($filename)) $locales[] = basename($filename);
  101. }
  102. return $locales;
  103. }
  104. /**
  105. * Detects the best locale based on HTTP ACCEPT_LANGUAGE
  106. * @param array $available_languages Array of available locales
  107. * @return string Locale
  108. */
  109. private function detectLocale($available_locales) {
  110. $hits = array();
  111. $bestlang = $this->cfg->locale;
  112. if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  113. preg_match_all("/([[:alpha:]]{1,8})(-([[:alpha:]|-]{1,8}))?(\s*;\s*q\s*=\s*(1\.0{0,3}|0\.\d{0,3}))?\s*(,|$)/i", $_SERVER['HTTP_ACCEPT_LANGUAGE'], $hits, PREG_SET_ORDER);
  114. $bestqval = 0;
  115. foreach ($hits as $arr) {
  116. $langprefix = strtolower ($arr[1]);
  117. $qvalue = empty($arr[5]) ? 1.0 : floatval($arr[5]);
  118. if (in_array($langprefix,$available_locales) && ($qvalue > $bestqval)) {
  119. $bestlang = $langprefix;
  120. $bestqval = $qvalue;
  121. }
  122. }
  123. }
  124. return $bestlang;
  125. }
  126. /**
  127. * Gets the page content for the specified name
  128. * @param string $name Content identifier
  129. * @return string HTML content
  130. */
  131. function getContent($name) {
  132. $ps = $this->db->prepare("SELECT text FROM magirc_content WHERE name = :name");
  133. $ps->bindParam(':name', $name, PDO::PARAM_STR);
  134. $ps->execute();
  135. return $ps->fetch(PDO::FETCH_COLUMN);
  136. }
  137. /**
  138. * Checks thet permission for the given type and target.
  139. * Terminates the program with an appropriate error message on failure.
  140. * (Used by the RESTful API)
  141. * @param string $type Choices: 'channel'
  142. * @param string $target For example the channel name
  143. */
  144. function checkPermission($type, $target) {
  145. $result = 200;
  146. switch($type) {
  147. case 'channel':
  148. $result = $this->denora->checkChannel($target);
  149. break;
  150. }
  151. // In case of error the application will terminate, otherwise it will continue normally
  152. switch ($result) {
  153. case 404: $this->slim->notFound();
  154. case 403: $this->slim->halt(403, $this->jsonOutput(array('error' => "HTTP 403 Access Denied")));
  155. }
  156. }
  157. /**
  158. * Encodes the given data as a JSON object.
  159. * (Used by the RESTful API)
  160. * @param mixed $data Data
  161. * @param boolean $datatables allow/forbid DataTables format
  162. * @param string $idcolumn Column name to use as index for the DataTables automatic row id. If not specified, the first column will be used.
  163. */
  164. function jsonOutput($data, $datatables = false, $idcolumn = null) {
  165. if ($datatables && @$_GET['format'] == "datatables") {
  166. if (!$idcolumn && count($data) > 0) $idcolumn = key($data[0]);
  167. foreach ($data as $key => $val) {
  168. if (is_array($data[$key])) $data[$key]["DT_RowId"] = $val[$idcolumn];
  169. else $data[$key]->DT_RowId = $val->$idcolumn;
  170. }
  171. echo json_encode(array('aaData' => $data));
  172. } else {
  173. echo json_encode($data);
  174. }
  175. }
  176. /**
  177. * Returns the session status
  178. * @return boolean true: valid session, false: invalid or no session
  179. */
  180. function sessionStatus() {
  181. if (!isset($_SESSION["loginUsername"])) {
  182. $_SESSION["message"] = "Access denied";
  183. return false;
  184. }
  185. if (!isset($_SESSION["loginIP"]) || ($_SESSION["loginIP"] != $_SERVER["REMOTE_ADDR"])) {
  186. $_SESSION["message"] = "Access denied";
  187. return false;
  188. }
  189. return true;
  190. }
  191. /**
  192. * Returns the given text with html tags for colors and styling
  193. * @param string $text IRC text
  194. * @return string HTML text
  195. */
  196. public static function irc2html($text) {
  197. $lines = explode("\n", utf8_decode($text));
  198. $out = '';
  199. foreach ($lines as $line) {
  200. $line = nl2br(htmlentities(utf8_decode($line), ENT_COMPAT));
  201. // replace control codes
  202. $line = preg_replace_callback('/[\003](\d{0,2})(,\d{1,2})?([^\003\x0F]*)(?:[\003](?!\d))?/', function($matches) {
  203. $colors = array('#FFFFFF', '#000000', '#00007F', '#009300', '#FF0000', '#7F0000', '#9C009C', '#FC7F00', '#FFFF00', '#00FC00', '#009393', '#00FFFF', '#0000FC', '#FF00FF', '#7F7F7F', '#D2D2D2');
  204. $options = '';
  205. if ($matches[2] != '') {
  206. $bgcolor = trim(substr($matches[2], 1));
  207. if ((int) $bgcolor < count($colors)) {
  208. $options .= 'background-color: ' . $colors[(int) $bgcolor] . '; ';
  209. }
  210. }
  211. $forecolor = trim($matches[1]);
  212. if ($forecolor != '' && (int) $forecolor < count($colors)) {
  213. $options .= 'color: ' . $colors[(int) $forecolor] . ';';
  214. }
  215. if ($options != '') {
  216. return '<span style="' . $options . '">' . $matches[3] . '</span>';
  217. } else {
  218. return $matches[3];
  219. }
  220. }, $line);
  221. $line = preg_replace('/[\002]([^\002\x0F]*)(?:[\002])?/', '<strong>$1</strong>', $line);
  222. $line = preg_replace('/[\x1F]([^\x1F\x0F]*)(?:[\x1F])?/', '<span style="text-decoration: underline;">$1</span>', $line);
  223. $line = preg_replace('/[\x12]([^\x12\x0F]*)(?:[\x12])?/', '<span style="text-decoration: line-through;">$1</span>', $line);
  224. $line = preg_replace('/[\x16]([^\x16\x0F]*)(?:[\x16])?/', '<span style="font-style: italic;">$1</span>', $line);
  225. $line = preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\S+]*(\?\S+)?)?)?)@', "<a href='$1' class='topic'>$1</a>", $line);
  226. // remove dirt
  227. $line = preg_replace('/[\x00-\x1F]/', '', $line);
  228. $line = preg_replace('/[\x7F-\xFF]/', '', $line);
  229. // append line
  230. if ($line != '') {
  231. $out .= $line;
  232. }
  233. }
  234. return $out;
  235. }
  236. }
  237. ?>