<?php /*

 ocPortal
 Copyright (c) ocProducts, 2004-2012

 See text/EN/licence.txt for full licencing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/

/**
 * @license		http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright	ocProducts Ltd
 * @package		downloads
 */

require_code('aed_module');

/**
 * Module page class.
 */
class Module_cms_downloads extends standard_aed_module
{
	var $lang_type='DOWNLOAD';
	var $select_name='NAME';
	var $permissions_require='mid';
	var $permissions_cat_require='downloads';
	var $permissions_cat_name='category_id';
	var $user_facing=true;
	var $seo_type='downloads_download';
	var $upload='file';
	var $javascript='var url=document.getElementById(\'url\'); var form=url.form; var crf=function() { var s=url.value!=\'\'; if (form.elements[\'copy_to_server\']) form.elements[\'copy_to_server\'].disabled=!s; if (form.elements[\'file_size\']) form.elements[\'file_size\'].disabled=!s; }; crf(); url.onchange=crf; url.onkeyup=crf; var cost=document.getElementById(\'cost\'); if (cost) { var form=cost.form; var crf2=function() { var s=(cost.value!=\'\') && (cost.value!=\'0\'); if (form.elements[\'submitter_gets_points\']) form.elements[\'submitter_gets_points\'].disabled=!s; }; crf2(); cost.onchange=crf2; cost.onkeyup=crf2; }';
	var $award_type='download';
	var $menu_label='SECTION_DOWNLOADS';
	var $table='download_downloads';

	var $donext_type=NULL;

	/**
	 * Standard modular entry-point finder function.
	 *
	 * @return ?array	A map of entry points (type-code=>language-code) (NULL: disabled).
	 */
	function get_entry_points()
	{
		return array_merge(array('misc'=>'MANAGE_DOWNLOADS')+(has_specific_permission(get_member(),'mass_import','cms_downloads')?array('import'=>'FTP_DOWNLOADS','import2'=>'FILESYSTEM_DOWNLOADS'):array()),parent::get_entry_points());
	}

	/**
	 * Standard modular privilege-overide finder function.
	 *
	 * @return array	A map of privileges that are overridable; sp to 0 or 1. 0 means "not category overridable". 1 means "category overridable".
	 */
	function get_sp_overrides()
	{
		require_lang('downloads');
		return array('download'=>1,'mass_import'=>0,'submit_cat_midrange_content'=>array(0,'ADD_DOWNLOAD_CATEGORY'),'edit_cat_midrange_content'=>array(0,'EDIT_DOWNLOAD_CATEGORY'),'delete_cat_midrange_content'=>array(0,'DELETE_DOWNLOAD_CATEGORY'),'submit_midrange_content'=>array(1,'ADD_DOWNLOAD'),'bypass_validation_midrange_content'=>array(1,'BYPASS_DOWNLOAD_VALIDATION'),'edit_own_midrange_content'=>array(1,'EDIT_OWN_DOWNLOAD'),'edit_midrange_content'=>array(1,'EDIT_DOWNLOAD'),'delete_own_midrange_content'=>array(1,'DELETE_OWN_DOWNLOAD'),'delete_midrange_content'=>array(1,'DELETE_DOWNLOAD'));
	}

	/**
	 * Standard aed_module run_start.
	 *
	 * @param  ID_TEXT		The type of module execution
	 * @return tempcode		The output of the run
	 */
	function run_start($type)
	{
		$this->cat_aed_module=new Module_cms_downloads_cat();
		$this->alt_aed_module=new Module_cms_downloads_alt();

		$GLOBALS['MODULE_CMS_DOWNLOADS']=$this;

		$GLOBALS['HELPER_PANEL_PIC']='pagepics/downloads';
		$GLOBALS['HELPER_PANEL_TUTORIAL']='tut_downloads';

		require_lang('downloads');
		require_code('downloads');
		require_code('downloads2');
		require_css('downloads');

		// Decide what to do
		if ($type=='misc') return $this->misc();
		if ($type=='import') return $this->import_interface();
		if ($type=='_import') return $this->_import();
		if ($type=='import2') return $this->import_interface2();
		if ($type=='_import2') return $this->_import2();

		return new ocp_tempcode();
	}

	/**
	 * The do-next manager for before download content management.
	 *
	 * @return tempcode		The UI
	 */
	function misc()
	{
		require_code('templates_donext');
		require_code('fields');
		return do_next_manager(get_screen_title('MANAGE_DOWNLOADS'),comcode_lang_string('DOC_DOWNLOADS'),
					array_merge(array(
						/*	 type							  page	 params													 zone	  */
						has_specific_permission(get_member(),'submit_cat_midrange_content','cms_downloads')?array('add_one_category',array('_SELF',array('type'=>'ac'),'_SELF'),do_lang('ADD_DOWNLOAD_CATEGORY')):NULL,
						has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_downloads')?array('edit_one_category',array('_SELF',array('type'=>'ec'),'_SELF'),do_lang('EDIT_DOWNLOAD_CATEGORY')):NULL,
						has_specific_permission(get_member(),'submit_cat_midrange_content','cms_downloads')?array('add_one_licence',array('_SELF',array('type'=>'av'),'_SELF'),do_lang('ADD_DOWNLOAD_LICENCE')):NULL,
						has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_downloads')?array('edit_one_licence',array('_SELF',array('type'=>'ev'),'_SELF'),do_lang('EDIT_DOWNLOAD_LICENCE')):NULL,
						has_specific_permission(get_member(),'mass_import')?array('import',array('_SELF',array('type'=>'import'),'_SELF'),do_lang('LOAD_FTP_FILES')):NULL,
						has_specific_permission(get_member(),'mass_import')?array('import',array('_SELF',array('type'=>'import2'),'_SELF'),do_lang('LOAD_FILESYSTEM_FILES')):NULL,
						has_specific_permission(get_member(),'submit_midrange_content','cms_downloads')?array('add_one',array('_SELF',array('type'=>'ad'),'_SELF'),do_lang('ADD_DOWNLOAD')):NULL,
						has_specific_permission(get_member(),'edit_own_midrange_content','cms_downloads')?array('edit_one',array('_SELF',array('type'=>'ed'),'_SELF'),do_lang('EDIT_DOWNLOAD')):NULL,
					),manage_custom_fields_donext_link('download'),manage_custom_fields_donext_link('download_category')),
					do_lang('MANAGE_DOWNLOADS')
		);
	}

