<commit_before><?php

if ( ! defined('EXT'))
{
	exit('Invalid file request');
}

/**
 * Seamlessly integrate Amazon S3 with your ExpressionEngine website.
 *
 * @package   	BucketList
 * @version   	1.0.0
 * @author    	<NAME> <<EMAIL>>
 * @copyright 	Copyright (c) 2009, <NAME>
 * @link      	http://eepro.co.uk/bucketlist/
 */

require_once 'resources/S3.php';

class Bucketlist extends Fieldframe_Fieldtype {
  
	/**
	 * Basic fieldtype information.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $info = array(
		'name'				=> 'BucketList',
		'version'			=> '1.0.0',
		'desc'				=> 'Seamlessly integrate Amazon S3 with your ExpressionEngine site.',
		'docs_url'			=> 'http://eepro.co.uk/bucketlist/',
		'versions_xml_url'	=> 'http://eepro.co.uk/addon-versions.xml'
	);

	/**
	 * Fieldtype requirements.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $requirements = array(
		'ff'        => '1.3.4',
		'cp_jquery' => '1.1'
	);
  
	/**
	 * Fieldtype extension hooks.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $hooks = array('sessions_start');
  
	/**
	 * Default site settings.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $default_site_settings = array(
		'access_key_id'		=> '',
		'allow_upload'		=> 'y',
		'secret_access_key'	=> '',
		'cache_duration' 	=> '3600',		// 60 minutes
		'use_ssl' 			=> 'n',
		'custom_url'		=> 'n'
	);
	
	/**
	 * The site ID.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $site_id = '';
	
	/**
	 * The class name.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $class = '';
	
	/**
	 * Lower-class classname.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $lower_class = '';
	
	/**
	 * The Session namespace.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $namespace = '';


	/**
	 * ----------------------------------------------------------------
	 * PRIVATE METHODS
	 * ----------------------------------------------------------------
	 */
	
