Ejemplo n.º 1
0
 public function view()
 {
     $page = PageRequest::GetSystemRequest();
     $pageview = $page->getView();
     $pagemetas = $pageview->meta;
     $view = $this->getView();
     // The main identifier for livefyre, retrieved from within the livefyre "install" section.
     // Transposed to siteId
     $siteid = ConfigHandler::Get('/livefyre/siteid');
     if (!$siteid) {
         $msg = 'Livefyre is not configured yet.';
         if (\Core\user()->checkAccess('g:admin')) {
             $msg .= '  Please <a href="' . \Core\resolve_link('/livefyre') . '">configure it now</a>';
         }
         return $msg;
     }
     // The "article" is the base url.  This doesn't change despite changing URLs.
     // Transposed to articleId
     $article = $page->getBaseURL();
     // The title, used in the collectionMeta.
     // Transposed to title
     $title = $pageview->title;
     // The canonical URL, used in the collectionMeta.
     $url = $pageview->canonicalurl;
     $view->assign('siteId', $siteid);
     $view->assign('articleId', $article);
     $view->assign('title', $title);
     $view->assign('url', $url);
 }
 /**
  * Get the resolved profile link for a given user
  *
  * @param UserModel $user
  * @return string
  */
 public static function ResolveProfileLink(UserModel $user)
 {
     if ($user->get('username')) {
         return \Core\resolve_link('/userprofile/view/' . $user->get('username'));
     } else {
         return \Core\resolve_link('/userprofile/view/' . $user->get('id'));
     }
 }
 /**
  * Based on the type of this entry, ie: int or ext, resolve the URL fully.
  *
  * @return string
  */
 public function getResolvedURL()
 {
     switch ($this->get('type')) {
         case 'int':
             return \Core\resolve_link($this->get('baseurl'));
             break;
         case 'ext':
             if (strpos(substr($this->get('baseurl'), 0, 8), '://') !== false) {
                 return $this->get('baseurl');
             } else {
                 return 'http://' . $this->get('baseurl');
             }
             break;
     }
 }
Ejemplo n.º 4
0
	/**
	 * Widget to display a simple site search box
	 */
	public function execute(){
		$view = $this->getView();

		$urlbase = '/page/search';
		$url = \Core\resolve_link($urlbase);

		if(PageRequest::GetSystemRequest()->getBaseURL() == $urlbase && PageRequest::GetSystemRequest()->getParameter('q')){
			$query = PageRequest::GetSystemRequest()->getParameter('q');
		}
		else{
			$query = null;
		}

		$view->assign('title', $this->getSetting('title'));
		$view->assign('url', $url);
		$view->assign('query', $query);
	}
Ejemplo n.º 5
0
/**
 * Resolve a dynamic or static link with smarty.
 *
 * @todo Finish documentation of smarty_function_link
 *
 * @param array  $params  Associative (and/or indexed) array of smarty parameters passed in from the template
 * @param Smarty $smarty  Parent Smarty template object
 *
 * @return string
 */
function smarty_function_link($params, $smarty){
	
	$assign= (isset($params['assign']))? $params['assign'] : false;
	
	// I don't really care what the parameter's called to be honest...
	if(isset($params['href'])) $href = $params['href'];
	elseif(isset($params['link'])) $href = $params['link'];
	elseif(isset($params['to'])) $href = $params['to'];
	elseif(isset($params[0])) $href = $params[0];
	else $href = '/';

	$originalHref = $href;
	
	$href = \Core\resolve_link($href);

	if(!$href && strpos($originalHref, 'public/') === 0){
		$file = \Core\Filestore\Factory::File($originalHref);
		if($file->exists()){
			$href = $file->getURL();
		}
	}

	if(isset($params['ssl'])){
		// Perform SSL translation of some sort.
		$ssl = (isset($_SERVER['HTTPS']));

		if(
			($ssl && $params['ssl'] == 'auto') ||
			$params['ssl'] == '1' ||
			$params['ssl'] == 'true'
		){
			$href = str_replace('http://', 'https://', $href);
		}
		elseif(!$params['ssl']){
			$href = str_replace('https://', 'http://', $href);
		}
	}

	if($assign){
		$smarty->assign($assign, $href);
	}
	else{
		return $href;
	}
}
Ejemplo n.º 6
0
 /**
  * The hook catch for the "/core/admin/view" hook.
  */
 public static function AdminHook()
 {
     // If this user doesn't have access to manage crons, just continue.
     if (!\Core\user()->checkAccess('p:/cron/viewlog')) {
         return;
     }
     $suffixtext = 'This could be a problem if you have scripts relying on it!  <a href="' . \Core\resolve_link('/cron/howto') . '">Read how to resolve this issue</a>.';
     // Lookup and make sure that the cron hooks have ran recently enough!
     $checks = [['cron' => 'hourly', 'modify' => '-1 hour', 'label' => 'hour'], ['cron' => 'daily', 'modify' => '-1 day', 'label' => 'day'], ['cron' => 'weekly', 'modify' => '-1 week', 'label' => 'week'], ['cron' => 'monthly', 'modify' => '-1 month', 'label' => 'month']];
     foreach ($checks as $check) {
         $time = new CoreDateTime();
         $cronfac = new ModelFactory('CronLogModel');
         $cronfac->where('cron = ' . $check['cron']);
         $time->modify($check['modify']);
         $cronfac->where('created >= ' . $time->getFormatted('U', Time::TIMEZONE_GMT));
         $count = $cronfac->count();
         if ($count == 0) {
             \Core\set_message('Your ' . $check['cron'] . ' cron has not run in the last ' . $check['label'] . '!  ' . $suffixtext, 'error');
             // Only complain to the admin once per view.
             return;
         }
     }
 }
Ejemplo n.º 7
0
	/**
	 * Resolve a URL to its Core version, (or call the urlCallback function if defined).
	 * 
	 * @param string $url
	 *
	 * @return string
	 */
	public function doLink($url){
		// In this method, $url may be an alias for a registered footnote.
		// If it is, pull that footnote source instead of the alias.
		if(isset($this->urls[$url])){
			$url = $this->urls[$url];
		}
		
		if(strpos($url, '://') !== false){
			// Skip translation for fully resolved links.
			return $url;
		}
		else{
			// Try to use Core to resolve this URL.
			$resolved = \Core\resolve_link($url);
			if($resolved !== null){
				return $resolved;
			}
			
			// Is there a supplemental method to handle these?
			if ($this->urlCallback)
				$url = call_user_func($this->urlCallback, $url);
			
			return $url;
		}
	}
Ejemplo n.º 8
0
/**
 * Render markup for an image tag in smarty
 *
 * The {img} smarty function is the recommended way to load images in templates from asset or public directories.
 * In addition to automatically resolving URLs, it can also handle server-side resizing and a few other nifty features.
 *
 * #### Image Types &amp; Animations
 *
 * As of Core 3.3.0, image types are preserved, so if a .jpg is requested, an image/jpeg is returned.
 * This changed from the previous behaviour where all images were converted to a PNG.
 *
 * Supported image types are `.jp[e]g`, `.png`, and `.gif`.
 *
 * If an animated gif is resized, the server will attempt to preserve the animation on the resized image.
 * This is done via imagemagick, (so that library needs to be present on the server in order for this trick to work).
 *
 * #### SEO Data
 *
 * As of Core 3.2.0, alt tags are automatically added to every image that does not have the alt attribute explicitly set.
 * This alt name is pulled from the filename of the image, with automatic capitalization and '_' => (space) converting.
 *
 * #### Smarty Parameters
 *
 *  * assign
 *    * string
 *    * Set to a string to assign that variable name instead of returning the output.
 *  * dimensions
 *    * Provide both width and height in pixels, along with special instructions
 *    * Structure is "widthxheight" with no spaces between the "x" and the two integers.
 *    * Special modes available are:
 *    * Carat "`^`" at the end of the string fits the smallest dimension instead of the largest.
 *    * Exclamation mark "`!`" at the end forces size regardless of aspect ratio.
 *    * Greater than "`>`" at the end will only increase image sizes.
 *    * Less than "`<`" at the end will only decrease image sizes.
 *  * file
 *    * \Core\Filestore\File
 *    * File object passed in to display
 *    * Either "file" or "src" is required.
 *  * height
 *    * int
 *    * Maximum image height (in pixels).
 *    * If both width and height are provided, the image will be constrained to both without any distortion.
 *  * inline
 *    * int "1" or "0", (default "0")
 *    * New in Core 4.2.0
 *    * Request that the resized image be encoded as base64 and inserted inline in the markdown instead of returned as the URL.
 *  * placeholder
 *    * string
 *    * placeholder image if the requested image is blank or not found.  Useful for optional fields that should still display something.
 *    * Current values: "building", "generic", "person", "person-tall", "person-wide", "photo"
 *  * src
 *    * string
 *    * Source filename to display.  This can start with "assets" for an asset, or "public" for a public file.
 *    * Either "file" or "src" is required.
 *  * width
 *    * int
 *    * Maximum image width (in pixels).
 *    * If both width and height are provided, the image will be constrained to both without any distortion.
 *
 * Any other parameter is transparently sent to the resulting `<img/>` tag.
 *
 *
 * #### Example Usage
 *
 * <pre>
 * {img src="public/gallery/photo123.png" width="123" height="123" placeholder="photo" alt="My photo 123"}
 * </pre>
 *
 * @param array  $params  Associative (and/or indexed) array of smarty parameters passed in from the template
 * @param Smarty $smarty  Parent Smarty template object
 *
 * @return string
 * @throws SmartyException
 */
