<?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
 */

/**
 * Standard code module initialisation function.
 */
function init__downloads()
{
	global $PT_PAIR_CACHE_D;
	$PT_PAIR_CACHE_D=array();
}

/**
 * Show a download licence for display
 */
function download_licence_script()
{
	$id=get_param_integer('id');

	$rows=$GLOBALS['SITE_DB']->query_select('download_licences',array('*'),array('id'=>$id),'',1);
	if (!array_key_exists(0,$rows))
	{
		warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
	}
	$licence_title=$rows[0]['l_title'];
	$licence_text=$rows[0]['l_text'];
	$echo=do_template('STANDALONE_HTML_WRAP',array('_GUID'=>'d8f60d5f6f56b08589ed6f4b874dad85','TITLE'=>$licence_title,'POPUP'=>true,'CONTENT'=>comcode_to_tempcode($licence_text,$GLOBALS['FORUM_DRIVER']->get_guest_id(),false)));
	$echo->evaluate_echo();
}

/**
 * Get tempcode for a download 'feature box' for the sgiven row
 *
 * @param  array			The database field row of this download
 * @param  boolean		Whether to show a picture
 * @param  boolean		Whether to show breadcrumbs
 * @param  ?ID_TEXT		The zone the download module we're using is in (NULL: find it)
 * @param  ?string		Text summary for result (e.g. highlighted portion of actual file from search result) (NULL: none)
 * @return tempcode		A box for this download, linking to the full download page
 */
function render_download_box($row,$pic=true,$include_breadcrumbs=true,$zone=NULL,$text_summary=NULL)
{
	require_css('downloads');

	if (is_null($zone)) $zone=get_module_zone('downloads');

	// Details
	$filesize=$row['file_size'];
	$filesize=($filesize>0)?clean_file_size($filesize):do_lang('UNKNOWN');
	$description=is_string($row['description'])?comcode_to_tempcode($row['description']):get_translated_tempcode($row['description']);
	$root=get_param_integer('root',db_get_first_id(),true);
	if (array_key_exists('id',$row))
	{
		$map=array('page'=>'downloads','type'=>'entry','id'=>$row['id'],'root'=>($root==db_get_first_id())?NULL:$root);
		if (get_page_name()=='downloads') $map+=propagate_ocselect();
		$download_url=build_url($map,$zone);
	} else
	{
		$download_url=new ocp_tempcode();
	}
	$date=get_timezoned_date($row['add_date'],false);
	$date_raw=$row['add_date'];

	$breadcrumbs=((get_option('show_dload_trees')=='1') && ($include_breadcrumbs))?download_breadcrumbs($row['category_id'],NULL,false,$zone):new ocp_tempcode();

	$pic_suffix='';
	$thumb_url='';
	$full_img_url='';
	if ((addon_installed('galleries')) && ($pic) && (array_key_exists('id',$row)))
	{
		// Images
		$rows=$GLOBALS['SITE_DB']->query_select('images',array('url','thumb_url','id'),array('cat'=>'download_'.strval($row['id'])),'',1,$row['default_pic']-1);
		if (array_key_exists(0,$rows))
		{
			$pic_suffix='_pic';
			require_code('images');
			$full_img_url=$rows[0]['url'];
			$thumb_url=ensure_thumbnail($rows[0]['url'],$rows[0]['thumb_url'],'galleries','images',$rows[0]['id']);
			$imgcode=do_image_thumb($thumb_url,/*'['.*/do_lang('DOWNLOAD_THUMBNAIL')/*.'] '.get_translated_text($row['description'])*/);
		} else $imgcode=new ocp_tempcode();
	} else $imgcode=new ocp_tempcode();

	require_code('feedback');
	$rating=($row['allow_rating']==1 && array_key_exists('id',$row))?display_rating($download_url,is_string($row['name'])?$row['name']:get_translated_text($row['name']),'downloads',strval($row['id']),'RATING_INLINE_STATIC',$row['submitter']):NULL;
	if (!is_null($rating))
		if (trim($rating->evaluate())=='') $rating=NULL;

	$licence_title=NULL;
	$licence_url=NULL;
	$licence_hyperlink=NULL;
	$licence=$row['download_licence'];
	if (!is_null($licence))
	{
		$licence_title=$GLOBALS['SITE_DB']->query_value_null_ok('download_licences','l_title',array('id'=>$licence));
		if (!is_null($licence_title))
		{
			$keep=symbol_tempcode('KEEP');
			$licence_url=find_script('download_licence').'?id='.strval($licence).$keep->evaluate();
			$licence_hyperlink=do_template('HYPERLINK_POPUP_WINDOW',array('_GUID'=>'58a9e5c99bd236290009b6eab44dbac3','TITLE'=>'','CAPTION'=>$licence_title,'URL'=>$licence_url,'WIDTH'=>'600','HEIGHT'=>'500','REL'=>'license'));
		} else
		{
			$licence=NULL; // Orphaned
		}
	}

	$may_download=has_specific_permission(get_member(),'download','downloads',array(strval($row['category_id'])));

	// Final template
	if (($full_img_url!='') && (url_is_local($full_img_url))) $full_img_url=get_custom_base_url().'/'.$full_img_url;
	return do_template('DOWNLOAD_BOX',array('_GUID'=>'7a4737e21bdb4bd15ac5fe8570915d08','TEXT_SUMMARY'=>$text_summary,'AUTHOR'=>$row['author'],'ID'=>array_key_exists('id',$row)?strval($row['id']):'','RATING'=>$rating,'VIEWS'=>integer_format($row['download_views']),'SUBMITTER'=>strval($row['submitter']),'DESCRIPTION'=>$description,'FILE_SIZE'=>$filesize,'DOWNLOADS'=>integer_format($row['num_downloads']),'DATE_RAW'=>strval($date_raw),'DATE'=>$date,'EDIT_DATE_RAW'=>is_null($row['edit_date'])?'':strval($row['edit_date']),'SIZE'=>$filesize,'URL'=>$download_url,'NAME'=>is_string($row['name'])?$row['name']:get_translated_text($row['name']),'BREADCRUMBS'=>$breadcrumbs,'IMG_URL'=>$thumb_url,'FULL_IMG_URL'=>$full_img_url,'IMGCODE'=>$imgcode,'LICENCE'=>is_null($licence)?NULL:strval($licence),'LICENCE_TITLE'=>$licence_title,'LICENCE_HYPERLINK'=>$licence_hyperlink,'MAY_DOWNLOAD'=>$may_download));
}