	/**
	 * The UI for importing FTP downloads.
	 *
	 * @return tempcode		The UI
	 */
	function import_interface()
	{
		$title=get_screen_title('FTP_DOWNLOADS');

		if (!function_exists('ftp_connect')) warn_exit(do_lang_tempcode('FTP_NEEDED'));

		check_specific_permission('mass_import');

		$post_url=build_url(array('page'=>'_SELF','type'=>'_import'),'_SELF');
		$submit_name=do_lang_tempcode('LOAD_FTP_FILES');
		$fields=new ocp_tempcode();
		require_code('form_templates');
		$fields->attach(form_input_line(do_lang_tempcode('FTP_SERVER_URL'),do_lang_tempcode('DESCRIPTION_FTP_SERVER_URL'),'server_url','ftp://ftp.example.com/files/',true));
		$fields->attach(form_input_tree_list(do_lang_tempcode('DESTINATION_PATH'),do_lang_tempcode('DESCRIPTION_DESTINATION_PATH'),'destination',NULL,'choose_download_category',array('addable_filter'=>true),true));
		$fields->attach(form_input_tick(do_lang_tempcode('KEEP_SUBFOLDERS'),do_lang_tempcode('DESCRIPTION_KEEP_SUBFOLDERS'),'subfolders',true));

		breadcrumb_set_parents(array(array('_SELF:_SELF:misc',do_lang_tempcode('MANAGE_DOWNLOADS'))));

		return do_template('FORM_SCREEN',array('_GUID'=>'3b0fadb204770861ab34a91fc062cf03','TITLE'=>$title,'HIDDEN'=>'','TEXT'=>paragraph(do_lang_tempcode('DESCRIPTION_LOAD_FTP_FILES')),'FIELDS'=>$fields,'SUBMIT_NAME'=>$submit_name,'URL'=>$post_url));
	}

	/**
	 * The actualiser for importing FTP downloads.
	 *
	 * @return tempcode		The UI
	 */
	function _import()
	{
		$destination=post_param_integer('destination');

		if (function_exists('set_time_limit')) @set_time_limit(0);

		check_specific_permission('mass_import'/*,array('downloads',$destination)*/);

		$server_url=post_param('server_url');
		$subfolders=post_param_integer('subfolders',0);

		// Firstly, parse the server URL, to make sure it is fine
		$parsed_url=@parse_url($server_url) OR warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL',escape_html($server_url)));
		if (!array_key_exists('scheme',$parsed_url)) warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL',escape_html($server_url)));
		if ($parsed_url['scheme']!='ftp')
		{
			//Error
			warn_exit(do_lang_tempcode('URL_BEGIN_FTP'));
		}
		if (substr($server_url,strlen($server_url)-1,1)!='/')
		{
			$server_url.='/';
		}

		$parsed_url=parse_url($server_url);
		//	$host=$parsed_url['scheme'].'://'.$parsed_url['host'].'/';
		$directory=array_key_exists('path',$parsed_url)?$parsed_url['path']:'';

		require_lang('installer');
		$conn_id=@ftp_connect(array_key_exists('host',$parsed_url)?$parsed_url['host']:'localhost',array_key_exists('port',$parsed_url)?$parsed_url['port']:21);
		if ($conn_id===false) warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER',escape_html($server_url))); // Yes it's FTP not HTTP, but lang string is ok
		if ((array_key_exists('user',$parsed_url)) && (array_key_exists('pass',$parsed_url)))
		{
			$login_result=@ftp_login($conn_id,$parsed_url['user'],$parsed_url['pass']) OR warn_exit(do_lang_tempcode('NO_FTP_LOGIN',@strval($php_errormsg)));
		} else
		{
			$login_result=@ftp_login($conn_id,'anonymous',get_option('staff_address')) OR warn_exit(do_lang_tempcode('NO_FTP_LOGIN',@strval($php_errormsg)));
		}

		breadcrumb_set_parents(array(array('_SELF:_SELF:misc',do_lang_tempcode('MANAGE_DOWNLOADS')),array('_SELF:_SELF:import',do_lang_tempcode('FTP_DOWNLOADS'))));

		// Check connection
		if (!$login_result)
		{
			warn_exit(do_lang_tempcode('FTP_ERROR'));
		}

		// Failsafe check
		if ((@ftp_nlist($conn_id,$directory.'/dev')!==false) && (@ftp_nlist($conn_id,$directory.'/etc')!==false) && (@ftp_nlist($conn_id,$directory.'/sbin')!==false))
			warn_exit(do_lang_tempcode('POINTS_TO_ROOT_SCARY',$directory));
		if ((@ftp_nlist($conn_id,$directory.'/Program files')!==false) && ((@ftp_nlist($conn_id,$directory.'/Users')!==false) || (@ftp_nlist($conn_id,$directory.'/Documents and settings')!==false)) && (@ftp_nlist($conn_id,$directory.'/Windows')!==false))
			warn_exit(do_lang_tempcode('POINTS_TO_ROOT_SCARY',$directory));

		// Actually start the scanning
		$num_added=$this->ftp_recursive_downloads_scan($conn_id,$server_url,$directory,$destination,$subfolders);

		ftp_close($conn_id);

		decache('main_recent_downloads');
		decache('main_download_tease');

		breadcrumb_set_self(do_lang_tempcode('DONE'));

		// Show it worked / Refresh
		$title=get_screen_title('FTP_DOWNLOADS');
		return $this->do_next_manager($title,do_lang_tempcode('SUCCESS_ADDED_DOWNLOADS',escape_html(integer_format($num_added))),NULL,$destination);
	}

	/**
	 * Worker function to do an FTP import.
	 *
	 * @param  resource			The FTP connection
	 * @param  URLPATH			The URL that is equivalent to the base path on our FTP
	 * @param  PATH				The directory we are scanning
	 * @param  AUTO_LINK			The destination downloading category
	 * @param  boolean			Whether we add hierarchically (as opposed to a flat category fill)
	 * @return integer			Number of downloads added
	 */
	function ftp_recursive_downloads_scan($conn_id,$url,$directory,$dest_cat,$make_subfolders)
	{
		$num_added=0;

		$groups=$GLOBALS['FORUM_DRIVER']->get_usergroup_list(false,true);

		$contents=@ftp_nlist($conn_id,$directory);
		if ($contents===false) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		foreach ($contents as $entry)
		{
			$full_entry=$entry;
			$parts=explode('/',$entry);
			$entry=$parts[count($parts)-1];

			// Is the entry a directory?
			if (@ftp_chdir($conn_id,$full_entry.'/'))
			{
				$full_path=$directory.$entry.'/';
				$full_url=$url.$entry.'/';
				if ($make_subfolders)
				{
					// Do we need to make new category, or is it already existant?
					$category_id=$GLOBALS['SITE_DB']->query_value_null_ok('download_categories c JOIN '.get_table_prefix().'translate t ON t.id=c.category','c.id AS id',array('parent_id'=>$dest_cat,'text_original'=>$entry));
					if (is_null($category_id))
					{
						// Add the directory
						$category_id=add_download_category(titleify($entry),$dest_cat,'','','');
						foreach (array_keys($groups) as $group_id)
							$GLOBALS['SITE_DB']->query_insert('group_category_access',array('module_the_name'=>'downloads','category_name'=>strval($category_id),'group_id'=>$group_id));
					}
					// Call this function again to recurse it
					$num_added+=$this->ftp_recursive_downloads_scan($conn_id,$full_url,$full_path,$category_id,true);
				} else
				{
					$num_added+=$this->ftp_recursive_downloads_scan($conn_id,$full_url,$full_path,$dest_cat,false);
				}
			} else
			{
				$full_url=$url.$entry;

				// Test to see if the file is already in our database
				$test=$GLOBALS['SITE_DB']->query_value_null_ok('download_downloads','url',array('url'=>$full_url));
				if (is_null($test))
				{
					// It is a file, so add it
					add_download($dest_cat,titleify($entry),$full_url,'',$GLOBALS['FORUM_DRIVER']->get_username(get_member()),'',NULL,1,1,1,1,'',$entry,ftp_size($conn_id,$entry),0,0);
					$num_added++;
				}
			}
		}

		return $num_added;
	}