	/**
	 * Checks that the S3 credentials have been set. Makes not attempt to check their validity.
	 *
	 * @access  private
	 * @return  bool
	 */
	function _check_s3_credentials()
	{
		return (isset($this->site_settings['access_key_id'])
			&& $this->site_settings['access_key_id'] !== ''
			&& isset($this->site_settings['secret_access_key'])
			&& $this->site_settings['secret_access_key'] !== '');
	}
	
	
	/**
	 * Checks whether the specified item exists on the S3 server.
	 *
	 * @access	private
	 * @param	string		$item_name		The full item path and name, including the bucket.
	 * @return	bool
	 */
	function _item_exists_on_s3($item_name = '')
	{
		// Clearly not, muppet.
		if ( ! $item_name)
		{
			return FALSE;
		}
		
		// Separate out the bucket name.
		$bucket_and_path = $this->_split_bucket_and_path_string($item_name);
		
		if ( ! $bucket_and_path['bucket'])
		{
			return FALSE;
		}
		
		// Make the call.
		$s3 = new S3($this->site_settings['access_key_id'], $this->site_settings['secret_access_key'], FALSE);
		return @$s3->getObjectInfo($bucket_and_path['bucket'], $bucket_and_path['item_path'], FALSE);
		
	}
	
	
	/**
	 * Validates the structure of an 'item' array. Returns a valid item array, with any extraneous
	 * information stripped out, or FALSE.
	 *
	 * @access	private
	 * @param 	array 			$item		The item to validate.
	 * @return 	array|bool
	 */
	function _validate_item($item = array())
	{
		if ( ! $item OR ! is_array($item))
		{
			return FALSE;
		}
		
		$default_item = array(
			'item_extension'	=> '',
			'item_is_folder'	=> '',
			'item_name'			=> '',
			'item_path'			=> '',
			'item_size'			=> ''
		);
		
		$item = array_merge($default_item, $item);
		
		/**
		 * Item extension is optional in this first check, as folders don't have one.
		 */
		
		$required_fields 	= array('item_is_folder', 'item_name', 'item_path', 'item_size');
		$valid_item 		= array();
		$missing_field		= FALSE;
		
		foreach ($required_fields AS $field_id)
		{
			if ($field_id != 'item_size' && ( ! is_string($item[$field_id]) OR $item[$field_id] == ''))
			{
				$missing_field = TRUE;
				break;
			}
			
			$valid_item[$field_id] = $item[$field_id];
		}
		
		// One last check. Files need extension.
		if (strtolower($valid_item['item_is_folder']) != 'y' && ( ! is_string($item['item_extension']) OR $item['item_extension'] == ''))
		{
			$missing_field = TRUE;
		}
		else
		{
			$valid_item['item_extension'] = strtolower($item['item_extension']);
		}
		
		if ($missing_field)
		{
			return FALSE;
		}
		else
		{
			// Bit of cleaning up, and we'll be done.
			$valid_item['item_is_folder'] 	= strtolower($valid_item['item_is_folder']);
			$valid_item['item_size']		= intval($valid_item['item_size']);
			
			return $valid_item;
		}
	}
	
	
	/**
	 * Parses a single Amazon S3 item, representing a single item of content in a bucket.
	 *
	 * @access	private
	 * @param	array		$s3_item	The S3 item to parse.
	 * @return	array
	 */
	function _parse_item_s3_result($s3_item = array())
	{
		// Steady butt.
		if ( ! $s3_item OR ! is_array($s3_item))
		{
			return array();
		}
		
		// Do we have the required information?
		$required_fields 	= array('name', 'time', 'size', 'hash');
		$item 				= array();
		$missing_field		= FALSE;
		
		foreach ($required_fields AS $field_id)
		{
			if ( ! array_key_exists($field_id, $s3_item) OR (is_string($s3_item[$field_id]) && $s3_item[$field_id] == ''))
			{
				$missing_field = TRUE;
				break;
			}
		}
		
		if ($missing_field)
		{
			return array();
		}
		
		// Extract the information we require.
		$item = array(
			'item_extension'	=> pathinfo($s3_item['name'], PATHINFO_EXTENSION),
			'item_is_folder'	=> (substr($s3_item['name'], -1) == '/') ? 'y' : 'n',
			'item_name'			=> pathinfo($s3_item['name'], PATHINFO_BASENAME),
			'item_path'			=> $s3_item['name'],
			'item_size'			=> intval($s3_item['size'])
		);
		
		return $item;
	}
	
	
	/**
	 * Validates the structure of a 'bucket' array. Returns a valid item array, with any extraneous
	 * information stripped out, or FALSE.
	 *
	 * @access	private
	 * @param 	array 			$bucket		The bucket to validate.
	 * @return 	array|bool
	 */
	function _validate_bucket($bucket = array())
	{
		if ( ! $bucket OR ! is_array($bucket))
		{
			return FALSE;
		}
		
		// Do we have the required information?
		$required_fields 	= array('bucket_id', 'bucket_items_cache_date', 'bucket_name', 'site_id');
		$valid_bucket 		= array();
		$missing_field		= FALSE;
		
		foreach ($required_fields AS $field_id)
		{
			if ( ! array_key_exists($field_id, $bucket))
			{
				$missing_field = TRUE;
				break;
			}
			
			$valid_bucket[$field_id] = $bucket[$field_id];
		}
		
		return ($missing_field ? FALSE : $valid_bucket);
	}
	
	
	/**
	 * Retrieves an item based on the saved field data.
	 *
	 * @access	private
	 * @param	string			$field_data		The saved field data (a full item path, including bucket).
	 * @return	array|bool
	 */
	function _load_item_using_field_data($field_data = '')
	{
		global $DB;
		
		if ( ! $field_data)
		{
			return FALSE;
		}
		
		// Trim the bucket from the start of the field data.
		if ($bucket_and_path = $this->_split_bucket_and_path_string($field_data))
		{
			$db_item = $DB->query("SELECT item_extension, item_is_folder, item_name, item_path, item_size
				FROM exp_bucketlist_items AS items
				INNER JOIN exp_bucketlist_buckets AS buckets
				ON buckets.bucket_id = items.bucket_id
				WHERE buckets.bucket_name = '" .$DB->escape_str($bucket_and_path['bucket']) ."'
				AND items.item_path = '" .$DB->escape_str($bucket_and_path['item_path']) ."'
				LIMIT 1");
			
			if ($db_item->num_rows == 1 && $item = $this->_validate_item($db_item->row))
			{
				return $item;
			}
		}
		
		return FALSE;
	}
	
	
	/**
	 * Retrieves all the buckets from the database.
	 *
	 * @access	private
	 * @return 	array
	 */
	function _load_all_buckets_from_db()
	{
		global $DB;
		
		$db_buckets = $DB->query("SELECT
				bucket_id, bucket_items_cache_date, bucket_name, site_id
			FROM exp_bucketlist_buckets
			WHERE site_id = '{$this->site_id}'");
			
		if ($db_buckets->num_rows == 0)
		{
			return array();
		}
		
		// Initialise the return array.
		$buckets = array();<commit_msg>Added ORDER BY clause when retrieving buckets from database, to ensure they are ordered alphabetically.<commit_after><?php

if ( ! defined('EXT'))
{
	exit('Invalid file request');
}

/**
 * Seamlessly integrate Amazon S3 with your ExpressionEngine website.
 *
 * @package   	BucketList
 * @version   	1.0.0
 * @author    	<NAME> <<EMAIL>>
 * @copyright 	Copyright (c) 2009, <NAME>
 * @link      	http://eepro.co.uk/bucketlist/
 */

require_once 'resources/S3.php';

class Bucketlist extends Fieldframe_Fieldtype {
  
	/**
	 * Basic fieldtype information.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $info = array(
		'name'				=> 'BucketList',
		'version'			=> '1.0.0',
		'desc'				=> 'Seamlessly integrate Amazon S3 with your ExpressionEngine site.',
		'docs_url'			=> 'http://eepro.co.uk/bucketlist/',
		'versions_xml_url'	=> 'http://eepro.co.uk/addon-versions.xml'
	);

	/**
	 * Fieldtype requirements.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $requirements = array(
		'ff'        => '1.3.4',
		'cp_jquery' => '1.1'
	);
  
	/**
	 * Fieldtype extension hooks.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $hooks = array('sessions_start');
  
	/**
	 * Default site settings.
	 *
	 * @access	public
	 * @var 	array
	 */
	public $default_site_settings = array(
		'access_key_id'		=> '',
		'allow_upload'		=> 'y',
		'secret_access_key'	=> '',
		'cache_duration' 	=> '3600',		// 60 minutes
		'use_ssl' 			=> 'n',
		'custom_url'		=> 'n'
	);
	
	/**
	 * The site ID.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $site_id = '';
	
	/**
	 * The class name.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $class = '';
	
	/**
	 * Lower-class classname.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $lower_class = '';
	
	/**
	 * The Session namespace.
	 *
	 * @access	private
	 * @var 	string
	 */
	private $namespace = '';


	/**
	 * ----------------------------------------------------------------
	 * PRIVATE METHODS
	 * ----------------------------------------------------------------
	 */
	
	/**
	 * Checks that the S3 credentials have been set. Makes not attempt to check their validity.
	 *
	 * @access  private
	 * @return  bool
	 */
	function _check_s3_credentials()
	{
		return (isset($this->site_settings['access_key_id'])
			&& $this->site_settings['access_key_id'] !== ''
			&& isset($this->site_settings['secret_access_key'])
			&& $this->site_settings['secret_access_key'] !== '');
	}
	
	
	/**
	 * Checks whether the specified item exists on the S3 server.
	 *
	 * @access	private
	 * @param	string		$item_name		The full item path and name, including the bucket.
	 * @return	bool
	 */
	function _item_exists_on_s3($item_name = '')
	{
		// Clearly not, muppet.
		if ( ! $item_name)
		{
			return FALSE;
		}
		
		// Separate out the bucket name.
		$bucket_and_path = $this->_split_bucket_and_path_string($item_name);
		
		if ( ! $bucket_and_path['bucket'])
		{
			return FALSE;
		}
		
		// Make the call.
		$s3 = new S3($this->site_settings['access_key_id'], $this->site_settings['secret_access_key'], FALSE);
		return @$s3->getObjectInfo($bucket_and_path['bucket'], $bucket_and_path['item_path'], FALSE);
		
	}
	
	
	/**
	 * Validates the structure of an 'item' array. Returns a valid item array, with any extraneous
	 * information stripped out, or FALSE.
	 *
	 * @access	private
	 * @param 	array 			$item		The item to validate.
	 * @return 	array|bool
	 */
	function _validate_item($item = array())
	{
		if ( ! $item OR ! is_array($item))
		{
			return FALSE;
		}
		
		$default_item = array(
			'item_extension'	=> '',
			'item_is_folder'	=> '',
			'item_name'			=> '',
			'item_path'			=> '',
			'item_size'			=> ''
		);
		
		$item = array_merge($default_item, $item);
		
		/**
		 * Item extension is optional in this first check, as folders don't have one.
		 */
		
		$required_fields 	= array('item_is_folder', 'item_name', 'item_path', 'item_size');
		$valid_item 		= array();
		$missing_field		= FALSE;
		
		foreach ($required_fields AS $field_id)
		{
			if ($field_id != 'item_size' && ( ! is_string($item[$field_id]) OR $item[$field_id] == ''))
			{
				$missing_field = TRUE;
				break;
			}
			
			$valid_item[$field_id] = $item[$field_id];
		}
		
		// One last check. Files need extension.
		if (strtolower($valid_item['item_is_folder']) != 'y' && ( ! is_string($item['item_extension']) OR $item['item_extension'] == ''))
		{
			$missing_field = TRUE;
		}
		else
		{
			$valid_item['item_extension'] = strtolower($item['item_extension']);
		}
		
		if ($missing_field)
		{
			return FALSE;
		}
		else
		{
			// Bit of cleaning up, and we'll be done.
			$valid_item['item_is_folder'] 	= strtolower($valid_item['item_is_folder']);
			$valid_item['item_size']		= intval($valid_item['item_size']);
			
			return $valid_item;
		}
	}
	
	
	/**
	 * Parses a single Amazon S3 item, representing a single item of content in a bucket.
	 *
	 * @access	private
	 * @param	array		$s3_item	The S3 item to parse.
	 * @return	array
	 */
	function _parse_item_s3_result($s3_item = array())
	{
		// Steady butt.
		if ( ! $s3_item OR ! is_array($s3_item))
		{
			return array();
		}
		
		// Do we have the required information?
		$required_fields 	= array('name', 'time', 'size', 'hash');
		$item 				= array();
		$missing_field		= FALSE;
		
		foreach ($required_fields AS $field_id)
		{
			if ( ! array_key_exists($field_id, $s3_item) OR (is_string($s3_item[$field_id]) && $s3_item[$field_id] == ''))
			{
				$missing_field = TRUE;
				break;
			}
		}
		
		if ($missing_field)
		{
			return array();
		}
		
		// Extract the information we require.
		$item = array(
			'item_extension'	=> pathinfo($s3_item['name'], PATHINFO_EXTENSION),
			'item_is_folder'	=> (substr($s3_item['name'], -1) == '/') ? 'y' : 'n',
			'item_name'			=> pathinfo($s3_item['name'], PATHINFO_BASENAME),
			'item_path'			=> $s3_item['name'],
			'item_size'			=> intval($s3_item['size'])
		);
		
		return $item;
	}
	
	
	/**
	 * Validates the structure of a 'bucket' array. Returns a valid item array, with any extraneous
	 * information stripped out, or FALSE.
	 *
	 * @access	private
	 * @param 	array 			$bucket		The bucket to validate.
	 * @return 	array|bool
	 */
	function _validate_bucket($bucket = array())
	{
		if ( ! $bucket OR ! is_array($bucket))
		{
			return FALSE;
		}
		
		// Do we have the required information?
		$required_fields 	= array('bucket_id', 'bucket_items_cache_date', 'bucket_name', 'site_id');
		$valid_bucket 		= array();
		$missing_field		= FALSE;
		
		foreach ($required_fields AS $field_id)
		{
			if ( ! array_key_exists($field_id, $bucket))
			{
				$missing_field = TRUE;
				break;
			}
			
			$valid_bucket[$field_id] = $bucket[$field_id];
		}
		
		return ($missing_field ? FALSE : $valid_bucket);
	}
	
	
	/**
	 * Retrieves an item based on the saved field data.
	 *
	 * @access	private
	 * @param	string			$field_data		The saved field data (a full item path, including bucket).
	 * @return	array|bool
	 */
	function _load_item_using_field_data($field_data = '')
	{
		global $DB;
		
		if ( ! $field_data)
		{
			return FALSE;
		}
		
		// Trim the bucket from the start of the field data.
		if ($bucket_and_path = $this->_split_bucket_and_path_string($field_data))
		{
			$db_item = $DB->query("SELECT item_extension, item_is_folder, item_name, item_path, item_size
				FROM exp_bucketlist_items AS items
				INNER JOIN exp_bucketlist_buckets AS buckets
				ON buckets.bucket_id = items.bucket_id
				WHERE buckets.bucket_name = '" .$DB->escape_str($bucket_and_path['bucket']) ."'
				AND items.item_path = '" .$DB->escape_str($bucket_and_path['item_path']) ."'
				LIMIT 1");
			
			if ($db_item->num_rows == 1 && $item = $this->_validate_item($db_item->row))
			{
				return $item;
			}
		}
		
		return FALSE;
	}
	
	
	/**
	 * Retrieves all the buckets from the database.
	 *
	 * @access	private
	 * @return 	array
	 */
	function _load_all_buckets_from_db()
	{
		global $DB;
		
		$db_buckets = $DB->query("SELECT
				bucket_id, bucket_items_cache_date, bucket_name, site_id
			FROM exp_bucketlist_buckets
			WHERE site_id = '{$this->site_id}'
			ORDER BY bucket_name ASC");
			
		if ($db_buckets->num_rows == 0)
		{
			return array();
		}
		
		// Initialise the return array.
		$buckets = array();
{'fraction_non_alphanumeric': 0.16874084919472915, 'fraction_numerical': 0.0061005368472425575, 'mean_word_length': 2.88, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6984639', 'n_tokens_mistral': 6746, 'n_tokens_neox': 5763, 'n_words': 1287}