/**
 * Get tempcode for a download category 'feature box' for the given row
 *
 * @param  array			The database field row of it
 * @param  ID_TEXT		The zone to use
 * @param  boolean		Whether to put it in a box
 * @return tempcode		A box for it, linking to the full page
 */
function render_download_category_box($row,$zone='_SEARCH',$put_in_box=true)
{
	$url=build_url(array('page'=>'downloads','type'=>'misc','id'=>($row['id']==db_get_first_id())?NULL:$row['id']),$zone);

	$breadcrumbs=mixed();
	$title=mixed();
	if ($put_in_box)
	{
		if (!is_null($row['parent_id']))
		{
			$breadcrumbs=download_breadcrumbs($row['parent_id'],NULL,false,$zone);
		}
		$title=get_translated_text($row['category']);
	}

	return do_template('SIMPLE_PREVIEW_BOX',array('_GUID'=>'aaea5f7f64297ab46aa3b3182fb57c37','BREADCRUMBS'=>$breadcrumbs,'TITLE'=>$title,'SUMMARY'=>get_translated_tempcode($row['description']),'URL'=>$url));
}

/**
 * Get a nice, formatted XHTML list of downloads, in download tree structure
 *
 * @param  ?AUTO_LINK	The currently selected entry (NULL: none selected)
 * @param  ?AUTO_LINK	Only show entries submitted by this member (NULL: no filter)
 * @param  ?AUTO_LINK	Download we do not want to show (NULL: none to not show)
 * @param  boolean		Whether to get a list of child categories (not just direct ones, recursively), instead of just IDs
 * @param  boolean		Whether to only show for what may be edited by the current member
 * @return tempcode		The list of entries
 */