	/**
	 * The UI for importing filesystem downloads.
	 *
	 * @return tempcode		The UI
	 */
	function import_interface2()
	{
		$title=get_screen_title('FILESYSTEM_DOWNLOADS');

		check_specific_permission('mass_import');

		$post_url=build_url(array('page'=>'_SELF','type'=>'_import2'),'_SELF');
		$submit_name=do_lang_tempcode('LOAD_FILESYSTEM_FILES');
		$fields=new ocp_tempcode();
		require_code('form_templates');
		$fields->attach(form_input_line(do_lang_tempcode('DIRECTORY'),do_lang_tempcode('DIRECTORY_RELATIVE_INSTALL'),'server_path','uploads/website_specific/my_downloads/',true));
		$fields->attach(form_input_tree_list(do_lang_tempcode('DESTINATION_PATH'),do_lang_tempcode('DESCRIPTION_DESTINATION_PATH'),'destination',NULL,'choose_download_category',array('addable_filter'=>true),true));
		$fields->attach(form_input_tick(do_lang_tempcode('KEEP_SUBFOLDERS'),do_lang_tempcode('DESCRIPTION_KEEP_SUBFOLDERS'),'subfolders',true));

		breadcrumb_set_parents(array(array('_SELF:_SELF:misc',do_lang_tempcode('MANAGE_DOWNLOADS'))));

		return do_template('FORM_SCREEN',array('_GUID'=>'b2a15e705e907f0b20373a80ca8839c6','TITLE'=>$title,'HIDDEN'=>'','TEXT'=>paragraph(do_lang_tempcode('DESCRIPTION_LOAD_FILESYSTEM_FILES')),'FIELDS'=>$fields,'SUBMIT_NAME'=>$submit_name,'URL'=>$post_url));
	}

	/**
	 * The actualiser for importing filesystem downloads.
	 *
	 * @return tempcode		The UI
	 */
	function _import2()
	{
		$destination=post_param_integer('destination');

		check_specific_permission('mass_import'/*,array('downloads',$destination)*/);

		if (function_exists('set_time_limit')) @set_time_limit(0);

		$server_path=post_param('server_path');
		if (substr($server_path,-1)=='/') $server_path=substr($server_path,0,strlen($server_path)-1);
		$base_path=get_custom_file_base().'/'.$server_path;
		$base_url=get_custom_base_url().'/'.$server_path;
		$subfolders=post_param_integer('subfolders',0);

		if (!file_exists($base_path)) warn_exit(do_lang_tempcode('DIRECTORY_NOT_FOUND',$server_path));

		/*	Needless because it's relative to ocPortal directory anyway
		// Failsafe check
		if ((file_exists($base_path.'/dev')) && (file_exists($base_path.'/etc')) && (file_exists($base_path.'/sbin')))
			warn_exit(do_lang_tempcode('POINTS_TO_ROOT_SCARY',$server_path));
		if ((file_exists($base_path.'/Program files')) && ((file_exists($base_path.'/Users')) || (file_exists($base_path.'/Documents and settings'))) && (file_exists($base_path.'/Windows')))
			warn_exit(do_lang_tempcode('POINTS_TO_ROOT_SCARY',$server_path));
		*/

		// Actually start the scanning
		$num_added=$this->filesystem_recursive_downloads_scan($base_path,$base_url,$destination,$subfolders);

		decache('main_recent_downloads');
		decache('main_download_tease');

		breadcrumb_set_parents(array(array('_SELF:_SELF:misc',do_lang_tempcode('MANAGE_DOWNLOADS')),array('_SELF:_SELF:import',do_lang_tempcode('FILESYSTEM_DOWNLOADS'))));
		breadcrumb_set_self(do_lang_tempcode('DONE'));

		// Show it worked / Refresh
		$title=get_screen_title('FILESYSTEM_DOWNLOADS');
		return $this->do_next_manager($title,do_lang_tempcode('SUCCESS_ADDED_DOWNLOADS',escape_html(integer_format($num_added))),NULL);
	}

	/**
	 * Worker function to do a filesystem import.
	 *
	 * @param  PATH				Filesystem-based path from where we are reading files
	 * @param  URLPATH			URL-based path from where we are reading files
	 * @param  AUTO_LINK			The destination downloading category
	 * @param  boolean			Whether we add hierarchically (as opposed to a flat category fill)
	 * @return integer			Number of downloads added
	 */
	function filesystem_recursive_downloads_scan($server_path,$server_url,$dest_cat,$make_subfolders)
	{
		$num_added=0;

		$groups=$GLOBALS['FORUM_DRIVER']->get_usergroup_list(false,true);

		$dh=@opendir($server_path);
		if ($dh!==false)
		{
			while (($entry=readdir($dh))!==false)
			{
				if (!should_ignore_file($entry,IGNORE_ACCESS_CONTROLLERS | IGNORE_HIDDEN_FILES))
				{
					$full_path=$server_path.'/'.$entry;
					$full_url=$server_url.'/'.rawurlencode($entry);

					// Is the entry a directory?
					if (is_dir($full_path))
					{
						if ($make_subfolders)
						{
							// Do we need to make new category, or is it already existant?
							$category_id=$GLOBALS['SITE_DB']->query_value_null_ok('download_categories c JOIN '.get_table_prefix().'translate t ON t.id=c.category','c.id AS id',array('parent_id'=>$dest_cat,'text_original'=>$entry));
							if (is_null($category_id))
							{
								// Add the directory
								$category_id=add_download_category(titleify($entry),$dest_cat,'','','');
								foreach (array_keys($groups) as $group_id)
									$GLOBALS['SITE_DB']->query_insert('group_category_access',array('module_the_name'=>'downloads','category_name'=>strval($category_id),'group_id'=>$group_id));
							}
							// Call this function again to recurse it
							$num_added+=$this->filesystem_recursive_downloads_scan($full_path,$full_url,$category_id,true);
						} else
						{
							$num_added+=$this->filesystem_recursive_downloads_scan($full_path,$full_url,$dest_cat,false);
						}
					} elseif (!is_link($full_path))
					{
						// Test to see if the file is already in our database
						$test=$GLOBALS['SITE_DB']->query_value_null_ok('download_downloads','url',array('url'=>$full_url));
						if (is_null($test))
						{
							// First let's see if we are allowed to add this (accessible by URL already)
							$myfile=@fopen($full_path,'rb');
							if ($myfile!==false)
							{
								$shouldbe=fread($myfile,8000);
								fclose($myfile);
							} else $shouldbe=NULL;
							global $HTTP_MESSAGE;
							$actuallyis=http_download_file($full_url,8000,false);
							if (($HTTP_MESSAGE=='200') && (!is_null($shouldbe)) && (strcmp($shouldbe,$actuallyis)==0))
							{
								// Ok, add it
								$filesize=filesize($full_path);
								add_download($dest_cat,titleify($entry),$full_url,'',$GLOBALS['FORUM_DRIVER']->get_username(get_member()),'',NULL,1,1,1,1,'',$entry,$filesize,0,0);
								$num_added++;
							}
						}
					}
				}
			}
		}

		return $num_added;
	}

