View file upload/includes/class_usercss.php

File size: 24.7Kb
<?php
/*======================================================================*\
|| #################################################################### ||
|| # vBulletin 4.0.5
|| # ---------------------------------------------------------------- # ||
|| # Copyright ©2000-2010 vBulletin Solutions Inc. All Rights Reserved. ||
|| # This file may not be redistributed in whole or significant part. # ||
|| # ---------------- VBULLETIN IS NOT FREE SOFTWARE ---------------- # ||
|| # http://www.vbulletin.com | http://www.vbulletin.com/license.html # ||
|| #################################################################### ||
\*======================================================================*/

/**
* Abstracted class that handles User CSS
*
* @package	vBulletin
* @version	$Revision: 32878 $
* @date		$Date: 2009-10-28 11:38:49 -0700 (Wed, 28 Oct 2009) $
*/
class vB_UserCSS
{
 	/**
 	* A list of valid properties along with verification info, permission checks, and
 	* mapping to actual CSS property names.
 	*
 	* @var	array
 	*/
 	var $properties = array(
 		'font_family' => array(
 			'callback'    => 'verify_font_family',
 			'cssproperty' => 'font-family',
 			'permission'  => 'caneditfontfamily'
 		),
 		'font_size' => array(
 			'callback'    => 'verify_size',
 			'cssproperty' => 'font-size',
 			'permission'  => 'caneditfontsize'
 		),

 		'color' => array(
 			'callback'    => 'verify_color',
 			'cssproperty' => 'color',
 			'permission'  => 'caneditcolors'
 		),
 		'linkcolor' => array(
 			'callback'    => 'verify_color',
 			'cssproperty' => 'color',
 			'permission'  => 'caneditcolors'
 		),
 		'shadecolor' => array(
 			'callback'    => 'verify_color',
 			'cssproperty' => 'color',
 			'permission'  => 'caneditcolors'
 		),

 		'background_color' => array(
 			'callback'    => 'verify_color',
 			'cssproperty' => 'background-color',
 			'permission'  => 'caneditcolors'
 		),
 		'background_image' => array(
 			'callback'    => 'verify_image',
 			'cssproperty' => 'background-image',
 			'permission'  => 'caneditbgimage'
 		),

		'background_repeat' => array(
			'callback'    => 'verify_repeat',
			'cssproperty' => 'background-repeat',
			'permission'  => 'caneditbgimage'
		),
 		'border_style' => array(
 			'callback'    => 'verify_border_style',
 			'cssproperty' => 'border-style',
 			'permission'  => 'caneditborders'
 		),
 		'border_width' => array(
 			'callback'    => 'verify_size',
 			'cssproperty' => 'border-width',
 			'permission'  => 'caneditborders'
 		),
 		'border_color' => array(
 			'callback'    => 'verify_color',
 			'cssproperty' => 'border-color',
 			'permission'  => 'caneditborders'
 		),
 		'padding' => array(
 			'callback'    => 'verify_box_outline_size',
 			'cssproperty' => 'padding',
 			'permission'  => 'caneditborders'
 		)
 	);

	/**
	* An array of information about the various CSS selectors/properties. See build_css_array().
	*
	* @var array
	*/
	var $cssedit = array();

	/**
	* An Array of the “store” of current data
	*
	* @var	array
	*/
	var $store = array();

	/**
	*  The data currently in the database
	*
	* @var	array
	*/
	var $existing = array();

	/**
	* An Array of tuples to be deleted from the database
	*
	* @var	array
	*/
	var $delete = array();

	/**
	* An integer referencing the User ID of the User for Whom the CSS changes are being made.
	*
	* @var	int
	*/
	var $userid = 0;

	/**
	* Array of permissions for the current user. Should be the format returned by cache_permissions()
	*
	* @var	array
	*/
	var $permissions = array();

	/**
	* Any errors that were encountered during the upload or verification process
	*
	* @var	array
	*/
	var $error = array();

	/**
	* Selector/property combinations that did not have valid values
	*
	* @var	array
	*/
	var $invalid = array();

	/**
	* Main registry object
	*
	* @var	vB_Registry
	*/
	var $registry = null;

	/**
	* The vBulletin database object
	*
	* @var	vB_Database
	*/
	var $dbobject = null;