function nice_get_downloads_tree($it=NULL,$submitter=NULL,$shun=NULL,$use_compound_list=false,$editable_filter=false)
{
	$tree=get_downloads_tree($submitter,NULL,NULL,NULL,$shun,NULL,$use_compound_list,$editable_filter);
	if ($use_compound_list) $tree=$tree[0];

	$out=''; // XHTMLXHMTML
	foreach ($tree as $category)
	{
		foreach ($category['entries'] as $eid=>$etitle)
		{
			$selected=($eid==$it);
			$line=do_template('DOWNLOAD_LIST_LINE',array('_GUID'=>'7bb13e4418b500cb2b330e629710138a','BREADCRUMBS'=>$category['breadcrumbs'],'DOWNLOAD'=>$etitle));
			$out.='<option value="'.(!$use_compound_list?strval($eid):$category['compound_list']).'"'.($selected?' selected="selected"':'').'>'.$line->evaluate().'</option>';
		}
	}

	if ($GLOBALS['XSS_DETECT']) ocp_mark_as_escaped($out);

	return make_string_tempcode($out);
}

/**
 * Get a list of maps containing all the downloads, and path information, under the specified category - and those beneath it, recursively.
 *
 * @param  ?MEMBER		Only show images/videos submitted by this member (NULL: no filter)
 * @param  ?AUTO_LINK	The category being at the root of our recursion (NULL: true root)
 * @param  ?string		The breadcrumbs up to this point in the recursion (NULL: blank, as we are starting the recursion)
 * @param  ?ID_TEXT		The name of the $category_id we are currently going through (NULL: look it up). This is here for efficiency reasons, as finding children IDs to recurse to also reveals the childs title
 * @param  ?integer		The number of recursive levels to search (NULL: all)
 * @param  ?AUTO_LINK	Download we do not want to show (NULL: none to not show)
 * @param  boolean		Whether to get a list of child categories (not just direct ones, recursively), instead of just IDs
 * @param  boolean		Whether to only show for what may be edited by the current member
 * @param  boolean		Whether to only show entries that are tar files (addons)
 * @return array			A list of maps for all categories. Each map entry containins the fields 'id' (category ID) and 'breadcrumbs' (to the category, including the categories own title), and more. Or if $use_compound_list, the tree structure built with pairs containing the compound list in addition to the child branches
 */
function get_downloads_tree($submitter=NULL,$category_id=NULL,$breadcrumbs=NULL,$title=NULL,$shun=NULL,$levels=NULL,$use_compound_list=false,$editable_filter=false,$tar_filter=false)
{
	if (is_null($category_id)) $category_id=db_get_first_id();

	if (!has_category_access(get_member(),'downloads',strval($category_id))) return array();

	if (is_null($breadcrumbs)) $breadcrumbs='';

	// Put our title onto our breadcrumbs
	if (is_null($title)) $title=get_translated_text($GLOBALS['SITE_DB']->query_value('download_categories','category',array('id'=>$category_id)));
	$breadcrumbs.=$title;

	$compound_list=strval($category_id).',';

	// We'll be putting all children in this entire tree into a single list
	$children=array();
	$children[0]=array();
	$children[0]['id']=$category_id;
	$children[0]['title']=$title;
	$children[0]['breadcrumbs']=$breadcrumbs;

	// Children of this category
	$rows=$GLOBALS['SITE_DB']->query_select('download_categories',array('id','category'),array('parent_id'=>$category_id),'',300/*reasonable limit*/);
	if (count($rows)==300) $rows=array();
	$where=array('category_id'=>$category_id);
	if (!is_null($submitter)) $where['submitter']=$submitter;
	$erows=$GLOBALS['SITE_DB']->query_select('download_downloads',array('id','name','submitter','original_filename'),$where,'ORDER BY add_date DESC',300/*reasonable limit*/);
	$children[0]['entries']=array();
	foreach ($erows as $row)
	{
		if (($tar_filter) && (substr(strtolower($row['original_filename']),-4)!='.tar')) continue;
		if (($editable_filter) && (!has_edit_permission('mid',get_member(),$row['submitter'],'cms_downloads',array('download_downloads',$category_id)))) continue;
		if ((!is_null($shun)) && ($shun==$row['id'])) continue;

		$children[0]['entries'][$row['id']]=get_translated_text($row['name']);
	}
	$children[0]['child_entry_count']=count($children[0]['entries']);
	if ($levels===0) // We throw them away now because they're not on the desired level
	{
		$children[0]['entries']=array();
	}
	$children[0]['child_count']=count($rows);
	$breadcrumbs.=' > ';
	if (($levels!==0) || ($use_compound_list))
	{
		foreach ($rows as $child)
		{
			$child_id=$child['id'];
			$child_title=get_translated_text($child['category']);
			$child_breadcrumbs=$breadcrumbs;

			$child_children=get_downloads_tree($submitter,$child_id,$child_breadcrumbs,$child_title,$shun,is_null($levels)?NULL:max(0,$levels-1),$use_compound_list,$editable_filter,$tar_filter);
			if ($use_compound_list)
			{
				list($child_children,$_compound_list)=$child_children;
				$compound_list.=$_compound_list;
			}

			if ($levels!==0)
			$children=array_merge($children,$child_children);
		}
	}
	$children[0]['compound_list']=$compound_list;

	return $use_compound_list?array($children,$compound_list):$children;
}