function smarty_function_img($params, $smarty){

	// Key/value array of attributes for the resulting HTML.
	$attributes = array();

	if(isset($params['file'])){
		$f = $params['file'];
		if(!$f instanceof \Core\Filestore\File){
			throw new SmartyException('{img} tag expects a \Core\Filestore\File object for the "file" parameter.');
		}
		unset($params['file']);
	}
	elseif(isset($params['src'])){
		$f = \Core\Filestore\Factory::File($params['src']);
		unset($params['src']);
	}
	else{
		$f = null;
	}

	// Some optional parameters, (and their defaults)
	$assign = $width = $height = $dimensions = $inline = false;
	$placeholder = $previewfile = null;

	if(isset($params['assign'])){
		$assign = $params['assign'];
		unset($params['assign']);
	}

	if(isset($params['width'])){
		$width = $params['width'];
		unset($params['width']);
	}

	if(isset($params['height'])){
		$height = $params['height'];
		unset($params['height']);
	}

	if(isset($params['dimensions'])){
		$dimensions = $params['dimensions'];
		$width = preg_replace('#[^0-9]?([0-9]*)x.*#', '$1', $dimensions);
		$height = preg_replace('#.*x([0-9]*)[^0-9]?#', '$1', $dimensions);
		unset($params['dimensions']);
	}

	if(isset($params['placeholder'])){
		$placeholder = $params['placeholder'];
		unset($params['placeholder']);
	}

	if(isset($params['inline'])){
		$inline = ($params['inline'] == '1');
		unset($params['inline']);
	}


	if($dimensions){
		// Passing in dimensions raw will allow the user more control over the size of the images.
		$d = $dimensions;
	}
	else{
		// If one is provided but not the other, just make them the same.
		if($width && !$height) $height = $width;
		if($height && !$width) $width = $height;

		$d = ($width && $height) ? $width . 'x' . $height : false;
	}

	// If the file doesn't exist and a placeholder was provided, use the appropriate placeholder image!
	if(!($f && $f->exists() && $f->isImage()) && $placeholder){
		// Try that!
		$f = \Core\Filestore\Factory::File('assets/images/placeholders/' . $placeholder . '.png');
	}

	if(!$f){
		throw new SmartyException('{img} tag requires either "src", "file", or a "placeholder" parameter.');
	}

	// Do the rest of the attributes that the user sent in (if there are any)
	foreach($params as $k => $v){
		$attributes[$k] = $v;
	}

	if($f instanceof Core\Filestore\Backends\FileRemote){
		// Erm... Give the original URL with the dimension requests.
		$attributes['src'] = $f->getURL();
		if($width) $attributes['width'] = $width;
		if($height) $attributes['height'] = $height;
	}
	else{
		// Try to lookup the preview file.
		// if it exists, then YAY... I can return that direct resource.
		// otherwise, I should check and see if the file is larger than a set filesize.
		// if it is, then I want to return a link to a controller to render that file instead of rendering the file from within the {img} tag.
		//
		// This is useful because any logic contained within this block will halt page execution!
		// To improve the perception of performance, that can be offloaded to the browser requesting the <img/> contents.
		$previewfile = $d ? $f->getQuickPreviewFile($d) : $f;

		if(!$previewfile){
			$attributes['src'] = '#';
			$attributes['title'] = 'No preview files available!';
		}
		elseif($inline && $f->getFilesize() < 1048576*4){
			// Overwrite the src attribute with the base64 contents.
			// This can only happen after the preview file exists!

			if(!$previewfile->exists()){
				// Since quick ran, ensure that it's actually resized!
				$previewfile = $f->getPreviewFile($d);
			}
			$attributes['src'] = 'data:' . $previewfile->getMimetype() . ';base64,' . base64_encode($previewfile->getContents());
		}
		elseif(!$previewfile->exists()){
			// Ok, it doesn't exist... return a link to the controller to render this file.
			$attributes['src'] = \Core\resolve_link('/file/preview') . '?f=' . $f->getFilenameHash() . '&d=' . $d;
		}
		else{
			$attributes['src'] = $previewfile->getURL();
		}
	}

	// All images need alt data!
	if(!isset($attributes['alt'])){
		$attributes['alt'] = $f->getTitle();
	}

	// Merge them back together in one string.
	$html = '<img';
	foreach($attributes as $k => $v) $html .= " $k=\"$v\"";
	$html .= '/>';

	// If the extended metadata was requested... look that up too!
	if(isset($params['includemeta']) && $params['includemeta']){

		$metahelper  = new \Core\Filestore\FileMetaHelper($f);
		$metacontent = $metahelper->getAsHTML();
		if($metacontent){
			$html = '<div class="image-metadata-wrapper">' . $html . $metacontent . '</div>';
		}
	}

	return $assign ? $smarty->assign($assign, $html) : $html;
}
Ejemplo n.º 9
0
 private function _viewAlbum(GalleryAlbumModel $album)
 {
     $view = $this->getView();
     $manager = \Core\user()->checkAccess('p:/gallery/manage_all');
     $editor = \Core\user()->checkAccess($album->get('editpermissions')) || $manager;
     $uploader = \Core\user()->checkAccess($album->get('uploadpermissions')) || $editor;
     $url = $album->get('rewriteurl');
     $images = $album->getLink('GalleryImage', 'weight');
     $lastupdated = $album->get('updated');
     if ($uploader) {
         $uploadform = new Form();
         $uploadform->set('action', \Core\resolve_link('/gallery/images_update/' . $album->get('id')));
         $uploadform->addElement('multifile', array('basedir' => $album->getFullUploadDirectory(), 'title' => 'Bulk Upload Files', 'name' => 'images', 'accept' => $album->get('accepttypes')));
         $uploadform->addElement('submit', array('value' => 'Save Gallery Changes'));
     } else {
         $uploadform = false;
     }
     // I need to attach a friendly URL for each image.
     // This gets a little tricky since each image doesn't have a unique title necessarily.
     foreach ($images as $i) {
         // I would like to know when the last change overall was, not just for the gallery.
         $lastupdated = max($lastupdated, $i->get('updated'));
     }
     $view->templatename = '/pages/gallery/view.tpl';
     $view->assign('album', $album);
     $view->assign('images', $images);
     $view->assign('editor', $editor);
     $view->assign('manager', $manager);
     $view->assign('uploader', $uploader);
     $view->assign('uploadform', $uploadform);
     $view->assign('userid', \Core\user()->get('id'));
     $view->updated = $lastupdated;
     // If there are images in this gallery, grab the first one to show as a preview!
     if (count($images)) {
         $view->meta['og:image'] = $images[0]->getFile()->getPreviewURL('200x200');
     }
     if ($editor) {
         $view->addControl('Gallery Albums Administration', '/gallery/admin', 'directory');
         $view->addControl('Edit Gallery Album', '/gallery/edit/' . $album->get('id'), 'edit');
     }
     if ($uploader) {
         // If they can upload images, they can rearrange them!
         $view->addControl(array('title' => 'Rearrange Images', 'link' => '/gallery/order/' . $album->get('id'), 'icon' => 'move'));
     }
 }
Ejemplo n.º 10
0
 /**
  * Page to display the currently installed themes and shortcuts to various operations therein.
  */
 public function index()
 {
     $view = $this->getView();
     $selected = ConfigHandler::Get('/theme/selected');
     $themes = ThemeHandler::GetAllThemes();
     $current = ThemeHandler::GetTheme($selected);
     // Set to true if multisite is enabled AND the page is currently on a child site.
     $multisite = Core::IsLibraryAvailable('multisite') && MultiSiteHelper::IsEnabled() && MultiSiteHelper::GetCurrentSiteID() != 0;
     $configDefault = ConfigHandler::GetConfig('/theme/default_template');
     $configSelected = ConfigHandler::GetConfig('/theme/selected');
     $configEmailDefault = ConfigHandler::GetConfig('/theme/default_email_template');
     // Only allow changing the theme if it's on the root site OR both config options are overrideable.
     $themeSelectionEnabled = !$multisite || $configDefault->get('overrideable') && $configSelected->get('overrideable');
     $emailSelectionEnabled = !$multisite || $configEmailDefault->get('overrideable');
     $configOptions = $current->getConfigs();
     if (!sizeof($configOptions)) {
         $optionForm = null;
     } else {
         $optionForm = new Form();
         $optionForm->set('callsmethod', 'AdminController::_ConfigSubmit');
         foreach ($configOptions as $c) {
             /** @var $c ConfigModel */
             if ($multisite) {
                 // Only pull the config options that are enabled for this specific site.
                 if ($c->get('overrideable')) {
                     $optionForm->addElement($c->getAsFormElement());
                 }
             } else {
                 // Sites that either
                 // do NOT have multisite installed
                 // nor have multisite enabled
                 // or on the root site, get all options.
                 $optionForm->addElement($c->getAsFormElement());
             }
         }
         if (sizeof($optionForm->getElements()) > 0) {
             // There is at least one element in the option forms!
             $optionForm->addElement('submit', ['value' => 'Save Configurable Options']);
         } else {
             // Reset the form back to null so that the section doesn't display.
             $optionForm = null;
         }
     }
     // The source objects to look for assets in.
     // Set initially to all the installed components.
     $assetsources = Core::GetComponents();
     // And add on the current theme.
     $assetsources[] = $current;
     // Load in all asset files available from the installed components and current theme.
     // these are assembled into a virtual directory listing.
     $assets = array();
     // Give me the current theme!
     foreach ($assetsources as $source) {
         /** @var Component_2_1 $source */
         $dir = $source->getAssetDir();
         if (!$dir) {
             continue;
         }
         $dirlen = strlen($dir);
         $name = $source->getName();
         $dh = \Core\Filestore\Factory::Directory($dir);
         $ls = $dh->ls(null, true);
         foreach ($ls as $obj) {
             // Skip directories.
             if (!$obj instanceof \Core\Filestore\File) {
                 continue;
             }
             /** @var $obj \Core\Filestore\File */
             $file = 'assets/' . substr($obj->getFilename(), $dirlen);
             // Since this is a template, it may actually be in a different location than where the package maintainer put it.
             // ie: user template user/templates/pages/user/view.tpl may be installed to themes/myawesometheme/pages/user/view.tpl instead.
             $newobj = \Core\Filestore\Factory::File($file);
             $assets[$file] = array('file' => $file, 'obj' => $newobj, 'component' => $name);
         }
     }
     // Now that the asset files have been loaded into a flat array, I need to convert that to the properly nested version.
     ksort($assets);
     $nestedassets = array();
     foreach ($assets as $k => $obj) {
         $parts = explode('/', $k);
         $lastkey = sizeof($parts) - 1;
         $thistarget =& $nestedassets;
         foreach ($parts as $i => $bit) {
             if ($i == $lastkey) {
                 $thistarget[$bit] = $obj;
             } else {
                 if (!isset($thistarget[$bit])) {
                     $thistarget[$bit] = [];
                 }
                 $thistarget =& $thistarget[$bit];
             }
         }
     }
     // Get the templates throughout the site.  These can include pages, emails, form elements, etc.
     $components = Core::GetComponents();
     $templates = array();
     foreach ($components as $c) {
         /** @var $c Component_2_1 */
         $dir = $c->getViewSearchDir();
         if (!$dir) {
             continue;
         }
         $dirlen = strlen($dir);
         $component = $c->getName();
         $dh = \Core\Filestore\Factory::Directory($dir);
         //$pagetplfiles = $dh->ls('tpl', true);
         $pagetplfiles = $dh->ls(null, true);
         // not sure why getFilename(path) isn't working as expected, but this works too.
         foreach ($pagetplfiles as $obj) {
             // I don't want directories.
             if ($obj instanceof \Core\Filestore\Directory) {
                 continue;
             }
             /** @var $obj \Core\Filestore\File */
             $file = substr($obj->getFilename(), $dirlen);
             // Since this is a template, it may actually be in a different location than where the package maintainer put it.
             // ie: user template user/templates/pages/user/view.tpl may be installed to themes/myawesometheme/pages/user/view.tpl instead.
             $tpl = Core\Templates\Template::Factory($file);
             $resolved = Core\Templates\Template::ResolveFile($file);
             $newobj = \Core\Filestore\Factory::File($resolved);
             $templates[$file] = array('file' => $file, 'resolved' => $resolved, 'obj' => $newobj, 'haswidgets' => $tpl->hasWidgetAreas(), 'component' => $component, 'has_stylesheets' => $tpl->hasOptionalStylesheets());
         }
     }
     // Now that the template files have been loaded into a flat array, I need to convert that to the properly nested version.
     ksort($templates);
     $nestedtemplates = array();
     foreach ($templates as $k => $obj) {
         $parts = explode('/', $k);
         $lastkey = sizeof($parts) - 1;
         $thistarget =& $nestedtemplates;
         foreach ($parts as $i => $bit) {
             if ($i == $lastkey) {
                 $thistarget[$bit] = $obj;
             } else {
                 if (!isset($thistarget[$bit])) {
                     $thistarget[$bit] = [];
                 }
                 $thistarget =& $thistarget[$bit];
             }
         }
     }
     $siteskinform = new Form();
     $siteskinform->set('callsmethod', 'ThemeController::SaveSiteSkins');
     $opts = ['' => '-- Public Default --'];
     foreach ($current->getSkins() as $skin) {
         $opts[$skin['file']] = $skin['title'];
     }
     foreach (ConfigHandler::FindConfigs('/theme/siteskin/') as $k => $config) {
         $siteskinform->addElement('select', ['name' => 'config[' . $k . ']', 'title' => $config->get('description'), 'value' => $config->getValue(), 'options' => $opts]);
     }
     $siteskinform->addElement('submit', ['value' => t('STRING_SAVE')]);
     $customdest = \Core\directory('themes/custom');
     $cssform = false;
     $cssprintform = false;
     if ($customdest->isWritable()) {
         $sets = [['file' => 'css/custom.css', 'form' => null], ['file' => 'css/custom_print.css', 'form' => null]];
         foreach ($sets as $k => $set) {
             // Load the editor for the custom CSS file, as this is a very common thing to do!
             $file = $set['file'];
             // And try to look up and find this damn file...
             $srcdirs = array();
             $srcdirs[] = ROOT_PDIR . 'themes/custom/assets/';
             $srcdirs[] = ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/assets/';
             foreach (Core::GetComponents() as $c) {
                 if ($c->getAssetDir()) {
                     $srcdirs[] = $c->getAssetDir();
                 }
             }
             foreach ($srcdirs as $dir) {
                 if (file_exists($dir . $file)) {
                     $file = $dir . $file;
                     break;
                 }
             }
             $fh = \Core\Filestore\Factory::File($file);
             $content = $fh->getContents();
             $m = new ThemeTemplateChangeModel();
             $m->set('content', $content);
             $m->set('filename', 'assets/css/custom.css');
             $form = Form::BuildFromModel($m);
             $form->set('callsmethod', 'ThemeController::_SaveEditorHandler');
             // I need to add the file as a system element so core doesn't try to reuse the same forms on concurrent edits.
             //$form->addElement('system', array('name' => 'revision', 'value' => $revision));
             $form->addElement('system', array('name' => 'file', 'value' => 'assets/' . $set['file']));
             $form->addElement('system', array('name' => 'filetype', 'value' => 'file'));
             // No one uses this anyways!
             $form->switchElementType('model[comment]', 'hidden');
             $form->getElement('model[content]')->set('id', 'custom_content_' . $k);
             $form->addElement('submit', array('value' => 'Save Custom CSS'));
             // Save it back down to the original array
             $sets[$k]['form'] = $form;
         }
         $cssform = $sets[0]['form'];
         $cssprintform = $sets[1]['form'];
     }
     $view->title = 'Theme Manager';
     $view->assign('themes', $themes);
     $view->assign('current', $current);
     $view->assign('options_form', $optionForm);
     $view->assign('assets', $nestedassets);
     $view->assign('templates', $nestedtemplates);
     $view->assign('url_themeeditor', \Core\resolve_link('/theme/editor'));
     $view->assign('url_themewidgets', \Core\resolve_link('/theme/widgets'));
     $view->assign('url_themestylesheets', \Core\resolve_link('/theme/selectstylesheets'));
     $view->assign('site_skins_form', $siteskinform);
     $view->assign('cssform', $cssform);
     $view->assign('cssprintform', $cssprintform);
     $view->assign('multisite', $multisite);
     $view->assign('theme_selection_enabled', $themeSelectionEnabled);
     $view->assign('email_selection_enabled', $emailSelectionEnabled);
 }
