BMLT Root Server
c_comdef_login.php
Go to the documentation of this file.
1 <?php
2 /***********************************************************************/
3 /** \file c_comdef_login.php
4 
5  \brief This presents a login dialog to the user, vets the login,
6  and establishes a session.
7 
8  We track admin logins through the use of PHP sessions. This allows the
9  login data to remain on the server. It also allows the login data to
10  be carried into AJAX calls.
11 
12  We're pretty anal about checking user credentials. We don't allow any
13  changes to happen to the DB unless the user has been vetted at the
14  time the DB access is made, but we do a lot of checking along the way.
15 
16  If you include this file at the top of any file that does admin, it will
17  check the session. If the session is not there, it will replace the
18  output with a login form, and will continue along the way, once the user
19  has logged in. If the session is set, it simply makes sure that the
20  session reflects a user that has a system login (it does not check the
21  user level), and stays out of the way.
22 
23  If the user authentication fails, then it does a PHP die(), and scrags
24  the whole thing. This prevents execution of any code beyond the bare
25  minimum necessary to authenticate.
26 
27  Cookies and JavaScript (and AJAX) are required to administer the server
28  (but not to use it as a regular site visitor). This form checks to see
29  if JavaScript is enabled, and if cookies are enabled.
30 
31  You should link to the c_comdef_login.css file for this form.
32 
33  This file is part of the Basic Meeting List Toolbox (BMLT).
34 
35  Find out more at: https://bmlt.app
36 
37  BMLT is free software: you can redistribute it and/or modify
38  it under the terms of the MIT License.
39 
40  BMLT is distributed in the hope that it will be useful,
41  but WITHOUT ANY WARRANTY; without even the implied warranty of
42  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43  MIT License for more details.
44 
45  You should have received a copy of the MIT License along with this code.
46  If not, see <https://opensource.org/licenses/MIT>.
47 */
48 defined('BMLT_EXEC') or die('Cannot Execute Directly'); // Makes sure that this file is in the correct context.
49 
50 require_once(dirname(dirname(dirname(__FILE__)))."/server/c_comdef_server.class.php");
51 require_once(dirname(dirname(dirname(__FILE__)))."/server/shared/classes/comdef_utilityclasses.inc.php");
52 
53 include(dirname(dirname(dirname(__FILE__))).'/server/config/get-config.php');
54 
55 $t_server = c_comdef_server::MakeServer(); // We initialize the server.
56 
57 $lang_enum = $t_server->GetServer()->GetLocalLang();
58 
59 // We use a cookie to store the language pref.
60 if (isset($_COOKIE) && isset($_COOKIE['bmlt_admin_lang_pref']) && $_COOKIE['bmlt_admin_lang_pref']) {
61  $bmlt_localization = $_COOKIE['bmlt_admin_lang_pref'];
62 }
63 
64 if (isset($http_vars['lang_enum']) && $http_vars['lang_enum']) {
65  $lang_enum = $http_vars['lang_enum'];
66 }
67 
68 if (isset($g_enable_language_selector) && $g_enable_language_selector) {
69  $expires = time() + (60 * 60 * 24 * 365); // Expire in one year.
70  setcookie('bmlt_admin_lang_pref', $lang_enum, $expires, '/');
71 }
72 
73 if (!isset($_SESSION)) {
74  session_start();
75 }
76 
77 // See if we are logging in or out
78 if ((isset($_GET['admin_action']) && ($_GET['admin_action'] == 'logout')) // No GET login.
79  || (isset($_POST['admin_action']) && ($_POST['admin_action'] == 'logout'))
80  || (isset($_POST['admin_action']) && ($_POST['admin_action'] == 'login')) // Only POST login.
81  ) {
82  // Belt and suspenders -nuke the stored login.
83  $_SESSION[$admin_session_name] = null;
84  unset($_SESSION[$admin_session_name]);
85  session_write_close(); // Close and reopen the session.
86  session_start();
87 
88  if (isset($_POST['admin_action']) && ($_POST['admin_action'] == 'login')) {
89  $login = isset($_POST['c_comdef_admin_login']) ? $_POST['c_comdef_admin_login'] : null;
90 
91  // If this is a valid login, we'll get an encrypted password back.
92  $enc_password = isset($_POST['c_comdef_admin_password']) ? $t_server->GetEncryptedPW($login, trim($_POST['c_comdef_admin_password'])) : null;
93  if (null != $enc_password) {
94  $_SESSION[$admin_session_name] = "$login\t$enc_password";
95  // If the login interrupted going somewhere else, we complete the journey.
96  if (isset($_POST['attemptedurl']) && $_POST['attemptedurl'] && (0 >= strpos('logout', $_POST['attemptedurl']))) {
97  ob_end_clean();
98  header('Location: '.$_POST['attemptedurl']);
99  }
100  } else {
101  // Otherwise, we just check to make sure this is a kosher user.
102  $user_obj = $t_server->GetCurrentUserObj();
103  if (!($user_obj instanceof c_comdef_user) || ($user_obj->GetUserLevel() == _USER_LEVEL_DISABLED)) {
104  // Get the display strings.
105  $localized_strings = c_comdef_server::GetLocalStrings();
106 
108 
109  // If the login is invalid, we terminate the whole kit and kaboodle, and inform the user they are persona non grata.
110  die('<h2 class="c_comdef_not_auth_3">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['not_auth_3']).'</h2>'.c_comdef_LoginForm($server).'</body></html>');
111  }
112  }
113  } elseif ((isset($_POST['admin_action']) && ($_POST['admin_action'] == 'logout')) || (isset($_GET['admin_action']) && ($_GET['admin_action'] == 'logout'))) {
115  }
116 
117  // Make sure these get wiped and deleted.
118  $_POST['admin_action'] = null;
119  $_POST['c_comdef_admin_login'] = null;
120  $_POST['c_comdef_admin_password'] = null;
121 
122  // Shouldn't have GET, but what the hell...
123  $_GET['admin_action'] = null;
124  $_GET['c_comdef_admin_login'] = null;
125  $_GET['c_comdef_admin_password'] = null;
126 
127  // Belt and suspenders -we set them to naught, then unset them.
128  unset($_POST['admin_action']);
129  unset($_POST['c_comdef_admin_login']);
130  unset($_POST['c_comdef_admin_password']);
131  unset($_GET['admin_action']);
132  unset($_GET['c_comdef_admin_login']);
133  unset($_GET['c_comdef_admin_password']);
134 }
135 
136 // See if a session has been started, or a login was attempted.
137 if (isset($_SESSION[$admin_session_name])) {
138  // Get the display strings.
139  $localized_strings = c_comdef_server::GetLocalStrings();
140 
141  // We double-check, and see if the user is valid.
142  $user_obj = $t_server->GetCurrentUserObj();
143  if (!($user_obj instanceof c_comdef_user) || ($user_obj->GetUserLevel() == _USER_LEVEL_DISABLED)) {
144  // If the login is invalid, we terminate the whole kit and kaboodle, and inform the user they are persona non grata.
145  die('<div class="c_comdef_not_auth_container_div"><div class="c_comdef_not_auth_div"><h1 class="c_comdef_not_auth_1">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['not_auth_1']).'</h1><h2 class="c_comdef_not_auth_2">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['not_auth_2']).'</h2></div></div></body></html>');
146  }
147 
148  if (!isset($supress_header) || !$supress_header) {
149  echo '<div class="bmlt_admin_logout_bar"><h4><a href="'.$_SERVER['PHP_SELF'].'?admin_action=logout">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['logout']). ($user_obj->GetLocalName() != '' ? ' ('.$user_obj->GetLocalName().')' : '') . '</a></h4>';
150  $server_info = GetServerInfo();
151  echo '<div class="server_version_display_div">'.htmlspecialchars($server_info['version']).'</div>';
152  echo '</div>';
153  echo '<div id="google_maps_api_error_div" class="bmlt_admin_google_api_key_error_bar item_hidden"><h4><a id="google_maps_api_error_a" href="https://bmlt.app/google-api-key/" target="_blank"></a></h4></div>';
154  }
155 } else {
157 }
158 
159 $t_server = null;
160 
161 /***********************************************************************/
162 /** \brief Copied verbatim from here: http://stackoverflow.com/questions/6768793/get-the-full-url-in-php
163 \returns a string, with the full URI.
164 */
165 function url_origin($s, $use_forwarded_host = false)
166 {
167  $ssl = ( !empty($s['HTTPS']) && $s['HTTPS'] == 'on' ) ? true:false;
168  $sp = strtolower($s['SERVER_PROTOCOL']);
169  $protocol = substr($sp, 0, strpos($sp, '/')) . ( ( $ssl ) ? 's' : '' );
170  $port = $s['SERVER_PORT'];
171  $port = ( (!$ssl && $port=='80') || ($ssl && $port=='443') ) ? '' : ':'.$port;
172  $host = ( $use_forwarded_host && isset($s['HTTP_X_FORWARDED_HOST']) ) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);
173  $host = isset($host) ? $host : $s['SERVER_NAME'] . $port;
174  return $protocol . '://' . $host;
175 }
176 
177 /***********************************************************************/
178 /** \brief Copied verbatim from here: http://stackoverflow.com/questions/6768793/get-the-full-url-in-php
179 \returns a string, with the full URI.
180 */
181 function full_url($s, $use_forwarded_host = false)
182 {
183  return url_origin($s, $use_forwarded_host) . $s['REQUEST_URI'];
184 }
185 
186 /********************************************************************************************************//**
187 \brief This function parses the main server version from the XML file.
188 \returns a string, containing the version info and banner.
189 ************************************************************************************************************/
190 function GetServerInfo()
191 {
192  $ret = null;
193 
194  if (file_exists(dirname(dirname(dirname(__FILE__))).'/client_interface/serverInfo.xml')) {
195  $info_file = new DOMDocument;
196  if ($info_file instanceof DOMDocument) {
197  if (@$info_file->load(dirname(dirname(dirname(__FILE__))).'/client_interface/serverInfo.xml')) {
198  $has_info = $info_file->getElementsByTagName("bmltInfo");
199 
200  if (($has_info instanceof domnodelist) && $has_info->length) {
201  $ret['version'] = $has_info->item(0)->nodeValue;
202  }
203  }
204  }
205  }
206 
207  $config_file_path = dirname(dirname(dirname(__FILE__))).'/server/config/get-config.php';
208 
209  if (file_exists($config_file_path)) {
210  include($config_file_path);
211  $localized_strings = c_comdef_server::GetLocalStrings();
212  if (isset($bmlt_title) && trim($bmlt_title)) {
213  $ret['title'] = trim($bmlt_title);
214  } else {
215  $ret['title'] = $localized_strings['comdef_server_admin_strings']['login_banner'];
216  }
217  if (isset($banner_text) && trim($banner_text)) {
218  $ret['banner_text'] = trim($banner_text);
219  } else {
220  $ret['banner_text'] = $localized_strings['comdef_server_admin_strings']['login_underbanner'];
221  }
222  }
223 
224  return $ret;
225 }
226 
227 /*******************************************************************/
228 /** \brief Returns HTML for the login form. If the user is not logged
229  in, then they get the form. Otherwise, the login is processed, or
230  the user is vetted.
231 
232  \returns a string, containing the form HTML.
233 */
234 function c_comdef_LoginForm( &$in_server ///< A reference to an instance of c_comdef_server
235  )
236 {
237  include(dirname(dirname(dirname(__FILE__))).'/server/config/get-config.php');
238 
239  $http_vars = array_merge($_GET, $_POST);
240 
241  $localized_strings = c_comdef_server::GetLocalStrings();
242  $server_info = GetServerInfo();
243 
245 
246  if (isset($http_vars) && is_array($http_vars) && count($http_vars) && isset($http_vars['lang_enum'])) {
247  $lang_name = $http_vars['lang_enum'];
248 
249  if (file_exists(dirname(__FILE__)."/lang/".$lang_name."/name.txt")) {
250  $comdef_global_language = $lang_name;
251  }
252  } elseif (isset($_SESSION) && is_array($_SESSION) && isset($_SESSION['lang_enum'])) {
253  $lang_name = $_SESSION['lang_enum'];
254 
255  if (file_exists(dirname(__FILE__)."/lang/".$lang_name."/name.txt")) {
256  $comdef_global_language = $lang_name;
257  }
258  }
259 
260  if (isset($_SESSION) && is_array($_SESSION)) {
261  $_SESSION['lang_enum'] = $comdef_global_language;
262  }
263 
264  $ret = '<div class="c_comdef_admin_login_form_container_div">';
265  // If there is no JavaScript, then this message is displayed, and the form will not be revealed.
266  $ret .= '<noscript><h1>'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['noscript']).'</h1></noscript>';
267  $ret .= '<h1 class="login_form_main_banner_h1">'.c_comdef_htmlspecialchars($server_info['title']).'</h1>';
268  $ret .= '<h2 class="login_form_secondary_banner_h2">'.c_comdef_htmlspecialchars($server_info['banner_text']).'</h2>';
269  $ret .= '<form method="post" class="c_comdef_admin_login_form" id="c_comdef_admin_login_form" action="'.c_comdef_htmlspecialchars($_SERVER['SCRIPT_NAME']);
270  $ret_temp = '';
271  foreach ($http_vars as $key => $value) {
272  switch ($key) {
273  // Skip these.
274  case 'c_comdef_admin_login':
275  case 'c_comdef_admin_password':
276  case 'admin_action':
277  case 'login':
278  break;
279 
280  default:
281  // Arrays need to be concatenated strings.
282  if (is_array($value)) {
283  $value = join(",", $value);
284  }
285  if ($ret_temp) {
286  $ret_temp .= '&amp;';
287  } else {
288  $ret_temp = '?';
289  }
290  $ret_temp .= c_comdef_htmlspecialchars($key).'='.c_comdef_htmlspecialchars($value);
291  break;
292  }
293  }
294  $ret .= '">'; // Only the login will go through post.
295  $ret .= '<input id="admin_action" type="hidden" name="admin_action" value="login" />';
296  $attempted_url = full_url($_SERVER);
297 
298  if (!preg_match('|logout|', $attempted_url)) {
299  $ret .= '<input id="attemptedurl" type="hidden" name="attemptedurl" value="'.c_comdef_htmlspecialchars($attempted_url).'" />';
300  }
301 
302  $ret .= '<div style="display:none" id="c_comdef_admin_login_form_inner_container_div" class="c_comdef_admin_login_form_inner_container_div">';
303  $ret .= '<div class="c_comdef_admin_login_form_line_div">';
304  $ret .= '<div class="c_comdef_admin_login_form_prompt">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['title']).'</div>';
305  $ret .= '<label for="c_comdef_admin_login">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['login']).$localized_strings['prompt_delimiter'].'</label>';
306  $ret .= '<input id="c_comdef_admin_login" type="text" name="c_comdef_admin_login" value="" />';
307  $ret .= '</div>';
308  $ret .= '<div class="c_comdef_admin_login_form_line_div">';
309  $ret .= '<label for="c_comdef_admin_password">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['password']).$localized_strings['prompt_delimiter'].'</label>';
310  $ret .= '<input type="password" id="c_comdef_admin_password" name="c_comdef_admin_password" value="" />';
311  $ret .= '</div>';
312  if (isset($g_enable_language_selector) && $g_enable_language_selector) {
313  $ret .= '<div id="lang_enum_select_div" class="c_comdef_admin_login_form_line_div">';
314  $ret .= '<select id="lang_enum_select" name="lang_enum">'.(defined('__DEBUG_MODE__') ? "\n" : '');
315  $lang_array = c_comdef_server::GetServer()->GetServerLangs();
316  foreach ($lang_array as $id => $name) {
317  if ($id && $name) {
318  $ret .= '<option value="'.c_comdef_htmlspecialchars($id).'"';
319  if ($comdef_global_language == $id) {
320  $ret .= ' selected="selected"';
321  }
322  $ret.= '>'.c_comdef_htmlspecialchars($name).'</option>'.(defined('__DEBUG_MODE__') ? "\n" : '');
323  }
324  }
325  $ret .= '</select>'.(defined('__DEBUG_MODE__') ? "\n" : '');
326  $ret .= '<div id="cookie_notice_div" class="bmlt_cookie_notice_div">'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['cookie_monster']).'</div>';
327  $ret .= '</div>';
328  }
329  $ret .= '<div class="c_comdef_admin_login_form_submit_div">';
330  $ret .= '<input type="submit" value="'.c_comdef_htmlspecialchars($localized_strings['comdef_server_admin_strings']['button']).'" />';
331  $ret .= '</div>';
332  $ret .= '<div class="server_version_display_login">';
333  $ret .= htmlspecialchars($server_info['version']);
334  $ret .= '</div>';
335  $ret .= '</div>';
336  // This is how we check for JavaScript availability and enabled cookies (Cookies are required for sessions).
337  // We reveal the form using JavaScript (It stays invisible if no JS), and we set a transitory cookie with JS to be read upon login.
338  $ret .= '</form>
339  <script type="text/javascript">
340  document.getElementById(\'c_comdef_admin_login_form_inner_container_div\').style.display=\'block\';
341  document.getElementById(\'c_comdef_admin_login\').focus();
342  document.cookie=\'comdef_test=test\';
343  </script>';
344  $ret .= '</div>';
345 
346  return $ret;
347 }
static GetLocalStrings($in_lang_enum=null)
This gets the appropriate language files, and puts all the the strings into an associative array...
$lang_enum
if($handler instanceof c_comdef_admin_ajax_handler)
This class handles BMLT users. One instance is created for each user on the server.
$ret
Definition: contact.php:226
global $comdef_global_language
The local server language enum (Will default to English)
$t_server
const _USER_LEVEL_DISABLED
c_comdef_LogoutUser()
This function can be called to terminate the session.
GetServerInfo()
This function parses the main server version from the XML file.
url_origin($s, $use_forwarded_host=false)
Copied verbatim from here: http://stackoverflow.com/questions/6768793/get-the-full-url-in-php.
global $http_vars
Definition: index.php:21
c_comdef_htmlspecialchars($in_string)
This function creates a displayable string.
$server
Definition: GetLangs.php:25
This class is the main server class. It instantiates a PDO database object, and is the starting point...
defined('BMLT_EXEC') or define('BMLT_EXEC'
Definition: index.php:3
$user_obj
Definition: index.php:7
full_url($s, $use_forwarded_host=false)
Copied verbatim from here: http://stackoverflow.com/questions/6768793/get-the-full-url-in-php.
$config_file_path
Definition: index.php:58
c_comdef_LoginForm(&$in_server)
Returns HTML for the login form. If the user is not logged in, then they get the form. Otherwise, the login is processed, or the user is vetted.
$_GET['switcher']