emailer.class.php
<?php


if (!defined('IN_DNP'))
{
	die('You\'re not supposed to be here.');
}

/**
* Class to send email. Based on a class by phpBB2.
*/
class emailer
{
	/**
	* Class instance, start of implementing Singleton pattern.
	*
	* private, cannot be accessed directly outside of this class
	*
	* @var object
	*/
	private static $instance;

	/**
	* The email recipient
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @var string
	*/
	private $to;

	/**
	* The email subject
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @var string
	*/
	private $subject;

	/**
	* The email body
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @var string
	*/
	private $body;

	/**
	* Who the email is from
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @var string
	*/
	private $from;

	/**
	* Host/domain
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @var string
	*/
	private $host;

	/**
	* Extra email headers
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @var string
	*/
	private $extra_headers;

	/**
	* Constructor. Sets host and initiates extra_headers.
	*
	* private, cannot be accessed directly outside of this class.
	*
	* @param  void
	* @return void
	*/
	private function __construct()
	{
		$this->host = preg_replace('#^www\.#i', '', dnp_getenv('SERVER_NAME'));
		$this->extra_headers = '';
	}

	/**
	* Creates an instance of the class. We do it this way to try and
	* implement the Singleton pattern.
	*
	* @param  void
	* @return object
	*/
	public static function getInstance()
	{
		if (!self::$instance)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	*/
	private function __clone() {}

	/**
	* Sets email parameters (To, From, and Subject)
	*
	* @param  string  $to       Recipient email
	* @param  string  $from     Who the email is from
	* @param  string  $subject  Subject of the email
	* @return void
	*/
	public function set_params($to, $from, $subject)
	{
		$this->to = trim($to);
		$this->from = trim($from);
		$this->from = (is_null($from)) ? "noreply@{$this->host}" : $this->from;
		$this->subject = trim($subject);
	}

	/**
	* Allows us to set extra headers aside from the standard ones in the send() function.
	*
	* @param  string  $headers  Extra headers seperated by \n
	* @return void
	*/
	public function extra_headers($headers = '')
	{
		$this->extra_headers .= str_replace("\r\n", "\n", $headers);
	}

	/**
	* Allows us to use templates for the email body
	*
	* @param  array   $tpl_vars  An array of var => replacement
	* @param  string  $tpl_file  Template filename
	* @return void
	*/
	public function use_template($tpl_vars, $tpl_file)
	{
		$tpl_file = (defined('IN_ADMIN') ? '..' : '.') . "/templates/$tpl_file";

		if (!is_array($tpl_vars) OR count($tpl_vars) == 0)
		{
			trigger_error('emailer->use_template - <code>$tpl_vars</code> must be an array, or is empty.', E_USER_ERROR);
		}

		if (!is_file($tpl_file))
		{
			trigger_error("emailer->use_template - '<code>$tpl_file</code>' is not a file or does not exist.", E_USER_ERROR);
		}

		if (!($fp = @fopen($tpl_file, 'r')))
		{
			trigger_error("emailer->use_template - Could not open template file: '<code>$tpl_file</code>'", E_USER_ERROR);
		}

		$this->body = fread($fp, filesize($tpl_file));

		foreach ($tpl_vars AS $var => $content)
		{
			$this->body = str_replace('{' . $var . '}', $content, $this->body);
		}
		fclose($fp);
	}

	/**
	* Wrapper of the mail() function, which also sets standard email headers,
	* plus any extra ones we may add in script via the extra_headers() function.
	*
	* @param  void
	* @return boolean  true if the email is sent, false if not.
	*/
	public function send()
	{
		$headers = "From: {$this->from}\n";
		$headers .= "Reply-To: {$this->from}\n";
		$headers .= "Return-Path: {$this->from}\n";
		$headers .= "Sender: {$this->from}\n";
		$headers .= "Message-ID: <" . dnp_hash(uniqid(time())) . "@{$this->host}>\n";
		$headers .= "MIME-Version: 1.0\n";
		$headers .= "Content-type: text/plain; charset=8859-9\n";
		$headers .= "Content-transfer-encoding: 8bit\n";
		$headers .= "Date: " . date('r', time()) . "\n";
		$headers .= "X-Priority: 3\n";
		$headers .= "X-MSMail-Priority: Normal\n";
		$headers .= "X-Mailer: Domain Name Portfolio via PHP/" . PHP_VERSION . "\n";
		$headers .= "X-MimeOLE: Produced By Domain Name Portfolio\n";

		if ($this->extra_headers != '')
		{
			$headers .= trim($this->extra_headers) . "\n";
		}

		if (@mail($this->to, $this->subject, $this->body, $headers))
		{
			return true;
		}
		return false;
	}
}

?>
functions.php
<?php



if (!defined('IN_DNP'))
{
	die('You\'re not supposed to be here.');
}

/**
* Strip any unsafe tags/chars/attributes from input values.
*
* @param  string   $value       Value to be cleaned
* @param  boolean  $strip_crlf  Strip \r\n ?
* @param  boolean  $is_email    If the value is an email, pass it through the email sanitize filter.
* @return string                Sanitized value.
*/
function sanitize($value, $strip_crlf = true, $is_email = false)
{
	$value = preg_replace('@&(?!(#[0-9]+|[a-z]+);)@si', '', $value);

	if ($is_email)
	{
		/**
		* PHP versions older than 5.2.11 have bugs in FILTER_SANITIZE_EMAIL
		* It allows characters that shouldn't be allowed.
		*
		* We will only sanitize the email if they are using 5.2.11 and greater.
		* This shouldn't pose a problem on < 5.2.11 cause we validate the email
		* later on anyway.
		*/
		if (version_compare(PHP_VERSION, '5.2.11', '>='))
		{
			$value = filter_var($value, FILTER_SANITIZE_EMAIL);
		}
	}
	else
	{
		$value = filter_var($value, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
	}

	// This will strip new line characters if $strip_crlf is set to true.
	if ($strip_crlf)
	{
		$value = preg_replace('@([\r\n])[\s]+@', '', $value);
	}

	return clean($value);
}

/**
* Clean values pulled from the database, although could be used on anything.
*
* Cleans either a string, or can clean an entire array of values:
*	clean($array);
*
* @param  mixed  $value  Value to be cleaned
* @return mixed          Cleaned array or string.
*/
function clean($value)
{
	if (is_array($value))
	{
		foreach ($value AS $key => $val)
		{
			if (is_string($val))
			{
				$value["$key"] = trim(stripslashes($val));
			}
			else if (is_array($val))
			{
				$value["$key"] = clean($value["$key"]);
			}
		}
		return $value;
	}
	return trim(stripslashes($value));
}

/**
* Will make sure a variable is valid.
*
* @param  string  $option  What to check
* @param  mixed   $value   What to check's value.
* @return mixed            Depending on the $option, could return a string, NULL, or boolean.
*/
function is($option, $value)
{
	global $db;

	switch ($option)
	{
		case 'orderby':
			if (!in_array($value, array('domain', 'category', 'registrar', 'regdate', 'expiry', 'price', 'status')))
			{
				return 'domain';
			}
			break;
		case 'catid':
			if (is_string($value))
			{
				return NULL;
			}
			else if (is_integer($value) AND !is('category', $value))
			{
				return NULL;
			}
			break;
		case 'email':
			return (bool)(preg_match('#^[a-z0-9.!\#$%&\'*+-/=?^_`{|}~]+@([0-9.]+|([^\s\'"<>]+\.+[a-z]{2,6}))$#si', $value));
			break;
		case 'injection':
			return (bool)(preg_match('#(To:|Bcc:|Cc:|Content-type:|Mime-version:|Content-Transfer-Encoding:)#i', urldecode($value)));
			break;
		case 'spam':
			preg_match_all('#(<a href|\[url|http[s]?://)#i', $value, $matches, PREG_PATTERN_ORDER);
			return (bool)(count($matches[0]) > 2);
			break;
		case 'domain':
			$getdomain = $db->query("
				SELECT *
				FROM " . TABLE_PREFIX . "domains
				WHERE " . (is_numeric($value) ? "domainid = " . intval($value) : "domain = '$value'") . "
			");

			$numrows = $db->num_rows($getdomain);
			$db->free_result($getdomain);

			return (bool)($numrows > 0);
			break;
		case 'category':
			if (is_numeric($value) AND $value == 0)
			{
				return true;
			}

			$getcategory = $db->query("
				SELECT *
				FROM " . TABLE_PREFIX . "categories
				WHERE " . (is_numeric($value) ? "catid = " . intval($value) : "title = '$category'") . "
			");

			$numrows = $db->num_rows($getcategory);
			$db->free_result($getcategory);

			return (bool)($numrows > 0);
			break;
		case 'expdate':
			$value = str_replace('-', '/', $value);

			// Expects mm/dd/yyyy Example: 8/30/2009
			if (preg_match('#[0-9]{2}/[0-9]{2}/[0-9]{4}#', $value))
			{
				$value = explode('/', $value);

				if ($value[2] < date('Y'))
				{
					return false;
				}

				if (checkdate($value[0], $value[1], $value[2]))
				{
					return true;
				}
			}
			return false;
			break;
	}
	return $value;
}

/**
* Get the users ip address.
*
* @param  void
* @return string  IP Address
*/
function get_ip()
{
	$ip = dnp_getenv('REMOTE_ADDR');

	if (dnp_getenv('HTTP_X_FORWARDED_FOR'))
	{
		if (preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', dnp_getenv('HTTP_X_FORWARDED_FOR'), $matches))
		{
			foreach ($matches[0] AS $match)
			{
				if (!preg_match('#^(10|172\.16|192\.168)\.#', $match))
				{
					$ip = $match;
					break;
				}
			}
			unset($matches);
		}
	}
	else if (dnp_getenv('HTTP_CLIENT_IP'))
	{
		$ip = dnp_getenv('HTTP_CLIENT_IP');
	}
	else if (dnp_getenv('HTTP_FROM'))
	{
		$ip = dnp_getenv('HTTP_FROM');
	}

	if (!filter_var($ip, FILTER_VALIDATE_IP))
	{
		return '0.0.0.0';
	}
	return $ip;
}

/**
* Returns an environment variable.
*
* @param  string  $varname  Variable name, eg: PHP_SELF
* @return string            Variable's value.
*/
function dnp_getenv($varname)
{
	if (isset($_SERVER[$varname]))
	{
		return $_SERVER[$varname];
	}
	else if (isset($_ENV[$varname]))
	{
		return $_ENV[$varname];
	}
	return '';
}

/**
* A wrapper for date that will format dates using the UTC timezone.
* This is used for domain expiration dates as UTC is pretty much 
* the standard for domain expiration dates.
*
* @param  string   $format     Date format
* @param  integer  $timestamp  Unix timestamp
* @return string               Formatted date
*/
function dnp_date($format, $timestamp)
{
	if (empty($timestamp))
	{
		$timestamp = time();
	}

	// Get the current timezone
	$current_tz = date_default_timezone_get();

	// Set to UTC, as that's pretty much the standard for domain expiration
	date_default_timezone_set('UTC');

	// format the time
	$date = date($format, $timestamp);

	// Set back to old timezone
	date_default_timezone_set($current_tz);

	return $date;
}

/**
* Returns a md5'ed hash.
*
* @param  string  $string  String to hash
* @return string  Hash
*/
function dnp_hash($string)
{
	return hash('md5', $string);
}

/**
* Helper function for encode_email
*
* @param  string  $char  Character to encode.
* @return string         Encoded character.
*/
function _encode_email_helper($char = 0)
{
	return '&#' . ord($char) . ';';
}

/**
* Encodes an email address, if that email is valid.
*
* At this time, this will mainly be used on database error pages, that
* places the email address in HTML.
*
* @param  string  $email  Email address to encode.
* @return string          Encoded email address if valid, or plain email if not valid.
*/
function encode_email($email)
{
	if (is('email', $email))
	{
		$chars = str_split($email);

		$encoded = filter_var($chars, FILTER_CALLBACK, array('options' => '_encode_email_helper'));
		$encoded = implode('', $encoded);

		unset($chars);

		return $encoded;
	}
	return $email;
}

/**
* Redirects to another URL.
*
* @param  string  $url  Destination url
* @return void
*/
function redirect($url)
{
	if (count($_SESSION))
	{
		session_write_close();
	}

	$url = filter_var($url, FILTER_SANITIZE_URL);

	header("Location: $url", true, 302);
	exit;
}

/**
* Generates the pagination.
*
* @param  integer  $numresults  Total number of results.
* @param  integer  $page        Current page
* @param  string   $orderby     Sort order
* @param  integer  $catid       Category ID (if any)
* @param  string   $search      Search query (will only be used for search.php)
* @return array                 Array consisting of SQL limit, and pagination links.
*/
function paginate($numresults, $page, $orderby = NULL, $catid = NULL, $search = NULL)
{
	//Generate image path according to calling script
    
    if(substr($_SERVER[REQUEST_URI],-13,-1)=='portfolio.ph'){
        $_navigationimg='./templates/default/images';        
    }else{
        $_navigationimg='../templates/admin/images';
    }

    global $config;

	$usedefault = (bool)($config->get('template') == 'default' AND !defined('IN_ADMIN'));
	$link = '';
	$extra = array();

	if ($numresults > 0)
	{
		$perpage = ($config->get('maxperpage') <= 10) ? 10 : $config->get('maxperpage');
		$numpages = ceil($numresults / $perpage);
		$numpages = ($numpages == 0) ? 1 : $numpages;
		$page = ($page < 1) ? 1 : ($page > $numpages ? $numpages : $page);

		$page1 = "1";
		$pageb = $page - 1;
		//$pageback = $pageb ? $pageb : ($page > $numpages ? $numpages : $page);
		$pagef = $page + 1;
		//$pageforward = $pagef <= $numpages ? $pagef : ($page <= $numpages ? $numpages : $page);

		// Currently using sort?
		if (!is_null($orderby))
		{
			array_push($extra, "&amp;sort=$orderby");
		}

		// Browsing a category?
		if (!is_null($catid))
		{
			array_push($extra, "&amp;cat=$catid");
		}

		// Searching?
		if (!is_null($search))
		{
			array_push($extra, '&amp;query=' . urlencode($search));
		}

		$extra = implode('', $extra);

		// Generate Links - I know, it looks messy, but it works :P
		// It'll be something like: 1 ... 4 5 6 7 8 ... 15
		if ($page >= 1)
		{
			$link .= " <a href=\"?page=$page1$extra\"><img src=\"$_navigationimg/first.png\" class=\"fix2\" title=\"<<\"/></a>";
		}
			
			//if ($page >= ($pageback) AND $page != ($pageback))
			if ($page >= ($pageb) AND $page != ($pageb))
		{
			//$link .= " <a href=\"?page=$pageback$extra\"><img src=\"../templates/admin/images/prev.png\" class=\"fix2\" title=\"<\"/></a>&nbsp;";
			$link .= " <a href=\"?page=$pageb$extra\"><img src=\"$_navigationimg/prev.png\" class=\"fix2\" title=\"<\"/></a>&nbsp;";
		}

		for ($i = ($page - 1), $stop = ($page + 7); $i <= $stop; ++$i)
		{
			if ($i < 1 OR $i > $numpages)
			{
				continue;
			}

			if ($page == $i)
			{
				//$link .= ($usedefault) ? " $i " : " [$i] ";
				$link .= "<span class=\"current\">$i</span>";
			}
			else
			{
				$link .= " <span class=\"numberfix\"><a href=\"?page=$i$extra\">$i</a></span> ";
			}
		}

		//if ($page <= ($pageforward) AND $page != ($pageforward))
		if ($page <= ($pagef) AND $page != ($pagef))
		{
			//$link .= " <a href=\"?page=$pageforward$extra\"><img src=\"../templates/admin/images/next.png\" class=\"fix2\" title=\">\"/></a>";
			$link .= " <a href=\"?page=$pagef$extra\"><img src=\"$_navigationimg/next.png\" class=\"fix2\" title=\">\"/></a>";
		}

		if ($page <= $numpages)
		{
			$link .= " <a href=\"?page=$numpages$extra\"><img src=\"$_navigationimg/last.png\" class=\"fix2\" title=\">>\"/></a>";
		}

		$lowerlimit = ($page - 1) * $perpage + 1;
		$upperlimit = $page * $perpage;

		if ($upperlimit > $numresults)
		{
			$upperlimit = $numresults;

			if ($lowerlimit > $numresults)
			{
				$lowerlimit = $numresults - $perpage;
			}
		}

		if ($lowerlimit <= 0)
		{
			$lowerlimit = 1;
		}
	}
	else
	{
		$lowerlimit = 1;
		$link = '';
	}

	return array(
		'limit' => $lowerlimit - 1,
		'link'  => $link
	);
}

/**
* Builds the HTML for categories and latest domains added.
*
* @param  string  $list  Which list to build.
* @return string         List HTML
*/
function build_list($list)
{
	global $db, $config;

	$uselegacy = (bool)($config->get('template') == 'legacy');

	switch ($list)
	{
		case 'cats':
			$getcats = $db->query("
				SELECT catid, title, description
				FROM " . TABLE_PREFIX . "categories
				ORDER BY title ASC
			") or $db->raise_error();

			if ($db->num_rows($getcats) > 0)
			{
				$class = '';

				while ($cat = $db->fetch_array($getcats))
				{
					$class = ($class == '') ? ' class="odd"' : '';

					$cat['description'] = ($cat['description'] != '') ? $cat['description'] : $cat['title'];

					$cat['numdomains'] = $db->query("
						SELECT COUNT(d2c.domainid) AS count
						FROM " . TABLE_PREFIX . "dom2cat AS d2c
						LEFT JOIN " . TABLE_PREFIX . "domains AS dom ON(dom.domainid = d2c.domainid)
						WHERE d2c.catid = $cat[catid]
							AND dom.hidden != 1
					", true);
					$cat['numdomains'] = $cat['numdomains']['count'];

					if ($uselegacy)
					{
						$listhtml .= "<a href=\"./portfolio.php?cat=$cat[catid]\" title=\"$cat[description]\">".substr($cat[title],0,16)." ($cat[numdomains])</a>\n";
					}
					else
					{
						$listhtml .= "<li><a href=\"./portfolio.php?cat=$cat[catid]\" title=\"$cat[description]\">".substr($cat[title],0,16)." <span style=\"color:#000;\">($cat[numdomains])&nbsp;&nbsp;&nbsp;</span></a></li>\n";
					}
					$listhtml = trim($listhtml);
				}
			}
			else
			{
				$listhtml = ($uselegacy) ? 'No Categories Yet' : '<span>No Categories Yet</span>';
			}
			$db->free_result($getcats);

			return trim($listhtml);
			break;
		case 'latest':
			$getlatest = $db->query("
				SELECT domainid, domain, added
				FROM " . TABLE_PREFIX . "domains
				WHERE hidden != 1
				ORDER BY added DESC
				LIMIT 5
			") or $db->raise_error();

			if ($db->num_rows($getlatest) == 0)
			{
				$listhtml = ($uselegacy) ? '&nbsp;- None' : '<li>None</li>';

			}
			else
			{
				$class = '';

				while ($latest = $db->fetch_array($getlatest))
				{
					$date = date('m/d/Y', $latest['added']);

					if ($uselegacy)
					{
						$listhtml .= "<a href=\"details.php?d=$latest[domainid]\" title=\"Details for $latest[domain]\">$latest[domain] ($date)</a>\n";
					}
					else
					{
						$listhtml .= "<li$class><a href=\"details.php?d=$latest[domainid]\" title=\"Details for $latest[domain]\">$latest[domain]</a> ($date)</li>\n";
					}
					$listhtml = trim($listhtml);

					$class = ($class == '') ? ' class="odd"' : '';
				}
			}
			$db->free_result($getlatest);

			return trim($listhtml);
			break;
		default:
			break;
	}
}

/**
* Gets current page name.
*
* @param  void
* @return string  Current page name.
*/
function dnp_page()
{
	$page = basename($_SERVER['SCRIPT_FILENAME'], '.php');

	if (empty($page) OR $page == 'index')
	{
		$page = 'home';
	}
	return $page;
}

/**
* Gets the latest version of Domain Name Portfolio.
* Borrowed from phpBB and modified - phpBB.com
*
* @param  boolean  $check  Check domainportfolio.us for latest version?
* @return string           Latest version if $check is true, current script version if not.
*/
function dnp_version($check = false)
{
	if ($check)
	{
		if ($fsock = @fsockopen('www.DNSPortfolio.com', 80, $errno, $errstr, 10))
		{
			fputs($fsock, "GET /current.txt HTTP/1.1\r\nHOST: www.DNSPortfolio.com\r\nConnection: close\r\n\r\n");

			$latest = '';
			$getinfo = false;

			while (!feof($fsock))
			{
				if ($getinfo)
				{
					$latest .= fread($fsock, 1024);
				}
				else
				{
					if (fgets($fsock, 1024) == "\r\n")
					{
						$getinfo = true;
					}
				}
			}
			fclose($fsock);

			$latest = array_map('trim', explode("\n", $latest));

			return implode('.', $latest);
		}
		return 'n/a';
	}
	else
	{
		return '1.7.0';
	}
}

/**
* Will get values from the database for forms, etc.
*
* @param  string   $option  What do we need the value for?
* @param  integer  $id      If it's for a domain or category (by ID)
* @return array             Data for given $option from the database.
*/
function get_value($option, $id = 0)
{
	global $db;

	switch ($option)
	{
		case 'contact':
			$domaininfo = $db->query("
				SELECT domain, status
				FROM " . TABLE_PREFIX . "domains
				WHERE " . (is_numeric($id) ? "domainid = '" . intval($id) . "'" : "domain = '$id'") . "
					AND hidden != 1
			", true) or $db->raise_error();
			return $domaininfo;
			break;
		case 'details':
		case 'domainedit':
			$domaininfo = $db->query("
				SELECT domains.*, d2c.*, IF(categories.title IS NULL, 'None', GROUP_CONCAT(categories.title SEPARATOR ', ')) AS category, domains.domainid AS domainid
				FROM " . TABLE_PREFIX . "domains AS domains
				LEFT JOIN " . TABLE_PREFIX . "dom2cat AS d2c ON (domains.domainid = d2c.domainid)
				LEFT JOIN " . TABLE_PREFIX . "categories AS categories ON (d2c.catid = categories.catid)
				WHERE " . (is_numeric($id) ? "domains.domainid = '" . intval($id) . "'" : "domains.domain = '$id'") . "
				GROUP BY COALESCE(d2c.domainid, RAND())
			", true) or $db->raise_error();
			return (count($domaininfo)) ? $domaininfo : array();
			break;
		case 'catedit':
			$catinfo = $db->query("
				SELECT title, description, keywords
				FROM " . TABLE_PREFIX . "categories
				WHERE catid = '$id'
			", true) or $db->raise_error();
			return (count($catinfo)) ? $catinfo : array();
			break;
		default:
			break;
	}
}

/**
* Builds the 'hide' dropdown menu in admin for the edit page.
*
* @param  string  $option  Which select to build.
* @param  string  $value   Select's value.
* @return string           The $option's HTML
*/
function build_select($option, $value = '')
{
	global $db;

	$values = array(
		'hidden' => array('No', 'Yes'),
		'issite' => array('No', 'Yes'),
		'status' => array('For Sale', 'Not For Sale', 'Make Offer', 'Sold')
	);

	$select = '';

	switch ($option)
	{
		case 'hidden':
		case 'issite':
			foreach ($values[$option] AS $key => $val)
			{
				$select .= "<option label=\"$val\" value=\"$key\"" . ($value == $key ? ' selected="selected"' : '') . ">$val</option>\n";
			}
			break;
		case 'status':
			foreach ($values[$option] AS $val)
			{
				$select .= "<option label=\"$val\" value=\"$val\"" . ($value == $val ? ' selected="selected"' : '') . ">$val</option>\n";
			}
			break;
		case 'category':
			//$select = '<option label="No Category" value=\"$cat[catid]\" selected="selected">No Category</option>' . "\n";

			$getcats = $db->query("
				SELECT catid, title
				FROM " . TABLE_PREFIX . "categories
				ORDER BY title ASC
			") or $db->raise_error();

			while ($cat = $db->fetch_array($getcats))
			{
				if ($value == '')
				{
					$select .= "<option label=\"$cat[title]\" value=\"$cat[catid]\">$cat[title]</option>\n";
				}
				else
				{
					$dom2cats = $db->fetch_all("
						SELECT domainid, catid
						FROM " . TABLE_PREFIX . "dom2cat
						WHERE domainid = $value
					", 'catid');

					$select .= "<option label=\"$cat[title]\" value=\"$cat[catid]\"";
					$select .= (in_array($cat['catid'], $dom2cats) ? ' selected="selected"' : '') . ">$cat[title]</option>\n";

				}
			}
			$db->free_result($getcats);
			break;
	}
	return $select;
}

/**
* Returns a 'nice', human-readable size - thanks to WordPress
*
* @param  integer  $bytes  Size to format
* @return string           Human-readable size.
*/
function size_format($bytes)
{
	$quant = array(
		'TB' => pow(1024, 4),
		'GB' => pow(1024, 3),
		'MB' => pow(1024, 2),
		'kB' => pow(1024, 1),
		'B'  => pow(1024, 0)
	);

	foreach ($quant AS $unit => $mag)
	{
		if (intval($bytes) >= $mag)
		{
			return number_format($bytes / $mag) . " $unit";
		}
	}
	return '-';
}

?>