	/**
	 * Standard aed_module list function.
	 *
	 * @return array				A triple: The tree field (tempcode), Search URL, Archive URL
	 */
	function nice_get_ajax_tree()
	{
		if ($GLOBALS['SITE_DB']->query_value('download_downloads','COUNT(*)')==0) inform_exit(do_lang_tempcode('NO_ENTRIES'));

		$search_url=build_url(array('page'=>'search','id'=>'downloads'),get_module_zone('search'));
		$archive_url=build_url(array('page'=>'downloads'),get_module_zone('downloads'));

		$only_owned=has_specific_permission(get_member(),'edit_midrange_content','cms_downloads')?NULL:get_member();
		$tree=form_input_tree_list(do_lang_tempcode('NAME'),'','id',NULL,'choose_download',array('only_owned'=>$only_owned,'editable_filter'=>true),true);
		return array($tree,$search_url,$archive_url);
	}

	/**
	 * Get tempcode for a download adding/editing form.
	 *
	 * @param  ?AUTO_LINK		The ID of the download (NULL: new)
	 * @param  SHORT_TEXT		The name of the download
	 * @param  ?AUTO_LINK		The download category (NULL: first)
	 * @param  URLPATH			The URL for the downloadable file
	 * @param  SHORT_TEXT		The name of the author
	 * @param  LONG_TEXT			Description for the download
	 * @param  LONG_TEXT			Additional comments for the download
	 * @param  ?AUTO_LINK		The ID of the download this download is out-moding (NULL: none)
	 * @param  BINARY				Whether the download is validated
	 * @param  ?BINARY			Whether rating is allowed (NULL: decide statistically, based on existing choices)
	 * @param  ?SHORT_INTEGER	Whether comments are allowed (0=no, 1=yes, 2=review style) (NULL: decide statistically, based on existing choices)
	 * @param  ?BINARY			Whether trackbacks are allowed (NULL: decide statistically, based on existing choices)
	 * @param  LONG_TEXT			Notes
	 * @param  ?integer			The file size (NULL: not added yet therefore unknown)
	 * @param  integer			The point cost of the download
	 * @param  BINARY				Whether the submitter gets the point cost
	 * @param  ?SHORT_TEXT		The original file name for the file (we can't rely on the one on disk) (NULL: not added yet therefore unknown)
	 * @param  ?AUTO_LINK		The licence to use (NULL: none)
	 * @param  integer			Which image to use for the downloads representative image (counts from 1)
	 * @return array				A pair: the tempcode for the visible fields, and the tempcode for the hidden fields
	 */
	function get_form_fields($id=NULL,$name='',$category_id=NULL,$url='',$author='',$description='',$comments='',$out_mode_id=NULL,$validated=1,$allow_rating=NULL,$allow_comments=NULL,$allow_trackbacks=NULL,$notes='',$file_size=NULL,$cost=0,$submitter_gets_points=1,$original_filename=NULL,$licence=NULL,$default_pic=1)
	{
		list($allow_rating,$allow_comments,$allow_trackbacks)=$this->choose_feedback_fields_statistically($allow_rating,$allow_comments,$allow_trackbacks);

		global $NON_CANONICAL_PARAMS;
		$NON_CANONICAL_PARAMS[]='validated';

		if ((is_null($id)) && (is_null($category_id)))
		{
			$NON_CANONICAL_PARAMS[]='cat';
			$NON_CANONICAL_PARAMS[]='name';
			$NON_CANONICAL_PARAMS[]='author';
			$NON_CANONICAL_PARAMS[]='description';
			$NON_CANONICAL_PARAMS[]='comments';
			$NON_CANONICAL_PARAMS[]='notes';

			$category_id=get_param_integer('cat',-1);
			if ($category_id==-1) $category_id=NULL;

			$name=get_param('name',$name);
			$author=get_param('author',$author);
			$description=get_param('description',$description);
			$comments=get_param('comments',$comments);
			$notes=get_param('notes',$notes);
		}

		$fields=new ocp_tempcode();
		$hidden=new ocp_tempcode();
		require_code('form_templates');
		handle_max_file_size($hidden);
		$fields->attach(form_input_line(do_lang_tempcode('NAME'),do_lang_tempcode('DESCRIPTION_NAME'),'name',$name,true));
		if (!is_null($original_filename)) $fields->attach(form_input_line(do_lang_tempcode('ORIGINAL_FILENAME'),do_lang_tempcode('DESCRIPTION_ORIGINAL_FILENAME'),'original_filename',$original_filename,false));
		$fields->attach(form_input_tree_list(do_lang_tempcode('CATEGORY'),do_lang_tempcode('DESCRIPTION_CATEGORY_TREE'),'category_id',NULL,'choose_download_category',array(),true,strval(is_null($category_id)?db_get_first_id():$category_id)));

		$set_name='file';
		$required=true;
		$set_title=do_lang_tempcode('FILE');
		$field_set=alternate_fields_set__start($set_name);

		$field_set->attach(form_input_upload(do_lang_tempcode('UPLOAD'),'','file',false));

		$field_set->attach(form_input_line(do_lang_tempcode('URL'),'','url',$url,false));

		$fields->attach(alternate_fields_set__end($set_name,$set_title,'',$field_set,$required));

		if (has_specific_permission(get_member(),'draw_to_server'))
			$fields->attach(form_input_tick(do_lang_tempcode('COPY_TO_SERVER'),do_lang_tempcode('DESCRIPTION_COPY_TO_SERVER'),'copy_to_server',false));
		$fields->attach(form_input_integer(do_lang_tempcode('_FILE_SIZE'),do_lang_tempcode('DESCRIPTION_FILE_SIZE'),'file_size',$file_size,false));
		if (addon_installed('authors'))
		{
			if ($author=='')
			{
				$author=$GLOBALS['SITE_DB']->query_value_null_ok('authors','author',array('forum_handle'=>get_member()));
				if (is_null($author)) $author=$GLOBALS['FORUM_DRIVER']->get_username(get_member());
			}
		}
		if (addon_installed('authors'))
		{
			$fields->attach(form_input_author(do_lang_tempcode('AUTHOR'),do_lang_tempcode('DESCRIPTION_AUTHOR'),'author',$author,true));
		}
		$fields->attach(form_input_text_comcode(do_lang_tempcode('DESCRIPTION'),do_lang_tempcode('DESCRIPTION_DESCRIPTION'),'description',$description,false));
		if ((is_null($id)) && (addon_installed('galleries')))
		{
			$fields->attach(form_input_upload(do_lang_tempcode('IMAGE'),'','img_file',false,NULL,NULL,true,str_replace(' ','',get_option('valid_images'))));
		}
		if ($validated==0)
		{
			$validated=get_param_integer('validated',0);
			if ($validated==1) attach_message(do_lang_tempcode('WILL_BE_VALIDATED_WHEN_SAVING'));
		}
		if (has_some_cat_specific_permission(get_member(),'bypass_validation_'.$this->permissions_require.'range_content',NULL,$this->permissions_cat_require))
			if (addon_installed('unvalidated'))
				$fields->attach(form_input_tick(do_lang_tempcode('VALIDATED'),do_lang_tempcode('DESCRIPTION_VALIDATED'),'validated',$validated==1));

		$fields->attach(do_template('FORM_SCREEN_FIELD_SPACER',array('SECTION_HIDDEN'=>$comments=='' && is_null($out_mode_id) && ($cost==0) && is_null($licence),'TITLE'=>do_lang_tempcode('ADVANCED'))));
		$fields->attach(form_input_text_comcode(do_lang_tempcode('ADDITIONAL_INFO'),do_lang_tempcode('DESCRIPTION_ADDITIONAL_INFO'),'comments',$comments,false));
		if (!is_null($id))
			$fields->attach(form_input_integer(do_lang_tempcode('DEFAULT_PICTURE'),do_lang_tempcode('DESCRIPTION_DEFAULT_PICTURE'),'default_pic',$default_pic,false));
		if (!is_null($id)) $fields->attach(form_input_tree_list(do_lang_tempcode('OUTMODE'),do_lang_tempcode('DESCRIPTION_OUTMODE'),'out_mode_id',NULL,'choose_download',array('shun'=>$id),false,is_null($out_mode_id)?'':strval($out_mode_id)));
		if (addon_installed('points'))
		{
			require_lang('points');
			$fields->attach(form_input_integer(do_lang_tempcode('COST'),do_lang_tempcode('DESCRIPTION_DOWNLOAD_COST'),'cost',$cost,true));
			$fields->attach(form_input_tick(do_lang_tempcode('SUBMITTER_GETS_POINTS'),do_lang_tempcode('DESCRIPTION_SUBMITTER_GETS_POINTS'),'submitter_gets_points',$submitter_gets_points==1));
		} else
		{
			$hidden->attach(form_input_hidden('cost',''));
		}
		$licences=nice_get_download_licences($licence);
		if (!$licences->is_empty())
		{
			$licences=nice_get_download_licences($licence,true);
			$fields->attach(form_input_list(do_lang_tempcode('LICENCE'),do_lang_tempcode('DESCRIPTION_DOWNLOAD_LICENCE'),'licence',$licences));
		}

		require_code('feedback2');
		$fields->attach(feedback_fields($allow_rating==1,$allow_comments==1,$allow_trackbacks==1,false,$notes,$allow_comments==2));

		if (!is_null($id))
			$hidden->attach(form_input_hidden('id',strval($id)));

		return array($fields,$hidden);
	}

