public static function email_verification($email, $hash) { global $DB; $status = false; $DB->query(' SELECT id, activation_key FROM nv_webusers WHERE email = ' . protect($email) . ' AND activation_key = ' . protect($hash) . ' '); $rs = $DB->first(); if (!empty($rs->id)) { $wu = new webuser(); $wu->load($rs->id); // access is only enabled for blocked users (access==1) which don't have a password nor an email verification date if ($wu->access == 1 && empty($wu->password) && empty($wu->email_verification_date)) { // email is confirmed through a newsletter subscribe request $wu->email_verification_date = time(); $wu->access = 0; $wu->activation_key = ""; $status = $wu->save(); } } return $status; }
function run() { global $user; global $layout; global $DB; global $website; $out = ''; $item = new webuser(); switch ($_REQUEST['act']) { // json data retrieval & operations case 'json': case 1: switch ($_REQUEST['oper']) { case 'del': // remove rows $ids = $_REQUEST['ids']; foreach ($ids as $id) { $item->load($id); $item->delete(); } echo json_encode(true); break; default: // list or search $page = intval($_REQUEST['page']); $max = intval($_REQUEST['rows']); $offset = ($page - 1) * $max; $orderby = $_REQUEST['sidx'] . ' ' . $_REQUEST['sord']; $where = ' website = ' . $website->id; if ($_REQUEST['_search'] == 'true' || isset($_REQUEST['quicksearch'])) { if (isset($_REQUEST['quicksearch'])) { $where .= $item->quicksearch($_REQUEST['quicksearch']); } else { if (isset($_REQUEST['filters'])) { $filters = $_REQUEST['filters']; if (is_array($filters)) { $filters = json_encode($filters); } $where .= navitable::jqgridsearch($filters); } else { // single search $where .= ' AND ' . navitable::jqgridcompare($_REQUEST['searchField'], $_REQUEST['searchOper'], $_REQUEST['searchString']); } } } $DB->queryLimit('id,avatar,username,email,fullname,groups,joindate,access,access_begin,access_end', 'nv_webusers', $where, $orderby, $offset, $max); $dataset = $DB->result(); $total = $DB->foundRows(); $dataset = grid_notes::summary($dataset, 'webuser', 'id'); global $webusers_groups_all; $webusers_groups_all = webuser_group::all_in_array(); //echo $DB->get_last_error(); $out = array(); for ($i = 0; $i < count($dataset); $i++) { $wug = str_replace('g', '', $dataset[$i]['groups']); $wug = explode(',', $wug); $wug = array_map(function ($in) { global $webusers_groups_all; if (empty($in)) { return; } return $webusers_groups_all[$in]; }, $wug); $blocked = 1; if ($dataset[$i]['access'] == 0 || $dataset[$i]['access'] == 2 && ($dataset[$i]['access_begin'] == 0 || $dataset[$i]['access_begin'] < time()) && ($dataset[$i]['access_end'] == 0 || $dataset[$i]['access_end'] > time())) { $blocked = 0; } $out[$i] = array(0 => $dataset[$i]['id'], 1 => empty($dataset[$i]['avatar']) ? '' : '<img title="' . $dataset[$i]['username'] . '" src="' . NAVIGATE_DOWNLOAD . '?wid=' . $website->id . '&id=' . urlencode($dataset[$i]['avatar']) . '&disposition=inline&width=32&height=32" />', 2 => '<div class="list-row" data-blocked="' . $blocked . '" title="' . $dataset[$i]['email'] . '">' . $dataset[$i]['username'] . '</div>', 3 => $dataset[$i]['fullname'], 4 => implode("<br />", $wug), 5 => core_ts2date($dataset[$i]['joindate'], true), 6 => $blocked == 0 ? '<img src="img/icons/silk/accept.png" />' : '<img src="img/icons/silk/cancel.png" />', 7 => $dataset[$i]['_grid_notes_html']); } navitable::jqgridJson($out, $page, $offset, $max, $total); break; } session_write_close(); exit; break; case 2: // edit/new form // edit/new form case 'create': case 'edit': if (!empty($_REQUEST['id'])) { $item->load(intval($_REQUEST['id'])); } if (isset($_REQUEST['form-sent'])) { $item->load_from_post(); try { $item->save(); property::save_properties_from_post('webuser', $item->id); $layout->navigate_notification(t(53, "Data saved successfully."), false, false, 'fa fa-check'); } catch (Exception $e) { $layout->navigate_notification($e->getMessage(), true, true); } if (!empty($item->id)) { users_log::action($_REQUEST['fid'], $item->id, 'save', $item->username, json_encode($_REQUEST)); } } else { if (!empty($item->id)) { users_log::action($_REQUEST['fid'], $item->id, 'load', $item->username); } } $out = webusers_form($item); break; case 4: // remove // remove case 'remove': if (!empty($_REQUEST['id'])) { $item->load(intval($_REQUEST['id'])); if ($item->delete() > 0) { $layout->navigate_notification(t(55, 'Item removed successfully.'), false); $out = webusers_list(); users_log::action($_REQUEST['fid'], $item->id, 'remove', $item->username, json_encode($_REQUEST)); } else { $layout->navigate_notification(t(56, 'Unexpected error.'), false); $out = webusers_form($item); } } break; case 90: // json request: timezones by country $timezones = property::timezones($_REQUEST['country']); if (empty($timezones)) { $timezones = property::timezones(); } echo json_encode($timezones); core_terminate(); break; case 'export': // export web users list to a CSV file users_log::action($_REQUEST['fid'], 0, 'export', "all", json_encode($_REQUEST)); webuser::export(); break; case 'webuser_groups_list': $out = webuser_groups_list(); break; case 'webuser_groups_json': $page = intval($_REQUEST['page']); $max = intval($_REQUEST['rows']); $offset = ($page - 1) * $max; $rs = webuser_group::all($_REQUEST['sidx'], $_REQUEST['sord']); $dataset = array(); foreach ($rs as $row) { $dataset[] = array('id' => $row->id, 'code' => $row->code, 'name' => $row->name); } $total = count($dataset); navitable::jqgridJson($dataset, $page, $offset, $max, $total, 'id'); session_write_close(); exit; break; case 'webuser_group_edit': $webuser_group = new webuser_group(); if (!empty($_REQUEST['id'])) { $webuser_group->load(intval($_REQUEST['id'])); } if (isset($_REQUEST['form-sent'])) { $webuser_group->load_from_post(); try { $ok = $webuser_group->save(); $layout->navigate_notification(t(53, "Data saved successfully."), false, false, 'fa fa-check'); users_log::action($_REQUEST['fid'], $webuser_group->id, 'save_webuser_group', $webuser_group->name, json_encode($_REQUEST)); } catch (Exception $e) { $layout->navigate_notification($e->getMessage(), true, true); } } else { users_log::action($_REQUEST['fid'], $webuser_group->id, 'load_webuser_group', $webuser_group->name, json_encode($_REQUEST)); } $out = webuser_groups_form($webuser_group); break; case 'webuser_group_delete': $webuser_group = new webuser_group(); if (!empty($_REQUEST['id'])) { $webuser_group->load(intval($_REQUEST['id'])); } try { $webuser_group->delete(); $layout->navigate_notification(t(55, 'Item removed successfully.'), false); $out = webuser_groups_list(); users_log::action($_REQUEST['fid'], $webuser_group->id, 'remove_webuser_group', $webuser_group->name, json_encode($_REQUEST)); } catch (Exception $e) { $out = $layout->navigate_message("error", t(24, 'Web users') . ' / ' . t(506, 'Groups'), t(56, 'Unexpected error.')); } break; case 0: // list / search result // list / search result case 'list': default: $out = webusers_list(); break; } return $out; }
function nvweb_webuser($vars = array()) { global $website; global $theme; global $current; global $webgets; global $webuser; global $DB; $webget = "webuser"; if (!isset($webgets[$webget])) { $webgets[$webget] = array(); global $lang; if (empty($lang)) { $lang = new language(); $lang->load($current['lang']); } // default translations $webgets[$webget]['translations'] = array('login_incorrect' => t(4, 'Login incorrect.'), 'subscribed_ok' => t(541, 'Your email has been successfully subscribed to the newsletter.'), 'subscribe_error' => t(542, 'There was a problem subscribing your email to the newsletter.'), 'email_confirmation' => t(454, "An e-mail with a confirmation link has been sent to your e-mail account."), 'click_to_confirm_account' => t(607, "Click on the link below to confirm your account"), 'email_confirmation_notice' => t(608, "This is an automated e-mail sent as a result of a newsletter subscription request. If you received this e-mail by error just ignore it."), 'forgot_password_success' => t(648, "An e-mail with a temporary password has been sent to your e-mail account."), 'forgot_password_error' => t(446, "We're sorry. Your contact request could not be sent. Please try again or find another way to contact us.")); // theme translations // if the web theme has custom translations for this string subtypes, use it (for the user selected language) /* just add the following translations to your json theme dictionary: "login_incorrect": "Login incorrect.", "subscribed_ok": "Your email has been successfully subscribed to the newsletter.", "subscribe_error": "There was a problem subscribing your email to the newsletter.", "email_confirmation": "An e-mail with a confirmation link has been sent to your e-mail account.", "click_to_confirm_account": "Click on the link below to confirm your account", "email_confirmation_notice": "This is an automated e-mail sent as a result of a newsletter subscription request. If you received this e-mail by error just ignore it." "forgot_password_success": "An e-mail with a temporary password has been sent to your e-mail account.", "forgot_password_error": "We're sorry. Your contact request could not be sent. Please try again or find another way to contact us." */ if (!empty($website->theme) && method_exists($theme, 't')) { foreach ($webgets[$webget]['translations'] as $code => $text) { $theme_translation = $theme->t($code); if (!empty($theme_translation) && $code != $theme_translation) { $webgets[$webget]['translations'][$code] = $theme_translation; } } } } $out = ''; switch ($vars['mode']) { case 'id': if (!empty($webuser->id)) { $out = $webuser->id; } break; case 'username': if (!empty($webuser->username)) { $out = $webuser->username; } break; case 'fullname': if (!empty($webuser->fullname)) { $out = $webuser->fullname; } break; case 'gender': if (!empty($webuser->gender)) { $out = $webuser->gender; } break; case 'newsletter': $out = $webuser->newsletter; break; case 'email': if (!empty($webuser->email)) { $out = $webuser->email; } break; case 'authenticate': $webuser_website = $vars['website']; if (empty($webuser_website)) { $webuser_website = $website->id; } $signin_username = $_REQUEST[empty($vars['username_field']) ? 'signin_username' : $vars['username_field']]; $signin_password = $_REQUEST[empty($vars['password_field']) ? 'signin_password' : $vars['password_field']]; // a page may have several forms, which one do we have to check? if (!empty($vars['form'])) { list($field_name, $field_value) = explode('=', $vars['form']); if ($_POST[$field_name] != $field_value) { return; } } // ignore empty (or partial empty) forms if (!empty($signin_username) && !empty($signin_password)) { $signed_in = $webuser->authenticate($webuser_website, $signin_username, $signin_password); if (!$signed_in) { $message = $webgets[$webget]['translations']['login_incorrect']; if (empty($vars['notify'])) { $vars['notify'] = 'inline'; } switch ($vars['notify']) { case 'alert': nvweb_after_body('js', 'alert("' . $message . '");'); break; case 'inline': $out = '<div class="nvweb-signin-form-error">' . $message . '</div>'; break; // javascript callback // javascript callback default: nvweb_after_body('js', $vars['error_callback'] . '("' . $message . '");'); break; } } else { $webuser->set_cookie(); if (!empty($vars['notify'])) { if ($vars['notify'] == 'callback') { nvweb_after_body('js', $vars['callback'] . '(true);'); } } } } break; case 'signout_link': $out = NVWEB_ABSOLUTE . $website->homepage() . '?webuser_signout'; break; case 'forgot_password': // pre checks: correct form, not spambot, email not empty and valid // load the associated user account // create temporary password and send email // TODO: don't change the password, just generate a link and let the user enter their preferred new password // a page may have several forms, which one do we have to check? if (!empty($vars['form'])) { list($field_name, $field_value) = explode('=', $vars['form']); if ($_POST[$field_name] != $field_value) { return; } } // check if this send request really comes from the website and not from a spambot if (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != $website->subdomain . '.' . $website->domain && parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != $website->domain) { return; } if (empty($vars['email_field'])) { $vars['email_field'] = 'newsletter_email'; } $email = $_REQUEST[$vars['email_field']]; $email = filter_var($email, FILTER_SANITIZE_EMAIL); if (!empty($vars['email_field']) && !empty($email)) { $ok = false; if (filter_var($email, FILTER_VALIDATE_EMAIL) !== FALSE) { $wu_id = $DB->query_single('id', 'nv_webusers', ' email = ' . protect($email) . ' AND website = ' . $website->id); $wu = new webuser(); if (!empty($wu_id)) { $wu->load($wu_id); if ($wu->access == 0 || $wu->access == 2 && ($wu->access_begin == 0 || time() > $wu->access_begin) && ($wu->access_end == 0 || time() < $wu->access_end)) { // generate new password $password = generate_password(8, false, 'luds'); $wu->set_password($password); $ok = $wu->save(); // send a message to communicate the new webuser's email $message = navigate_compose_email(array(array('title' => $website->name, 'content' => t(451, "This is an automated e-mail sent as a result of a password request process. If you received this e-mail by error just ignore it.")), array('title' => t(1, "User"), 'content' => $wu->username), array('title' => t(2, "Password"), 'content' => $password), array('footer' => '<a href="' . $website->absolute_path() . $website->homepage() . '">' . $website->name . '</a>'))); @nvweb_send_email($website->name, $message, $wu->email); } } } if ($ok) { $message = $webgets[$webget]['translations']['forgot_password_success']; } else { $message = $webgets[$webget]['translations']['forgot_password_error']; } if (empty($vars['notify'])) { $vars['notify'] = 'inline'; } switch ($vars['notify']) { case 'alert': nvweb_after_body('js', 'alert("' . $message . '");'); break; case 'inline': if ($ok) { $out = '<div class="nvweb-forgot-password-form-success">' . $message . '</div>'; } else { $out = '<div class="nvweb-forgot-password-form-error">' . $message . '</div>'; } break; case 'boolean': $out = $ok; break; case 'false': break; // javascript callback // javascript callback case 'callback': default: if ($ok) { nvweb_after_body('js', $vars['callback'] . '("' . $message . '");'); } else { if (!empty($vars['error_callback'])) { nvweb_after_body('js', $vars['error_callback'] . '("' . $message . '");'); } else { nvweb_after_body('js', $vars['callback'] . '("' . $message . '");'); } } break; } } break; case 'signup': // TODO // pre checks: correct form, not spambot, email not empty and valid // get the profile data from the form // more checks: password strength & confirmation, etc. // save the new webuser account // prepare account confirmation (unless not required by webget attributes) // leave the account blocked // generate an activation key // send confirmation email // if no account confirmation is required, auto login break; case 'avatar': $size = '48'; $extra = ''; if (!empty($vars['size'])) { $size = intval($vars['size']); } if (!empty($vars['border'])) { $extra .= '&border=' . $vars['border']; } if (!empty($webuser->avatar)) { $out = '<img class="' . $vars['class'] . '" src="' . NVWEB_OBJECT . '?type=image' . $extra . '&id=' . $webuser->avatar . '" width="' . $size . 'px" height="' . $size . 'px"/>'; } else { if (!empty($vars['default'])) { // the comment creator has not an avatar, but the template wants to show a default one // 3 cases: // numerical -> ID of the avatar image file in Navigate CMS // absolute path (http://www...) // relative path (/img/avatar.png) -> path to the avatar file included in the THEME used if (is_numeric($vars['default'])) { $out = '<img class="' . $vars['class'] . '" src="' . NVWEB_OBJECT . '?type=image' . $extra . '&id=' . $vars['default'] . '" width="' . $size . 'px" height="' . $size . 'px"/>'; } else { if (strpos($vars['default'], 'http://') === 0) { $out = '<img class="' . $vars['class'] . '" src="' . $vars['default'] . '" width="' . $size . 'px" height="' . $size . 'px"/>'; } else { if ($vars['default'] == 'none') { $out = ''; } else { $out = '<img class="' . $vars['class'] . '"src="' . NAVIGATE_URL . '/themes/' . $website->theme . '/' . $vars['default'] . '" width="' . $size . 'px" height="' . $size . 'px"/>'; } } } } else { $gravatar_hash = ""; $gravatar_default = 'blank'; if (!empty($vars['gravatar_default'])) { $gravatar_default = $vars['gravatar_default']; } if (!empty($webuser->email)) { $gravatar_hash = md5(strtolower(trim($webuser->email))); } if (!empty($gravatar_hash) && $gravatar_default != 'none') { // gravatar real url: https://www.gravatar.com/avatar/ // we use libravatar to get more userbase $gravatar_url = 'https://seccdn.libravatar.org/avatar/' . $gravatar_hash . '?s=' . $size . '&d=' . $gravatar_default; $out = '<img class="' . $vars['class'] . '" src="' . $gravatar_url . '" width="' . $size . 'px" height="' . $size . 'px"/>'; } else { $out = '<img class="' . $vars['class'] . '" src="data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" width="' . $size . 'px" height="' . $size . 'px"/>'; } } } break; case 'newsletter_subscribe': // a page may have several forms, which one do we have to check? if (!empty($vars['form'])) { list($field_name, $field_value) = explode('=', $vars['form']); if ($_POST[$field_name] != $field_value) { return; } } // check if this send request really comes from the website and not from a spambot if (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != $website->subdomain . '.' . $website->domain && parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != $website->domain) { return; } if (empty($vars['email_field'])) { $vars['email_field'] = 'newsletter_email'; } $email = $_REQUEST[$vars['email_field']]; $email = filter_var($email, FILTER_SANITIZE_EMAIL); if (!empty($vars['email_field']) && !empty($email)) { $ok = false; if (filter_var($email, FILTER_VALIDATE_EMAIL) !== FALSE) { $wu_id = $DB->query_single('id', 'nv_webusers', ' email = ' . protect($email) . ' AND website = ' . $website->id); $wu = new webuser(); if (!empty($wu_id)) { $wu->load($wu_id); if ($wu->access == 0 || $wu->access == 2 && ($wu->access_begin == 0 || time() > $wu->access_begin) && ($wu->access_end == 0 || time() < $wu->access_end)) { $wu->newsletter = 1; $ok = $wu->save(); } } if (empty($wu_id) || $wu->access == 1 && !empty($wu->activation_key)) { // create a new webuser account with that email $username = strtolower(substr($email, 0, strpos($email, '@'))); // left part of the email if (!empty($username) && !in_array($username, array('info', 'admin', 'contact', 'demo', 'test'))) { // check if the proposed username already exists, // in that case use the full email as username // ** if the email already exists, the subscribe process only updates the newsletter setting! $wu_id = $DB->query_single('id', 'nv_webusers', ' username = '******' AND website = ' . $website->id); } if (!empty($wu_id)) { // oops, user already exists... try another username -- the full email address $wu_id = $DB->query_single('id', 'nv_webusers', ' username = '******' AND website = ' . $website->id); if (empty($wu_id)) { // ok, email is a new username $username = $email; } else { // nope, email is already used (this code should never execute **) $username = uniqid($username . '-'); } } else { // new sign up $wu->id = 0; $wu->website = $website->id; $wu->email = $email; $wu->newsletter = 1; $wu->language = $current['lang']; // infer the webuser language by the active website language $wu->username = $username; $wu->access = 1; // user is blocked until the server recieves an email confirmation } $wu->activation_key = md5($wu->email . rand(1, 9999999)); $ok = $wu->save(); // send a message to verify the new user's email $email_confirmation_link = $website->absolute_path() . '/nv.webuser/verify?email=' . $wu->email . '&hash=' . $wu->activation_key; $message = navigate_compose_email(array(array('title' => $website->name, 'content' => $webgets[$webget]['translations']['click_to_confirm_account'] . '<br />' . '<a href="' . $email_confirmation_link . '">' . $email_confirmation_link . '</a>'), array('footer' => $webgets[$webget]['translations']['email_confirmation_notice'] . '<br />' . '<a href="' . $website->absolute_path() . $website->homepage() . '">' . $website->name . '</a>'))); @nvweb_send_email($website->name, $message, $wu->email); $pending_confirmation = true; } } $message = $webgets[$webget]['translations']['subscribe_error']; if ($pending_confirmation) { $message = $webgets[$webget]['translations']['email_confirmation']; } else { if ($ok) { $message = $webgets[$webget]['translations']['subscribed_ok']; } } if (empty($vars['notify'])) { $vars['notify'] = 'inline'; } switch ($vars['notify']) { case 'alert': nvweb_after_body('js', 'alert("' . $message . '");'); break; case 'inline': if ($ok) { $out = '<div class="nvweb-newsletter-form-success">' . $message . '</div>'; } else { $out = '<div class="nvweb-newsletter-form-error">' . $message . '</div>'; } break; case 'boolean': $out = $ok; break; case 'false': break; // javascript callback // javascript callback case 'callback': default: if ($ok) { nvweb_after_body('js', $vars['callback'] . '("' . $message . '");'); } else { if (!empty($vars['error_callback'])) { nvweb_after_body('js', $vars['error_callback'] . '("' . $message . '");'); } else { nvweb_after_body('js', $vars['callback'] . '("' . $message . '");'); } } break; } } break; } return $out; }
} else { if (!empty($_COOKIE["webuser"])) { $webuser->load_by_hash($_COOKIE['webuser']); } } // if the webuser was removed, it doesn't exist anymore, // $session/$_COOKIE may have obsolete data, force a log out // also check date range access if (empty($webuser->id) && (!empty($session['webuser']) || !empty($_COOKIE['webuser'])) || !$webuser->access_allowed()) { $webuser->unset_cookie(); unset($webuser); $webuser = new webuser(); } if (!empty($webuser->id)) { $webuser->lastseen = core_time(); $webuser->save(false); // don't trigger the webuser_modified event } // check if the webuser wants to sign out if (isset($_REQUEST['webuser_signout'])) { $webuser->unset_cookie(); unset($webuser); $webuser = new webuser(); } $current['webuser'] = $session['webuser']; setlocale(LC_ALL, $website->languages[$session['lang']]['system_locale']); date_default_timezone_set($webuser->timezone ? $webuser->timezone : $website->default_timezone); // help developers to find problems if ($current['navigate_session'] == 1 && APP_DEBUG) { error_reporting(E_ALL ^ E_NOTICE); ini_set('display_errors', true);