	/**
	* Constructor. Sets up the data for the specified user.
	*
	* @param	vB_Registry
	* @param	integer		User to process
	* @param	boolean		Whether to fetch their existing CSS data
	*/
	function vB_UserCSS(&$registry, $userid, $fetch_data = true)
	{
		$this->registry =& $registry;

		if (is_object($registry->db))
		{
			$this->dbobject =& $registry->db;
		}

		$this->set_userid($userid, $fetch_data);

		$this->cssedit = $this->build_css_array();

		($hook = vBulletinHook::fetch_hook('usercss_create')) ? eval($hook) : false;
	}

	/**
	* Sets the user we're working with. Automatically sets permissions as well.
	*
	* @param	integer	User to process
	* @param	boolean	Whether to fetch existing CSS data
	*
	* @return	boolean	True on success
	*/
	function set_userid($userid, $fetch = true)
	{
		$userid = intval($userid);

		if ($userid == $this->registry->userinfo['userid'])
		{
			$this->userid = $userid;
			$this->permissions = $this->registry->userinfo['permissions'];
		}
		else if ($user = $this->dbobject->query_first("SELECT * FROM " . TABLE_PREFIX . "user WHERE userid = $userid"))
		{
			$this->userid = $userid;
			$this->permissions = cache_permissions($user, false);
		}
		else
		{
			global $vbphrase;
			$this->error[] = fetch_error('invalidid', $vbphrase['user'], $this->registry->options['contactuslink']);
			return false;
		}

		if ($fetch)
		{
			$this->existing = $this->fetch_existing();
		}

		return true;
	}

	/**
	* Explicitly set permissions. Useful if you want to override the permissions
	* for the user being processed.
	*
	* @param	array
	*/
	function set_permissions($permissions)
	{
		$this->permissions = $permissions;
	}