	/**
	 * Standard aed_module submitter getter.
	 *
	 * @param  ID_TEXT		The entry for which the submitter is sought
	 * @return array			The submitter, and the time of submission (null submission time implies no known submission time)
	 */
	function get_submitter($id)
	{
		$rows=$GLOBALS['SITE_DB']->query_select('download_downloads',array('submitter','add_date'),array('id'=>intval($id)),'',1);
		if (!array_key_exists(0,$rows)) return array(NULL,NULL);
		return array($rows[0]['submitter'],$rows[0]['add_date']);
	}

	/**
	 * Standard aed_module cat getter.
	 *
	 * @param  AUTO_LINK		The entry for which the cat is sought
	 * @return mixed			The cat
	 */
	function get_cat($id)
	{
		$temp=$GLOBALS['SITE_DB']->query_value_null_ok('download_downloads','category_id',array('id'=>$id));
		if (is_null($temp)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		return $temp;
	}

	/**
	 * Standard aed_module edit form filler.
	 *
	 * @param  ID_TEXT		The entry being edited
	 * @return array			A tuple of lots of info
	 */
	function fill_in_edit_form($_id)
	{
		$id=intval($_id);

		$myrows=$GLOBALS['SITE_DB']->query_select('download_downloads',array('*'),array('id'=>$id),'',1);
		if (!array_key_exists(0,$myrows))
		{
			warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		}
		$myrow=$myrows[0];

		$cat=$myrow['category_id'];

		list($fields,$hidden)=$this->get_form_fields($id,get_translated_text($myrow['name']),$cat,$myrow['url'],$myrow['author'],get_translated_text($myrow['description']),get_translated_text($myrow['comments']),$myrow['out_mode_id'],$myrow['validated'],$myrow['allow_rating'],$myrow['allow_comments'],$myrow['allow_trackbacks'],$myrow['notes'],$myrow['file_size'],$myrow['download_cost'],$myrow['download_submitter_gets_points'],$myrow['original_filename'],$myrow['download_licence'],$myrow['default_pic']);

		if (has_delete_permission('mid',get_member(),$myrow['submitter'],'cms_downloads',array('downloads',$cat)))
		{
			$radios=form_input_radio_entry('delete','0',true,do_lang_tempcode('LEAVE'));
			$radios->attach(form_input_radio_entry('delete','1',false,do_lang_tempcode('DELETE_PARTIAL')));
			$radios->attach(form_input_radio_entry('delete','2',false,do_lang_tempcode('DELETE_FULL')));
			$delete_fields=form_input_radio(do_lang_tempcode('DELETE_STATUS'),do_lang_tempcode('DESCRIPTION_DELETE_STATUS'),'delete',$radios);
		} else $delete_fields=new ocp_tempcode();

		return array($fields,$hidden,$delete_fields,'',true);
	}

	/**
	 * Standard aed_module add actualiser.
	 *
	 * @return ID_TEXT			The ID of the new entry
	 */
	function add_actualisation()
	{
		$category_id=post_param_integer('category_id');
		$name=post_param('name');
		$description=post_param('description');
		$author=post_param('author',get_site_name());
		$_out_mode_id=post_param('out_mode_id','');
		$out_mode_id=($_out_mode_id=='')?-1:intval($_out_mode_id);
		if ($out_mode_id==-1) $out_mode_id=NULL;
		$_licence=post_param('licence','');
		$licence=($_licence=='')?-1:intval($_licence);
		if ($licence==-1) $licence=NULL;
		$validated=post_param_integer('validated',0);
		$comments=post_param('comments');
		$allow_trackbacks=post_param_integer('allow_trackbacks',0);
		$allow_rating=post_param_integer('allow_rating',0);
		$allow_comments=post_param_integer('allow_comments',0);
		$notes=post_param('notes','');
		$file_size=post_param_integer('file_size',0);
		$cost=post_param_integer('cost',0);
		$submitter_gets_points=post_param_integer('submitter_gets_points',0);
		$copy_to_server=post_param_integer('copy_to_server',0);
		if (!has_specific_permission(get_member(),'draw_to_server')) $copy_to_server=0;

		$urls=get_url('url','file','uploads/downloads',2,OCP_UPLOAD_ANYTHING,false,'','',$copy_to_server==1);
		if ($urls[0]=='')
		{
			warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN_UPLOAD'));
		}
		$original_filename=$urls[2];

		if ((substr($urls[0],0,8)!='uploads/') && (is_null(http_download_file($urls[0],0,false))) && (!is_null($GLOBALS['HTTP_MESSAGE_B'])))
			attach_message($GLOBALS['HTTP_MESSAGE_B'],'warn');

		$id=add_download($category_id,$name,fixup_protocolless_urls($urls[0]),$description,$author,$comments,$out_mode_id,$validated,$allow_rating,$allow_comments,$allow_trackbacks,$notes,$original_filename,$file_size,$cost,$submitter_gets_points,$licence);
		if (addon_installed('galleries'))
		{
			require_code('permissions2');
			set_category_permissions_from_environment('galleries','download_'.strval($id));

			$img_urls=get_url('','img_file','uploads/galleries',0,OCP_UPLOAD_IMAGE,true);
			if ($img_urls[0]!='')
			{
				add_image('','download_'.strval($id),'',$img_urls[0],$img_urls[1],1,0,0,0,'');
			}
		}

		$this->donext_type=$category_id;

		if ((!is_null(get_param('redirect',NULL))) && (addon_installed('galleries')))
		{
			$redirect_url=build_url(array('page'=>'downloads','type'=>'entry','id'=>$id),get_module_zone('downloads'));
			$add_image_url=build_url(array('page'=>'cms_galleries','type'=>'ad','cat'=>'download_'.strval($id),'redirect'=>$redirect_url->evaluate()),get_module_zone('cms_galleries'));
			$this->do_next_description=do_lang_tempcode('DOWNLOAD_ADDED',escape_html($add_image_url->evaluate()));
		}

		if ($validated==1)
		{
			if ((has_actual_page_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'downloads')) && (has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'downloads',strval($category_id))))
				syndicate_described_activity('downloads:ACTIVITY_ADD_DOWNLOAD',$name,'','','_SEARCH:downloads:entry:'.strval($id),'','','downloads');
		}