Ejemplo n.º 11
0
 public function delete()
 {
     $view = $this->getView();
     $request = $this->getPageRequest();
     // This is a POST-only page.
     if (!$request->isPost()) {
         return View::ERROR_BADREQUEST;
     }
     if (!$this->setAccess('p:/content/manage_all')) {
         return View::ERROR_ACCESSDENIED;
     }
     $m = new ContentModel($request->getParameter(0));
     $link = \Core\resolve_link($m->get('baseurl'));
     if (!$m->exists()) {
         return View::ERROR_NOTFOUND;
     }
     $m->delete();
     \Core\set_message('Removed ' . $m->get('nickname') . ' successfully!', 'success');
     $hist = $request->getReferrer();
     if ($hist == $link) {
         \Core\redirect('/admin/pages');
     } else {
         \Core\go_back();
     }
 }
Ejemplo n.º 12
0
	/**
	 * Get the content to be inserted into the <head> tag for this view.
	 *
	 * @return string
	 */
	public function getHeadContent(){
		$minified = ConfigHandler::Get('/core/markup/minified');

		// First, the basic ones.
		if($minified){
			$data = array_merge($this->stylesheets, $this->head, $this->scripts['head']);
		}
		else{
			$data = array_merge(
				['<!-- BEGIN STYLESHEET INSERTIONS -->'],
				$this->stylesheets,
				['<!-- END STYLESHEET INSERTIONS -->'],
				['<!-- BEGIN HEAD CONTENT INSERTIONS -->'],
				$this->head,
				['<!-- END HEAD CONTENT INSERTIONS -->'],
				['<!-- BEGIN JAVASCRIPT INSERTIONS -->'],
				$this->scripts['head'],
				['<!-- END JAVASCRIPT INSERTIONS -->']
			);
		}


		// Some of the automatic settings only get set if no errors.
		if($this->error == View::ERROR_NOERROR){

			// Custom meta tag :: http-equiv="last-modified"
			if($this->updated !== null){
				// last-modified is no longer a valid attribute in HTML5
				//$data[] = '<meta http-equiv="last-modified" content="' . Time::FormatGMT($this->updated, Time::TIMEZONE_GMT, Time::FORMAT_RFC2822) . '" />';
				$this->meta['article:modified_time'] = Time::FormatGMT($this->updated, Time::TIMEZONE_GMT, Time::FORMAT_ISO8601);
			}

			// Set the generator metatag, (this is handled internally within the tag)
			$this->meta['generator'] = true;

			// Some standard tags that also have og equivalents.
			if(!isset($this->meta['og:title'])){
				$this->meta['og:title'] = $this->title;
			}

			// Set the canonical url if not set.
			if($this->canonicalurl === null){
				$this->canonicalurl = \Core\resolve_link($this->baseurl);
			}

			// Set the canonical URL in the necessary spots (if it's not in error)
			if($this->canonicalurl !== false){
				$this->meta['canonical'] = $this->canonicalurl;
			}

			$this->meta['og:site_name'] = SITENAME;
		}

		// Merge in the standard meta names and properties now.
		$data = array_merge($data, $this->meta->fetch());


		if ($minified) {
			$out = implode('', $data);
		}
		else {
			$out = '<!-- BEGIN Automatic HEAD generation -->' . "\n\n" . implode("\n", $data) . "\n\n" . '<!-- END Automatic HEAD generation -->';
		}

		return trim($out);
	}