/**
 * Get a nice, formatted XHTML list extending from the root, and showing all subcategories, and their subcategories (ad infinitum). The tree bit is because each entry in the list is shown to include the path through the tree that gets to it
 *
 * @param  ?AUTO_LINK	The currently selected category (NULL: none selected)
 * @param  boolean		Whether to make the list elements store comma-separated child lists instead of IDs
 * @param  boolean		Whether to only show for what may be added to by the current member
 * @return tempcode		The list of categories
 */
function nice_get_download_category_tree($it=NULL,$use_compound_list=false,$addable_filter=false)
{
	$tree=get_download_category_tree(NULL,NULL,NULL,false,$use_compound_list,NULL,$addable_filter);
	if ($use_compound_list) $tree=$tree[0];

	$out=''; // XHTMLXHTML
	foreach ($tree as $category)
	{
		if (($addable_filter) && (!$category['addable'])) continue;

		$selected=($category['id']==$it);
		$line=do_template('DOWNLOAD_LIST_LINE_2',array('_GUID'=>'0ccffeff5b80b1840188b839aee8d9f2','BREADCRUMBS'=>$category['breadcrumbs'],'FILECOUNT'=>'?'));
		$out.='<option value="'.(!$use_compound_list?strval($category['id']):$category['compound_list']).'"'.($selected?' selected="selected"':'').'>'.$line->evaluate().'</option>';
	}

	if ($GLOBALS['XSS_DETECT']) ocp_mark_as_escaped($out);

	return make_string_tempcode($out);
}

/**
 * Get a nice, formatted XHTML list to select a download licence
 *
 * @param  ?AUTO_LINK	The currently selected licence (NULL: none selected)
 * @param  boolean		Whether to allow an N/A selection
 * @return tempcode		The list of categories
 */
function nice_get_download_licences($it=NULL,$allow_na=false)
{
	$list=new ocp_tempcode();
	if ($allow_na) $list->attach(form_input_list_entry('-1',false,do_lang_tempcode('NA_EM')));
	$rows=$GLOBALS['SITE_DB']->query_select('download_licences',array('id','l_title'));
	foreach ($rows as $row)
	{
		$list->attach(form_input_list_entry(strval($row['id']),$it==$row['id'],$row['l_title']));
	}
	return $list;
}

/**
 * Get a list of maps containing all the subcategories, and path information, of the specified category - and those beneath it, recursively.
 *
 * @param  ?AUTO_LINK	The category being at the root of our recursion (NULL: true root category)
 * @param  ?string		The breadcrumbs up to this point in the recursion (NULL: blank, as we are starting the recursion)
 * @param  ?ID_TEXT		The category name of the $category_id we are currently going through (NULL: look it up). This is here for efficiency reasons, as finding children IDs to recurse to also reveals the childs title
 * @param  boolean		Whether to collect download counts with our tree information
 * @param  boolean		Whether to make a compound list (a pair of a comma-separated list of children, and the child array)
 * @param  ?integer		The number of recursive levels to search (NULL: all)
 * @param  boolean		Whether to only show for what may be added to by the current member
 * @return array			A list of maps for all subcategories. Each map entry containins the fields 'id' (category ID) and 'breadcrumbs' (path to the category, including the categories own title). There is also an additional 'downloadcount' entry if stats were requested
 */
