public static function _SaveLicense(Form $form) { try { $model = $form->getModel(); $msg = $model->exists() ? 'Updated' : 'Created'; $model->save(); } catch (ModelValidationException $e) { Core::SetMessage($e->getMessage(), 'error'); return false; } catch (Exception $e) { \Core\ErrorManagement\exception_handler($e); Core::SetMessage($e->getMessage(), 'error'); return false; } Core::SetMessage($msg . ' license successfully!', 'success'); return '/packagerepositorylicense/admin'; }
* but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/agpl-3.0.txt. */ /** * Include the system bootstrap. * This basically does everything..... */ // When working on the core, it's best to switch this back to core/bootstrap.php! // Set this to true to skip checking for the compiled version. $skipcompiled = true; try{ if(!$skipcompiled && file_exists('core/bootstrap.compiled.php')) require_once('core/bootstrap.compiled.php'); else require_once('core/bootstrap.php'); $request = PageRequest::GetSystemRequest(); $request->execute(); $request->render(); } catch(Exception $e){ if(function_exists('\\Core\\ErrorManagement\\exception_handler')){ \Core\ErrorManagement\exception_handler($e, true); } }
public static function UpdateHandler(\Form $form){ /** @var \UserModel $user */ $user = $form->getElement('user')->get('value'); $userid = $user->get('id'); $usermanager = \Core\user()->checkAccess('p:/user/users/manage'); // Only allow this if the user is either the same user or has the user manage permission. if(!($userid == \Core\user()->get('id') || $usermanager)){ \Core\set_message('t:MESSAGE_ERROR_INSUFFICIENT_ACCESS_PERMISSIONS'); return false; } if(!$user->exists()){ \Core\set_message('t:MESSAGE_ERROR_REQUESTED_RESOURCE_NOT_FOUND'); return false; } $userisactive = $user->get('active'); $user->setFromForm($form); if($userisactive == 1 && $user->get('active') == 0){ // User was set from active to inactive. // Instead of setting to a new account, set to deactivated. $user->set('active', '-1'); } elseif($userisactive == -1 && $user->get('active') == 0){ // User was deactivated before, reset back to that. // This is because the active form element is simply an on/off checkbox. $user->set('active', '-1'); } $user->save(); if($userisactive == 0 && $user->get('active') == 1){ // If the user wasn't active before, but is now.... // Send an activation notice email to the user. try{ $email = new \Email(); $email->templatename = 'emails/user/activation.tpl'; $email->assign('user', $user); $email->assign('sitename', SITENAME); $email->assign('rooturl', ROOT_URL); $email->assign('loginurl', \Core\resolve_link('/user/login')); $email->setSubject('Welcome to ' . SITENAME); $email->to($user->get('email')); // TESTING //error_log($email->renderBody()); $email->send(); } catch(\Exception $e){ \Core\ErrorManagement\exception_handler($e); } } // If this was the current user, update the session data too! if($user->get('id') == \core\user()->get('id')){ Session::SetUser($user); if(\ConfigHandler::Get('/user/profileedits/requireapproval') && \Core::IsComponentAvailable('model-audit')){ \Core\set_message('t:MESSAGE_SUCCESS_UPDATED_OWN_USER_ACCOUNT_PENDING_APPROVAL'); } else{ \Core\set_message('t:MESSAGE_SUCCESS_UPDATED_OWN_USER_ACCOUNT'); } } else{ \Core\set_message('t:MESSAGE_SUCCESS_UPDATED_USER_ACCOUNT'); } return true; }
/** * @todo Finish documentation of smarty_function_widgetarea * @param array $params Associative (and/or indexed) array of smarty parameters passed in from the template * @param Smarty_Internal_Template $smarty Parent Smarty template object * * @return string|void */ function smarty_function_widgetarea($params, $smarty) { // Get all widgets set to load in this area. $body = ''; $baseurl = PageRequest::GetSystemRequest()->getBaseURL(); $template = $smarty->template_resource; $tmpl = $smarty->getTemplateVars('__core_template'); $topview = ($tmpl instanceof \Core\Templates\TemplateInterface) ? $tmpl->getView() : \Core\view(); $parameters = []; $name = null; $installable = null; $assign = null; foreach($params as $k => $v){ switch($k){ case 'name': $name = $v; break; case 'installable': $installable = $v; break; case 'assign': $assign = $v; break; default: $parameters[$k] = $v; break; } } // I need to resolve the page template down to the base version in order for the lookup to work. foreach(Core\Templates\Template::GetPaths() as $base){ if(strpos($template, $base) === 0){ $template = substr($template, strlen($base)); break; } } // Given support for page-level widgets, this logic gets slightly more difficult... $factory = new ModelFactory('WidgetInstanceModel'); $factory->order('weight'); if(Core::IsComponentAvailable('multisite') && MultiSiteHelper::IsEnabled()){ $factory->whereGroup('or', ['site = -1', 'site = ' . MultiSiteHelper::GetCurrentSiteID()]); } $subwhere = new Core\Datamodel\DatasetWhereClause(); $subwhere->setSeparator('OR'); // First, the skin-level where clause. $skinwhere = new Core\Datamodel\DatasetWhereClause(); $skinwhere->setSeparator('AND'); $skinwhere->addWhere('template = ' . $template); $skinwhere->addWhere('widgetarea = ' . $name); $subwhere->addWhere($skinwhere); // And second, the page-level where clause. if($baseurl){ $pagewhere = new Core\Datamodel\DatasetWhereClause(); $pagewhere->setSeparator('AND'); $pagewhere->addWhere('page_baseurl = ' . $baseurl); $pagewhere->addWhere('widgetarea = ' . $name); $subwhere->addWhere($pagewhere); } $factory->where($subwhere); $widgetcount = 0; try{ $widgets = $factory->get(); } catch(Exception $e){ if(DEVELOPMENT_MODE){ $body .= '<p class="message-error">Exception while trying to load widget area ' . $name . '!</p>'; $body .= '<pre class="xdebug-var-dump">' . $e->getMessage() . '</pre>'; } else{ \Core\ErrorManagement\exception_handler($e, false); } $widgets = []; ++$widgetcount; } foreach ($widgets as $wi) { /** @var $wi WidgetInstanceModel */ // User cannot access this widget? Don't display it... if(!\Core\user()){ continue; } if (!\Core\user()->checkAccess($wi->get('access'))){ continue; } if($installable){ $wi->set('installable', $installable); } $view = $wi->execute($parameters); // Some widgets may return simply a blank string. Those should just be ignored. if ($view == ''){ continue; } // If it's just a string, return that. if (is_string($view)) { $contents = $view; } elseif($view->error == View::ERROR_NOERROR){ // Ensure that the widget's View knows it's linked to a parent! $view->parent = $topview; $contents = $view->fetch(); } else{ $contents = 'Error displaying widget [' . $wi->get('baseurl') . '], returned error [' . $view->error . ']'; } ++$widgetcount; // Does this widget have controls attached to it? $widget = $wi->getWidget(); if($widget->controls instanceof ViewControls && $widget->controls->hasLinks()){ $contents = '<div class="widget-controls-wrapper">' . '<menu id="widget-controls-' . $wi->get('id') . '">' . $widget->controls->fetch() . '</menu>' . '</div>' . $contents; } $body .= '<div class="widget">' . $contents . '</div>'; } // Do some sanitizing for the css data $class = 'widgetarea-' . strtolower(str_replace(' ', '', $name)); $html = '<div class="widgetarea ' . $class . '" widgetarea="' . $name . '">' . $body . '</div>'; // No widgets, no inner content! if($widgetcount == 0){ $html = ''; } if($assign){ $smarty->assign($assign, $html); } else{ return $html; } }
/** * Form Handler for logging in. * * @static * * @param \Form $form * * @return bool|null|string */ public static function LoginHandler(\Form $form){ /** @var \FormElement $e */ $e = $form->getElement('email'); /** @var \FormElement $p */ $p = $form->getElement('pass'); /** @var \UserModel $u */ $u = \UserModel::Find(array('email' => $e->get('value')), 1); if(!$u){ // Log this as a login attempt! $logmsg = 'Failed Login. Email not registered' . "\n" . 'Email: ' . $e->get('value') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login', $logmsg); $e->setError('t:MESSAGE_ERROR_USER_LOGIN_EMAIL_NOT_FOUND'); return false; } if($u->get('active') == 0){ // The model provides a quick cut-off for active/inactive users. // This is the control managed with in the admin. $logmsg = 'Failed Login. User tried to login before account activation' . "\n" . 'User: '******'email') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login', $logmsg, null, $u->get('id')); $e->setError('t:MESSAGE_ERROR_USER_LOGIN_ACCOUNT_NOT_ACTIVE'); return false; } elseif($u->get('active') == -1){ // The model provides a quick cut-off for active/inactive users. // This is the control managed with in the admin. $logmsg = 'Failed Login. User tried to login after account deactivation.' . "\n" . 'User: '******'email') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login', $logmsg, null, $u->get('id')); $e->setError('t:MESSAGE_ERROR_USER_LOGIN_ACCOUNT_DEACTIVATED'); return false; } try{ /** @var \Core\User\AuthDrivers\datastore $auth */ $auth = $u->getAuthDriver('datastore'); } catch(Exception $e){ $e->setError('t:MESSAGE_ERROR_USER_LOGIN_PASSWORD_AUTH_DISABLED'); return false; } // This is a special case if the password isn't set yet. // It can happen with imported users or if a password is invalidated. if($u->get('password') == ''){ // Use the Nonce system to generate a one-time key with this user's data. $nonce = \NonceModel::Generate( '20 minutes', ['type' => 'password-reset', 'user' => $u->get('id')] ); $link = '/datastoreauth/forgotpassword?e=' . urlencode($u->get('email')) . '&n=' . $nonce; $email = new \Email(); $email->setSubject('Initial Password Request'); $email->to($u->get('email')); $email->assign('link', \Core\resolve_link($link)); $email->assign('ip', REMOTE_IP); $email->templatename = 'emails/user/initialpassword.tpl'; try{ $email->send(); \SystemLogModel::LogSecurityEvent('/user/initialpassword/send', 'Initial password request sent successfully', null, $u->get('id')); \Core\set_message('t:MESSAGE_INFO_USER_LOGIN_MUST_SET_NEW_PASSWORD_INSTRUCTIONS_HAVE_BEEN_EMAILED'); return true; } catch(\Exception $e){ \Core\ErrorManagement\exception_handler($e); \Core\set_message('t:MESSAGE_ERROR_USER_LOGIN_MUST_SET_NEW_PASSWORD_UNABLE_TO_SEND_EMAIL'); return false; } } if(!$auth->checkPassword($p->get('value'))){ // Log this as a login attempt! $logmsg = 'Failed Login. Invalid password' . "\n" . 'Email: ' . $e->get('value') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login/failed_password', $logmsg, null, $u->get('id')); // Also, I want to look up and see how many login attempts there have been in the past couple minutes. // If there are too many, I need to start slowing the attempts. $time = new \CoreDateTime(); $time->modify('-5 minutes'); $securityfactory = new \ModelFactory('SystemLogModel'); $securityfactory->where('code = /user/login/failed_password'); $securityfactory->where('datetime > ' . $time->getFormatted(\Time::FORMAT_EPOCH, \Time::TIMEZONE_GMT)); $securityfactory->where('ip_addr = ' . REMOTE_IP); $attempts = $securityfactory->count(); if($attempts > 4){ // Start slowing down the response. This should help deter brute force attempts. // (x+((x-7)/4)^3)-4 sleep( ($attempts+(($attempts-7)/4)^3)-4 ); // This makes a nice little curve with the following delays: // 5th attempt: 0.85 // 6th attempt: 2.05 // 7th attempt: 3.02 // 8th attempt: 4.05 // 9th attempt: 5.15 // 10th attempt: 6.52 // 11th attempt: 8.10 // 12th attempt: 10.05 } $e->setError('t:MESSAGE_ERROR_USER_LOGIN_INCORRECT_PASSWORD'); $p->set('value', ''); return false; } if($form->getElementValue('redirect')){ // The page was set via client-side javascript on the login page. // This is the most reliable option. $url = $form->getElementValue('redirect'); } elseif(REL_REQUEST_PATH == '/user/login'){ // If the user came from the registration page, get the page before that. $url = $form->referrer; } else{ // else the registration link is now on the same page as the 403 handler. $url = REL_REQUEST_PATH; } // Well, record this too! \SystemLogModel::LogSecurityEvent('/user/login', 'Login successful (via password)', null, $u->get('id')); // yay... $u->set('last_login', \CoreDateTime::Now('U', \Time::TIMEZONE_GMT)); $u->save(); \Core\Session::SetUser($u); // Allow an external script to override the redirecting URL. $overrideurl = \HookHandler::DispatchHook('/user/postlogin/getredirecturl'); if($overrideurl){ $url = $overrideurl; } return $url; }
/** * Function that is fired off on page load. * This checks if a form was submitted and that form was present in the SESSION. * * @return null */ public static function CheckSavedSessionData() { // This needs to ignore the /form/savetemporary.ajax page! // This is a custom page that's meant to intercept all POST submissions. if(preg_match('#^/form/(.*)\.ajax$#', REL_REQUEST_PATH)) return; // There has to be data in the session. $forms = \Core\Session::Get('FormData/*'); $formid = (isset($_REQUEST['___formid'])) ? $_REQUEST['___formid'] : false; $form = false; foreach ($forms as $k => $v) { // If the object isn't a valid object after unserializing... if (!($el = unserialize($v))) { \Core\Session::UnsetKey('FormData/' . $k); continue; } // Check the expires time if ($el->get('expires') <= Time::GetCurrent()) { \Core\Session::UnsetKey('FormData/' . $k); continue; } if ($k == $formid) { // Remember this for after all the checks have finished. $form = $el; } } // No form found... simple enough if (!$form) return; // Otherwise /** @var $form Form */ // Ensure the submission types match up. if (strtoupper($form->get('method')) != $_SERVER['REQUEST_METHOD']) { \Core\set_message('t:MESSAGE_ERROR_FORM_SUBMISSION_TYPE_DOES_NOT_MATCH'); return; } // Ensure the REFERRER and original URL match up. if($_SERVER['HTTP_REFERER'] != $form->originalurl){ // @todo This is reported to be causing issues with production sites. // If found true, this check may need to be removed / refactored. //\Core\set_message('Form submission referrer does not match, please try your submission again.', 'error'); SystemLogModel::LogInfoEvent( 'Form Referrer Mismatch', 'Form referrer does not match! Submitted: [' . $_SERVER['HTTP_REFERER'] . '] Expected: [' . $form->originalurl . ']' ); //return; } // Run though each element submitted and try to validate it. if (strtoupper($form->get('method')) == 'POST') $src =& $_POST; else $src =& $_GET; $form->loadFrom($src); // Try to load the form from that form. That will call all of the model's validation logic // and will throw exceptions if it doesn't. try{ $form->getModel(); // Still good? if (!$form->hasError()){ $status = call_user_func($form->get('callsmethod'), $form); } else{ $status = false; } } catch(ModelValidationException $e){ \Core\set_message($e->getMessage(), 'error'); $status = false; } catch(GeneralValidationException $e){ \Core\set_message($e->getMessage(), 'error'); $status = false; } catch(Exception $e){ if(DEVELOPMENT_MODE){ // Developers get the full message \Core\set_message($e->getMessage(), 'error'); } else{ // While users of production-enabled sites get a friendlier message. \Core\set_message('t:MESSAGE_ERROR_FORM_SUBMISSION_UNHANDLED_EXCEPTION'); } Core\ErrorManagement\exception_handler($e); $status = false; } // The form was submitted. Set its persistent flag to true so that whatever may be listening for it can retrieve the user's values. $form->persistent = true; // Regardless, bundle this form back into the session so the controller can use it if needed. \Core\Session::Set('FormData/' . $formid, serialize($form)); // Fail statuses. if ($status === false) return; if ($status === null) return; // Guess it's not false and not null... must be good then. // @todo Handle an internal save procedure for "special" groups such as pageinsertables and what not. // Cleanup \Core\Session::UnsetKey('FormData/' . $formid); if ($status === 'die'){ // If it's set to die, simply exit the script without outputting anything. exit; } elseif($status === 'back'){ if($form->referrer && $form->referrer != REL_REQUEST_PATH){ // Go back to the original form's referrer. \Core\redirect($form->referrer); } else{ // Use Core to guess which page to redirect back to, (not as reliable). \Core\go_back(); } } elseif ($status === true){ // If the return code is boolean true, it's a reload. \Core\reload(); } elseif($status === REL_REQUEST_PATH || $status === CUR_CALL){ // If the page returned the same page as the current url, force a reload, (as redirect will ignore it) \Core\reload(); } else{ // Anything else gets sent to the redirect system. \core\redirect($status); } }
/** * Render the View to the browser. */ public function render(){ \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Starting PageRequest->render()'); $view = $this->getView(); $page = $this->getPageModel(); // Dispatch the hooks here if it's a 404 or 403. if ($view->error == View::ERROR_ACCESSDENIED || $view->error == View::ERROR_NOTFOUND) { // Let other things chew through it... (optionally) HookHandler::DispatchHook('/core/page/error-' . $view->error, $view); } try { // This will pre-fetch the contents of the entire page and store it into memory. // If it is cacheable, then it will be cached and used for the next execution. // If the user has the view user activity permission, add the link to that page! if(\Core\user()->checkAccess('p:user_activity_list') && $page && $page->exists()){ $view->addControl( 'User Activity Details', '/useractivity/details?filter[baseurl]=' . $page->get('baseurl'), 'eye' ); } $view->fetch(); } catch (Exception $e) { // If something happens in the rendering of the template... consider it a server error. $view->error = View::ERROR_SERVERERROR; $view->baseurl = '/error/error/500'; $view->setParameters(array()); $view->templatename = '/pages/error/error500.tpl'; $view->mastertemplate = ConfigHandler::Get('/theme/default_template'); $view->assignVariable('exception', $e); \Core\ErrorManagement\exception_handler($e); $view->fetch(); } if($this->isCacheable()){ $uakey = \Core\UserAgent::Construct()->getPseudoIdentifier(); $urlkey = $this->host . $this->uri; $expires = $page->get('expires'); // Number of seconds. $key = 'page-cache-' . md5($urlkey . '-' . $uakey); $d = new \Core\Date\DateTime(); $d->modify('+' . $expires . ' seconds'); $view->headers['Cache-Control'] = 'max-age=' . $expires; $view->headers['Expires'] = $d->format('r', \Core\Date\Timezone::TIMEZONE_GMT); $view->headers['Vary'] = 'Accept-Encoding,User-Agent,Cookie'; $view->headers['X-Core-Cached-Date'] = \Core\Date\DateTime::NowGMT('r'); $view->headers['X-Core-Cached-Server'] = 1; // @todo Implement multi-server support. $view->headers['X-Core-Cached-Render-Time'] = \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->getTimeFormatted(); // Record the actual View into cache. \Core\Cache::Set($key, $view, $expires); // And record the key onto an index cache record so there's a record of what to delete on updates. $indexkey = $page->getIndexCacheKey(); $index = \Core\Cache::Get($indexkey, SECONDS_ONE_DAY); if(!$index){ $index = []; } $index[] = $key; \Core\Cache::Set($indexkey, $index, SECONDS_ONE_DAY); } elseif(($reason = $this->isNotCacheableReason()) !== null){ $view->headers['X-Core-NotCached-Reason'] = $reason; } $view->headers['X-Core-Render-Time'] = \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->getTimeFormatted(); $view->render(); // Make sure I update any existing page now that the controller has ran. if ($page && $page->exists() && $view->error == View::ERROR_NOERROR) { // Only increase the pageview count if the visitor is not a bot. // UA detection isn't very accurate, but this isn't for precision accuracy, merely a rough estimate. if(!\Core\UserAgent::Construct()->isBot()){ $page->set('pageviews', $page->get('pageviews') + 1); } $page->set('last_template', $view->templatename); $page->set('body', $view->fetchBody()); $page->save(); } // Just before the page stops execution... HookHandler::DispatchHook('/core/page/postrender'); }
/** * Fetch this view as an HTML string. * @return mixed|null|string */ public function fetch() { if($this->_fetchCache !== null){ // w00t ;) return $this->_fetchCache; } try{ $body = $this->fetchBody(); \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record( 'Fetched application content from within View->fetch() for ' . $this->templatename ); } catch(Exception $e){ $this->error = View::ERROR_SERVERERROR; \Core\ErrorManagement\exception_handler($e, ($this->mode == View::MODE_PAGE)); $body = ''; } // If there's no template, I have nothing to even do! if ($this->mastertemplate === false) { return $body; } // Else if it's null, it's just not set yet :p // @deprecated here! elseif ($this->mastertemplate === null) { $this->mastertemplate = ConfigHandler::Get('/theme/default_template'); } // Whee! //var_dump($this->templatename, Core\Templates\Template::ResolveFile($this->templatename)); // Content types take priority on controlling the master template. if ($this->contenttype == View::CTYPE_JSON) { $mastertpl = false; } else { // Master template depends on the render mode. switch ($this->mode) { case View::MODE_PAGEORAJAX: if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){ $mastertpl = false; $this->mode = View::MODE_AJAX; } else{ $mastertpl = ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/skins/' . $this->mastertemplate; $this->mode = View::MODE_PAGE; } break; case View::MODE_NOOUTPUT: case View::MODE_AJAX: $mastertpl = false; break; case View::MODE_PAGE: case View::MODE_EMAILORPRINT: $mastertpl = Core\Templates\Template::ResolveFile('skins/' . $this->mastertemplate); //$mastertpl = ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/skins/' . $this->mastertemplate; break; case View::MODE_WIDGET: $mastertpl = Core\Templates\Template::ResolveFile('widgetcontainers/' . $this->mastertemplate); break; } } // If there's *still* no template, I still have nothing to do. if (!$mastertpl) return $body; $template = \Core\Templates\Template::Factory($mastertpl); // Ensure that the template is linked to this View correctly. $template->setView($this); //$template = new Core\Templates\Template(); //$template->setBaseURL('/'); // Page-level views have some special variables. if ($this->mode == View::MODE_PAGE) { $template->assign('breadcrumbs', $this->getBreadcrumbs()); $template->assign('controls', $this->controls); $template->assign('messages', Core::GetMessages()); // Tack on the pre and post body variables from the current page. //$body = CurrentPage::GetBodyPre() . $body . CurrentPage::GetBodyPost(); } // Widgets need some special variables too. //if($this->mode == View::MODE_WIDGET){ // //var_dump($this->getVariable('widget')); die(); // $template->assign('widget', $this->getVariable('widget')); //} // This logic is needed for the SEO title, since that's usually completely human unfriendly. if(isset($this->meta['title']) && $this->meta['title']){ $template->assign('seotitle', $this->meta['title']); } else{ $template->assign('seotitle', $this->getTitle()); } $template->assign('title', $this->getTitle()); $template->assign('body', $body); // The body needs some custom classes for assisting the designers. // These are mainly pulled from the UA. $ua = \Core\UserAgent::Construct(); $this->bodyclasses = array_merge($this->bodyclasses, $ua->getPseudoIdentifier(true)); // Provide a way for stylesheets to target this page specifically. switch ($this->error) { case View::ERROR_BADREQUEST: case View::ERROR_PAYMENTREQUIRED: case View::ERROR_ACCESSDENIED: case View::ERROR_NOTFOUND: case View::ERROR_METHODNOTALLOWED: case View::ERROR_NOTACCEPTABLE: case View::ERROR_PROXYAUTHENTICATIONREQUIRED: case View::ERROR_REQUESTTIMEOUT: case View::ERROR_CONFLICT: case View::ERROR_GONE: case View::ERROR_LENGTHREQUIRED: case View::ERROR_PRECONDITIONFAILED: case View::ERROR_ENTITYTOOLARGE: case View::ERROR_URITOOLARGE: case View::ERROR_UNSUPPORTEDMEDIATYPE: case View::ERROR_RANGENOTSATISFIABLE: case View::ERROR_EXPECTATIONFAILED: case View::ERROR_UNAUTHORIZED: $url = 'error-' . $this->error; break; case 403: $url = "error-403 page-user-login"; break; default: $url = strtolower(trim(preg_replace('/[^a-z0-9\-]*/i', '', str_replace('/', '-', $this->baseurl)), '-')); } while($url != ''){ $this->bodyclasses[] = 'page-' . $url; $url = substr($url, 0, strrpos($url, '-')); } $bodyclasses = strtolower(implode(' ', $this->bodyclasses)); $template->assign('body_classes', $bodyclasses); try{ $data = $template->fetch(); } catch(SmartyException $e){ $this->error = View::ERROR_SERVERERROR; error_log('[view error]'); error_log('Template name: [' . $mastertpl . ']'); \Core\ErrorManagement\exception_handler($e); require(ROOT_PDIR . 'core/templates/halt_pages/fatal_error.inc.html'); die(); } catch(TemplateException $e){ $this->error = View::ERROR_SERVERERROR; error_log('[view error]'); error_log('Template name: [' . $mastertpl . ']'); \Core\ErrorManagement\exception_handler($e); require(ROOT_PDIR . 'core/templates/halt_pages/fatal_error.inc.html'); die(); } if($this->mode == View::MODE_EMAILORPRINT && $this->contenttype == View::CTYPE_HTML){ // Inform other elements that the page is just about to be rendered. HookHandler::DispatchHook('/core/page/rendering', $this); // Replace the </head> tag with the head data from the current page // and the </body> with the foot data from the current page. // This is needed to be done at this stage because some element in // the template after rendering may add additional script to the head. // Also tack on any attributes for the <html> tag. if(preg_match('#</head>#i', $data)){ // I need to do preg_replace because I only want to replace the FIRST instance of </head> $data = preg_replace('#</head>#i', $this->getHeadContent() . "\n" . '</head>', $data, 1); } } elseif ($this->mode == View::MODE_PAGE && $this->contenttype == View::CTYPE_HTML) { // Inform other elements that the page is just about to be rendered. HookHandler::DispatchHook('/core/page/rendering', $this); // Metadata! w00t // Replace the </head> tag with the head data from the current page // and the </body> with the foot data from the current page. // This is needed to be done at this stage because some element in // the template after rendering may add additional script to the head. // Also tack on any attributes for the <html> tag. if(preg_match('#</head>#i', $data)){ // I need to do preg_replace because I only want to replace the FIRST instance of </head> $data = preg_replace('#</head>#i', $this->getHeadContent() . "\n" . '</head>', $data, 1); } if(preg_match('#</body>#i', $data)){ // I need to use strrpos because I only want the LAST instance of </body> $match = strrpos($data, '</body>'); $foot = $this->getFootContent(); if(defined('ENABLE_XHPROF') && function_exists('xhprof_disable')){ require_once('xhprof_lib/utils/xhprof_lib.php'); #SKIPCOMPILER require_once('xhprof_lib/utils/xhprof_runs.php'); #SKIPCOMPILER $xhprof_data = xhprof_disable(); $namespace = trim(str_replace(['.', '/'], '-', HOST . REL_REQUEST_PATH), '-'); $xhprof_runs = new XHProfRuns_Default(); $run_id = $xhprof_runs->save_run($xhprof_data, $namespace); define('XHPROF_RUN', $run_id); define('XHPROF_SOURCE', $namespace); $xhprof_link = sprintf( '<a href="' . SERVERNAME . '/xhprof/index.php?run=%s&source=%s" target="_blank">View XHprof Profiler Report</a>' . "\n", $run_id, $namespace ); } else{ $xhprof_link = ''; } // If the viewmode is regular and DEVELOPMENT_MODE is enabled, show some possibly useful information now that everything's said and done. if (DEVELOPMENT_MODE) { $legend = '<div class="fieldset-title">%s<i class="icon-chevron-down expandable-hint"></i><i class="icon-chevron-up collapsible-hint"></i></div>' . "\n"; $debug = ''; $debug .= '<pre class="xdebug-var-dump screen">'; $debug .= '<fieldset class="debug-section collapsible" id="debug-section-template-information">'; $debug .= sprintf($legend, 'Template Information'); $debug .= "<span>"; $debug .= 'Base URL: ' . $this->baseurl . "\n"; $debug .= 'Template Requested: ' . $this->templatename . "\n"; $debug .= 'Template Actually Used: ' . \Core\Templates\Template::ResolveFile($this->templatename) . "\n"; $debug .= 'Master Skin: ' . $this->mastertemplate . "\n"; $debug .= "</span>"; $debug .= '</fieldset>'; $debug .= '<fieldset class="debug-section collapsible" id="debug-section-performance-information">'; $debug .= sprintf($legend, 'Performance Information'); $debug .= "<span>"; $debug .= $xhprof_link; $debug .= "Database Reads: " . \Core\Utilities\Profiler\DatamodelProfiler::GetDefaultProfiler()->readCount() . "\n"; $debug .= "Database Writes: " . \Core\Utilities\Profiler\DatamodelProfiler::GetDefaultProfiler()->writeCount() . "\n"; //$debug .= "Number of queries: " . DB::Singleton()->counter . "\n"; //$debug .= "Amount of memory used by PHP: " . \Core\Filestore\format_size(memory_get_usage()) . "\n"; $debug .= "Amount of memory used by PHP: " . \Core\Filestore\format_size(memory_get_peak_usage(true)) . "\n"; $profiler = Core\Utilities\Profiler\Profiler::GetDefaultProfiler(); $debug .= "Total processing time: " . $profiler->getTimeFormatted() . "\n"; $debug .= "</span>"; $debug .= '</fieldset>'; $debug .= '<fieldset class="debug-section collapsible" id="debug-section-profiler-information">'; $debug .= sprintf($legend, 'Core Profiler'); $debug .= "<span>"; $debug .= $profiler->getEventTimesFormatted(); $debug .= "</span>"; $debug .= '</fieldset>'; $debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-components-information">'; // Tack on what components are currently installed. $debug .= sprintf($legend, 'Available Components'); $debugcomponents = array_merge(Core::GetComponents(), Core::GetDisabledComponents()); $debug .= "<span>"; // Give me sorting! ksort($debugcomponents); foreach ($debugcomponents as $l => $v) { if($v->isEnabled() && $v->isReady()){ $debug .= '[<span style="color:green;">Enabled</span>]'; } elseif($v->isEnabled() && !$v->isReady()){ $debug .= '[<span style="color:red;">!ERROR!</span>]'; } else{ $debug .= '[<span style="color:red;">Disabled</span>]'; } $debug .= $v->getName() . ' ' . $v->getVersion() . "<br/>"; } $debug .= "</span>"; $debug .= '</fieldset>'; $debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-hooks-information">'; // I wanna see what hooks are registered too! $debug .= sprintf($legend, 'Registered Hooks'); foreach(HookHandler::GetAllHooks() as $hook){ $debug .= "<span>"; /** @var $hook Hook */ $debug .= $hook->name; if($hook->description) $debug .= ' <em> - ' . $hook->description . '</em>'; $debug .= "\n" . '<span style="color:#999;">Return expected: ' . $hook->returnType . '</span>'; $debug .= "\n" . '<span style="color:#999;">Attached by ' . $hook->getBindingCount() . ' binding(s).</span>'; foreach($hook->getBindings() as $b){ $debug .= "\n" . ' * ' . $b['call']; } $debug .= "\n\n"; $debug .= "</span>"; } $debug .= '</fieldset>'; // Display the licensed content on this application $debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-licenser-information">'; $debug .= sprintf($legend, 'Licensed Information'); $lic = \Core\Licenser::GetRaw(); $debug .= '<div>'; foreach($lic as $dat){ $debug .= $dat['url'] . '::' . $dat['feature'] . ' => ' . $dat['value'] . "\n"; } $debug .= '</div></fieldset>'; $debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-includes-information">'; // I want to see how many files were included. $debug .= sprintf($legend, 'Included Files'); $debug .= '<span>Number: ' . sizeof(get_included_files()) . "</span>"; $debug .= '<span>'. implode("<br/>", get_included_files()) . "</span>"; $debug .= '</fieldset>'; $debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-query-information">'; $debug .= sprintf($legend, 'Query Log'); $profiler = \Core\Utilities\Profiler\DatamodelProfiler::GetDefaultProfiler(); $debug .= '<div>' . $profiler->getEventTimesFormatted() . '</div>'; $debug .= '</fieldset>'; // Display all the i18n strings available on the system. $debug .= '<fieldset class="debug-section collapsible collapsed" id="debug-section-i18nstrings-information">'; $debug .= sprintf($legend, 'I18N Strings Available'); $strings = \Core\i18n\I18NLoader::GetAllStrings(); $debug .= '<ul>'; foreach($strings as &$s){ $debug .= '<li>' . $s['key'] . '</li>'; } $debug .= '</ul>'; $debug .= '</fieldset>'; $debug .= '</pre>'; // And append! $foot .= "\n" . $debug; } $data = substr_replace($data, $foot . "\n" . '</body>', $match, 7); } $data = preg_replace('#<html#', '<html ' . $this->getHTMLAttributes(), $data, 1); // This logic has been migrated to the {$body_classes} variable. /* if(preg_match('/<body[^>]*>/', $data, $matches)){ // body is $matches[0]. $fullbody = $matches[0]; if($fullbody == '<body>'){ $body = '<body class="' . $bodyclass . '">'; } elseif(strpos($fullbody, 'class=') === false){ // Almost as easy, other elements but no class. $body = substr($fullbody, 0, -1) . ' class="' . $bodyclass . '">'; } else{ // parsing HTML is far easier with XML objects. $node = new SimpleXMLElement($fullbody . '</body>'); $body = '<body'; foreach($node->attributes() as $k => $v){ if($k == 'class'){ $body .= ' ' . $k . '="' . $bodyclass . ' ' . $v . '"'; } else{ $body .= ' ' . $k . '="' . $v . '"'; } } $body .= '>'; } // And replace! $data = preg_replace('#<body[^>]*>#', $body, $data, 1); } */ } $this->_fetchCache = $data; return $data; }
/** * Save handler for the index edit form. * * This form just manages the page data for the /blog listing. * @param Form $form * * @return bool|mixed|null */ public static function BlogIndexFormHandler(Form $form) { try { /** @var PageModel $page */ $page = $form->getModel('page'); $page->save(); // Clear the page cache $page->purgePageCache(); Core::SetMessage('Updated Listing Information', 'success'); return 'back'; } catch (Exception $e) { \Core\ErrorManagement\exception_handler($e); Core::SetMessage($e->getMessage(), 'error'); return false; } }
/** * View to import a given feed into the system. * * @return int */ public function import() { if (!$this->setAccess('p:/blog/manage_all')) { return View::ERROR_ACCESSDENIED; } $view = $this->getView(); $request = $this->getPageRequest(); $blog = new BlogModel($request->getParameter(0)); $blogid = $blog->get('id'); if (!$blog->exists()) { return View::ERROR_NOTFOUND; } if ($request->isPost()) { $view->mode = View::MODE_NOOUTPUT; $view->contenttype = View::CTYPE_HTML; $view->record = false; $view->templatename = null; $view->render(); // Try to perform the import. try { $results = $blog->importFeed(true); } catch (Exception $e) { echo '<p class="message-error">' . $e->getMessage() . '</p>'; \Core\ErrorManagement\exception_handler($e); die; } echo 'DONE!' . "<br/>\n"; echo 'Added: ' . $results['added'] . "<br/>\n"; echo 'Updated: ' . $results['updated'] . "<br/>\n"; echo 'Skipped: ' . $results['skipped'] . "<br/>\n"; } $view->addBreadcrumb($blog->get('title'), $blog->get('rewriteurl')); $view->title = 'Import Blog Feed'; //$view->assign('changelog', $results['changelog']); //$view->assign('added', $results['added']); //$view->assign('updated', $results['updated']); //$view->assign('skipped', $results['skipped']); //$view->assign('deleted', $results['deleted']); }
/** * Simple controller to activate a user account. * Meant to be called with json only. */ public function activate(){ $req = $this->getPageRequest(); $view = $this->getView(); $userid = $req->getPost('user') ? $req->getPost('user') : $req->getParameter('user'); $active = ($req->getPost('status') !== null) ? $req->getPost('status') : $req->getParameter('status'); if($active === '') $active = 1; // default. if(!\Core\user()->checkAccess('p:/user/users/manage')){ return View::ERROR_ACCESSDENIED; } if(!$req->isPost()){ return View::ERROR_BADREQUEST; } if(!$userid){ return View::ERROR_BADREQUEST; } $user = UserModel::Construct($userid); if(!$user->exists()){ return View::ERROR_NOTFOUND; } $user->set('active', $active); $user->save(); // Send an activation notice email to the user if the active flag is set to true. if($active){ try{ $email = new Email(); if(!$user->get('password')){ // Generate a Nonce for this user with the password reset. // Use the Nonce system to generate a one-time key with this user's data. $nonce = NonceModel::Generate( '1 week', ['type' => 'password-reset', 'user' => $user->get('id')] ); $setpasswordlink = \Core\resolve_link('/datastoreauth/forgotpassword?e=' . urlencode($user->get('email')) . '&n=' . $nonce); } else{ $setpasswordlink = null; } $email->templatename = 'emails/user/activation.tpl'; $email->assign('user', $user); $email->assign('sitename', SITENAME); $email->assign('rooturl', ROOT_URL); $email->assign('loginurl', \Core\resolve_link('/user/login')); $email->assign('setpasswordlink', $setpasswordlink); $email->setSubject('Welcome to ' . SITENAME); $email->to($user->get('email')); // TESTING //error_log($email->renderBody()); $email->send(); } catch(\Exception $e){ \Core\ErrorManagement\exception_handler($e); } } if($req->isJSON()){ $view->mode = View::MODE_AJAX; $view->contenttype = View::CTYPE_JSON; $view->jsondata = array( 'userid' => $user->get('id'), 'active' => $user->get('active'), ); } else{ \Core\go_back(); } }
/** * Resolve a url or application path to a fully-resolved URL. * * This can also be an already-resolved link. If so, no action is taken * and the original URL is returned unchanged. * * @param string $url * * @return string The full url of the link, including the http://... */ function resolve_link($url) { // Allow "#" to be verbatim without translation. if ($url == '#') return $url; // Allow already-resolved links to be returned verbatim. if (strpos($url, '://') !== false) return $url; // <strike>FIRST</strike> Second THING!?!?! // All URLs should be case insensitive. // As such, I *should* be able to safely strlower everything and be fine. // This is particularly important because all URL lookups from the database are performed in lowercase. //$url = strtolower($url); // Allow links starting with ? to be read as the current page. if($url{0} == '?'){ $url = REL_REQUEST_PATH . $url; } // Allow multisite URLs to be passed in natively. if(stripos($url, 'site:') === 0){ $slashpos = strpos($url, '/'); $site = substr($url, 5, $slashpos-5); $url = substr($url, $slashpos); } else{ $site = null; } try{ $a = \PageModel::SplitBaseURL($url, $site); } catch(\Exception $e){ // Well, this isn't a fatal error, so just warn the admin and continue on. \Core\ErrorManagement\exception_handler($e); error_log('Unable to resolve URL [' . $url . '] due to exception [' . $e->getMessage() . ']'); return ''; } // Instead of going through the overhead of a pagemodel call, SplitBaseURL provides what I need! return $a['fullurl']; }