		return strval($id);
	}

	/**
	 * Standard aed_module edit actualiser.
	 *
	 * @param  ID_TEXT		The entry being edited
	 */
	function edit_actualisation($_id)
	{
		$id=intval($_id);

		$validated=post_param_integer('validated',fractional_edit()?INTEGER_MAGIC_NULL:0);

		$category_id=post_param_integer('category_id',INTEGER_MAGIC_NULL);
		$name=post_param('name');
		$out_mode_id=post_param_integer('out_mode_id',fractional_edit()?INTEGER_MAGIC_NULL:-1);
		if ($out_mode_id==-1) $out_mode_id=NULL;
		$licence=post_param_integer('licence',fractional_edit()?INTEGER_MAGIC_NULL:-1);
		if ($licence==-1) $licence=NULL;

		if (!fractional_edit())
		{
			$copy_to_server=post_param_integer('copy_to_server',0);
			if (!has_specific_permission(get_member(),'draw_to_server')) $copy_to_server=0;
			$urls=get_url('url','file','uploads/downloads',2,OCP_UPLOAD_ANYTHING,false,'','',$copy_to_server==1);
			$url=fixup_protocolless_urls($urls[0]);

			if (($url!='') && (substr($urls[0],0,8)!='uploads/') && (is_null(http_download_file($urls[0],0,false))) && (!is_null($GLOBALS['HTTP_MESSAGE_B'])))
				attach_message($GLOBALS['HTTP_MESSAGE_B'],'warn');
		} else $url=STRING_MAGIC_NULL;

		$description=post_param('description',STRING_MAGIC_NULL);
		$author=post_param('author',STRING_MAGIC_NULL);
		$comments=post_param('comments',STRING_MAGIC_NULL);
		$default_pic=post_param_integer('default_pic',INTEGER_MAGIC_NULL);
		$allow_rating=post_param_integer('allow_rating',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$allow_comments=post_param_integer('allow_comments',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$notes=post_param('notes',STRING_MAGIC_NULL);
		$file_size=post_param_integer('file_size',INTEGER_MAGIC_NULL);
		$cost=post_param_integer('cost',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$submitter_gets_points=post_param_integer('submitter_gets_points',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$original_filename=post_param('original_filename',STRING_MAGIC_NULL);
		if ((!fractional_edit()) && ($original_filename==''))
		{
			$original_filename=$urls[2];
		}
		$allow_trackbacks=post_param_integer('allow_trackbacks',fractional_edit()?INTEGER_MAGIC_NULL:0);

		$this->donext_type=$category_id;

		if (($validated==1) && ($GLOBALS['SITE_DB']->query_value('download_downloads','validated',array('id'=>$id))==0)) // Just became validated, syndicate as just added
		{
			$submitter=$GLOBALS['SITE_DB']->query_value('download_downloads','submitter',array('id'=>$id));

			if ((has_actual_page_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'downloads')) && (has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'downloads',strval($category_id))))
				syndicate_described_activity(($submitter!=get_member())?'downloads:ACTIVITY_VALIDATE_DOWNLOAD':'downloads:ACTIVITY_ADD_DOWNLOAD',$name,'','','_SEARCH:downloads:entry:'.strval($id),'','','downloads',1,$submitter);
		}

		edit_download($id,$category_id,$name,$url,$description,$author,$comments,$out_mode_id,$default_pic,$validated,$allow_rating,$allow_comments,$allow_trackbacks,$notes,$original_filename,$file_size,$cost,$submitter_gets_points,$licence,post_param('meta_keywords',STRING_MAGIC_NULL),post_param('meta_description',STRING_MAGIC_NULL));

		if (addon_installed('galleries'))
		{
			require_code('permissions2');
			set_category_permissions_from_environment('galleries','download_'.strval($id));
		}
	}

	/**
	 * Standard aed_module delete actualiser.
	 *
	 * @param  ID_TEXT		The entry being deleted
	 */
	function delete_actualisation($_id)
	{
		$id=intval($_id);

		$delete_status=post_param('delete','leave');
		delete_download($id,!($delete_status=='2'));
	}

	/**
	 * The do-next manager for after download content management (events only).
	 *
	 * @param  tempcode		The title (output of get_screen_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?AUTO_LINK	The ID of whatever was just handled (NULL: N/A)
	 * @return tempcode		The UI
	 */
	function do_next_manager($title,$description,$id)
	{
		return $this->cat_aed_module->_do_next_manager($title,$description,is_null($id)?NULL:intval($id),$this->donext_type);
	}

}

/**
 * Module page class.
 */
class Module_cms_downloads_alt extends standard_aed_module
{
	var $lang_type='DOWNLOAD_LICENCE';
	var $select_name='TITLE';
	var $permissions_require='cat_high';
	var $user_facing=false;
	var $menu_label='SECTION_DOWNLOADS';

	var $donext_type=NULL;

	/**
	 * Standard modular entry list fetcher.
	 *
	 * @return tempcode	The list
	 */
	function nice_get_entries()
	{
		return nice_get_download_licences();
	}

	/**
	 * Get tempcode for a download adding/editing form.
	 *
	 * @param  ID_TEXT		The title of the licence
	 * @param  LONG_TEXT		The text of the licence
	 * @return tempcode		The fields
	 */
	function get_form_fields($title='',$text='')
	{
		$fields=new ocp_tempcode();
		require_code('form_templates');
		$fields->attach(form_input_line(do_lang_tempcode('TITLE'),do_lang_tempcode('DESCRIPTION_TITLE'),'title',$title,true));
		$fields->attach(form_input_text_comcode(do_lang_tempcode('TEXT'),do_lang_tempcode('DESCRIPTION_LICENCE_TEXT'),'text',$text,true));

		return $fields;
	}

	/**
	 * Standard aed_module edit form filler.
	 *
	 * @param  ID_TEXT		The entry being edited
	 * @return tempcode		The fields
	 */
	function fill_in_edit_form($_id)
	{
		$id=intval($_id);

		$myrows=$GLOBALS['SITE_DB']->query_select('download_licences',array('*'),array('id'=>$id));
		if (!array_key_exists(0,$myrows))
		{
			warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		}
		$myrow=$myrows[0];

		$fields=$this->get_form_fields($myrow['l_title'],$myrow['l_text']);

		return $fields;
	}

	/**
	 * Standard aed_module add actualiser.
	 *
	 * @return ID_TEXT			The ID of the new entry
	 */
	function add_actualisation()
	{
		$id=add_download_licence(post_param('title'),post_param('text'));

		return strval($id);
	}

	/**
	 * Standard aed_module edit actualiser.
	 *
	 * @param  ID_TEXT		The entry being edited
	 */
	function edit_actualisation($_id)
	{
		$id=intval($_id);

		edit_download_licence($id,post_param('title'),post_param('text'));
	}

	/**
	 * Standard aed_module delete actualiser.
	 *
	 * @param  ID_TEXT		The entry being deleted
	 */
	function delete_actualisation($_id)
	{
		$id=intval($_id);

		delete_download_licence($id);
	}

	/**
	 * The do-next manager for after download content management (events only).
	 *
	 * @param  tempcode		The title (output of get_screen_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?AUTO_LINK	The ID of whatever was just handled (NULL: N/A)
	 * @return tempcode		The UI
	 */
	function do_next_manager($title,$description,$id)
	{
		return $GLOBALS['MODULE_CMS_DOWNLOADS']->cat_aed_module->_do_next_manager($title,$description,NULL,NULL,$id);
	}

}

/**
 * Module page class.
 */
class Module_cms_downloads_cat extends standard_aed_module
{
	var $lang_type='DOWNLOAD_CATEGORY';
	var $select_name='NAME';
	var $permissions_require='cat_mid';
	var $permission_module='downloads';
	var $seo_type='downloads_category';
	var $upload='image';
	var $award_type='download_category';
	var $protect_first=1;
	var $menu_label='SECTION_DOWNLOADS';

	/**
	 * Standard aed_module list function.
	 *
	 * @return array				A triple: The tree field (tempcode), Search URL, Archive URL
	 */
	function nice_get_ajax_tree()
	{
		$search_url=build_url(array('page'=>'search','id'=>'download_categories'),get_module_zone('search'));
		$archive_url=build_url(array('page'=>'downloads'),get_module_zone('downloads'));

		$tree=form_input_tree_list(do_lang_tempcode('NAME'),'','id',NULL,'choose_download_category',array(),true);
		return array($tree,$search_url,$archive_url);
	}

	/**
	 * Get tempcode for a download category adding/editing form.
	 *
	 * @param  SHORT_TEXT	The name of the download category
	 * @param  ?AUTO_LINK	The download category parent (NULL: use root)
	 * @param  LONG_TEXT		Description
	 * @param  LONG_TEXT		Notes
	 * @param  ?AUTO_LINK	The ID of the download category (NULL: we're adding, not editing)
	 * @param  URLPATH		The rep-image for the download category
	 * @return array			A pair: the tempcode for the visible fields, and the tempcode for the hidden fields
	 */
	function get_form_fields($category='',$parent_id=NULL,$description='',$notes='',$category_id=-1,$rep_image='')
	{
		if ((is_null($parent_id)) && ($category_id==-1))
		{
			global $NON_CANONICAL_PARAMS;
			$NON_CANONICAL_PARAMS[]='parent_id';

			$parent_id=get_param_integer('parent_id',-1);
			if ($parent_id==-1) $parent_id=db_get_first_id();
		}

		$fields=new ocp_tempcode();
		require_code('form_templates');
		$fields->attach(form_input_line(do_lang_tempcode('NAME'),do_lang_tempcode('DESCRIPTION_NAME'),'category',$category,true));
		if (!is_null($parent_id))
		{
			$fields->attach(form_input_tree_list(do_lang_tempcode('PARENT'),do_lang_tempcode('DESCRIPTION_PARENT'),'parent_id',NULL,'choose_download_category',array(),true,strval($parent_id)));
		}
		$fields->attach(form_input_text_comcode(do_lang_tempcode('DESCRIPTION'),do_lang_tempcode('DESCRIPTION_DESCRIPTION'),'description',$description,false));
		if (get_value('disable_staff_notes')!=='1')
			$fields->attach(form_input_text(do_lang_tempcode('NOTES'),do_lang_tempcode('DESCRIPTION_NOTES'),'notes',$notes,false));
		$hidden=new ocp_tempcode();
		handle_max_file_size($hidden,'image');
		$fields->attach(form_input_upload(do_lang_tempcode('REPRESENTATIVE_IMAGE'),do_lang_tempcode('DESCRIPTION_REPRESENTATIVE_IMAGE'),'rep_image',false,$rep_image,NULL,true,str_replace(' ','',get_option('valid_images'))));

		// Permissions
		$fields->attach($this->get_permission_fields(($category_id==-1)?NULL:strval($category_id),NULL,($category=='')));

		return array($fields,$hidden);
	}

	/**
	 * Standard aed_module edit form filler.
	 *
	 * @param  ID_TEXT		The entry being edited
	 * @return tempcode		The edit form
	 */
	function fill_in_edit_form($id)
	{
		$category_id=intval($id);

		$rows=$GLOBALS['SITE_DB']->query_select('download_categories',array('*'),array('id'=>$category_id),'',1);
		if (!array_key_exists(0,$rows))
		{
			warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		}
		$myrow=$rows[0];

		return $this->get_form_fields(get_translated_text($myrow['category']),$myrow['parent_id'],get_translated_text($myrow['description']),$myrow['notes'],$category_id,$myrow['rep_image']);
	}

	/**
	 * Standard aed_module add actualiser.
	 *
	 * @return ID_TEXT		The entry added
	 */
	function add_actualisation()
	{
		$category=post_param('category');
		$parent_id=post_param_integer('parent_id');
		$description=post_param('description');
		$notes=post_param('notes','');
		$urls=get_url('image_url','rep_image','uploads/grepimages',0,OCP_UPLOAD_IMAGE);
		$rep_image=$urls[0];

		$category_id=add_download_category($category,$parent_id,$description,$notes,$rep_image);
		$this->set_permissions(strval($category_id));

		return strval($category_id);
	}

	/**
	 * Standard aed_module edit actualiser.
	 *
	 * @param  ID_TEXT		The entry being edited
	 */
	function edit_actualisation($id)
	{
		$category_id=intval($id);

		$category=post_param('category');
		$parent_id=post_param_integer('parent_id',INTEGER_MAGIC_NULL);
		if ($parent_id==-1) $parent_id=NULL;
		$description=post_param('description',STRING_MAGIC_NULL);
		$notes=post_param('notes',STRING_MAGIC_NULL);
		if (!fractional_edit())
		{
			$urls=get_url('image_url','rep_image','uploads/grepimages',0,OCP_UPLOAD_IMAGE);
			$rep_image=$urls[0];
			if (($rep_image=='') && (post_param_integer('rep_image_unlink',0)!=1)) $rep_image=NULL;
		} else $rep_image=STRING_MAGIC_NULL;

		edit_download_category($category,$parent_id,$description,$category_id,$notes,$rep_image,post_param('meta_keywords',STRING_MAGIC_NULL),post_param('meta_description',STRING_MAGIC_NULL));
		if (!fractional_edit())
		{
			$this->set_permissions(strval($category_id));
		}
	}

	/**
	 * Standard aed_module delete actualiser.
	 *
	 * @param  ID_TEXT		The entry being deleted
	 */
	function delete_actualisation($id)
	{
		$category_id=intval($id);

		check_delete_permission('cat_high',NULL);

		delete_download_category($category_id);
	}

	/**
	 * The do-next manager for after download content management (event types only).
	 *
	 * @param  tempcode		The title (output of get_screen_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?AUTO_LINK	The ID of whatever was just handled (NULL: N/A)
	 * @return tempcode		The UI
	 */
	function do_next_manager($title,$description,$id)
	{
		return $this->_do_next_manager($title,$description,NULL,is_null($id)?NULL:intval($id));
	}

	/**
	 * The do-next manager for after download content management.
	 *
	 * @param  tempcode		The title (output of get_screen_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?AUTO_LINK	The ID of whatever was just handled (NULL: delete/NA)
	 * @param  ?AUTO_LINK	The category ID we were working in (NULL: deleted/NA)
	 * @param  ?AUTO_LINK	The download licence ID we were working in (NULL: deleted/NA)
	 * @return tempcode		The UI
	 */
	function _do_next_manager($title,$description,$id=NULL,$category_id=NULL,$download_licence_id=NULL)
	{
		breadcrumb_set_self(do_lang_tempcode('DONE'));

		require_code('templates_donext');

		if ((is_null($id)) && (is_null($category_id)))
		{
			return do_next_manager($title,$description,
						NULL,
						NULL,
						/*		TYPED-ORDERED LIST OF 'LINKS'		*/
						/*	 page	 params				  zone	  */
						array('_SELF',array('type'=>'ad'),'_SELF'),							// Add one
						NULL,							 // Edit this
						has_specific_permission(get_member(),'edit_own_midrange_content','cms_downloads')?array('_SELF',array('type'=>'ed'),'_SELF'):NULL,											// Edit one
						NULL,							// View this
						array('downloads',array('type'=>'misc'),get_module_zone('downloads')),									 // View archive
						NULL,	  // Add to category
						has_specific_permission(get_member(),'submit_cat_midrange_content','cms_downloads')?array('_SELF',array('type'=>'ac'),'_SELF'):NULL,					  // Add one category
						has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_downloads')?array('_SELF',array('type'=>'ec'),'_SELF'):NULL,					  // Edit one category
						NULL,			 // Edit this category
						NULL,																						 // View this category
						/*	  SPECIALLY TYPED 'LINKS'				  */
						array(
							/*	 type							  page	 params													 zone	  */
							has_specific_permission(get_member(),'mass_import','cms_downloads')?array('import',array('_SELF',array('type'=>'import'),'_SELF'),do_lang('LOAD_FTP_FILES')):NULL,
						),
						array(),
						array(
							/*	 type							  page	 params													 zone	  */
							has_specific_permission(get_member(),'submit_cat_highrange_content','cms_downloads')?array('add_one_licence',array('_SELF',array('type'=>'av'),'_SELF'),do_lang('ADD_DOWNLOAD_LICENCE')):NULL,
							has_specific_permission(get_member(),'edit_cat_highrange_content','cms_downloads')?array('edit_one_licence',array('_SELF',array('type'=>'ev'),'_SELF'),do_lang('EDIT_DOWNLOAD_LICENCE')):NULL
						),
						do_lang('LICENCES')
			);
		}

		$special_links=array(has_specific_permission(get_member(),'mass_import','cms_downloads')?array('import',array('_SELF',array('type'=>'import'),'_SELF'),do_lang('LOAD_FTP_FILES')):NULL);

		if ((addon_installed('galleries')) && (!is_null($id)))
		{
			require_lang('galleries');
			$special_links[]=(has_specific_permission(get_member(),'submit_midrange_content','cms_galleries',array('galleries','download_'.strval($id))) && (!is_null($id)))?array('add_image_to_this',array('cms_galleries',array('type'=>'ad','cat'=>'download_'.strval($id)),get_module_zone('cms_galleries'))):NULL;
		}

		return do_next_manager($title,$description,
					NULL,
					NULL,
					/*		TYPED-ORDERED LIST OF 'LINKS'		*/
					/*	 page	 params				  zone	  */
					is_null($id)?NULL:array('_SELF',array('type'=>'ad','cat'=>$category_id),'_SELF'),											// Add one
					(is_null($id) || (!has_specific_permission(get_member(),'edit_own_midrange_content','cms_downloads',array('downloads',$category_id))))?NULL:array('_SELF',array('type'=>'_ed','id'=>$id),'_SELF'),							 // Edit this
					has_specific_permission(get_member(),'edit_own_midrange_content','cms_downloads')?array('_SELF',array('type'=>'ed'),'_SELF'):NULL,											// Edit one
					is_null($id)?NULL:array('downloads',array('type'=>'entry','id'=>$id),get_module_zone('downloads')),						  // View this
					array('downloads',array('type'=>'misc'),get_module_zone('downloads')),									 // View archive
					(!is_null($id))?NULL:array('_SELF',array('type'=>'ad','cat'=>$category_id),'_SELF'),	  // Add to category
					has_specific_permission(get_member(),'submit_cat_midrange_content','cms_downloads')?array('_SELF',array('type'=>'ac'),'_SELF'):NULL,				// Add one category
					has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_downloads')?array('_SELF',array('type'=>'ec'),'_SELF'):NULL,				// Edit one category
					has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_downloads')?array('_SELF',array('type'=>'_ec','id'=>$category_id),'_SELF'):NULL,			// Edit this category
					array('downloads',array('type'=>'misc','id'=>($category_id==db_get_first_id())?NULL:$category_id),get_module_zone('downloads')),	// View this category
					/*	  SPECIALLY TYPED 'LINKS'				  */
					$special_links,
					array(),
					array(
						/*	 type							  page	 params													 zone	  */
						has_specific_permission(get_member(),'submit_cat_highrange_content','cms_downloads')?array('add_one_licence',array('_SELF',array('type'=>'av'),'_SELF'),do_lang('ADD_DOWNLOAD_LICENCE')):NULL,
						has_specific_permission(get_member(),'edit_cat_highrange_content','cms_downloads')?array('edit_one_licence',array('_SELF',array('type'=>'ev'),'_SELF'),do_lang('EDIT_DOWNLOAD_LICENCE')):NULL
					),
					do_lang('LICENCES')
		);

	}

}