function get_download_category_tree($category_id=NULL,$breadcrumbs=NULL,$title=NULL,$do_stats=true,$use_compound_list=false,$levels=NULL,$addable_filter=false)
{
	if ($levels==-1) return array();

//	if (!has_category_access(get_member(),'downloads',strval($category_id))) return array();

	if (is_null($category_id)) $category_id=db_get_first_id();
	if (is_null($breadcrumbs)) $breadcrumbs='';

	// Put our title onto our breadcrumbs
	if (is_null($title)) $title=get_translated_text($GLOBALS['SITE_DB']->query_value('download_categories','category',array('id'=>$category_id)));
	$breadcrumbs.=$title;

	// We'll be putting all children in this entire tree into a single list
	$children=array();
	$children[0]=array();
	$children[0]['id']=$category_id;
	$children[0]['title']=$title;
	$children[0]['breadcrumbs']=$breadcrumbs;
	$children[0]['compound_list']=strval($category_id).',';
	if ($addable_filter) $children[0]['addable']=has_submit_permission('mid',get_member(),get_ip_address(),'cms_downloads',array('downloads',$category_id));
	if ($do_stats) $children[0]['filecount']=$GLOBALS['SITE_DB']->query_value('download_downloads','COUNT(*)',array('category_id'=>$category_id));

	// Children of this category
	$rows=$GLOBALS['SITE_DB']->query_select('download_categories',array('id','category'),array('parent_id'=>$category_id),'',300/*reasonable*/);
	if (count($rows)==300) $rows=array();
	$children[0]['child_count']=count($rows);
	$breadcrumbs.=' > ';
	if ($levels!==0)
	{
		foreach ($rows as $child)
		{
			$child_id=$child['id'];
			$child_title=get_translated_text($child['category']);
			$child_breadcrumbs=$breadcrumbs;

			$child_children=get_download_category_tree($child_id,$child_breadcrumbs,$child_title,$do_stats,$use_compound_list,is_null($levels)?NULL:max(0,$levels-1),$addable_filter);
			if ($use_compound_list)
			{
				list($child_children,$_compound_list)=$child_children;
				$children[0]['compound_list'].=$_compound_list;
			}

			$children=array_merge($children,$child_children);
		}
	}

	return $use_compound_list?array($children,$children[0]['compound_list']):$children;
}

/**
 * Get a formatted XHTML string of the route back to the specified root, from the specified category.
 *
 * @param  AUTO_LINK		The category we are finding for
 * @param  ?AUTO_LINK	The root of the tree (NULL: the true root)
 * @param  boolean		Whether to include category links at this level (the recursed levels will always contain links - the top level is optional, hence this parameter)
 * @param  ?ID_TEXT		The zone the download module we're using is in (NULL: find it)
 * @return tempcode		The breadcrumbs
 */
function download_breadcrumbs($category_id,$root=NULL,$no_link_for_me_sir=true,$zone=NULL)
{
	if (is_null($root)) $root=db_get_first_id();
	if (is_null($zone)) $zone=get_module_zone('downloads');

	$url=build_url(array('page'=>'downloads','type'=>'misc','id'=>($category_id==db_get_first_id())?NULL:$category_id,'root'=>($root==db_get_first_id())?NULL:$root)+propagate_ocselect(),$zone);

	if (($category_id==$root) || ($category_id==db_get_first_id()))
	{
		if ($no_link_for_me_sir) return new ocp_tempcode();
		$title=get_translated_text($GLOBALS['SITE_DB']->query_value('download_categories','category',array('id'=>$category_id)));
		return hyperlink($url,escape_html($title),false,false,do_lang_tempcode('GO_BACKWARDS_TO',$title),NULL,NULL,'up');
	}

	global $PT_PAIR_CACHE_D;
	if (!array_key_exists($category_id,$PT_PAIR_CACHE_D))
	{
		$category_rows=$GLOBALS['SITE_DB']->query_select('download_categories',array('parent_id','category'),array('id'=>$category_id),'',1);
		if (!array_key_exists(0,$category_rows)) warn_exit(do_lang_tempcode('CAT_NOT_FOUND',strval($category_id)));
		$PT_PAIR_CACHE_D[$category_id]=$category_rows[0];
	}

	$title=get_translated_text($PT_PAIR_CACHE_D[$category_id]['category']);
	if (!$no_link_for_me_sir)
	{
		$tpl_url=do_template('BREADCRUMB_SEPARATOR');
		$tpl_url->attach(hyperlink($url,escape_html($title),false,false,do_lang_tempcode('GO_BACKWARDS_TO',$title),NULL,NULL,'up'));
	} else $tpl_url=new ocp_tempcode();

	if ($PT_PAIR_CACHE_D[$category_id]['parent_id']==$category_id) fatal_exit(do_lang_tempcode('RECURSIVE_TREE_CHAIN',strval($category_id)));
	$below=download_breadcrumbs($PT_PAIR_CACHE_D[$category_id]['parent_id'],$root,false,$zone);

	$below->attach($tpl_url);
	return $below;
}

