public function render() { if (!$this->get('basedir')) { throw new Exception('MultiFileInput cannot be rendered without a basedir attribute!'); } // Make sure it ends with a trailing slash. if (substr($this->get('basedir'), -1) != '/') { $this->_attributes['basedir'] .= '/'; } //var_dump($_SESSION['multifileinputobjects'], serialize($this->_attributes)); die(); // This is a slightly different element than the traditional form system, as it must be able to be called without // the rest of the form system on submit. // This is because this system will do an ajax submit to do the actual upload. if (!is_array(\Core\Session::Get('multifileinputobjects'))) { \Core\Session::Set('multifileinputobjects', []); } // I don't need this key to be cryptographically secure, just generally unique. $key = md5(serialize($this->_attributes)); foreach (\Core\Session::Get('multifileinputobjects') as $obj) { if (!isset($obj['key'])) { continue; } if ($obj['key'] == $key) { $this->set('id', $obj['id']); } } if (!isset($this->_attributes['id'])) { // This system requires a valid id. $this->set('id', 'multifileinput-' . Core::RandomHex('2')); } $this->set('key', $key); $this->set('uploadkey', $key); // Convert the string representation of a filesize to the raw bytes. $size = strtoupper(str_replace(' ', '', ini_get('upload_max_filesize'))); if (strpos($size, 'G') !== false) { $size = preg_replace('/[^0-9]/', '', $size); $size = $size * (1024 * 1024 * 1024); } elseif (strpos($size, 'M') !== false) { $size = preg_replace('/[^0-9]/', '', $size); $size = $size * (1024 * 1024); } elseif (strpos($size, 'K') !== false) { $size = preg_replace('/[^0-9]/', '', $size); $size = $size * 1024; } $this->set('maxsize', $size); // Now that the session variable has been initialized, the traditional session variable is reliable. $_SESSION['multifileinputobjects'][$key] = array('obj' => serialize($this), 'key' => $key, 'id' => $this->_attributes['id']); return parent::render(); }
/** * Load the values from either the page request or the session data. * * @param PageRequest $request */ public function load(PageRequest $request){ // First, load everything from the session. $this->loadSession(); $a = array(); $s = array(); $p = array(); // Check the sort keys? if($this->hassort){ if($request->getParameter('sortkey')){ $this->setSortKey($request->getParameter('sortkey')); $s['sortkey'] = $this->_sortkey; } if($request->getParameter('sortdir')){ $this->setSortDirection($request->getParameter('sortdir')); $s['sortdir'] = $this->_sortdir; } } // Did the user change a filter? // If a filter was changed, reset back to page 1! if($request->getParameter('filter')){ $filters = $request->getParameter('filter'); foreach($filters as $f => $v){ if(!isset($this->_elementindexes['filter[' . $f . ']'])) continue; /** @var $el FormElement */ $el = $this->_elementindexes['filter[' . $f . ']']; $el->setValue($v); // Remember this for the session data. $a[$f] = $v; $this->setPage(1); $p['page'] = 1; } } // How 'bout the pagination? elseif($this->haspagination){ if($request->getParameter('page')){ $this->setPage($request->getParameter('page')); $p['page'] = $this->_currentpage; } elseif($request->getParameter('limit')){ $this->setPage(1); $p['page'] = 1; $this->setLimit($request->getParameter('limit')); $p['limit'] = $this->_limit; } // Don't change the filter sets, those have been cached and are fine as-is. } else{ // No pagination or filters were modified... don't do anything. } if(sizeof($a)){ \Core\Session::Set('filters/' . $this->_name, $a); } if(sizeof($s)){ \Core\Session::Set('filtersort/' . $this->_name, $s); } if(sizeof($p)){ \Core\Session::Set('filterpage/' . $this->_name, $p); } }
/** * Check the user's IP in the blacklist and see if it's found. * * If it is and has a high enough submission rate, (in a 24 hour period), then block the user completely and immediately. */ public static function CheckIP() { $record = \sfsBlacklistModel::Construct(REMOTE_IP); // It's not in there, YAY! if (!$record->exists()) { return; } // Is the submission score high enough? $highscore = 100; if ($record->get('submissions') > $highscore) { // YOU can haz good party tiem nau \SystemLogModel::LogSecurityEvent('/security/blocked', 'Blocking IP due to over ' . $highscore . ' submissions to sfs in a 24 hour period.'); die('IP Blocked due to high spam score'); } // Submissions listed, but not exceedingly high? $warnlevel = 5; if ($record->get('submissions') > $warnlevel) { if (\Core\Session::Get('security_antispam_allowed') === null) { $html = '<html><body>'; $html .= '<!-- You smell of spam.... are you sure you didn\'t come from a can?-->'; if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['happyfuntime']) && \Core\Session::Get('happyfuntimecheck')) { // It's an attempt! if ($_POST['happyfuntime'] == \Core\Session::Get('happyfuntimecheck')) { \SystemLogModel::LogSecurityEvent('/security/unblocked', 'User successfully answered an anti-bot math question, unblocking.'); \Core\Session::Set('security_antispam_allowed', true); } else { \SystemLogModel::LogSecurityEvent('/security/captchafailed', 'User attempted, but failed in answering an anti-bot math question.'); $html .= '<b>NOPE!</b>'; } } \SystemLogModel::LogSecurityEvent('/security/blocked', 'Blocking IP due to over ' . $warnlevel . ' submissions to sfs in a 24 hour period.'); $random1 = rand(4, 6) * 2; $random2 = rand(1, 3) * 2; $random3 = rand(1, 2); switch ($random3) { case 1: $result = $random1 / $random2; $operation = 'divided by'; break; case 2: $result = $random1 * $random2; $operation = 'multiplied by'; break; } \Core\Session::Set('happyfuntimecheck', $result); switch ($random2) { case 1: $random2 = 'oNe'; break; case 2: $random2 = 'Tw0'; break; case 3: $random2 = 'ThRe'; break; case 4: $random2 = 'Foor'; break; case 5: $random2 = 'fIve'; break; case 6: $random2 = 'Siix'; break; } $html .= '<form method="POST"><p>What is ' . $random1 . ' ' . $operation . ' ' . $random2 . '?</p><input type="text" name="happyfuntime" size="3"/><input type="submit" value="GO"/></form></body></html>'; die($html); } } }
public function testSharedSessionBackedFacebookIgnoresUnsupportedKeyInClear() { $_SERVER['HTTP_HOST'] = 'fbrell.com'; $fb = new PersistentFBPublic(array('appId' => self::APP_ID, 'secret' => self::SECRET, 'sharedSession' => true)); $key = '--invalid--'; $val = 'foo'; $session_var_name = sprintf('%s_fb_%s_%s', $fb->publicGetSharedSessionID(), self::APP_ID, $key); \Core\Session::Set($session_var_name, $val); $fb->publicClearPersistentData($key); $this->assertTrue(array_key_exists($session_var_name, $_SESSION)); $this->assertFalse($fb->publicGetPersistentData($key)); }
/** * Add a message to the user's stack. * It will be displayed the next time the user (or session) renders the page. * * @param string $messageText The message to send to the user * @param string $messageType The type of message, "success", "info", or "error" * * @return void */ static public function SetMessage($messageText, $messageType = 'info') { if(trim($messageText) == '') return; $messageType = strtolower($messageType); // CLI doesn't use sessions. if(EXEC_MODE == 'CLI'){ $messageText = preg_replace('/<br[^>]*>/i', "\n", $messageText); echo "[" . $messageType . "] - " . $messageText . "\n"; } else{ $stack = Session::Get('message_stack', []); $stack[] = array( 'mtext' => $messageText, 'mtype' => $messageType, ); Session::Set('message_stack', $stack); } }
/** * Sync the search index fields of every model on the system. * * @return int */ public function syncSearchIndex(){ // Admin-only page. if(!\Core\user()->checkAccess('g:admin')){ return View::ERROR_ACCESSDENIED; } // Just run through every component currently installed and reinstall it. // This will just ensure that the component is up to date and correct as per the component.xml metafile. $view = $this->getView(); $changes = []; $outoftime = false; $counter = 0; $resume = \Core\Session::Get('syncsearchresume', 1); $timeout = ini_get('max_execution_time'); // Dunno why this is returning 0, but if it is, reset it to 30 seconds! if(!$timeout) $timeout = 30; $memorylimit = ini_get('memory_limit'); if(stripos($memorylimit, 'M') !== false){ $memorylimit = str_replace(['m', 'M'], '', $memorylimit); $memorylimit *= (1024*1024); } elseif(stripos($memorylimit, 'G') !== false){ $memorylimit = str_replace(['g', 'G'], '', $memorylimit); $memorylimit *= (1024*1024*1024); } foreach(\Core::GetComponents() as $c){ /** @var Component_2_1 $c */ if($outoftime){ break; } foreach($c->getClassList() as $class => $file){ if($outoftime){ break; } if($class == 'model'){ continue; } if(strrpos($class, 'model') !== strlen($class) - 5){ // If the class doesn't explicitly end with "Model", it's also not a model. continue; } if(strpos($class, '\\') !== false){ // If this "Model" class is namespaced, it's not a valid model! // All Models MUST reside in the global namespace in order to be valid. continue; } $ref = new ReflectionClass($class); if(!$ref->getProperty('HasSearch')->getValue()){ // This model doesn't have the searchable flag, skip it. continue; } $c = ['name' => $class, 'count' => 0]; $fac = new ModelFactory($class); while(($m = $fac->getNext())){ ++$counter; if($counter < $resume){ // Allow this process to be resumed where it left off, since it may take more than 30 seconds. continue; } if(\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->getTime() + 5 >= $timeout){ // OUT OF TIME! // Remember where this process left off and exit. \Core\Session::Set('syncsearchresume', $counter); $outoftime = true; break; } if(memory_get_usage(true) + 40485760 >= $memorylimit){ // OUT OF MEMORY! // Remember where this process left off and exit. \Core\Session::Set('syncsearchresume', $counter); $outoftime = true; break; } /** @var Model $m */ $m->set('search_index_pri', '!'); $m->save(); $c['count']++; } $changes[] = $c; } } if(!$outoftime){ // It finished! Unset the resume counter. \Core\Session::UnsetKey('syncsearchresume'); } $view->title = 'Sync Searchable Index'; $view->assign('changes', $changes); $view->assign('outoftime', $outoftime); }
/** * Handler to actually perform the import. * * @param \Form $form * @return bool */ public static function FormHandler2(\Form $form) { $filename = Session::Get('user-import/file'); $file = Factory::File($filename); /** @var $contents \Core\Filestore\Contents\ContentCSV */ $contents = $file->getContentsObject(); // If the user checked that it has a header... do that. $contents->_hasheader = $form->getElement('has_header')->get('checked'); // Merge $merge = $form->getElement('merge_duplicates')->get('checked'); // Handle the map-to directives. $maptos = array(); foreach($form->getElements() as $el){ if(strpos($el->get('name'), 'mapto[') === 0 && $el->get('value')){ $k = substr($el->get('name'), 6, -1); $maptos[$k] = $el->get('value'); } } // Handle the group mappings $groups = $form->getElement('groups[]')->get('value'); // And keep a log of the bad transfers and some other data. $counts = ['created' => 0, 'updated' => 0, 'failed' => 0, 'skipped' => 0]; Session::Set('user-import/fails', []); $incoming = $contents->parse(); foreach($incoming as $record){ try{ // Create a data map of this record for fields to actually map over. $dat = array(); foreach($maptos as $recordkey => $userkey){ $dat[$userkey] = $record[$recordkey]; } // No email, NO IMPORT! if(!$dat['email']){ $counts['skipped']++; continue; } // Try to find this record by email, since that's a primary key. $existing = \UserModel::Find(['email = ' . $dat['email'] ], 1); if($existing && !$merge){ // Skip existing records. $counts['skipped']++; } elseif($existing){ // Update! $existing->setFromArray($dat); $existing->setGroups($groups); if($existing->save()){ $counts['updated']++; } else{ $counts['skipped']++; } } else{ $new = new \UserModel(); $new->setFromArray($dat); $new->setGroups($groups); $new->save(); $counts['created']++; } } catch(\Exception $e){ // @todo Handle this die($e->getMessage()); } // } Session::Set('user-import/counts', $counts); return true; }
/** * This is the form handler for a password protected page. * * @return bool */ public static function PasswordProtectHandler(Form $form){ /** @var PageModel $page */ $page = $form->getElementValue('page'); $val = $form->getElementValue('passinput'); if( $val !== $page->get('password_protected') ){ \Core\set_message('t:MESSAGE_ERROR_INCORRECT_PASSWORD'); return false; } else { \Core\Session::Set('page-password-protected/' . $page->get('baseurl'), $val); return true; } }
/** * 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); } }
/** * {@inheritdoc} * * @see BaseFacebook::clearPersistentData() */ protected function clearPersistentData($key) { if (!in_array($key, self::$kSupportedKeys)) { self::errorLog('Unsupported key passed to clearPersistentData.'); return; } $session_var_name = $this->constructSessionVariableName($key); \Core\Session::Set($session_var_name, null); }
/** * View to sudo as another user. */ public function sudo(){ $view = $this->getView(); $req = $this->getPageRequest(); $id = $req->getParameter(0); if($id){ $model = UserModel::Construct($id); if(!\Core\user()->checkAccess('p:/user/users/sudo')){ return View::ERROR_ACCESSDENIED; } if(!$req->isPost()){ return View::ERROR_BADREQUEST; } if(!$model->exists()){ return View::ERROR_NOTFOUND; } \Core\Session::Set('user_sudo', $model); } elseif(\Core\Session::Get('user_sudo') !== null){ \Core\Session::UnsetKey('user_sudo'); } \Core\redirect('/'); }
/** * Add a message to the user's stack. * It will be displayed the next time the user (or session) renders the page. * * @param string $message_text The message text or the MESSAGE_ string constant for i18n and automatic type detection! * @param string $message_type * * @return boolean (on success) */ function set_message($messageText, $messageType = 'info'){ if(strpos($messageText, 't:MESSAGE_') === 0){ // It's an i18n message! Retrieve the locale version of text and the message type. $messageText = substr($messageText, 2); if(strpos($messageText, 'MESSAGE_SUCCESS_') === 0){ $messageType = 'success'; } elseif(strpos($messageText, 'MESSAGE_ERROR_') === 0){ $messageType = 'error'; } elseif(strpos($messageText, 'MESSAGE_TUTORIAL_') === 0){ $messageType = 'tutorial'; } elseif(strpos($messageText, 'MESSAGE_WARNING_') === 0){ $messageType = 'warning'; } elseif(strpos($messageText, 'MESSAGE_INFO_') === 0){ $messageType = 'info'; } else{ $messageType = 'info'; } if(func_num_args() > 1){ // Use func_call to call 1, as I need to pass in the other options too! $messageText = call_user_func_array('t', func_get_args()); } else{ $messageText = t($messageText); } } // CLI doesn't use sessions, echo directly to stdout instead. if(EXEC_MODE == 'CLI'){ $messageText = preg_replace('/<br[^>]*>/i', "\n", $messageText); echo "[" . $messageType . "] - " . $messageText . "\n"; } else{ $stack = Session::Get('message_stack', []); $stack[] = array( 'mtext' => $messageText, 'mtype' => $messageType, ); Session::Set('message_stack', $stack); } }
public function stopError($code, $error){ if(sizeof($this->_last) == 0){ // Nothing to do, you must use start first! return; } $last = array_pop($this->_last); $time = microtime(true) - $last['start']; $timeFormatted = \Core\time_duration_format($time, 2); if($last['type'] == 'read'){ ++$this->_reads; } else{ ++$this->_writes; } if(DEVELOPMENT_MODE) { // Add this data to the SESSION if the site is currently in DEV mode. $events = Session::Get('datamodel_profiler_events/events', []); $events[] = [ 'query' => $last['query'], 'type' => $last['type'], 'time' => $time, 'errno' => $code, 'error' => $error, 'caller' => $last['caller'], 'rows' => 0 ]; Session::Set('datamodel_profiler_events/events', $events); if($last['type'] == 'read') { Session::Set('datamodel_profiler_events/reads', Session::Get('datamodel_profiler_events/reads') + 1); } else { Session::Set('datamodel_profiler_events/writes', Session::Get('datamodel_profiler_events/writes') + 1); } } if(defined('DMI_QUERY_LOG_TIMEOUT') && DMI_QUERY_LOG_TIMEOUT >= 0){ if(DMI_QUERY_LOG_TIMEOUT == 0 || ($time * 1000) >= DMI_QUERY_LOG_TIMEOUT ){ \Core\Utilities\Logger\append_to('query', '[' . $timeFormatted . '] ' . $last['query'], 0); } } }
public function createImage() { $ini = microtime(true); /** Initialization */ $this->imageAllocate(); /** Text insertion */ $text = $this->getCaptchaText(); $fontcfg = $this->fonts[array_rand($this->fonts)]; $this->writeText($text, $fontcfg); \Core\Session::Set($this->sessionVar, $text); /** Transformations */ if (!empty($this->lineWidth)) { $this->writeLine(); } $this->waveImage(); if ($this->blur && function_exists('imagefilter')) { imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR); } $this->reduceImage(); if ($this->debug) { imagestring($this->im, 1, 1, $this->height - 8, "{$text} {$fontcfg['font']} " . round((microtime(true) - $ini) * 1000) . "ms", $this->gdFgColor); } /** Output */ $this->writeImage(); $this->cleanup(); }