PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/frontend_authentication/extension.driver.php

https://github.com/bauhouse/sym-extensions
PHP | 320 lines | 231 code | 85 blank | 4 comment | 35 complexity | fe26f986bfc68723a3ca0fa58696771f MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. Class extension_frontend_authentication extends Extension{
  3. public function about(){
  4. return array('name' => 'Front End Authentication',
  5. 'version' => '1.0',
  6. 'release-date' => '2008-09-24',
  7. 'author' => array('name' => 'Symphony Team',
  8. 'website' => 'http://www.symphony21.com',
  9. 'email' => 'team@symphony21.com')
  10. );
  11. }
  12. public function uninstall(){
  13. $this->_Parent->Configuration->remove('frontend-authentication');
  14. $this->_Parent->saveConfig();
  15. }
  16. public function getSubscribedDelegates(){
  17. return array(
  18. array(
  19. 'page' => '/system/preferences/',
  20. 'delegate' => 'AddCustomPreferenceFieldsets',
  21. 'callback' => 'appendPreferences'
  22. ),
  23. array(
  24. 'page' => '/frontend/',
  25. 'delegate' => 'FrontendPageResolved',
  26. 'callback' => '__authenticate'
  27. ),
  28. array(
  29. 'page' => '/frontend/',
  30. 'delegate' => 'FrontendEventPostProcess',
  31. 'callback' => '__appendEventXML'
  32. ),
  33. array(
  34. 'page' => '/frontend/',
  35. 'delegate' => 'FrontendParamsResolve',
  36. 'callback' => '__processForgottenPasswordRequest'
  37. ),
  38. array(
  39. 'page' => '/system/preferences/',
  40. 'delegate' => 'Save',
  41. 'callback' => '__SavePreferences'
  42. ),
  43. );
  44. }
  45. public function __SavePreferences($context){
  46. $context['settings']['frontend-authentication']['email-subject'] = $context['settings']['frontend-authentication']['email-subject'];
  47. $context['settings']['frontend-authentication']['email-body'] = $context['settings']['frontend-authentication']['email-body'];
  48. if(!isset($_POST['settings']['frontend-authentication']['use-sessions'])){
  49. $context['settings']['frontend-authentication']['use-sessions'] = 'no';
  50. }
  51. }
  52. private static function __replaceParams($string, $params){
  53. foreach($params as $key => $value){
  54. $string = str_replace("{\$$key}", $value, $string);
  55. }
  56. return $string;
  57. }
  58. public function __processForgottenPasswordRequest($context){
  59. if(isset($_POST['action']['front-end-authentication']['forgot'])){
  60. $username = (function_exists('mysql_real_escape_string')
  61. ? mysql_real_escape_string($_POST['front-end-authentication']['username'])
  62. : addslashes($_POST['front-end-authentication']['username']));
  63. $password = $this->__getPasswordFromUsername($username);
  64. if(strlen($password) > 0){
  65. $params = $context['params'];
  66. $params += array('username' => $username, 'password' => $password);
  67. $subject = self::__replaceParams(stripslashes($this->_Parent->Configuration->get('email-subject', 'frontend-authentication')), $params);
  68. $body = self::__replaceParams(stripslashes($this->_Parent->Configuration->get('email-body', 'frontend-authentication')), $params);
  69. General::sendEmail($username, 'noreply@' . parse_url($params['root'], PHP_URL_HOST), $params['website-name'], $subject, $body);
  70. define_safe('FRONT_END_AUTHENTICATION_EMAIL_SENT', true);
  71. return;
  72. }
  73. define_safe('FRONT_END_AUTHENTICATION_EMAIL_SENT', false);
  74. return;
  75. }
  76. }
  77. public function __appendEventXML($context){
  78. if(defined('FRONT_END_AUTHENTICATION_SUCCESSFUL')){
  79. $context['xml']->appendChild(new XMLElement('front-end-authentication', NULL, array('status' => (FRONT_END_AUTHENTICATION_SUCCESSFUL == true ? 'authenticated' : 'invalid'))));
  80. }
  81. elseif(defined('FRONT_END_AUTHENTICATION_EMAIL_SENT')){
  82. $context['xml']->appendChild(new XMLElement('front-end-authentication', NULL, array('password-retrieval-email-status' => (FRONT_END_AUTHENTICATION_EMAIL_SENT == true ? 'sent' : 'failed'))));
  83. }
  84. }
  85. private function __createCookie($username, $password){
  86. if($this->_Parent->Configuration->get('use-sessions', 'frontend-authentication') == 'yes'){
  87. $_SESSION[__SYM_COOKIE_PREFIX_ . 'front-end-authentication'] = array('username' => $username, 'password' => md5($password));
  88. }
  89. else{
  90. $Cookie = new Cookie(__SYM_COOKIE_PREFIX_ . 'front-end-authentication', (24 * 60 * 60), __SYM_COOKIE_PATH__);
  91. $Cookie->set('username', $username);
  92. $Cookie->set('password', md5($password));
  93. }
  94. }
  95. private function __expireCookie(){
  96. session_destroy();
  97. $Cookie = new Cookie(__SYM_COOKIE_PREFIX_ . 'front-end-authentication', (24 * 60 * 60), __SYM_COOKIE_PATH__);
  98. $Cookie->expire();
  99. }
  100. private function __validate($username, $password, $isHash=false){
  101. $username = (function_exists('mysql_real_escape_string') ? mysql_real_escape_string($username) : addslashes($username));
  102. $password = (function_exists('mysql_real_escape_string') ? mysql_real_escape_string($password) : addslashes($password));
  103. $username_field = $this->_Parent->Configuration->get('username-field', 'frontend-authentication');
  104. $password_field = $this->_Parent->Configuration->get('password-field', 'frontend-authentication');
  105. $sql = "SELECT `t1`.entry_id
  106. FROM `tbl_entries_data_{$username_field}` AS `t1`
  107. LEFT JOIN `tbl_entries_data_{$password_field}` AS `t2` ON t1.entry_id = t2.entry_id
  108. WHERE `t1`.value = '{$username}' AND ".($isHash ? "MD5(`t2`.`value`)" : "t2.value")." = '{$password}'
  109. LIMIT 1";
  110. $id = $this->_Parent->Database->fetchVar('entry_id', 0, $sql);
  111. return ((integer)$id > 0);
  112. }
  113. private function __getPasswordFromUsername($username){
  114. $username = (function_exists('mysql_real_escape_string') ? mysql_real_escape_string($username) : addslashes($username));
  115. $username_field = $this->_Parent->Configuration->get('username-field', 'frontend-authentication');
  116. $password_field = $this->_Parent->Configuration->get('password-field', 'frontend-authentication');
  117. $sql = "SELECT `t2`.value AS `password`
  118. FROM `tbl_entries_data_{$username_field}` AS `t1`
  119. LEFT JOIN `tbl_entries_data_{$password_field}` AS `t2` ON t1.entry_id = t2.entry_id
  120. WHERE `t1`.value = '{$username}'
  121. LIMIT 1";
  122. return $this->_Parent->Database->fetchVar('password', 0, $sql);
  123. }
  124. public function __authenticate($context){
  125. $path = '/' . $this->_Parent->resolvePagePath($context['page_data']['id']);
  126. $bOnLoginPage = ($path == $context['parent']->Configuration->get('login-page', 'frontend-authentication'));
  127. if($this->_Parent->Configuration->get('use-sessions', 'frontend-authentication') == 'yes'){
  128. session_start();
  129. }
  130. if(isset($_GET['front-end-authentication-logout'])){
  131. $this->__expireCookie();
  132. }
  133. ## Check for post data, use it for creation of a cookie
  134. if(isset($_POST['action']['front-end-authentication']['login'])){
  135. $username = $_POST['front-end-authentication']['username'];
  136. $password = $_POST['front-end-authentication']['password'];
  137. if($this->__validate($username, $password)){
  138. $this->__createCookie($username, $password);
  139. define_safe('FRONT_END_AUTHENTICATION_SUCCESSFUL', true);
  140. if($bOnLoginPage) redirect(URL);
  141. return;
  142. }
  143. define_safe('FRONT_END_AUTHENTICATION_SUCCESSFUL', false);
  144. }
  145. ## Check for a session, and validate it
  146. elseif($this->_Parent->Configuration->get('use-sessions', 'frontend-authentication') == 'yes'){
  147. if(isset($_SESSION[__SYM_COOKIE_PREFIX_ . 'front-end-authentication'])){
  148. $username = $_SESSION[__SYM_COOKIE_PREFIX_ . 'front-end-authentication']['username'];
  149. $password = $_SESSION[__SYM_COOKIE_PREFIX_ . 'front-end-authentication']['password'];
  150. if($this->__validate($username, $password, true)){
  151. define_safe('FRONT_END_AUTHENTICATION_SUCCESSFUL', true);
  152. if($bOnLoginPage) redirect(URL);
  153. return;
  154. }
  155. $this->__expireCookie();
  156. }
  157. }
  158. ## Check for a cookie, and validate it
  159. elseif(isset($_COOKIE[__SYM_COOKIE_PREFIX_ . 'front-end-authentication'])){
  160. $username = $_COOKIE[__SYM_COOKIE_PREFIX_ . 'front-end-authentication']['username'];
  161. $password = $_COOKIE[__SYM_COOKIE_PREFIX_ . 'front-end-authentication']['password'];
  162. if($this->__validate($username, $password, true)){
  163. define_safe('FRONT_END_AUTHENTICATION_SUCCESSFUL', true);
  164. if($bOnLoginPage) redirect(URL);
  165. return;
  166. }
  167. $this->__expireCookie();
  168. }
  169. $types = $context['page_data']['type'];
  170. ## No luck, kick to login page
  171. if(!$bOnLoginPage && is_array($types) && in_array($context['parent']->Configuration->get('page-type', 'frontend-authentication'), $types))
  172. $context['page_data'] = $context['page']->resolvePage(trim($context['parent']->Configuration->get('login-page', 'frontend-authentication'), '/'));
  173. }
  174. public function appendPreferences($context){
  175. $group = new XMLElement('fieldset');
  176. $group->setAttribute('class', 'settings');
  177. $group->appendChild(new XMLElement('legend', 'Front End Authentication'));
  178. $div = new XMLElement('div', NULL, array('class' => 'group'));
  179. $label = Widget::Label('Page Type');
  180. $label->appendChild(Widget::Input('settings[frontend-authentication][page-type]', General::Sanitize($context['parent']->Configuration->get('page-type', 'frontend-authentication'))));
  181. $div->appendChild($label);
  182. $pages = $this->_Parent->Database->fetch("SELECT `id`, `title` FROM `tbl_pages` ORDER BY `title` ASC");
  183. $label = Widget::Label('Login Page');
  184. $options = array();
  185. if(is_array($pages) && !empty($pages)){
  186. foreach($pages as $page){
  187. $path = '/' . $this->_Parent->resolvePagePath($page['id']);
  188. $options[] = array($path, $context['parent']->Configuration->get('login-page', 'frontend-authentication') == $path, $path);
  189. }
  190. }
  191. $label->appendChild(Widget::Select('settings[frontend-authentication][login-page]', $options));
  192. $div->appendChild($label);
  193. $group->appendChild($div);
  194. $group->appendChild(new XMLElement('p', 'Any page with this type will check for a valid cookie, otherwise be thrown to a login screen', array('class' => 'help')));
  195. $div = new XMLElement('div', NULL, array('class' => 'group'));
  196. $fields = $this->_Parent->Database->fetch("SELECT t1.*, t2.name as `section` FROM `tbl_fields` AS `t1`
  197. LEFT JOIN `tbl_sections` AS `t2` ON `t1`.parent_section = t2.id
  198. WHERE `t1`.type NOT IN ('checkbox', 'select', 'sectionlink', 'date', 'textarea', 'upload', 'author')
  199. ORDER BY t1.`parent_section` ASC, t1.`element_name` ASC");
  200. $label = Widget::Label('Username Field');
  201. $options = array();
  202. if(is_array($fields) && !empty($fields)){
  203. foreach($fields as $field){
  204. $options[] = array($field['id'], $context['parent']->Configuration->get('username-field', 'frontend-authentication') == $field['id'], $field['section'] . ' > ' . $field['label']);
  205. }
  206. }
  207. $label->appendChild(Widget::Select('settings[frontend-authentication][username-field]', $options));
  208. $div->appendChild($label);
  209. $label = Widget::Label('Password Field');
  210. $options = array();
  211. if(is_array($fields) && !empty($fields)){
  212. foreach($fields as $field){
  213. $options[] = array($field['id'], $context['parent']->Configuration->get('password-field', 'frontend-authentication') == $field['id'], $field['section'] . ' > ' . $field['label']);
  214. }
  215. }
  216. $label->appendChild(Widget::Select('settings[frontend-authentication][password-field]', $options));
  217. $div->appendChild($label);
  218. $group->appendChild($div);
  219. $group->appendChild(new XMLElement('p', 'Both fields must be from the same section', array('class' => 'help')));
  220. $label = Widget::Label();
  221. $input = Widget::Input('settings[frontend-authentication][use-sessions]', 'yes', 'checkbox');
  222. if($this->_Parent->Configuration->get('use-sessions', 'frontend-authentication') == 'yes') $input->setAttribute('checked', 'checked');
  223. $label->setValue($input->generate() . ' Use sessions instead of cookies');
  224. $group->appendChild($label);
  225. $group->appendChild(new XMLElement('p', 'Sessions expire when the browser is closed. They are stored on the server are considered more secure than cookies.', array('class' => 'help')));
  226. $label = Widget::Label('Password Retrieval Email Subject');
  227. $label->appendChild(Widget::Input('settings[frontend-authentication][email-subject]', stripslashes($context['parent']->Configuration->get('email-subject', 'frontend-authentication'))));
  228. $group->appendChild($label);
  229. $label = Widget::Label('Password Retrieval Email Body');
  230. $label->appendChild(Widget::Textarea('settings[frontend-authentication][email-body]', 10, 50, stripslashes($context['parent']->Configuration->get('email-body', 'frontend-authentication'))));
  231. $group->appendChild($label);
  232. $group->appendChild(new XMLElement('p', 'Use <code>{$password}</code> and <code>{$username}</code> for dynamic values. Any parameters in the XSLT can also be used. E.G. <code>{$root}</code>', array('class' => 'help')));
  233. $context['wrapper']->appendChild($group);
  234. }
  235. }