Ejemplo n.º 13
0
 /**
  * Helper function to save a blog article, both new and existing.
  *
  * @static
  *
  * @param Form $form
  * @return string Redirect URL
  */
 public static function BlogArticleFormHandler(Form $form)
 {
     try {
         /** @var $page PageModel */
         $page = $form->getModel('page');
         /** @var $article BlogArticleModel */
         $article = $form->getModel('model');
         // I need to update some of the article information from the page info.
         $article->set('title', $page->get('title'));
         /** @var $pageauthor PageMetaModel|null */
         $pageauthor = $page->getMeta('author');
         if ($pageauthor && $pageauthor->get('meta_value_title') && $pageauthor->get('meta_value')) {
             // Allow the user to override who is posting this article, if set.
             $article->set('authorid', $pageauthor->get('meta_value'));
         } elseif ($pageauthor && $pageauthor->get('meta_value_title')) {
             // If they never selected a valid user, allow that to go through too.
             // The page will have saved the name that they type in regardless.
             $article->set('authorid', 0);
         } else {
             // Otherwise Set the article author to the current user.
             $article->set('authorid', \Core\user()->get('id'));
             $page->setMeta('author', \Core\user()->getDisplayName());
             $page->setMeta('authorid', \Core\user()->get('id'));
         }
         $isnew = !$article->exists();
         // Blog pages are not selectable.  Otherwise there would just be WAY too many of them!
         // This addresses bug #321
         $page->set('selectable', 0);
         if ($article->get('status') == 'published' && !$article->get('published')) {
             // If it's new and is published... set the published date to right now!
             $article->set('published', Time::GetCurrentGMT());
         }
         $article->save();
         // Set the baseurl and some other data on the page
         $page->set('baseurl', $article->get('baseurl'));
         $page->set('component', 'blog');
         $page->set('editurl', '/blog/article/update/' . $article->get('blogid') . '/' . $article->get('id'));
         $page->save();
         // Clear the page cache
         $page->purgePageCache();
         // if it's new, allow the user to post it to facebook.
         if (isset($_POST['facebook_post']) && $_POST['facebook_post']) {
             // facebook_post
             $token = substr($_POST['facebook_post'], strpos($_POST['facebook_post'], ':') + 1);
             $fbid = substr($_POST['facebook_post'], 0, strpos($_POST['facebook_post'], ':'));
             $from = \Core\user()->get('facebook_id');
             // yay....
             $args = array('access_token' => $token, 'from' => $from, 'link' => \Core\resolve_link($article->get('rewriteurl')), 'name' => $article->get('title'), 'caption' => '', 'description' => $article->getTeaser(), 'message' => '');
             // Some optional arguments
             if ($article->getImage()) {
                 $args['picture'] = $article->getImage()->getPreviewURL('300x300');
             }
             $args['ref'] = 'coreplus';
             $facebook = new Facebook(array('appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET));
             $publish_result = $facebook->api('/' . $fbid . '/feed', 'POST', $args);
             $article->set('fb_account_id', $fbid);
             $article->set('fb_post_id', $publish_result['id']);
             $article->save();
         }
         Core::SetMessage(($isnew ? 'Created' : 'Updated') . ' blog article successfully!', 'success');
         return 'back';
         //return $article->get('baseurl');
     } catch (ModelValidationException $e) {
         Core::SetMessage($e->getMessage(), 'error');
         return false;
     } catch (FacebookApiException $e) {
         // Facebook errors are not critical, as the post is still created.
         Core::SetMessage($e->getMessage(), 'error');
         return $article->get('rewriteurl');
     } catch (Exception $e) {
         \Core\ErrorManagement\exception_handler($e);
         Core::SetMessage($e->getMessage(), 'error');
         return false;
     }
 }
Ejemplo n.º 14
0
 private function _viewBlogArticle(BlogModel $blog, BlogArticleModel $article)
 {
     $view = $this->getView();
     /** @var $page PageModel */
     $page = $article->getLink('Page');
     //$articles = $blog->getLink('BlogArticle');
     $manager = \Core\user()->checkAccess('p:/blog/manage_all');
     $editor = \Core\user()->checkAccess($blog->get('manage_articles_permission ')) || $manager;
     $author = UserModel::Construct($article->get('authorid'));
     //$authorid = $author->get('id');
     //var_dump($page->getMeta('keywords')); die();
     if (!$article->isPublished()) {
         // Is it actually not published, or just marked for a future publish date?
         if ($article->get('status') == 'published') {
             $publishdate = new CoreDateTime($article->get('published'));
             Core::SetMessage('Article is set to be published on ' . $publishdate->getFormatted('F jS, Y \\a\\t h:ia'), 'info');
         } else {
             Core::SetMessage('Article not published yet!', 'info');
         }
     }
     //$view->templatename = $page->get('page_template') ? $page->get('page_template') : 'pages/blog/article_view.tpl';
     $view->templatename = 'pages/blog/article_view.tpl';
     //$view->addBreadcrumb($blog->get('title'), $blog->get('rewriteurl'));
     $view->title = $article->get('title');
     $view->meta['title'] = $article->get('title');
     $view->updated = $article->get('updated');
     $view->canonicalurl = \Core\resolve_link($article->get('rewriteurl'));
     $view->meta['og:type'] = 'article';
     if ($article->get('image')) {
         $image = \Core\Filestore\Factory::File($article->get('image'));
         $view->meta['og:image'] = $image->getPreviewURL('200x200');
     }
     //if($author){
     //	/** @var $author User */
     //	//$view->meta['author'] = $author->getDisplayName();
     //	$view->meta['author'] = $author;
     //}
     $view->meta['description'] = $article->getTeaser();
     $view->assign('author', $author->exists() ? $author : null);
     $view->assign('article', $article);
     $view->assign('body', \Core\parse_html($article->get('body')));
     if ($editor) {
         $view->addControl('Edit Article', '/blog/article/update/' . $article->get('id'), 'edit');
         if ($article->get('status') == 'draft') {
             $view->addControl(['title' => 'Publish Article', 'link' => '/blog/article/publish/' . $blog->get('id') . '/' . $article->get('id'), 'icon' => 'arrow-up', 'confirm' => 'Publish article?']);
         }
         $view->addControl(array('title' => 'Delete Article', 'link' => '/blog/article/delete/' . $article->get('id'), 'icon' => 'remove', 'confirm' => 'Remove blog article?'));
     }
     // Add the extra view types for this page
     $view->addHead('<link rel="alternate" type="application/atom+xml" title="' . $page->get('title') . ' Atom Feed" href="' . \Core\resolve_link($blog->get('baseurl')) . '.atom"/>');
     $view->addHead('<link rel="alternate" type="application/rss+xml" title="' . $page->get('title') . ' RSS Feed" href="' . \Core\resolve_link($blog->get('baseurl')) . '.rss"/>');
     $view->addControl('RSS Feed', \Core\resolve_link($blog->get('baseurl')) . '.rss', 'rss');
 }
/**
 * @deprecated 2013.07 - cpowell
 *             The {img} function now supports all of what this did.
 *
 * @param array  $params  Associative (and/or indexed) array of smarty parameters passed in from the template
 * @param Smarty $smarty  Parent Smarty template object
 *
 * @return string
 * @throws SmartyException
 */
function smarty_function_file_thumbnail($params, $smarty){

	error_log('file_thumbnail is deprecated, please use the {img} tag instead.', E_USER_DEPRECATED);
	
	// Key/value array of attributes for the resulting HTML.
	$attributes = array();
	
	if(!isset($params['file'])){
		throw new SmartyException('Required parameter [file] not provided for file_thumbnail!');
	}
	
	// Some optional parameters, (and their defaults)
	$size = $d = $assign = $width = $height = false;
	
	
	$file = $params['file'];
	unset($params['file']);
	
	// $file should be a File...
	if(!$file instanceof \Core\Filestore\File){
		throw new SmartyException('Invalid parameter [file] for file_thumbnail, must be a \Core\Filestore\File!');
	}
	
	if(isset($params['assign'])){
		$assign = $params['assign'];
		unset($params['assign']);
	}
	
	if(isset($params['width'])){
		$width = $params['width'];
		unset($params['width']);
	}
	
	if(isset($params['height'])){
		$height = $params['height'];
		unset($params['height']);
	}
	
	if(isset($params['dimensions'])){
		$d = $params['dimensions'];
		
		if(is_numeric($d)){
			$width = $d;
			$height = $d;
		}
		else{
			// New method. Split on the "x" and that should give me the width/height.
			$vals = explode('x', strtolower($d));
			$width = (int)$vals[0];
			$height = (int)$vals[1];
		}
		unset($params['dimensions']);
	}

	
	// If one is provided but not the other, just make them the same.
	if(!$d){
		if($width && !$height) $height = $width;
		if($height && !$width) $width = $height;

		$d = ($width && $height) ? $width . 'x' . $height : false;
	}
	
	
	if(!$file->exists()){
		$icon = \Core\Filestore\Factory::File('assets/images/mimetypes/notfound.png');
		$attributes['src'] = $d ? $icon->getPreviewURL($d) : $icon->getURL();
	}
	elseif($file->isPreviewable()){
		if($file->getFilesize() < (1024*1024*4)){
			// Files that are smaller than a certain size can probably be safely rendered on this pageload.
			$attributes['src'] = $file->getPreviewURL($d);
		}
		else{
			// Larger files should be rendered independently.
			// This causes each image to be longer, but should not cause a script timeout.
			$attributes['src'] = \Core\resolve_link('/file/preview/' . $file->getFilenameHash() . '?size=' . $d);
		}
	}
	else{
		$icon = \Core\Filestore\Factory::File('assets/images/mimetypes/' . str_replace('/', '-', strtolower($file->getMimetype()) ) . '.png');
		if(!$icon->isReadable()) $icon = Core::File('assets/images/mimetypes/unknown.png');
		$attributes['src'] = $icon->getURL();
	}
	
	// Do the rest of the attributes that the user sent in (if there are any)
	foreach($params as $k => $v){
		$attributes[$k] = $v;
	}
	
	// Merge them back together in one string.
	$html = '<img';
	foreach($attributes as $k => $v) $html .= " $k=\"$v\"";
	$html .= '/>';
	
	return $assign ? $smarty->assign($assign, $html) : $html;
}
 /**
  * Get the repository XML as a string that can be returned to the browser or cached for future use.
  *
  * @param string|null $serverid      The server ID making the request, or null for anonymous.
  * @param string|null $limitPackager Limit the packager returned to at least version X.Y.
  * 
  * @return RepoXML
  */
 public static function GetAsRepoXML($serverid, $limitPackager)
 {
     $repo = new RepoXML();
     $repo->setDescription(ConfigHandler::Get('/package_repository/description'));
     $gpg = new Core\GPG\GPG();
     $keysfound = [];
     $where = [];
     if ($limitPackager) {
         $where[] = 'packager LIKE ' . $limitPackager . '%';
     }
     $packages = PackageRepositoryPackageModel::Find($where, null, 'type DESC, key ASC, version');
     foreach ($packages as $pkg) {
         /** @var PackageRepositoryPackageModel $pkg */
         $package = new PackageXML(null);
         $package->setType($pkg->get('type'));
         $package->setName($pkg->get('name'));
         $package->setVersion($pkg->get('version'));
         $package->setPackager($pkg->get('packager'));
         $package->setDescription($pkg->get('description'));
         $package->setKey($pkg->get('gpg_key'));
         if (!in_array($pkg->get('gpg_key'), $keysfound)) {
             $keysfound[] = $pkg->get('gpg_key');
         }
         $package->setFileLocation(\Core\resolve_link('/packagerepository/download?file=' . $pkg->get('file')));
         $upgrades = $pkg->get('requires');
         foreach ($upgrades as $dat) {
             $package->setRequire($dat['type'], $dat['name'], $dat['version'], $dat['operation']);
         }
         $upgrades = $pkg->get('provides');
         foreach ($upgrades as $dat) {
             $package->setProvide($dat['type'], $dat['name'], $dat['version']);
         }
         $upgrades = $pkg->get('upgrades');
         foreach ($upgrades as $dat) {
             $package->setUpgrade($dat['from'], $dat['to']);
         }
         $screens = $pkg->get('screenshots');
         foreach ($screens as $dat) {
             $f = \Core\Filestore\Factory::File($dat);
             $package->setScreenshot($f->getURL());
         }
         $package->setChangelog($pkg->get('changelog'));
         $repo->addPackage($package);
     }
     return $repo;
 }
Ejemplo n.º 17
0
	/**
	 * 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.
	 *
	 * @deprecated
	 * @see \Core\resolve_link
	 *
	 * @param string $url
	 *
	 * @return string The full url of the link, including the http://...
	 */
	public static function ResolveLink($url) {
		trigger_error('Core::ResolveLink is deprecated, please use \\Core\\resolve_link() instead.', E_USER_DEPRECATED);
		return \Core\resolve_link($url);
	}
Ejemplo n.º 18
0
 /**
  * Get the resolved link for this blog article.  Will be remote if it's a remote article.
  *
  * @return string
  */
 public function getResolvedLink()
 {
     if ($this->get('link')) {
         return $this->get('link');
     } else {
         return \Core\resolve_link($this->get('baseurl'));
     }
 }
	/**
	 * 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;
	}
Ejemplo n.º 20
0
 /**
  * Page to enable Facebook logins for user accounts.
  *
  * @return int|null|string
  */
 public function enable()
 {
     $request = $this->getPageRequest();
     $auths = \Core\User\Helper::GetEnabledAuthDrivers();
     if (!isset($auths['facebook'])) {
         // Facebook isn't enabled, simply redirect to the home page.
         \Core\redirect('/');
     }
     if (!FACEBOOK_APP_ID) {
         \Core\redirect('/');
     }
     if (!FACEBOOK_APP_SECRET) {
         \Core\redirect('/');
     }
     // If it was a POST, then it should be the first page.
     if ($request->isPost()) {
         $facebook = new Facebook(['appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET]);
         // Did the user submit the facebook login request?
         if (isset($_POST['login-method']) && $_POST['login-method'] == 'facebook' && $_POST['access-token']) {
             try {
                 $facebook->setAccessToken($_POST['access-token']);
                 /** @var int $fbid The user ID from facebook */
                 $fbid = $facebook->getUser();
                 /** @var array $user_profile The array of user data from Facebook */
                 $user_profile = $facebook->api('/me');
             } catch (Exception $e) {
                 \Core\set_message($e->getMessage(), 'error');
                 \Core\go_back();
                 return null;
             }
             // If the user is logged in, then the verification logic is slightly different.
             if (\Core\user()->exists()) {
                 // Logged in users, the email must match.
                 if (\Core\user()->get('email') != $user_profile['email']) {
                     \Core\set_message('Your Facebook email is ' . $user_profile['email'] . ', which does not match your account email!  Unable to link accounts.', 'error');
                     \Core\go_back();
                     return null;
                 }
                 $user = \Core\user();
             } else {
                 /** @var \UserModel|null $user */
                 $user = UserModel::Find(['email' => $user_profile['email']], 1);
                 if (!$user) {
                     \Core\set_message('No local account found with the email ' . $user_profile['email'] . ', please <a href="' . \Core\resolve_link('/user/register') . '"create an account</a> instead.', 'error');
                     \Core\go_back();
                     return null;
                 }
             }
             // Send an email with a nonce link that will do the actual activation.
             // This is a security feature so just anyone can't link another user's account.
             $nonce = NonceModel::Generate('20 minutes', null, ['user' => $user, 'access_token' => $_POST['access-token']]);
             $email = new Email();
             $email->to($user->get('email'));
             $email->setSubject('Facebook Activation Request');
             $email->templatename = 'emails/facebook/enable_confirmation.tpl';
             $email->assign('link', \Core\resolve_link('/facebook/enable/' . $nonce));
             if ($email->send()) {
                 \Core\set_message('An email has been sent to your account with a link enclosed.  Please click on that to complete activation within twenty minutes.', 'success');
                 \Core\go_back();
                 return null;
             } else {
                 \Core\set_message('Unable to send a confirmation email, please try again later.', 'error');
                 \Core\go_back();
                 return null;
             }
         }
     }
     // If there is a nonce enclosed, then it should be the second confirmation page.
     // This is the one that actually performs the action.
     if ($request->getParameter(0)) {
         /** @var NonceModel $nonce */
         $nonce = NonceModel::Construct($request->getParameter(0));
         if (!$nonce->isValid()) {
             \Core\set_message('Invalid key requested.', 'error');
             \Core\redirect('/');
             return null;
         }
         $nonce->decryptData();
         $data = $nonce->get('data');
         /** @var UserModel $user */
         $user = $data['user'];
         try {
             $facebook = new Facebook(['appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET]);
             $facebook->setAccessToken($data['access_token']);
             $facebook->getUser();
             $facebook->api('/me');
         } catch (Exception $e) {
             \Core\set_message($e->getMessage(), 'error');
             \Core\redirect('/');
             return null;
         }
         $user->enableAuthDriver('facebook');
         /** @var \Facebook\UserAuth $auth */
         $auth = $user->getAuthDriver('facebook');
         $auth->syncUser($data['access_token']);
         \Core\set_message('Linked Facebook successfully!', 'success');
         // And log the user in!
         if (!\Core\user()->exists()) {
             $user->set('last_login', \CoreDateTime::Now('U', \Time::TIMEZONE_GMT));
             $user->save();
             \Core\Session::SetUser($user);
         }
         \Core\redirect('/');
         return null;
     }
 }
Ejemplo n.º 21
0
	public function set($key, $value){
		switch($key){
			case 'class':
				$this->class = $value;
				break;
			case 'confirm':
				$this->confirm = $value;
				break;
			case 'icon':
				$this->icon = $value;
				break;
			case 'link':
			case 'url':
			case 'href': // Just for an alias of the link.
				$this->link = \Core\resolve_link($value);
				break;
			case 'title':
				$this->title = $value;
				break;
			default:
				$this->otherattributes[$key] = $value;
				break;
		}
	}
Ejemplo n.º 22
0
 /**
  * Execute the navigator and return the exit code of the application.
  *
  * @return int
  * @throws \Exception
  */
 public function render()
 {
     if (!$this->_view) {
         throw new \Exception('No view provided, please set one first!');
     }
     if (!($this->canupload || $this->canaccess)) {
         return \View::ERROR_ACCESSDENIED;
     }
     $resolved = \Core\resolve_link($this->_baseurl);
     // Tack on the system-defined uri-based options.
     $resolved .= (strpos($resolved, '?') === false ? '?' : '&') . 'controls=' . ($this->usecontrols ? '1' : '0') . '&uploader=' . ($this->useuploader ? '1' : '0');
     // This is meant to be called from most of the change directory methods, so it needs to drop that argument.
     $resolvedwmode = $resolved . '&mode=' . $this->_mode;
     // Get a list of the view modes along with current directories and titles.
     $viewmodes = array(['mode' => 'icon', 'title' => 'View as Icons', 'icon' => 'th-large', 'link' => $resolved . '&dir=' . urlencode($this->_cwd) . '&mode=icon'], ['mode' => 'list', 'title' => 'View as List', 'icon' => 'th-list', 'link' => $resolved . '&dir=' . urlencode($this->_cwd) . '&mode=list']);
     // This will create a navigatable tree of directory listings for the user.
     //$tree = explode('/', substr($dirname, strlen($basedirname)));
     $tree = explode('/', $this->_cwd);
     $treestack = '';
     foreach ($tree as $k => $v) {
         if (!trim($v)) {
             unset($tree[$k]);
         } else {
             $treestack .= '/' . $v;
             $tree[$k] = array('name' => $v, 'stack' => $treestack, 'href' => $resolvedwmode . '&dir=' . urlencode($treestack));
         }
     }
     // The base directory, because it may not be in /public necessarily.
     $base = Filestore\Factory::Directory($this->_basedir);
     $dir = Filestore\Factory::Directory($this->_basedir . $this->_cwd);
     // Allow automatic creation of the root directory.
     if ($this->_cwd == '' && !$dir->exists()) {
         $dir->mkdir();
     }
     if (!$dir->exists()) {
         return \View::ERROR_NOTFOUND;
     }
     $dirlen = strlen($dir->getPath());
     $baselen = strlen($base->getPath());
     $directories = array();
     $files = array();
     foreach ($dir->ls() as $file) {
         if ($file instanceof Filestore\Directory) {
             // Give me a count of children in that directory.  I need to do the logic custom here because I only want directories and images.
             $count = 0;
             foreach ($file->ls() as $subfile) {
                 if ($file instanceof Filestore\Directory) {
                     $count++;
                 } elseif ($file instanceof Filestore\File && Filestore\check_file_mimetype($this->_accept, $file->getMimetype(), $file->getExtension()) == '') {
                     $count++;
                 }
             }
             $directories[$file->getBasename()] = array('object' => $file, 'name' => $file->getBasename(), 'browsename' => substr($file->getPath(), $dirlen), 'children' => $count, 'href' => $resolvedwmode . '&dir=' . urlencode(substr($file->getPath(), $baselen)));
         } elseif ($file instanceof Filestore\File) {
             // I only want images
             if (Filestore\check_file_mimetype($this->_accept, $file->getMimetype(), $file->getExtension()) != '') {
                 continue;
             }
             $files[$file->getBaseFilename()] = array('object' => $file, 'name' => $file->getBaseFilename(), 'browsename' => substr($file->getFilename(), $baselen), 'selectname' => $file->getURL(), 'corename' => $file->getFilename(false));
         }
     }
     // Sorting would be nice!
     ksort($directories, SORT_STRING | SORT_FLAG_CASE);
     ksort($files, SORT_STRING | SORT_FLAG_CASE);
     // If it's a nested directory, provide a link back to the parent.
     if ($this->_cwd == '') {
         $uplink = null;
     } elseif ($this->_cwd == '/') {
         $uplink = null;
     } else {
         $uplink = $resolvedwmode . '&dir=' . urlencode(dirname(substr($dir->getPath(), $baselen)));
     }
     // Only certain people are allowed the rights to upload here.
     if ($this->canupload && $this->useuploader) {
         $uploadform = new \Form();
         //$uploadform->set('action', \Core\resolve_link('/mediamanagernavigator/upload'));
         $uploadform->addElement('multifile', array('basedir' => $this->_basedir . $this->_cwd, 'title' => 'Upload Files', 'name' => 'files', 'accept' => $this->_accept));
         //$uploadform->addElement('submit', array('value' => 'Upload Files'));
         $uploadform->clearFromSession();
     } else {
         $uploadform = false;
     }
     if ($this->canupload && $this->usecontrols) {
         $this->_view->addControl(['link' => '#', 'title' => 'Create Directory', 'icon' => 'folder-close', 'class' => 'directory-create']);
     }
     if ($this->usecontrols) {
         foreach ($viewmodes as $viewmode) {
             if ($viewmode['mode'] == $this->_mode) {
                 continue;
             }
             $this->_view->addControl($viewmode);
         }
     }
     switch ($this->_mode) {
         case 'list':
             $this->_view->templatename = 'pages/mediamanagernavigator/index/list.tpl';
             break;
         default:
             $this->_view->templatename = 'pages/mediamanagernavigator/index/icons.tpl';
     }
     $this->_view->assign('directories', array_values($directories));
     $this->_view->assign('files', array_values($files));
     $this->_view->assign('location_tree', $tree);
     $this->_view->assign('location', $treestack);
     $this->_view->assign('uploadform', $uploadform);
     $this->_view->assign('baseurl', $resolvedwmode);
     $this->_view->assign('mode', $this->_mode);
     $this->_view->assign('uplink', $uplink);
     $this->_view->assign('canupload', $this->canupload);
     $this->_view->assign('usecontrols', $this->usecontrols);
     return \View::ERROR_NOERROR;
 }
 /**
  * Get the repository XML as a string that can be returned to the browser or cached for future use.
  *
  * @return string
  */
 private function _getRepoXML()
 {
     $repo = new RepoXML();
     $repo->setDescription(ConfigHandler::Get('/package_repository/description'));
     $dir = Factory::Directory(\ConfigHandler::Get('/package_repository/base_directory'));
     $coredir = $dir->getPath() . 'core/';
     $componentdir = $dir->getPath() . 'components/';
     $themedir = $dir->getPath() . 'themes/';
     $tmpdir = Factory::Directory('tmp/exports/');
     $gpg = new Core\GPG\GPG();
     $keysfound = [];
     $private = ConfigHandler::Get('/package_repository/is_private') || strpos($dir->getPath(), ROOT_PDIR) !== 0;
     $addedpackages = 0;
     $failedpackages = 0;
     $iterator = new \Core\Filestore\DirectoryIterator($dir);
     // Only find signed packages.
     $iterator->findExtensions = ['asc'];
     // Recurse into sub directories
     $iterator->recursive = true;
     // No directories
     $iterator->findDirectories = false;
     // Just files
     $iterator->findFiles = true;
     // And sort them by their filename to make things easy.
     $iterator->sortBy('filename');
     // Ensure that the necessary temp directory exists.
     $tmpdir->mkdir();
     foreach ($iterator as $file) {
         /** @var \Core\Filestore\File $file */
         $fullpath = $file->getFilename();
         // Used in the XML file.
         if ($private) {
             $relpath = \Core\resolve_link('/packagerepository/download?file=' . substr($file->getFilename(), strlen($dir->getPath())));
         } else {
             $relpath = $file->getFilename(ROOT_PDIR);
         }
         // Drop the .asc extension.
         $basename = $file->getBasename(true);
         // Tarball of the temporary package
         $tgz = Factory::File($tmpdir->getPath() . $basename);
         $output = [];
         // I need to 1) retrieve and 2) verify the key for this package.
         try {
             $signature = $gpg->verifyFileSignature($fullpath);
             if (!in_array($signature->keyID, $keysfound)) {
                 $repo->addKey($signature->keyID, null, null);
                 $keysfound[] = $signature->keyID;
             }
         } catch (\Exception $e) {
             trigger_error($fullpath . ' was not able to be verified as authentic, (probably because the GPG public key was not available)');
             $failedpackages++;
             continue;
         }
         // decode and untar it in a temp directory to get the package.xml file.
         exec('gpg --homedir "' . GPG_HOMEDIR . '" -q -d "' . $fullpath . '" > "' . $tgz->getFilename() . '" 2>/dev/null', $output, $ret);
         if ($ret) {
             trigger_error('Decryption of file ' . $fullpath . ' failed!');
             $failedpackages++;
             continue;
         }
         exec('tar -xzf "' . $tgz->getFilename() . '" -C "' . $tmpdir->getPath() . '" ./package.xml', $output, $ret);
         if ($ret) {
             trigger_error('Unable to extract package.xml from' . $tgz->getFilename());
             unlink($tmpdir->getPath() . $basename);
             $failedpackages++;
             continue;
         }
         // Read in that package file and append it to the repo xml.
         $package = new PackageXML($tmpdir->getPath() . 'package.xml');
         $package->getRootDOM()->setAttribute('key', $signature->keyID);
         $package->setFileLocation($relpath);
         $repo->addPackage($package);
         $addedpackages++;
         // But I can still cleanup!
         unlink($tmpdir->getPath() . 'package.xml');
         $tgz->delete();
     }
     return $repo->asPrettyXML();
 }
Ejemplo n.º 24
0
	public function set($key, $value) {
		$key = strtolower($key);

		switch ($key) {
			case 'class':
				$this->classnames[] = $value;
				break;
			case 'value': // Drop into special logic.
				$this->setValue($value);
				break;
			case 'label': // This is an alias for title.
				$this->_attributes['title'] = $value;
				break;
			case 'options':
				// This will require a little bit more attention, as if only the title
				// is given, use that for the value as well.
				if (!is_array($value)) {
					$this->_attributes[$key] = $value;
				}
				elseif(\Core\is_numeric_array($value)) {
					$o = array();
					foreach ($value as $v) {
						$o[$v] = $v;
					}
					$this->_attributes[$key] = $o;
				}
				else{
					// It's an associative or other array, the keys are important!
					$this->_attributes[$key] = $value;
				}
				break;
			case 'autocomplete':
				if($value === false || $value === '0' | $value === 0 || $value === 'off'){
					$this->_attributes[$key] = 'off';
				}
				elseif($value === true || $value === '1' || $value === 1 || $value === 'on' || $value === ''){
					$this->_attributes[$key] = 'on';
				}
				else{
					// Resolve this to an actual URL using Core's built-in resolution system.
					$this->_attributes[$key] = \Core\resolve_link($value);
				}
				break;
			case 'persistent':
				$this->persistent = $value;
				break;
			default:
				$this->_attributes[$key] = $value;
				break;
		}
	}
	/**
	 * Add a repository to the site.
	 * This will also handle the embedded keys, (as of 2.4.5).
	 *
	 * This contains the first step and second steps.
	 */
	public function repos_add() {
		$request = $this->getPageRequest();
		$view    = $this->getView();

		$site = new UpdateSiteModel();

		$form = Form::BuildFromModel($site);
		$form->set('action', \Core\resolve_link('/updater/repos/add'));
		$form->addElement('submit', array('value' => 'Next'));

		$view->title = 'Add Repo';
		// Needed because dynamic pages do not record navigation.
		$view->addBreadcrumb('Repositories', 'updater/repos');

		$view->assign('form', $form);

		if(!is_dir(GPG_HOMEDIR)){
			// Try to create it?
			if(is_writable(dirname(GPG_HOMEDIR))){
				// w00t
				mkdir(GPG_HOMEDIR);
			}
			else{
				\Core\set_message(GPG_HOMEDIR . ' does not exist and could not be created!  Please fix this before proceeding!', 'error');
				$form = null;
			}
		}
		elseif(!is_writable(GPG_HOMEDIR)){
			\Core\set_message(GPG_HOMEDIR . ' is not writable!  Please fix this before proceeding!', 'error');
			$form = null;
		}


		// This is the logic for step 2 (confirmation).
		// This is after all the template logic from step 1 because it will fallback to that form if necessary.
		if($request->isPost()){
			$url      = $request->getPost('model[url]');
			$username = $request->getPost('model[username]');
			$password = $request->getPost('model[password]');

			// Validate and standardize this repo url.
			// This is because most people will simply type repo.corepl.us.
			if(strpos($url, '://') === false){
				$url = 'http://' . $url;
			}

			// Lookup that URL first!
			if(UpdateSiteModel::Count(array('url' => $url)) > 0){
				\Core\set_message($url . ' is already used!', 'error');
				return;
			}

			// Load up a new Model, that's the easiest way to pull the repo data.
			$model = new UpdateSiteModel();
			$model->setFromArray([
				'url' => $url,
				'username' => $username,
				'password' => $password,
			]);

			// From here on out, populate the previous form with this new model.
			$form = Form::BuildFromModel($model);
			$form->set('action', \Core\resolve_link('/updater/repos/add'));
			$form->addElement('submit', array('value' => 'Next'));
			$view->assign('form', $form);

			/** @var \Core\Filestore\Backends\FileRemote $remote */
			$remote = $model->getFile();

			if($remote->requiresAuthentication()){
				if(!$username){
					\Core\set_message($url . ' requires authentication!', 'error');
					return;
				}
				else{
					\Core\set_message('Invalid credentials for ' . $url, 'error');
					return;
				}
			}

			if(!$model->isValid()){
				\Core\set_message($url . ' does not appear to be a valid repository!', 'error');
				return;
			}

			$repo = new RepoXML();
			$repo->loadFromFile($remote);

			// Make sure the keys are good
			if(!$repo->validateKeys()){
				\Core\set_message('There were invalid/unpublished keys in the repo!  Refusing to import.', 'error');
				return;
			}

			// The very final bit of this logic is to look and see if there's a "confirm" present.
			// If there is, the user clicked accept on the second page and I need to go ahead and import the data.
			if($request->getPost('confirm')){
				$model->set('description', $repo->getDescription());
				$model->save();
				$keysimported = 0;
				$keycount     = sizeof($repo->getKeys());
				$gpg          = new \Core\GPG\GPG();

				foreach($repo->getKeys() as $keyData){
					try{
						$gpg->importKey($keyData['key']);
						++$keysimported;
					}
					catch(Exception $e){
						\Core\set_message('Unable to import key [' . $keyData['key'] . '] from keyserver!', 'error');
					}
				}

				if(!$keycount){
					\Core\set_message('Added repository site successfully!', 'success');
				}
				elseif($keycount != $keysimported){
					\Core\set_message('Added repository site, but unable to import ' . ($keycount-$keysimported) . ' key(s).', 'info');
				}
				else{
					\Core\set_message('Added repository site and imported ' . $keysimported . ' key(s) successfully!', 'success');
				}

				\core\redirect('/updater/repos');
			}

			$view->templatename = 'pages/updater/repos_add2.tpl';
			$view->assign('description', $repo->getDescription());
			$view->assign('keys', $repo->getKeys());
			$view->assign('url', $url);
			$view->assign('username', $username);
			$view->assign('password', $password);
		}
	}
Ejemplo n.º 26
0
	/**
	 * Execute the controller and method this page request points to.
	 */
	public function execute() {

		\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Starting PageRequest->execute()');

		if($this->isCacheable()){
			$uakey = \Core\UserAgent::Construct()->getPseudoIdentifier();
			$urlkey = $this->host . $this->uri;
			$expires = $this->getPageModel()->get('expires');
			$key = 'page-cache-' . md5($urlkey . '-' . $uakey);

			$cached = \Core\Cache::Get($key, $expires);
			if($cached && $cached instanceof View){
				$this->_pageview = $cached;
				$this->_cached = true;
				return;
			}
		}

		// Anything that needs to fire off *before* the page is rendered.
		// This includes widgets, script addons, and anything else that needs a CurrentPage.
		HookHandler::DispatchHook('/core/page/preexecute');

		// Load the underlying controller.
		$pagedat   = $this->splitParts();

		/** @var View $view The valid view object for this page */
		$view = $this->getView();

		// The controller must exist first!
		// (note, the SplitParts logic already takes care of the "Is this a valid controller" logic)
		if (!(isset($pagedat['controller']) && $pagedat['controller'])) {
			$view->error = View::ERROR_NOTFOUND;
			return;
		}

		$component = Core::GetComponentByController($pagedat['controller']);

		//////////////////////////////////////////////////////////////////////////////
		///  In this block of logic, either the page is executed and a view returned,
		///  or a view is generated with an error.
		//////////////////////////////////////////////////////////////////////////////
		if (!$component) {
			// Not found
			$view->error = View::ERROR_NOTFOUND;
			return;
		}
		elseif(!is_a($component, 'Component_2_1')) {
			$view->error = View::ERROR_NOTFOUND;
			return;
		}

		// Any method that starts with a "_" is an internal-only method!
		if ($pagedat['method']{0} == '_') {
			$view->error = View::ERROR_NOTFOUND;
			return;
		}

		// It also must be a part of the class... obviously
		if (!method_exists($pagedat['controller'], $pagedat['method'])) {
			$view->error = View::ERROR_NOTFOUND;
			return;
		}


		/** @var $controller Controller_2_1 This will be a Controller object. */
		$controller = Controller_2_1::Factory($pagedat['controller']);

		$view->baseurl = $this->getBaseURL();
		$controller->setView($view);

		// Make sure that the controller can access this object.
		$controller->setPageRequest($this);

		// The main page object.
		$page = $this->getPageModel();

		// Check the access string first, (if there is one)
		if ($controller->accessstring !== null) {
			// Update the page's access string, (just in case it's saved at the end of execution)
			$page->set('access', $controller->accessstring);

			// And if the user doesn't have access to it...
			if (!\Core\user()->checkAccess($controller->accessstring)) {
				$view->error = View::ERROR_ACCESSDENIED;
				return;
			}
		}

		if($page->get('password_protected')) {
			if(\Core\Session::Get('page-password-protected/' . $page->get('baseurl')) !== $page->get('password_protected')){
				$view->templatename = '/pages/page/passwordprotected.tpl';

				$form = new Form();

				$form->set('callsmethod', 'PageRequest::PasswordProtectHandler');
				$form->addElement(
					'system', [
						'name'  => 'page',
						'value' => $page
					]
				);

				$form->addElement(
					'password', [
						'name'      => 'passinput',
						'title'     => 'Password',
						'required'  => 'required',
						'maxlength' => 128
					]
				);
				$form->addElement(
					'submit', [
						'value' => 'Submit'
					]
				);

				$view->assign('form', $form);

				return;
			}
		}

		// If the parent Controller object has a method named $pagedat['method'], assume it's a security error!
		// This is because if the parent Controller object has a method, it's most likely a utility method
		// that shouldn't be called from the public web!
		foreach(get_class_methods('Controller_2_1') as $parentmethod){
			$parentmethod = strtolower($parentmethod);
			if($parentmethod == $pagedat['method']){
				$view->error = View::ERROR_BADREQUEST;
				return;
			}
		}

		// Additional security logic for existing pages in multi-site mode.
		// If this exact URL is registered to another site, then
		// don't allow this site to display it.
		if(!$page->exists() && Core::IsComponentAvailable('multisite') && MultiSiteHelper::IsEnabled()){
			$site = MultiSiteHelper::GetCurrentSiteID();

			$anypage = PageModel::Find(['baseurl = ' . $page->get('baseurl')], 1);

			if($anypage){

				if($anypage->get('site') == -1){
					// If this is a global page.... that's ok.
					// Just remap the page variable to this one!
					$page = $anypage;
				}
				elseif($anypage->get('site') == $site){
					// Strange... it should have located this page...
					// Anyway, it's allowed, the site matches up.
					$page = $anypage;
				}
				else{
					\Core\redirect($anypage->getResolvedURL());
				}
			}
		}

		$return = call_user_func(array($controller, $pagedat['method']));
		if (is_int($return)) {
			// A generic error code was returned.  Create a View with that code and return that instead.
			$view->error = $return;
			//return;
		}
		elseif(is_a($return, 'View') && $return != $view){
			// The controller method changed the view, (which is allowed),
			// but this needs to be remapped to this object so render knows about it.
			$this->_pageview = $view = $return;
		}
		elseif ($return === null) {
			// Hopefully it's setup!
			$return = $controller->getView();
			if($return != $view){
				$this->_pageview = $view = $return;
			}
		}
		elseif(!is_a($return, 'View')){
			if(DEVELOPMENT_MODE){
				var_dump('Controller method returned', $return);
				die('Sorry, but this controller did not return a valid object.  Please ensure that your method returns either an integer, null, or a View object!');
			}
			else{
				$view->error = View::ERROR_SERVERERROR;
				return;
			}
		}
		// No else needed, else it's a valid object.


		// You may be asking why $view is one object, but $return is the return from page execution.
		// GREAT QUESTION, The $view is the original view object created from the page request.  That is passed into
		// the controller and exposed via $this->getView().  The return can be a view, int, or other status indicator.
		// However since the controller can return a different view, that view should be used instead!
		///** @var $return View */


		// Allow the controller to assign controls via a shortcut function.
		if($view->error == View::ERROR_NOERROR){
			$controls = $controller->getControls();

			// This method may do absolutely nothing, add the controls to the view itself, or return an array of them.
			if(is_array($controls)){
				foreach($controls as $control){
					$view->addControl($control);
				}
			}
		}


		// For some of the options, there may be some that can be used for a fuzzy page, ie: a page's non-fuzzy template,
		// title, or meta information.
		if($view->error == View::ERROR_NOERROR){
			if ($page->exists()) {
				$defaultpage = $page;
			} else {
				$defaultpage = null;
				$url         = $view->baseurl;
				while ($url != '') {
					$url = substr($url, 0, strrpos($url, '/'));
					$p   = PageModel::Find(array('baseurl' => $url, 'fuzzy' => 1), 1);
					if ($p === null) continue;
					if ($p->exists()) {
						$defaultpage = $p;
						break;
					}
				}
				if ($defaultpage === null) {
					// Fine....
					$defaultpage = $page;
				}
			}

			$defaultmetas = $defaultpage->getLink('PageMeta');

			// Make a list of the existing ones so I know which ones not to overwrite!
			// Just the key will suffice quite nicely.
			$currentmetas = array();
			foreach($view->meta as $k => $meta){
				$currentmetas[] = $k;
			}

			// Load some of the page information into the view now!
			foreach($defaultmetas as $meta){
				/** @var $meta PageMetaModel */
				$key = $meta->get('meta_key');

				$viewmeta = $meta->getViewMetaObject();

				// again, allow the executed controller have the final say on meta information.
				if ($meta->get('meta_value_title') && !in_array($key, $currentmetas)) {
					$view->meta[$key] = $viewmeta;
				}
			}


			// Since the controller already ran, do not overwrite the title.
			if ($view->title === null){
				$view->title = $defaultpage->get('title');
			}

			// Tracker to see if this page, (or a parent's page), is an admin-level page.
			// This is required because "admin" pages may have a different skin and should always have the dashboard as the top-level breadcrumb.
			/** @var boolean $isadmin */
			$isadmin = ($page->get('admin') == '1');

			$parents = array();
			$parenttree = $page->getParentTree();
			foreach ($parenttree as $parent) {
				/** @var PageModel $parent */
				$parents[] = array(
					'title' => $parent->get('title'),
					'link'  => $parent->getResolvedURL()
				);

				// Since I'm here, check if this page is an admin page.
				if($parent->get('admin')){
					$isadmin = true;
				}
			}
			$view->breadcrumbs = array_merge($parents, $view->breadcrumbs);

			if($isadmin && $view->baseurl != '/admin'){
				// Make sure that admin is the top breadcrumb.
				// This block doesn't need to apply for the actual admin page itself, as that doesn't need its own breadcrumb :/
				$adminlink = \Core\resolve_link('/admin');
				if(!isset($view->breadcrumbs[0])){
					// Nothing is even set!
					$view->breadcrumbs[] = ['title' => 'Administration', 'link' => $adminlink];
				}
				elseif($view->breadcrumbs[0]['link'] != $adminlink){
					// It's set, but not to admin.
					$view->breadcrumbs = array_merge([['title' => 'Administration', 'link' => $adminlink]], $view->breadcrumbs);
				}
			}
		}
		else{
			$defaultpage = null;
			$isadmin = false;
		}


		if(
			$view->mode == View::MODE_PAGEORAJAX &&
			$this->isAjax() &&
			$view->jsondata !== null &&
			$view->templatename === null
		){
			// Allow the content type to be overridden for ajax pages that have JSON data embedded in them.
			$view->contenttype = View::CTYPE_JSON;
		}


		if($view->mode == View::MODE_NOOUTPUT){
			$view->mastertemplate = false;
			$view->templatename = null;
		}
		elseif(
			$view->error == View::ERROR_NOERROR &&
			$view->contenttype == View::CTYPE_HTML &&
			$view->templatename === null
		){
			// Try to guess the templatename if it wasn't set.
			// This
			$cnameshort           = (strpos($pagedat['controller'], 'Controller') == strlen($pagedat['controller']) - 10) ? substr($pagedat['controller'], 0, -10) : $pagedat['controller'];
			$view->templatename = strtolower('/pages/' . $cnameshort . '/' . $pagedat['method'] . '.tpl');
		}
		elseif(
			$view->error == View::ERROR_NOERROR &&
			$view->contenttype == View::CTYPE_XML &&
			$view->templatename === null
		){
			$cnameshort           = (strpos($pagedat['controller'], 'Controller') == strlen($pagedat['controller']) - 10) ? substr($pagedat['controller'], 0, -10) : $pagedat['controller'];
			$view->templatename = Template::ResolveFile(strtolower('pages/' . $cnameshort . '/' . $pagedat['method'] . '.xml.tpl'));
		}

		// In addition to the autogeneration, also support the page_template from the datastore.
		if($defaultpage && $defaultpage->get('page_template')){
			// Switch the template over to that custom one.
			// Some legacy data will have the fully resolved path for this template.
			// This has been switched to just the basename of the custom template,
			// but legacy data be legacy, 'yo.                            0.o

			$base     = substr($view->templatename, 0, -4);
			$override = $defaultpage->get('page_template');
			if($base && strpos($override, $base) === 0){
				$view->templatename = $override;
			}
			elseif($base){
				$view->templatename = $base . '/' . $override;
			}
		}

		// Guess which theme skin (mastertemplate) should be used if one wasn't specified.
		if($view->mastertemplate == 'admin'){
			// If the master template is set explictly to be the admin skin, then transpose that to the set admin skin.
			// This is useful for the pages that may not be under the "/admin" umbrella, but still rendered with the admin UI.
			$view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template');
		}
		elseif($view->mastertemplate){
			// No change needed, just skip the below cases.
		}
		elseif($view->mastertemplate === false){
			// If the master template is explictly set to false, the page wanted no master template!
		}
		elseif($isadmin){
			// This page doesn't have a master template set, but it or a parent is set as an admin-level page.
			$view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template');
		}
		elseif ($defaultpage && $defaultpage->get('theme_template')) {
			// Master template set in the database?
			$view->mastertemplate = $defaultpage->get('theme_template');
		}
		elseif($defaultpage && $defaultpage->exists() && $defaultpage->get('admin')){
			// Or an admin level page?
			$view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template');
		}
		elseif(sizeof($view->breadcrumbs) && $view->breadcrumbs[0]['title'] == 'Administration'){
			// Whatever, close e-damn-nough!
			// This happens for pages that don't actually exist, like "edit"....
			$view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template');
		}
		else{
			$view->mastertemplate = ConfigHandler::Get('/theme/default_template');
		}

		// First of all, if the current theme is not available, reset back to the first theme available!
		if(!($theme = ThemeHandler::GetTheme())){
			/** @var \Theme\Theme $theme */
			$theme = ThemeHandler::GetTheme('base-v2');
			$view->mastertemplate = 'basic.tpl';
			\Core\set_message('t:MESSAGE_ERROR_INVALID_THEME_SELECTED');
		}

		// Make sure the selected mastertemplate actually exists!
		if($view->mastertemplate !== false){
			$themeskins = $theme->getSkins();
			$mastertplgood = false;
			foreach($themeskins as $skin){
				if($skin['file'] == $view->mastertemplate){
					// It's located!
					$mastertplgood =true;
					break;
				}
			}

			// A few special cases.
			if($view->mastertemplate == 'blank.tpl'){
				// This is acceptable as a default one.
				$mastertplgood =true;
			}

			if(!$mastertplgood){
				// Just use the first one instead!
				trigger_error('Invalid skin [' . $view->mastertemplate . '] selected for this page, skin is not located within the selected theme!  Using first available instead.', E_USER_NOTICE);
				$view->mastertemplate = $themeskins[0]['file'];
			}
		}

		// Handle some of the new automatic meta data associated with Pages and the resulting View.

		if(\ConfigHandler::Get('/core/page/indexable') == 'deny'){
			// Administratively set to noindex on all pages.
			$view->addMetaName('robots', 'noindex');
		}
		elseif(!$page->get('indexable')){
			// Bots have no business indexing user-action pages.
			$view->addMetaName('robots', 'noindex');
		}
		if(!isset($view->meta['title'])){
			$view->meta['title'] = $page->getSEOTitle();
		}

		HookHandler::DispatchHook('/core/page/postexecute');

		\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Completed PageRequest->execute()');
	}
Ejemplo n.º 27
0
	/**
	 * Add a control into the page template.
	 *
	 * Useful for embedding functions and administrative utilities inline without having to adjust the
	 * application template.
	 *
	 * @param string|array $title       The title to set for this control
	 * @param string $link        The link to set for this control
	 * @param string|array $class The class name or array of attributes to set on this control
	 *                            If this is an array, it should be an associative array for the advanced parameters
	 */
	public function addControl($title, $link = null, $class = 'edit') {
		$control = new \ViewControl();

		// Completely associative-array based version!
		if(func_num_args() == 1 && is_array($title)){
			foreach($title as $k => $v){
				$control->set($k, $v);
			}
		}
		else{
			// Advanced method, allow for associative arrays.
			if(is_array($class)){
				foreach($class as $k => $v){
					$control->set($k, $v);
				}
			}
			// Default method; just a string for the class name.
			else{
				$control->class = $class;
			}

			$control->title = $title;
			$control->link = \Core\resolve_link($link);
		}

		$this->getControls()->addLink($control);
	}
Ejemplo n.º 28
0
/**
 * Return a valid resolved "A" tag, with whatever inner content preserved.
 *
 * This is the recommended way to handle &lt;a/&gt; tags in Core templates.
 * The href attribute is automatically resolved to the primary rewrite URL,
 * and all additional links, (mostly), are passed through to the template as-is.
 *
 * #### Smarty Parameters
 *
 *  * assign
 *    * Assign the result to a variable instead of printing it to stdout.
 *  * confirm
 *    * Set to a string to prompt the user with the string before submitting the link via a POST request.
 *  * history
 *    * Set to a number, (1, 2, etc), to set the href to that user's last nth page from history.
 *
 * #### Standard Example
 *
 * <pre>
 * // The smarty line
 * {a href="/content/view/1"}Something Blah{/a}
 * // Resolves to
 * &lt;a href="/homepage"&gt;Something Blah&lt;/a&gt;
 * </pre>
 *
 * #### External Link
 *
 * Also works with already-resolved or external links
 *
 * <pre>
 * {a href="http://corepl.us" target="_blank"}Link Somewhere!{/a}
 * // Resolves to
 * &lt;a href="http://corepl.use" target="_blank"&gt;Link Somewhere!&lt;/a&gt;
 * </pre>
 *
 * #### Multisite Links
 *
 * When multi-site is installed and activated, cross-site links can also be used that resolve based on that site's criteria.
 *
 * <pre>
 * {a href="site:12/content/view/5"}Child #12 About Page{/a}
 * // Resolves to
 * &lt;a href="http://child-12-url.example.com/about-us"&gt;Child #12 About Page&lt;/a&gt;
 * </pre>
 *
 * @param array       $params  Associative (and/or indexed) array of smarty parameters passed in from the template
 * @param string|null $content Null on opening pass, rendered source of the contents inside the block on closing pass
 * @param Smarty      $smarty  Parent Smarty template object
 * @param boolean     $repeat  True at the first call of the block-function (the opening tag) and
 * false on all subsequent calls to the block function (the block's closing tag).
 * Each time the function implementation returns with $repeat being TRUE,
 * the contents between {func}...{/func} are evaluated and the function implementation
 * is called again with the new block contents in the parameter $content.
 *
 * @return string
 */
function smarty_block_a($params, $content, $smarty, &$repeat){
	// This only needs to be called once.
	if($repeat) return '';

	$assign= false;

	// Start the A tag
	$newcontent = '<a';

	// Allow "confirm" text to override the href and onClick functions.
	// This has the cool ability of not requiring jquery to run, since it is all handled with PHP logic.
	if(isset($params['confirm'])){
		$params['onclick'] = 'return Core.ConfirmEvent(this);';
		$params['data-href'] = \Core\resolve_link($params['href']);
		$params['data-confirm'] = $params['confirm'];
		$params['href'] = '#false';
	}

	// Add in any attributes.
	foreach($params as $k => $v){
		$k = strtolower($k);
		switch($k){
			case 'href':
				$newcontent .= ' href="' . \Core\resolve_link($v) . '"';
				break;
			case 'history':
			case 'back':
				$newcontent .= ' href="' . \Core\page_request()->getReferrer() . '"';
				break;
			case 'assign':
				$assign = $v;
				break;
			case 'alt':
			case 'title':
			case 'data-confirm':
				// These all support translation via the "t:" prefix!
				if(strpos($v, 't:') === 0){
					$newcontent .= " $k=\"" . str_replace('"', '&quot;', t(substr($v, 2))) . "\"";
				}
				else{
					$newcontent .= " $k=\"" . str_replace('"', '&quot;', $v) . "\"";
				}
			break;
			default:
				// Standard non-fun values :p
				$newcontent .= " $k=\"" . str_replace('"', '&quot;', $v) . "\"";
		}
	}
	// Close the starting tag.
	$newcontent .= '>';

	// Add any content inside.
	$newcontent .= $content;

	// Close the set.
	$newcontent .= '</a>';

	if($assign){
		$smarty->assign($assign, $newcontent);
		return '';
	}
	else{
		return $newcontent;
	}
}
Ejemplo n.º 29
0
	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;
	}
Ejemplo n.º 30
0
 private function _setupFileBrowser(View $view, PageRequest $request, $type)
 {
     $view->templatename = 'pages/tinymce/browser-icons.tpl';
     $view->mastertemplate = 'blank.tpl';
     $view->record = false;
     $accesspermission = 'p:/tinymce/filebrowser/access';
     $uploadpermission = 'p:/tinymce/filebrowser/upload';
     $sandboxconfig = '/tinymce/filebrowser/sandbox-user-uploads';
     if ($type == 'image') {
         $accept = 'image/*';
     } else {
         $accept = '*';
     }
     if (!\Core\user()->checkAccess($accesspermission)) {
         return View::ERROR_ACCESSDENIED;
     }
     // Get a listing of files in the appropriate directory.
     if (ConfigHandler::Get($sandboxconfig)) {
         $basedirname = 'public/tinymce/' . \Core\user()->get('id') . '/';
     } else {
         $basedirname = 'public/tinymce/';
     }
     if ($request->getParameter('dir')) {
         $dirname = $basedirname . str_replace('..', '', $request->getParameter('dir'));
     } else {
         $dirname = $basedirname;
     }
     // This will create a navigatable tree of directory listings for the user.
     $tree = explode('/', substr($dirname, strlen($basedirname)));
     $treestack = '';
     foreach ($tree as $k => $v) {
         if (!trim($v)) {
             unset($tree[$k]);
         } else {
             $treestack .= '/' . $v;
             $tree[$k] = array('name' => $v, 'stack' => $treestack);
         }
     }
     $dir = \Core\Filestore\Factory::Directory($dirname);
     // Allow automatic creation of the root directory.
     if ($dirname == $basedirname && !$dir->exists()) {
         $dir->mkdir();
     }
     if (!$dir->exists()) {
         return View::ERROR_NOTFOUND;
     }
     $dirlen = strlen($dir->getPath());
     $directories = array();
     $files = array();
     foreach ($dir->ls() as $file) {
         if ($file instanceof \Core\Filestore\Directory) {
             // Give me a count of children in that directory.  I need to do the logic custom here because I only want directories and imgaes.
             $count = 0;
             foreach ($file->ls() as $subfile) {
                 if ($file instanceof \Core\Filestore\Directory) {
                     $count++;
                 } elseif ($file instanceof \Core\Filestore\File) {
                     if ($type == 'image' && $file->isImage() || $type == 'file') {
                         $count++;
                     }
                 }
             }
             $directories[$file->getBasename()] = array('object' => $file, 'name' => $file->getBasename(), 'browsename' => substr($file->getPath(), $dirlen), 'children' => $count);
         } elseif ($file instanceof \Core\Filestore\File) {
             // I only want images
             if ($type == 'image' && !$file->isImage()) {
                 continue;
             }
             $files[$file->getBaseFilename()] = array('object' => $file, 'name' => $file->getBaseFilename(), 'selectname' => $file->getURL());
         }
     }
     // Sorting would be nice!
     ksort($directories);
     ksort($files);
     // Size presets
     $size = \Core\user()->get('/tinymce/filebrowser/size');
     if (!$size) {
         $size = 'lg';
     }
     switch ($size) {
         case 'sm':
             $sizepx = 16;
             break;
         case 'med':
             $sizepx = 32;
             break;
         case 'lg':
             $sizepx = 64;
             break;
         case 'xl':
             $sizepx = 128;
             break;
         default:
             $size = 'lg';
             $sizepx = 64;
     }
     // Only certain people are allowed the rights to upload here.
     if (\Core\user()->checkAccess($uploadpermission)) {
         $uploadform = new Form();
         $uploadform->set('action', \Core\resolve_link('/tinymce/' . $type . '/upload'));
         $uploadform->addElement('multifile', array('basedir' => $dirname, 'title' => 'Upload Files', 'name' => 'files', 'accept' => $accept));
         //$uploadform->addElement('submit', array('value' => 'Bulk Upload'));
     } else {
         $uploadform = false;
     }
     // Give me some useful tips to show the user.
     $tips = array('You can drag and drop files from your local machine to upload them!', 'You can double click on a directory to browse that directory.', 'You can single click on a file or directory to view more information about that file.', 'You can use the direction arrows on your keyboard to navigate between files!', 'Pressing ESCAPE will deselect any selected files.', 'You are free to rename or delete files at will, but be aware, you may delete a file you need!');
     $view->assign('directories', array_values($directories));
     $view->assign('files', array_values($files));
     $view->assign('size', $size);
     $view->assign('sizepx', $sizepx);
     $view->assign('location_tree', $tree);
     $view->assign('location', $treestack);
     $view->assign('tip', $tips[rand(0, sizeof($tips) - 1)]);
     $view->assign('uploadform', $uploadform);
     return View::ERROR_NOERROR;
 }