/**
 * Count the downloads and subcategories underneath the specified category, recursively.
 *
 * @param  AUTO_LINK		The ID of the category for which count details are collected
 * @return array			The number of downloads is returned in $output['num_downloads'], and the number of subcategories is returned in $output['num_children'], and the (possibly recursive) number of downloads is returned in $output['num_downloads_children'].
 */
function count_download_category_children($category_id)
{
	static $total_categories=NULL;
	if (is_null($total_categories)) $total_categories=$GLOBALS['SITE_DB']->query_value('download_categories','COUNT(*)');

	$out=array();
	$out['num_children']=$GLOBALS['SITE_DB']->query_value('download_categories','COUNT(*)',array('parent_id'=>$category_id));
	$out['num_downloads']=$GLOBALS['SITE_DB']->query_value('download_downloads','COUNT(*)',array('category_id'=>$category_id,'validated'=>1));

	$out['num_downloads_children']=$out['num_downloads'];
	if ($total_categories<200) // Make sure not too much, performance issue
	{
		$rows=$GLOBALS['SITE_DB']->query_select('download_categories',array('id'),array('parent_id'=>$category_id));
		foreach ($rows as $child)
		{
			$temp=count_download_category_children($child['id']);
			$out['num_downloads_children']+=$temp['num_downloads_children'];
		}
	}

	return $out;
}

/**
 * Get tempcode to view the downloads in a download category.
 *
 * @param  AUTO_LINK		The download category ID
 * @param  AUTO_LINK		The virtual root
 * @param  ?string		Force an order (NULL: don't)
 * @return tempcode		The UI
 */
function get_category_downloads($category_id,$root,$order=NULL)
{
	$max=get_param_integer('max',30);
	$start=get_param_integer('start',0);

	// WHERE clause
	if (get_option('downloads_subcat_narrowin')=='1')
	{
		require_code('ocfiltering');
		$map=ocfilter_to_sqlfragment(strval($category_id).'*','id','download_categories','parent_id','category_id','id');
	} else
	{
		$map='category_id='.strval($category_id);
	}
	if (!has_specific_permission(get_member(),'see_unvalidated')) $map.=' AND validated=1';

	// ocSelect
	$ocselect=either_param('active_filter','');
	if ($ocselect!='')
	{
		require_code('ocselect');
		$content_type='download';
		list($ocselect_extra_select,$ocselect_extra_join,$ocselect_extra_where)=ocselect_to_sql($GLOBALS['SITE_DB'],parse_ocselect($ocselect),$content_type,'');
		$extra_select_sql=implode('',$ocselect_extra_select);
		$extra_join_sql=implode('',$ocselect_extra_join);
		$map.=$ocselect_extra_where;
	} else
	{
		$extra_select_sql='';
		$extra_join_sql='';
	}

	// How many might there have been? (So we know how to browse pages nicely)
	$max_rows=$GLOBALS['SITE_DB']->query_value_null_ok_full('SELECT COUNT(*) FROM '.get_table_prefix().'download_downloads r'.$extra_join_sql.' WHERE '.$map);

	// Quick security check
	if (is_null($order))
	{
		$order=get_param('order',NULL);
		if (is_null($order))
		{
			if ($max_rows<1000)
			{
				$order='t.text_original ASC';
			} else
			{
				$order='num_downloads DESC';
			}
		}
	}
	if ((strtoupper($order)!=strtoupper('t.text_original ASC')) && (strtoupper($order)!=strtoupper('t.text_original DESC')) && (strtoupper($order)!=strtoupper('file_size ASC')) && (strtoupper($order)!=strtoupper('file_size DESC'))
		&& (strtoupper($order)!=strtoupper('num_downloads DESC')) && (strtoupper($order)!=strtoupper('add_date ASC'))
		&& (strtoupper($order)!=strtoupper('add_date DESC'))) log_hack_attack_and_exit('ORDERBY_HACK');
	global $NON_CANONICAL_PARAMS;
	$NON_CANONICAL_PARAMS[]='order';

	// Fetch
	$rows=$GLOBALS['SITE_DB']->query('SELECT r.*,t.text_original'.$extra_select_sql.' FROM '.get_table_prefix().'download_downloads r'.$extra_join_sql.' LEFT JOIN '.get_table_prefix().'translate t ON '.db_string_equal_to('t.language',user_lang()).' AND r.name=t.id WHERE '.$map.' ORDER BY '.$order,$max,$start);
	$out=new ocp_tempcode();
	foreach ($rows as $myrow)
	{
		if ($GLOBALS['RECORD_LANG_STRINGS_CONTENT'] || is_null($myrow['text_original'])) $myrow['text_original']=get_translated_text($myrow['description']);

		$out->attach(render_download_box($myrow,true,false));
	}
	if ($out->is_empty()) return $out;

	require_code('templates_pagination');
	$out->attach(pagination(do_lang_tempcode('SECTION_DOWNLOADS'),$category_id,$start,'start',$max,'max',$max_rows,$root,'misc',true));
	return $out;
}