	/**
	* Fetches the existing data for the selected user
	*
	* @return	array	Array of [selector][property] = value
	*/
	function fetch_existing()
	{
		$usercss_result = $this->dbobject->query_read("
			SELECT * FROM " . TABLE_PREFIX . "usercss
			WHERE userid = " . $this->userid . "
			ORDER BY selector
		");

		$existing = array();
		while ($usercss = $this->dbobject->fetch_array($usercss_result))
		{
			$existing["$usercss[selector]"]["$usercss[property]"] = $usercss['value'];
		}

		$this->dbobject->free_result($usercss_result);

		return $existing;
	}

	/**
	* Parses a particular property and sets it for storage/deletion if successful.
	*
	* @param	string	Selector
	* @param	string	Property
	* @param	string	Value
	*
	* @return	boolean
	*/
	function parse($selector, $property, $value = '')
	{
		$propertyinfo = $this->properties["$property"];

		if (empty($propertyinfo) OR $value == '')
		{
			$this->delete["$selector"][] = $property;
			return true;
		}
		else
		{
			$valid = false;

			if (empty($propertyinfo['callback']))
			{
				$valid = true;
			}
			else
			{
				$callback = $propertyinfo['callback'];
				if ($this->$callback($value))
				{
					$valid = true;
				}
			}

			if ($valid)
			{
				if ($this->existing["$selector"]["$property"] != $value)
				{
					$this->store["$selector"]["$property"] = $value;
				}
			}
			else
			{
				$this->invalid["$selector"]["$property"] = ' usercsserror ';
			}

			($hook = vBulletinHook::fetch_hook('usercss_parse')) ? eval($hook) : false;

			return $valid;
		}
	}

	/**
	* Saves the updated properties to the database.
	*/
	function save()
	{
		// First, we want to remove any properties they don't have access to.
		// This is in case they lost some permissions;
		// leaving them around leads to unexpected behavior.
		$prop_del = array();
		foreach ($this->properties AS $property => $propertyinfo)
		{
			if (!($this->permissions['usercsspermissions'] & $this->registry->bf_ugp_usercsspermissions["$propertyinfo[permission]"]))
			{
				$prop_del[] = $this->dbobject->escape_string($property);
			}
		}

		if ($prop_del)
		{
			$this->dbobject->query_write("
				DELETE FROM " . TABLE_PREFIX . "usercss
				WHERE userid = " . $this->userid . "
					AND property IN ('" . implode("','", $prop_del) . "')
			");
		}

		// now go for any entries that we emptied -- these are being removed
		if (!empty($this->delete))
		{
			foreach ($this->delete as $selector => $properties)
			{
				foreach ($properties as $property)
				{
					if (!empty($this->existing["$selector"]["$property"]))
					{
						$this->dbobject->query_write("
							DELETE FROM " . TABLE_PREFIX . "usercss
							WHERE userid = " . $this->userid . "
								AND selector = '" . $this->dbobject->escape_string($selector) . "'
								AND property = '" . $this->dbobject->escape_string($property) . "'
						");
					}

					unset($this->existing["$selector"]["$property"]);
				}

			}
		}

		// and for new/changed ones...
		if (!empty($this->store))
		{
			$value = array();

			foreach ($this->store as $selector => $properties)
			{
				foreach ($properties as $property => $value)
				{
					$values[] = "
						(" . $this->userid . ",
						'" . $this->dbobject->escape_string($selector) . "',
						'" . $this->dbobject->escape_string($property) . "',
						'" . $this->dbobject->escape_string($value) . "')
					";

					$this->dbobject->query_write("
						DELETE FROM " . TABLE_PREFIX . "usercss
						WHERE userid = " . $this->userid . "
							AND selector = '" . $this->dbobject->escape_string($selector) . "'
							AND property = '" . $this->dbobject->escape_string($property) . "'
					");
				}
			}

			if ($values)
			{
				$this->dbobject->query_write("
					INSERT INTO " . TABLE_PREFIX . "usercss
						(userid, selector, property, value)
					VALUES
						" . implode(", ", $values)
				);
			}

		}

		$this->update_css_cache();
	}

	/**
	* Fetches the array of CSS data that would be used if save were called.
	* Good for previews.
	*
	* @return	array	Array of CSS data [selector][property] = value
	*/
	function fetch_effective()
	{
		$usercss_cache = $this->fetch_existing();

		if ($this->delete)
		{
			foreach ($this->delete AS $selector => $properties)
			{
				foreach ($properties AS $property)
				{
					unset($usercss_cache["$selector"]["$property"]);
				}
			}
		}

		if ($this->store)
		{
			foreach ($this->store AS $selector => $properties)
			{
				foreach ($properties AS $property => $value)
				{
					$usercss_cache["$selector"]["$property"] = $value;
				}
			}
		}

		return $usercss_cache;
	}


	/**
	* Updates this user's CSS cache.
	*
	* @return	string	Compiled CSS
	*/
	function update_css_cache()
	{
		$buildcss = $this->build_css();

		$this->dbobject->query_write("
			REPLACE INTO " . TABLE_PREFIX . "usercsscache
				(userid, cachedcss, buildpermissions)
			VALUES
				(" . $this->userid . ", '" . $this->dbobject->escape_string($buildcss) . "', " . intval($this->permissions['usercsspermissions']) . ")
		");

		return $buildcss;
	}

	/**
	* Builds an individual CSS property into an array
	*
	* @param	array	(By Ref) Array to write into
	* @param	string	Selector group ID. Will be resolved to actual selectors.
	* @param	string	Property name (to be resolved to a CSS property)
	* @param	string	Value to set that property to
	*/
	function build_css_property(&$css, $selectorgroup, $property, $value)
	{
		$selectorgroupinfo = $this->cssedit["$selectorgroup"];

		if (!in_array($property, $selectorgroupinfo['properties']) OR $value == ''  OR !$this->check_css_permission($selectorgroup, $property, $this->permissions))
		{
			return;
		}

		if (isset($selectorgroupinfo['selectors']))
		{
			$selectors = array();
			foreach ($selectorgroupinfo['selectors'] AS $realselector)
			{
				$selectors[] = ($realselector != '#usercss' ? '#usercss ' : '') . $realselector;
			}
		}
		else
		{
			$selectors = array(
				($selectorgroup != '#usercss' ? '#usercss ' : '') . $selectorgroup
			);
		}

		if (!$selectors)
		{
			return;
		}

		$selector_list = implode(', ', $selectors);

		$propertyinfo = $this->properties["$property"];

		if ($property == 'background_image')
		{
			preg_match("/^([0-9]+),([0-9]+)$/", $value, $picture);
			$value = "url(attachment.php?/*sessionurl*/attachmentid=$picture[2])";
		}

		$css["$selector_list"]["$propertyinfo[cssproperty]"] = $value;

		// if we are dealing with the inputs group and we are NOT handling borders, apply the same styles to <option> and <optgroup>
		if ($selectorgroup == 'inputs' AND strpos($propertyinfo['cssproperty'], 'border') === false)
		{
			$css['#usercss option, #usercss optgroup']["$propertyinfo[cssproperty]"] = $value;
		}

		if ($property == 'background_color' AND !isset($css["$selector_list"]['background-image']))
		{
			// a color is set, but no image, so we need to blank out the image
			$css["$selector_list"]['background-image'] = 'none';
		}

		if ($propertyinfo['cssproperty'] == 'color' AND $selectorgroupinfo['overridelink'])
		{
			$this->build_css_property($css, $selectorgroupinfo['overridelink'], 'linkcolor', $value);
		}

		($hook = vBulletinHook::fetch_hook('usercss_build_property')) ? eval($hook) : false;
	}

	/**
	* Builds the compiled CSS.
	*
	* @param	array	Optional array of data to build the CSS from; defaults to the existing values
	*
	* @return	string	Compiled CSS
	*/
	function build_css($usercss_cache = null)
	{
		if (!is_array($usercss_cache))
		{
			$usercss_cache = $this->fetch_existing();
		}

		$css = array();

		foreach (array_keys($this->cssedit) AS $selector)
		{
			if (!isset($usercss_cache["$selector"]))
			{
				continue;
			}

			foreach ($usercss_cache["$selector"] AS $property => $value)
			{
				$this->build_css_property($css, $selector, $property, $value);
			}
		}

		$csstext = '';
		foreach ($css AS $selector_list => $properties)
		{
			$csstext .= "$selector_list {\n";
			foreach ($properties AS $property => $propvalue)
			{
				$csstext .= "\t$property: $propvalue;\n";
			}
			$csstext .= "}\n\n";
		}

		($hook = vBulletinHook::fetch_hook('usercss_build_css')) ? eval($hook) : false;

		return trim($csstext);
	}

	/**
	* Checks permissions for the specified selector/property.
	*
	* @param	string	Selector
	* @param	string	Property
	* @param	array	Array of permissions to check against
	*
	* @return	boolean
	*/
	function check_css_permission($selector, $property, $permissions)
	{
		$permfield = $this->properties["$property"]['permission'];

		if ($permfield == 'caneditbgimage')
		{
			return ($this->registry->options['socnet'] & $this->registry->bf_misc_socnet['enable_albums'] AND $this->permissions['usercsspermissions'] & $this->registry->bf_ugp_usercsspermissions["$permfield"]) ? true : false;
		}

		return ($this->permissions['usercsspermissions'] & $this->registry->bf_ugp_usercsspermissions["$permfield"]) ? true : false;
	}

	/**
	* Build an array of information about how to display the user CSS editor page
	*
	* @return	array
	*/
	function build_display_array()
	{
		$display = array(
			'main' => array(
				'phrasename' => 'usercss_main',
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'border_style',
					'border_width',
					'border_color',
					'color' => 'text',
					'padding',
					'linkcolor' => 'main_a',
					'font_family' => 'text',
					'shadecolor' => 'shadetext'
				)
			),
			'tableborder' => array(
				'phrasename' => 'usercss_tableborder',
				'properties' => null // inherit from build_css_array's value
			),
			'tabletitle' => array(
				'phrasename' => 'usercss_tabletitle',
				'properties' => null // inherit from build_css_array's value
			),
			'tableheader' => array(
				'phrasename' => 'usercss_tableheader',
				'properties' => null // inherit from build_css_array's value
			),
			'tablefooter' => array(
				'phrasename' => 'usercss_tablefooter',
				'properties' => null // inherit from build_css_array's value
			),
			'alternating1' => array(
				'phrasename' => 'usercss_alternating1',
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color',
					'linkcolor' => 'alternating1_a'
				)
			),
			'alternating2' => array(
				'phrasename' => 'usercss_alternating2',
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color',
					'linkcolor' => 'alternating2_a'
				)
			),
			'inputs' => array(
				'phrasename' => 'usercss_inputs',
				'properties' => null // inherit from build_css_array's value
			),
		);

		($hook = vBulletinHook::fetch_hook('usercss_build_display_array')) ? eval($hook) : false;

		return $display;
	}

	/**
	* Returns an array of information about selectors and properties
	*
	* @return	array
	*/
	function build_css_array()
	{
		$css = array(
			'main' => array(
				'selectors'	=> array(
					''
				),
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'border_style',
					'border_width',
					'border_color',
					'padding'
				)
			),
			'main_a' => array(
				'selectors' => array(
					'a'
				),
				'properties' => array(
					'linkcolor'
				)
			),

			'text' => array(
				'selectors'	=> array(
					'.block',
					'.blockhead',
					'h2 .blockhead',
					'.blocksubhead',
					'.blockbody',
					'.blockrow',
					'.blockfoot',
					'.alt1',
					'.alt2',
					'.popupmenu',
					'legend',
					'td',
					'th',
					'p',
					'li'
				),
				'properties' => array(
					'font_family',
					'color'
				)
			),

			'shadetext' => array(
				'selectors'	=> array(
					'.shade',
					'.time',
					'legend'
				),
				'properties' => array(
					'shadecolor'
				),
				'overridelink' => 'shadetext_a'
			),
			'shadetext_a' => array(
				'selectors'	=> array(
					'.shade a',
					'.time a'
				),
				'properties' => array(
					'linkcolor'
				),
				'noinputset' => true
			),

			'tableborder' => array(
				'selectors'	=> array(
					'.block',
					'.popupmenu',
				),
				'properties' => array(
					'border_style',
					'border_width',
					'border_color',
					'padding',
					'background_color',
	 				'background_image',
	 				'background_repeat',
				)
			),

			'tabletitle' => array(
				'selectors'	=> array(
					'.blockhead'
				),
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color'
				),
				'overridelink' => 'tabletitle_a'
			),
			'tabletitle_a' => array(
				'selectors'	=> array(
					'.blocksubhead a'
				),
				'properties' => array(
					'linkcolor'
				),
				'noinputset' => true
			),

			'tableheader' => array(
				'selectors'	=> array(
					'.blocksubhead',
				),
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color'
				),
				'overridelink' => 'tableheader_a'
			),
			'tableheader_a' => array(
				'selectors'	=> array(
					'.blocksubhead a',
				),
				'properties' => array(
					'linkcolor'
				),
				'noinputset' => true
			),

			'tablefooter' => array(
				'selectors'	=> array(
					'.blockfoot',
				),
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color'
				),
				'overridelink' => 'tablefooter_a'
			),
			'tablefooter_a' => array(
				'selectors'	=> array(
					'.blockfoot a',
				),
				'properties' => array(
					'linkcolor'
				),
				'noinputset' => true
			),