/**
 * Get a templated view of the subcategories directly under the specified category.
 *
 * @param  AUTO_LINK		The category the subcategories are being found for
 * @param  ?AUTO_LINK	The pretend root of our download system (NULL: true root). This system is provided for large sites to be able to do virtually seperated download systems
 * @param  ?ID_TEXT		The zone the download module we're using is in (NULL: find it)
 * @param  ?string		The order to show results in (NULL: default)
 * @return tempcode		The templated view
 */
function get_download_sub_categories($category_id,$root=NULL,$zone=NULL,$order=NULL)
{
	if (is_null($order)) $order='t.text_original ASC';
	if (is_null($root)) $root=db_get_first_id();
	if (is_null($zone)) $zone=get_module_zone('downloads');

	$rows=$GLOBALS['SITE_DB']->query_select('download_categories c LEFT JOIN '.get_table_prefix().'translate t ON '.db_string_equal_to('language',user_lang()).' AND c.category=t.id',array('rep_image','c.id','category','text_original','description'),array('parent_id'=>$category_id),(($order=='t.text_original ASC')?'':('ORDER BY '.$order)),400/*reasonable limit*/);
	if ($order=='t.text_original ASC')
	{
		global $M_SORT_KEY;
		$M_SORT_KEY='text_original';
		usort($rows,'multi_sort');
	}
	if (count($rows)==400) $rows=array(); // Too much, performance issue
	$out=new ocp_tempcode();
	foreach ($rows as $myrow)
	{
		if (!has_category_access(get_member(),'downloads',strval($myrow['id']))) continue;

		if ($GLOBALS['RECORD_LANG_STRINGS_CONTENT'] || is_null($myrow['text_original'])) $myrow['text_original']=get_translated_text($myrow['category']);

		$child_id=$myrow['id'];
		$child_title=$myrow['text_original'];

		$info=count_download_category_children($child_id);
		$num_children=$info['num_children'];
		$num_downloads=$info['num_downloads_children'];
		$display_string=do_lang_tempcode('CATEGORY_SUBORDINATE',integer_format($num_downloads),integer_format($num_children));

		$url=build_url(array('page'=>'downloads','type'=>'misc','id'=>($child_id==db_get_first_id())?NULL:$child_id,'root'=>($root==db_get_first_id())?NULL:$root,'order'=>get_param('order',NULL))+propagate_ocselect(),$zone);

		if ($myrow['rep_image']!='')
		{
			require_code('images');
			$rep_image=do_image_thumb($myrow['rep_image'],'');
		} else $rep_image=new ocp_tempcode();

		$ajax_edit_url='_SEARCH:cms_downloads:type=__ec:id='.strval($child_id);

		$description=get_translated_tempcode($myrow['description']);

		$out->attach(do_template('CATEGORY_ENTRY',array('_GUID'=>'8bfb36d75a85e2a7fbf5222f8fc61c7d','DESCRIPTION'=>$description,'ID'=>strval($child_id),'NAME_FIELD'=>'category','AJAX_EDIT_URL'=>$ajax_edit_url,'URL'=>$url,'REP_IMAGE'=>$rep_image,'CHILDREN'=>$display_string,'NAME'=>$child_title,'NAME_PLAIN'=>$child_title)));
	}
	if ($out->is_empty()) return $out;

	return do_template('CATEGORY_LIST',array('_GUID'=>'2de3e2cdd0180a584b4f4ec72652716f','CONTENT'=>$out));
}