			'alternating1' => array(
				'selectors'	=> array(
					'.blockrow'
				),
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color',
				)
			),
			'alternating1_a' => array(
				'selectors'	=> array(
					'a'
				),
				'properties' => array(
					'linkcolor'
				)
			),

			'alternating2' => array(
				'selectors'	=> array(
					'.alt2'
				),
				'properties' => array(
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'color',
				)
			),
			'alternating2_a' => array(
				'selectors'	=> array(
					'.alt2 a'
				),
				'properties' => array(
					'linkcolor'
				)
			),

			'inputs' => array(
				'selectors'	=> array(
					'.formcontrols input',
					'.formcontrols select',
					'.formcontrols textarea',
					'formcontrols .button'
					// also styles option and optgroup, but we use a hack to prevent it from applying border styles - see $this->build_css_property()
				),
				'properties' => array(
					'font_family',
					'font_size',
					'color',
					'background_color',
	 				'background_image',
	 				'background_repeat',
					'border_style',
					'border_width',
					'border_color'
				)
			),
		);

		($hook = vBulletinHook::fetch_hook('usercss_build_css_array')) ? eval($hook) : false;

		return $css;
	}

	/**
	* Verifies a padding/margin/border-width (shortcut) property
	*
	* @param	string	Proposed CSS property. May be modified
	*
	* @return	boolean	True if value
	*/
	function verify_box_outline_size($value)
	{
		return preg_match('/^((^|\s+)\d+(\.\d+)?(%|in|cm|mm|em|ex|pt|pc|px)){1,4}$/siU', $value);
	}

	/**
	* Verifies the a border-style property.
	*
	* @param	string	Value to verfiy. May be modified.
	*
	* @return	boolean	True if value.
	*/
	function verify_border_style($value)
	{
		return preg_match('/^(none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset)$/', $value);
	}

	/**
	* Verifies the a font-family property.
	*
	* @param	string	Value to verfiy. May be modified.
	*
	* @return	boolean	True if value.
	*/
	function verify_font_family(&$value)
	{
		return !empty($value);
	}

	/**
	* Verifies the a size property.
	*
	* @param	string	Value to verfiy. May be modified.
	*
	* @return	boolean	True if value.
	*/
	function verify_size($value)
	{
		return preg_match('/^(((([0-9])+\.)?[0-9]+)(%|in|cm|mm|em|ex|pt|pc|px)|xx-small|x-small|smaller|small|medium|large|larger|x-large|xx-large)$/', $value);
	}

	/**
	* Verifies the a color property.
	*
	* @param	string	Value to verfiy. May be modified.
	*
	* @return	boolean	True if value.
	*/
	function verify_color(&$value)
	{
		if (preg_match('/^(#([a-f0-9]{3}){1,2}|\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3})$/siU', $value))
		{
			return true;
		}
		else if (preg_match('/^[a-f0-9]{3}([a-f0-9]{3})?$/siU', $value))
		{
			$value = "#$value";
			return true;
		}
		else
		{
			return preg_match('/^[a-z0-9]+$/siU', $value);
		}
	}

	/**
	* Verifies the an image property. Must come from this user's album and the album must be public/profile.
	*
	* @param	string	Value to verfiy. May be modified.
	*
	* @return	boolean	True if value.
	*/
	function verify_image(&$value)
	{

		if (!($this->registry->options['socnet'] & $this->registry->bf_misc_socnet['enable_albums']))
		{
			$value = '';
			return true;
		}

		$foundalbum = preg_match('#albumid=([0-9]+)#', $value, $albumid);
		$foundpicture = preg_match('#attachmentid=([0-9]+)#', $value, $attachmentid);

		require_once(DIR . '/includes/class_bootstrap_framework.php');
		require_once(DIR . '/vb/types.php');
		vB_Bootstrap_Framework::init();
		$types = vB_Types::instance();
		$contenttypeid = intval($types->getContentTypeID('vBForum_Album'));

		if ($foundalbum AND $foundpicture AND $picture = $this->dbobject->query_first("
			SELECT album.userid
			FROM " . TABLE_PREFIX . "attachment AS a
			INNER JOIN " . TABLE_PREFIX . "album AS album ON (a.contentid = album.albumid)
			WHERE
				a.attachmentid = " . intval($attachmentid[1]) . "
	 				AND
	 			a.contenttypeid = $contenttypeid
	 				AND
	 			album.state IN ('profile', 'public')
	 				AND
	 			album.userid = " . $this->userid . "
	 				AND
	 			album.albumid = " . intval($albumid[1]) . "
	 	"))
	 	{
	 		$value = $albumid[1] . "," . $attachmentid[1];
	 		return true;
	 	}
	 	else
	 	{
	 		return false;
	 	}
	}

	/**
	* Verifies the a background-repeat property.
	*
	* @param	string	Value to verfiy. May be modified.
	*
	* @return	boolean	True if value.
	*/
	function verify_repeat(&$value)
	{
		return preg_match("/^(repeat|no-repeat|repeat-x|repeat-y)$/", $value);
	}

	/**
	* Builds the array for various admin-controlled select options (font sizes, etc).
	* Determines the CSS value and internal phrase key if there is one.
	*
	* @param	string	Raw string. Line break and pipe delimited.
	*
	* @return	array	Array prepared for select building
	*/
	function build_select_option($input_string)
	{
		$lines = preg_split("/(\n|\r\n|\r)/", $input_string, -1, PREG_SPLIT_NO_EMPTY);

		$output = array();
		foreach ($lines AS $line)
		{
			$parts = explode('|', $line);
			$key = trim($parts[0]);
			$value = isset($parts[1]) ? trim($parts[1]) : $key;
			$output["$key"] = $value;
		}

		return $output;
	}

	/**
	* Builds an array for select boxes in the admin CP. This includes the necessary phrasing.
	*
	* @param	string	Raw string. Line break and pipe delimited.
	* @param	string	Prefix for the phrases
	*
	* @return	array	Array prepared for select building
	*/
	function build_admin_select_option($input_string, $phrase_prefix)
	{
		global $vbphrase;

		$options = $this->build_select_option($input_string);

		$output = array('' => '');
		foreach ($options AS $key => $value)
		{
			$output["$value"] = !empty($vbphrase["$phrase_prefix$key"]) ? $vbphrase["$phrase_prefix$key"] : $key;
		}

		return $output;
	}
}


/*======================================================================*\
|| ####################################################################
|| # CVS: $RCSfile$ - $Revision: 32878 $
|| ####################################################################
\*======================================================================*/
?>