<?php /*

 Composr
 Copyright (c) ocProducts, 2004-2016

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

/**
 * Module page class.
 */
class Module_filedump
{
    /**
     * Find details of the module.
     *
     * @return ?array Map of module info (null: module is disabled).
     */
    public function info()
    {
        $info = array();
        $info['author'] = 'Chris Graham';
        $info['organisation'] = 'ocProducts';
        $info['hacked_by'] = null;
        $info['hack_version'] = null;
        $info['version'] = 4;
        $info['update_require_upgrade'] = true;
        $info['locked'] = false;
        return $info;
    }

    /**
     * Uninstall the module.
     */
    public function uninstall()
    {
        $GLOBALS['SITE_DB']->drop_table_if_exists('filedump');

        delete_privilege('delete_anything_filedump');
        delete_privilege('upload_filedump');
        delete_privilege('upload_anything_filedump');

        $GLOBALS['SITE_DB']->query_delete('group_page_access', array('page_name' => 'filedump'));

        //require_code('files');
        //deldir_contents(get_custom_file_base() . '/uploads/filedump', true);
    }

    /**
     * Install the module.
     *
     * @param  ?integer $upgrade_from What version we're upgrading from (null: new install)
     * @param  ?integer $upgrade_from_hack What hack version we're upgrading from (null: new-install/not-upgrading-from-a-hacked-version)
     */
    public function install($upgrade_from = null, $upgrade_from_hack = null)
    {
        if (is_null($upgrade_from)) {
            $GLOBALS['SITE_DB']->create_table('filedump', array(
                'id' => '*AUTO',
                'name' => 'ID_TEXT',
                'path' => 'URLPATH',
                'description' => 'SHORT_TRANS',
                'the_member' => 'MEMBER'
            ));

            add_privilege('FILEDUMP', 'upload_anything_filedump', false);
            add_privilege('FILEDUMP', 'upload_filedump', true);
            add_privilege('FILEDUMP', 'delete_anything_filedump', false);

            $usergroups = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(false, true);
            foreach (array_keys($usergroups) as $id) {
                $GLOBALS['SITE_DB']->query_insert('group_page_access', array('page_name' => 'filedump', 'zone_name' => 'cms', 'group_id' => $id)); // Don't want to let anyone do filedump stuff just because we let them manage content
            }
        }

        if ((!is_null($upgrade_from)) && ($upgrade_from < 4)) {
            if (addon_installed('redirects_editor')) {
                $GLOBALS['SITE_DB']->query_delete('redirects', array('r_from_page' => 'filedump', 'r_from_zone' => 'collaboration', 'r_to_page' => 'filedump', 'r_to_zone' => 'cms', 'r_is_transparent' => 1));
            }

            $GLOBALS['SITE_DB']->query_update('privilege_list', array('p_section' => 'FILEDUMP'), array('p_section' => 'FILE_DUMP'));
        }
    }

    /**
     * Find entry-points available within this module.
     *
     * @param  boolean $check_perms Whether to check permissions.
     * @param  ?MEMBER $member_id The member to check permissions as (null: current user).
     * @param  boolean $support_crosslinks Whether to allow cross links to other modules (identifiable via a full-page-link rather than a screen-name).
     * @param  boolean $be_deferential Whether to avoid any entry-point (or even return null to disable the page in the Sitemap) if we know another module, or page_group, is going to link to that entry-point. Note that "!" and "browse" entry points are automatically merged with container page nodes (likely called by page-groupings) as appropriate.
     * @return ?array A map of entry points (screen-name=>language-code/string or screen-name=>[language-code/string, icon-theme-image]) (null: disabled).
     */
    public function get_entry_points($check_perms = true, $member_id = null, $support_crosslinks = true, $be_deferential = false)
    {
        if ($member_id === null) {
            $member_id = get_member();
        }

        $ret = array(
            'browse' => array('FILEDUMP', 'menu/cms/filedump'),
        );
        if ($GLOBALS['FORUM_DRIVER']->is_super_admin($member_id)) {
            $ret += array(
                'broken' => array('FIND_BROKEN_FILEDUMP_LINKS', 'menu/adminzone/tools/cleanup'),
            );
        }
        return $ret;
    }

    public $title;
    public $place;

    /**
     * Module pre-run function. Allows us to know metadata for <head> before we start streaming output.
     *
     * @return ?Tempcode Tempcode indicating some kind of exceptional output (null: none).
     */
    public function pre_run()
    {
        require_lang('filedump');

        $type = get_param_string('type', 'browse');

        if ($type == 'browse') {
            $place = filter_naughty(get_param_string('place', '/'));
            if (substr($place, -1, 1) != '/') {
                $place .= '/';
            }

            set_feed_url('?mode=filedump&select=' . urlencode($place));

            // Show breadcrumbs
            $dirs = explode('/', substr($place, 0, strlen($place) - 1));
            $pre = '';
            $breadcrumbs = array();
            foreach ($dirs as $i => $d) {
                if ($i == 0) {
                    $d = do_lang('FILEDUMP');
                }

                if (array_key_exists($i + 1, $dirs)) {
                    $breadcrumbs_page_link = build_page_link(array('page' => '_SELF', 'place' => $pre . $dirs[$i] . '/'), '_SELF');
                    $breadcrumbs[] = array($breadcrumbs_page_link, $d);
                }
                $pre .= $dirs[$i] . '/';
            }
            if ($breadcrumbs !== array()) {
                $breadcrumbs[] = array('', $d);
                breadcrumb_set_parents($breadcrumbs);
            } else {
                breadcrumb_set_self(($i == 1) ? do_lang_tempcode('FILEDUMP') : protect_from_escaping(escape_html($d)));
            }

            $this->place = $place;

            $this->title = get_screen_title('FILEDUMP');
        }

        if ($type == 'embed') {
            $this->title = get_screen_title('FILEDUMP_EMBED');
        }

        if ($type == 'add') {
            $this->title = get_screen_title('FILEDUMP_UPLOAD');
        }

        if ($type == 'mass') {
            $action = post_param_string('action');
            switch ($action) {
                case 'edit':
                    $this->title = get_screen_title('FILEDUMP_EDIT');
                    break;

                case 'delete':
                    $this->title = get_screen_title('FILEDUMP_DELETE');
                    break;

                case 'zip':
                    $GLOBALS['OUTPUT_STREAMING'] = false;

                    $this->title = get_screen_title('FILEDUMP_ZIP');
                    break;

                default:
                    $this->title = get_screen_title('FILEDUMP_MOVE');
                    break;
            }

            breadcrumb_set_parents(array(array('_SELF:_SELF', do_lang_tempcode('FILEDUMP'))));

            if ((post_param_integer('confirmed', 0) != 1) && ($action != 'edit'/*edit too trivial/specific to need a confirm*/)) {
                breadcrumb_set_self(do_lang_tempcode('CONFIRM'));
            }
        }

        if ($type == 'broken') {
            $this->title = get_screen_title('FIND_BROKEN_FILEDUMP_LINKS');
        }

        if ($type == '_broken') {
            $this->title = get_screen_title('FIX_BROKEN_FILEDUMP_LINKS');
        }

        return null;
    }

    /**
     * Execute the module.
     *
     * @return Tempcode The result of execution.
     */
    public function run()
    {
        require_lang('filedump');
        require_css('filedump');
        require_code('filedump');
        require_code('files');
        require_code('files2');

        $type = get_param_string('type', 'browse');

        if ($type == 'browse') {
            return $this->do_gui();
        }
        if ($type == 'embed') {
            return $this->do_embed();
        }
        if ($type == 'mass') {
            return $this->do_mass();
        }
        if ($type == 'add_category') {
            return $this->do_add_folder();
        }
        if ($type == 'add') {
            return $this->do_upload();
        }
        if ($type == 'broken') {
            return $this->broken();
        }
        if ($type == '_broken') {
            return $this->_broken();
        }

        return new Tempcode();
    }

    /**
     * The main user interface for the file dump.
     *
     * @return Tempcode The UI.
     */
    public function do_gui()
    {
        require_code('form_templates');
        require_code('images');

        disable_php_memory_limit();

        $place = $this->place;

        $type_filter = get_param_string('type_filter', '');

        $search = get_param_string('search', '', true);
        if ($search == do_lang('SEARCH')) {
            $search = '';
        }

        $sort = get_param_string('sort', 'time ASC');
        if (strpos($sort, ' ') === false) {
            $sort = 'time ASC';
        }
        list($order, $direction) = explode(' ', $sort, 2);
        if ($direction != 'ASC' && $direction != 'DESC') {
            $direction = 'ASC';
        }

        $recurse = get_param_integer('recurse', 0);

        // Check directory exists
        $full_path = get_custom_file_base() . '/uploads/filedump' . $place;
        if (!file_exists(get_custom_file_base() . '/uploads/filedump' . $place)) {
            if (has_privilege(get_member(), 'upload_filedump')) {
                cms_file_put_contents_safe($full_path . '/index.html', '', FILE_WRITE_FIX_PERMISSIONS | FILE_WRITE_SYNC_FILE);
            }
        }

        // Find all files in the filedump directory
        $db_rows = array();
        $something_editable = false;
        $files = array();
        $dir_contents = get_directory_contents(get_custom_file_base() . '/uploads/filedump' . $place, trim($place, '/'), false, $recurse == 1);
        foreach ($dir_contents as $filename) {
            $_place = dirname($filename);
            if ($_place == '.') {
                $_place = '';
            }
            $_place = '/' . $_place . (($_place == '') ? '' : '/');
            $filename = basename($filename);

            if (!should_ignore_file('uploads/filedump' . $_place . $filename, IGNORE_ACCESS_CONTROLLERS | IGNORE_HIDDEN_FILES)) {
                $_full = get_custom_file_base() . '/uploads/filedump' . $_place . $filename;
                if (!file_exists($_full)) {
                    continue; // Broken symlink or (?) permission problem
                }

                if (!isset($db_rows[$_place])) {
                    $db_rows[$_place] = list_to_map('name', $GLOBALS['SITE_DB']->query_select('filedump', array('*'), array('path' => cms_mb_substr($_place, 0, 80))));
                }

                $is_directory = !is_file($_full);

                $db_row = isset($db_rows[$_place][$filename]) ? $db_rows[$_place][$filename] : null;

                $_description = isset($db_row) ? get_translated_text($db_row['description']) : '';

                if ($is_directory) {
                    if (!$this->_folder_search($_place . $filename . '/', $_description, $search, $type_filter)) {
                        continue;
                    }
                } else {
                    if (!$this->_matches_filter($filename, $_description, $search, $type_filter)) {
                        continue;
                    }
                }

                if ($is_directory) {
                    $filesize = get_directory_size($_full);
                    $timestamp = null;
                } else {
                    $filesize = filesize($_full);
                    $timestamp = filemtime($_full);
                }

                $editable = ((!is_null($db_row)) && ($db_row['the_member'] == get_member())) || (has_privilege(get_member(), 'delete_anything_filedump'));
                if ($editable) {
                    $something_editable = true;
                }

                $files[] = array(
                    'filename' => $is_directory ? ($filename . '/') : $filename,
                    'place' => $_place,
                    '_description' => $_description,
                    '_size' => $filesize,
                    '_time' => $timestamp,
                    'submitter' => isset($db_row) ? $db_row['the_member'] : null,
                    'is_directory' => $is_directory,
                    'editable' => $editable,
                );
            }
        }

        // Sorting
        switch ($order) {
            case 'time':
                @sort_maps_by($files, '_time');
                break;
            case 'name':
                @sort_maps_by($files, 'filename');
                break;
            case 'size':
                @sort_maps_by($files, '_size');
                break;
        }
        if ($direction == 'DESC') {
            $files = array_reverse($files);
        }

        // Pagination
        $max_rows = count($files);
        $start = get_param_integer('start', 0);
        $max = get_param_integer('max', 50);
        $files = array_slice($files, $start, $max);

        $thumbnails = array();

        if (count($files) > 0) { // If there are some files
            require_code('templates_columned_table');
            $header_row = columned_table_header_row(array(
                do_lang_tempcode('FILENAME'),
                do_lang_tempcode('DESCRIPTION'),
                do_lang_tempcode('menus:LINK'),
                do_lang_tempcode('SUBMITTER'),
                do_lang_tempcode('DATE_TIME'),
                do_lang_tempcode('ACTIONS'),
                do_lang_tempcode('CHOOSE'),
            ));

            $url = mixed();

            $rows = new Tempcode();
            foreach ($files as $i => $file) {
                $filename = $file['filename'];
                $_place = $file['place'];
                $_full = get_custom_file_base() . '/uploads/filedump' . $_place . $filename;

                $_description = $file['_description'];
                if ($_description != '') {
                    $description = make_string_tempcode($_description);
                    $description_2 = $description;
                } else {
                    $description = new Tempcode();
                    $description_2 = ($is_directory) ? do_lang_tempcode('FOLDER') : new Tempcode();
                }

                $editable = $file['editable'];

                $width = mixed();
                $height = mixed();
                $dims = cms_getimagesize($_full);
                if ($dims !== false) {
                    list($width, $height) = $dims;
                }

                $file += array(
                    'description' => $description,
                    'description_2' => $description_2,
                    'width' => $width,
                    'height' => $height,
                    'size' => clean_file_size($file['_size']),
                    'time' => is_null($file['_time']) ? null : get_timezoned_date($file['_time'], false),
                    'editable' => $editable,
                );

                if ($file['is_directory']) { // Directory
                    $url = build_url(array('page' => '_SELF', 'place' => $_place . $filename, 'sort' => $sort, 'type_filter' => $type_filter, 'search' => $search, 'recurse' => $recurse), '_SELF');

                    $is_image = false;

                    $image_url = find_theme_image('icons/48x48/menu/_generic_admin/view_this_category');

                    $embed_url = mixed();
                } else { // File
                    $url = get_custom_base_url() . '/uploads/filedump' . str_replace('%2F', '/', rawurlencode($_place . $filename));

                    if (is_saveable_image($url)) {
                        $is_image = true;
                        $image_url = $url;
                    } else {
                        $is_image = false;
                        $image_url = find_theme_image('no_image');
                    }

                    $embed_url = build_url(array('page' => '_SELF', 'type' => 'embed', 'place' => $_place, 'file' => $filename), '_SELF');
                }

                $choose_action = new Tempcode();
                if ($file['editable']) {
                    $choose_action->attach(do_template('COLUMNED_TABLE_ROW_CELL_TICK', array(
                        '_GUID' => 'd5085d4d602d24f7df25bcaf24db0d79',
                        'LABEL' => do_lang_tempcode('CHOOSE'),
                        'NAME' => 'select_' . strval($i),
                        'VALUE' => rtrim($filename, '/'),
                        'HIDDEN' => form_input_hidden('place_file_' . strval($i), $_place),
                    )));
                } else {
                    $choose_action = do_lang_tempcode('NA_EM');
                }

                // Thumbnail
                $thumbnail = do_image_thumb($image_url, $file['description_2'], false, false, null, null, true);
                $thumbnails[] = array(
                    'FILENAME' => $filename,
                    'PLACE' => $_place,
                    'THUMBNAIL' => $thumbnail,
                    'IS_IMAGE' => $is_image,
                    'URL' => $url,
                    'DESCRIPTION' => $file['description_2'],
                    '_SIZE' => is_null($file['_size']) ? '' : strval($file['_size']),
                    'SIZE' => $file['size'],
                    '_TIME' => is_null($file['_time']) ? '' : strval($file['_time']),
                    'TIME' => is_null($file['time']) ? '' : $file['time'],
                    'WIDTH' => is_null($file['width']) ? '' : strval($file['width']),
                    'HEIGHT' => is_null($file['height']) ? '' : strval($file['height']),
                    'IS_DIRECTORY' => $file['is_directory'],
                    'CHOOSABLE' => $file['editable'],
                    'ACTIONS' => $choose_action,
                    'EMBED_URL' => $embed_url,
                );

                // Editable(?) filename
                if ($file['editable']) {
                    $filename_field = do_template('COLUMNED_TABLE_ROW_CELL_LINE', array(
                        '_GUID' => 'bce082b134f751615785189bf1cedbe2',
                        'LABEL' => do_lang_tempcode('FILENAME'),
                        'NAME' => 'filename_value_' . strval($i),
                        'VALUE' => rtrim($filename, '/'),
                        'HIDDEN_NAME' => 'filename_file_' . strval($i),
                        'HIDDEN_VALUE' => rtrim($filename, '/'),
                    ));
                } else {
                    $filename_field = make_string_tempcode(escape_html($filename));
                }

                // Editable(?) description
                if ($file['editable']) {
                    $description_field = do_template('COLUMNED_TABLE_ROW_CELL_LINE', array(
                        '_GUID' => '22ef464010277ceedb72f8f38f897af6',
                        'LABEL' => do_lang_tempcode('DESCRIPTION'),
                        'NAME' => 'description_value_' . strval($i),
                        'VALUE' => $file['description'],
                        'HIDDEN_NAME' => 'description_file_' . strval($i),
                        'HIDDEN_VALUE' => rtrim($filename, '/'),
                    ));
                } else {
                    $description_field = make_string_tempcode(escape_html($file['description']));
                }

                // Size
                if (!is_null($file['width'])) {
                    $size = do_lang_tempcode('FILEDUMP_SIZE', escape_html($file['size']), escape_html(strval($file['width'])), escape_html(strval($file['height'])));
                } else {
                    $size = make_string_tempcode(escape_html($file['size']));
                }
                $size = hyperlink($url, $size, !$file['is_directory']/*files go to new window*/, false);

                // Submitter
                if (!is_null($file['submitter'])) {
                    $owner = $GLOBALS['FORUM_DRIVER']->member_profile_hyperlink($file['submitter']);
                    if (is_null($owner)) {
                        $owner = do_lang_tempcode('DELETED');
                    }
                } else {
                    $owner = do_lang_tempcode('UNKNOWN');
                }

                // Listing row
                $rows->attach(columned_table_row(array(
                    $filename_field,
                    $description_field,
                    $size,
                    $owner,
                    is_null($file['time']) ? do_lang_tempcode('NA') : make_string_tempcode(escape_html($file['time'])),
                    is_null($embed_url) ? ($file['is_directory'] ? do_lang_tempcode('IS_DIRECTORY') : new Tempcode()) : hyperlink($embed_url, do_lang_tempcode('_FILEDUMP_EMBED'), false, false),
                    $choose_action
                ), false));
            }

            $listing = do_template('COLUMNED_TABLE', array('_GUID' => '1c0a91d47c5fc8a7c2b35c7d9b36132f', 'HEADER_ROW' => $header_row, 'ROWS' => $rows));
        } else {
            $listing = new Tempcode();
        }

        // Find directories we could move stuff into / upload to
        $directories = get_directory_contents(get_custom_file_base() . '/uploads/filedump', '', false, true, false);
        $directories[] = '';
        sort($directories);
        $other_directories = $directories;
        $filtered_directories = $directories;
        if ($recurse == 0) {
            foreach ($other_directories as $i => $directory) {
                if ('/' . $directory . (($directory == '') ? '' : '/') == $place) {
                    unset($other_directories[$i]);
                    break;
                }
            }
        }
        $filtered_directories_misses = array();
        foreach ($filtered_directories as $i => $directory) {
            if (!$this->_folder_search('/' . $directory . (($directory == '') ? '' : '/'), '', $search, $type_filter, false)) {
                unset($filtered_directories[$i]);
                $filtered_directories_misses[] = $directory;
            }
        }

        // Do a form so people can upload their own stuff
        if (has_privilege(get_member(), 'upload_filedump')) {
            $post_url = build_url(array('page' => '_SELF', 'type' => 'add', 'uploading' => 1), '_SELF');

            $submit_name = do_lang_tempcode('FILEDUMP_UPLOAD');

            $max_filesize = floatval(get_max_file_size());
            $text = new Tempcode();
            if ($max_filesize < 30.0) {
                $config_url = get_upload_limit_config_url();
                $text->attach(do_lang_tempcode(is_null($config_url) ? 'MAXIMUM_UPLOAD' : 'MAXIMUM_UPLOAD_STAFF', escape_html(($max_filesize > 10.0) ? integer_format(intval($max_filesize)) : float_format($max_filesize / 1024.0 / 1024.0)), escape_html(is_null($config_url) ? '' : $config_url)));
            }

            $fields = new Tempcode();
            url_default_parameters__enable();
            $fields->attach(form_input_upload_multi(do_lang_tempcode('FILES'), do_lang_tempcode('DESCRIPTION_FILES'), 'files', true));
            $fields->attach(form_input_line(do_lang_tempcode('DESCRIPTION'), do_lang_tempcode('DESCRIPTION_DESCRIPTION_FILES'), 'description', '', false));
            $list = new Tempcode();
            foreach ($directories as $directory) {
                $_directory = '/' . $directory . (($directory == '') ? '' : '/');
                $list->attach(form_input_list_entry($_directory, ($_directory == $place), '/' . $directory));
            }
            $fields->attach(form_input_list(do_lang_tempcode('FOLDER'), '', 'place', $list));

            url_default_parameters__disable();

            $hidden = new Tempcode();
            handle_max_file_size($hidden);

            $upload_form = do_template('FORM', array(
                '_GUID' => '70279f3714ec90a5b3defec04a357b11',
                'TABINDEX' => strval(get_form_field_tabindex()),
                'SKIP_REQUIRED' => true,
                'HIDDEN' => $hidden,
                'TEXT' => $text,
                'FIELDS' => $fields,
                'SUBMIT_NAME' => $submit_name,
                'SUBMIT_ICON' => 'menu___generic_admin__add_one',
                'URL' => $post_url,
            ));
        } else {
            $upload_form = new Tempcode();
        }

        // Do a form so people can make folders
        if ((get_option('is_on_folder_create') == '1') && (has_privilege(get_member(), 'upload_filedump'))) {
            $post_url = build_url(array('page' => '_SELF', 'type' => 'add_category'), '_SELF');

            $submit_name = do_lang_tempcode('FILEDUMP_CREATE_FOLDER');

            $fields = new Tempcode();
            $fields->attach(form_input_line(do_lang_tempcode('NAME'), do_lang_tempcode('DESCRIPTION_FOLDER_NAME'), 'name', '', true));
            $fields->attach(form_input_line(do_lang_tempcode('DESCRIPTION'), new Tempcode(), 'description', '', false));

            $hidden = form_input_hidden('place', $place);

            $create_folder_form = do_template('FORM', array(
                '_GUID' => '043f9b595d3699b7d8cd7f2284cdaf98',
                'TABINDEX' => strval(get_form_field_tabindex()),
                'SKIP_REQUIRED' => true,
                'SECONDARY_FORM' => true,
                'HIDDEN' => $hidden,
                'TEXT' => '',
                'FIELDS' => $fields,
                'SUBMIT_NAME' => $submit_name,
                'SUBMIT_ICON' => 'menu___generic_admin__add_one_category',
                'URL' => $post_url,
            ));
        } else {
            $create_folder_form = new Tempcode();
        }

        $post_url = build_url(array('page' => '_SELF', 'type' => 'mass', 'redirect' => get_self_url(true, false, array('filename' => null/*Don't auto-open the embed overlay*/))), '_SELF');

        require_code('templates_pagination');
        $pagination_listing = pagination(do_lang_tempcode('FILES'), $start, 'start', $max, 'max', $max_rows, false, 5, null, 'tab__listing');
        $pagination_thumbnails = pagination(do_lang_tempcode('FILES'), $start, 'start', $max, 'max', $max_rows, false, 5, null, 'tab__thumbnails');

        return do_template('FILEDUMP_SCREEN', array(
            '_GUID' => '3f49a8277a11f543eff6488622949c84',
            'TITLE' => $this->title,
            'PLACE' => $place,
            'THUMBNAILS' => $thumbnails,
            'LISTING' => $listing,
            'UPLOAD_FORM' => $upload_form,
            'CREATE_FOLDER_FORM' => $create_folder_form,
            'TYPE_FILTER' => $type_filter,
            'SEARCH' => $search,
            'SORT' => $sort,
            'PAGINATION_LISTING' => $pagination_listing,
            'PAGINATION_THUMBNAILS' => $pagination_thumbnails,
            'POST_URL' => $post_url,
            'DIRECTORIES' => $directories,
            'OTHER_DIRECTORIES' => $other_directories,
            'FILTERED_DIRECTORIES' => $filtered_directories,
            'FILTERED_DIRECTORIES_MISSES' => $filtered_directories_misses,
            'SOMETHING_EDITABLE' => $something_editable,
        ));
    }

    /**
     * Find whether a file matches the search filter. If there is no filter, anything will match.
     *
     * @param  PATH $place Folder path.
     * @param  string $description Folder description.
     * @param  string $search Search filter.
     * @param  string $type_filter Type filter.
     * @set images videos audios others
     * @param  boolean $recursive Whether to search recursively.
     * @return boolean Whether it passes the filter.
     */
    public function _folder_search($place, $description, $search, $type_filter, $recursive = true)
    {
        if ($type_filter == '') {
            if ($search != '') {
                if ((stripos(basename($place), $search) !== false) || (stripos($description, $search) !== false)) {// Directory itself matches
                    return true;
                }
            } else {
                return true;
            }
        }

        $db_rows = list_to_map('name', $GLOBALS['SITE_DB']->query_select('filedump', array('*'), array('path' => cms_mb_substr($place, 0, 80))));

        $handle = opendir(get_custom_file_base() . '/uploads/filedump' . $place);
        while (false !== ($filename = readdir($handle))) {
            if (!should_ignore_file('uploads/filedump' . $place . $filename, IGNORE_ACCESS_CONTROLLERS | IGNORE_HIDDEN_FILES)) {
                $_full = get_custom_file_base() . '/uploads/filedump' . $place . $filename;
                if (!file_exists($_full)) {
                    continue; // Broken symlink or (?) permission problem
                }

                $is_directory = !is_file($_full);

                $db_row = isset($db_rows[$filename]) ? $db_rows[$filename] : null;

                $_description = isset($db_row) ? get_translated_text($db_row['description']) : '';

                if (($is_directory) && ($recursive)) {
                    if ($this->_folder_search($place . $filename . '/', $_description, $search, $type_filter, $recursive)) {
                        return true; // Look deeper
                    }
                } else {
                    if ($this->_matches_filter($filename, $_description, $search, $type_filter)) {
                        return true; // File under matches
                    }
                }
            }
        }
        closedir($handle);

        return false;
    }

    /**
     * Find whether a file matches the search filter. If there is no filter, anything will match.
     *
     * @param  ID_TEXT $filename Filename.
     * @param  string $_description File description.
     * @param  string $search Search filter.
     * @param  string $type_filter Type filter.
     * @set images videos audios others
     * @return boolean Whether it passes the filter.
     */
    public function _matches_filter($filename, $_description, $search, $type_filter)
    {
        if ($search != '') {
            if ((stripos($filename, $search) === false) && (stripos($_description, $search) === false)) {
                return false;
            }
        }

        switch ($type_filter) {
            case 'images':
                if (!is_image($filename)) {
                    return false;
                }
                break;

            case 'videos':
                if ((substr(strtolower($filename), -4) == '.mp3') || (substr(strtolower($filename), -4) == '.wav') || (substr(strtolower($filename), -4) == '.ogg')) {
                    return false;
                }
                if (!is_video($filename, true)) {
                    return false;
                }
                break;

            case 'audios':
                if (!is_audio($filename, false)) {
                    return false;
                }
                break;

            case 'others':
                if (is_image($filename)) {
                    return false;
                }
                if (is_video($filename, true)) {
                    return false;
                }
                if ((substr(strtolower($filename), -4) == '.mp3') || (substr(strtolower($filename), -4) == '.wav') || (substr(strtolower($filename), -4) == '.ogg')) {
                    return false;
                }
                break;
        }

        return true;
    }

    /**
     * The main user interface for the file dump.
     *
     * @return Tempcode The UI.
     */
    public function do_embed()
    {
        require_code('form_templates');
        require_code('images');

        $place = get_param_string('place');
        $file = get_param_string('file');

        $url = get_custom_base_url() . '/uploads/filedump' . str_replace('%2F', '/', rawurlencode($place . $file));
        $path = get_custom_file_base() . '/uploads/filedump' . $place . $file;

        $generated = mixed();
        $rendered = mixed();
        if (cms_srv('REQUEST_METHOD') == 'POST') {
            $generated = '[media';
            $param = post_param_string('description', '');
            if ($param != '') {
                $generated .= ' description="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('type', '');
            if ($param != '') {
                $generated .= ' type="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('framed', '0');
            if ($param != '') {
                $generated .= ' framed="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('width', '');
            if ($param != '') {
                $generated .= ' width="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('height', '');
            if ($param != '') {
                $generated .= ' height="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('align', '');
            if ($param != '') {
                $generated .= ' align="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('float', '');
            if ($param != '') {
                $generated .= ' float="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('thumb', '0');
            if ($param != '') {
                $generated .= ' thumb="' . comcode_escape($param) . '"';
            }
            $param = post_param_string('thumb_url', '');
            if ($param != '') {
                $generated .= ' thumb_url="' . comcode_escape($param) . '"';
            }
            $generated .= ']uploads/filedump' . $place . $file . '[/media]';

            $rendered = comcode_to_tempcode($generated);
        }

        $_description = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'description', array('name' => cms_mb_substr($file, 0, 80), 'path' => cms_mb_substr($place, 0, 80)));
        if (is_null($_description)) {
            $description = post_param_string('description', '');
        } else {
            $description = post_param_string('description', get_translated_text($_description));
        }

        require_lang('comcode');

        $adv = do_lang('BLOCK_IND_ADVANCED');

        $fields = new Tempcode();

        $fields->attach(form_input_line_comcode(do_lang_tempcode('COMCODE_TAG_attachment_PARAM_description_TITLE'), do_lang('COMCODE_TAG_attachment_PARAM_description'), 'description', $description, false));

        $_description = do_lang('COMCODE_TAG_attachment_PARAM_type');
        if (substr($_description, 0, strlen($adv) + 1) == $adv) {
            $_description = substr($_description, 0, strlen($adv) + 1);
        }
        $list = new Tempcode();
        $list->attach(form_input_list_entry('', false, do_lang('MEDIA_TYPE_')));
        require_code('media_renderer');
        $hooks = find_all_hooks('systems', 'media_rendering');
        foreach (array_keys($hooks) as $hook) {
            require_code('hooks/systems/media_rendering/' . $hook);
            $ob = object_factory('Hook_media_rendering_' . $hook);
            $hooks[$hook] = $ob->get_type_label();
        }
        asort($hooks);
        foreach ($hooks as $option_val => $option_label) {
            $list->attach(form_input_list_entry($option_val, ($option_val == post_param_string('type', is_image($file) ? 'image_websafe' : '')), $option_label));
        }
        $fields->attach(form_input_list(do_lang_tempcode('COMCODE_TAG_attachment_PARAM_type_TITLE'), $_description, 'type', $list, null, false, false));

        $fields->attach(form_input_tick(do_lang_tempcode('COMCODE_TAG_attachment_PARAM_framed_TITLE'), do_lang_tempcode('COMCODE_TAG_attachment_PARAM_framed'), 'framed', post_param_integer('framed', 0) == 1));

        $fields->attach(form_input_integer(do_lang_tempcode('WIDTH'), do_lang_tempcode('COMCODE_TAG_attachment_PARAM_width'), 'width', post_param_integer('width', null), false));

        $fields->attach(form_input_integer(do_lang_tempcode('HEIGHT'), do_lang_tempcode('COMCODE_TAG_attachment_PARAM_height'), 'height', post_param_integer('height', null), false));

        /*
        $_description = do_lang ('COMCODE_TAG_attachment_PARAM_align');
        if (substr($_description, 0, strlen($adv) + 1) == $adv) {
            $_description = substr($_description, 0, strlen($adv) + 1);
        }
        $list = new Tempcode();
        foreach (explode('|', $_description) as $option) {
            list($option_val, $option_label) = explode('=', $option, 2);
            $list->attach(form_input_list_entry($option_val, ($option_val == post_param_string('align', '')), $option_label));
        }
        $fields->attach(form_input_list(do_lang_tempcode ('COMCODE_TAG_attachment_PARAM_align_TITLE'), '', 'align', $list, null, false, false));
        */

        $_description = do_lang('COMCODE_TAG_attachment_PARAM_float');
        if (substr($_description, 0, strlen($adv) + 1) == $adv) {
            $_description = substr($_description, 0, strlen($adv) + 1);
        }
        $list = new Tempcode();
        foreach (explode('|', $_description) as $option) {
            list($option_val, $option_label) = explode('=', $option, 2);
            $list->attach(form_input_list_entry($option_val, ($option_val == post_param_string('float', '')), $option_label));
        }
        $fields->attach(form_input_list(do_lang_tempcode('COMCODE_TAG_attachment_PARAM_float_TITLE'), '', 'float', $list, null, false, false));

        $_description = do_lang('COMCODE_TAG_attachment_PARAM_thumb');
        if (substr($_description, 0, strlen($adv) + 1) == $adv) {
            $_description = substr($_description, 0, strlen($adv) + 1);
        }
        $_description = cms_preg_replace_safe('#\s*' . do_lang('BLOCK_IND_DEFAULT') . ': ["\']([^"]*)["\'](?-U)\.?(?U)#Ui', '', $_description);
        $thumb_ticked = true;
        if (cms_srv('REQUEST_METHOD') == 'POST') {
            $thumb_ticked = (post_param_integer('thumb', 0) == 1);
        }
        $fields->attach(form_input_tick(do_lang_tempcode('COMCODE_TAG_attachment_PARAM_thumb_TITLE'), ucfirst(substr($_description, 12)), 'thumb', $thumb_ticked));

        $_description = do_lang('COMCODE_TAG_attachment_PARAM_thumb_url');
        if (substr($_description, 0, strlen($adv) + 1) == $adv) {
            $_description = substr($_description, 0, strlen($adv) + 1);
        }
        $fields->attach(form_input_line_comcode(do_lang_tempcode('COMCODE_TAG_attachment_PARAM_thumb_url_TITLE'), $_description, 'thumb_url', post_param_string('thumb_url', null), false));

        $form = do_template('FORM', array(
            '_GUID' => 'b1502bd870aded49d27d7478806d53ed',
            'FIELDS' => $fields,
            'HIDDEN' => '',
            'TEXT' => '',
            'URL' => get_self_url(),
            'SUBMIT_NAME' => do_lang_tempcode('GENERATE_COMCODE'),
            'SUBMIT_ICON' => 'buttons__proceed',
            'TARGET' => '_self',
        ));

        $image_sizes = mixed();
        if (is_saveable_image($file)) {
            $size = cms_getimagesize($path);
            if ($size !== false) {
                $ratio = floatval($size[1]) / floatval($size[0]);

                $_image_sizes = array();
                if (intval(get_option('thumb_width')) < $size[0]) {
                    $_image_sizes[intval(get_option('thumb_width'))] = 'FILEDUMP_IMAGE_URLS_SMALL';
                }
                if (730 < $size[0]) {
                    $_image_sizes[730] = 'FILEDUMP_IMAGE_URLS_MEDIUM';
                }
                $_image_sizes[$size[0]] = 'FILEDUMP_IMAGE_URLS_LARGE';

                $image_sizes = array();
                foreach ($_image_sizes as $width => $lng_str) {
                    $size_url = make_string_tempcode($url);
                    if ($width != $size[0]) {
                        $size_url = symbol_tempcode('THUMBNAIL', array($url, strval($width)));
                    }

                    $height = intval(floatval($width) * $ratio);
                    $image_sizes[] = array(
                        'LABEL' => do_lang_tempcode($lng_str, escape_html(strval($width)), escape_html(strval($height))),
                        'SIZE_URL' => $size_url,
                        'SIZE_WIDTH' => strval($width),
                        'SIZE_HEIGHT' => strval($height),
                    );
                }
            }
        }

        $_existing_count = find_filedump_links($place . $file);
        if (isset($_existing_count[$place . $file])) {
            $existing_count = count($_existing_count[$place . $file]['references']);
        } else {
            $existing_count = 0;
        }

        return do_template('FILEDUMP_EMBED_SCREEN', array(
            '_GUID' => 'f82e0225f9b94fd96c5f61eac9c56e3d',
            'TITLE' => $this->title,
            'FORM' => $form,
            'GENERATED' => $generated,
            'RENDERED' => $rendered,
            'URL' => $url,
            'IMAGE_SIZES' => $image_sizes,
            'EXISTING_COUNT' => strval($existing_count),
        ));
    }

    /**
     * The actualiser for handling mass actions.
     *
     * @return Tempcode The UI.
     */
    public function do_mass()
    {
        $action = post_param_string('action');
        switch ($action) {
            case 'zip':
                require_code('zip');
                $file_array = array();
                break;

            case 'edit':
            case 'delete':
                break;

            default:
                $target = $action;
                if ($target == '') {
                    warn_exit(do_lang_tempcode('SELECT_AN_ACTION'));
                }

                $action = 'move';
                break;
        }

        $files_str = '';
        if ($action != 'edit') {
            $files = array();
            foreach (array_keys($_POST) as $key) {
                $matches = array();
                if (preg_match('#^select_(\d+)$#', $key, $matches) != 0) {
                    $place = post_param_string('place_file_' . $matches[1]);

                    $file = post_param_string($key);
                    $files[] = array($file, $place);

                    if ($files_str != '') {
                        $files_str .= ', ';
                    }
                    $files_str .= $file;
                }
            }
        } else {
            $files = array();
            $descriptions = array();
            foreach (array_keys($_POST) as $key) {
                $matches = array();
                if (preg_match('#^description_file_(\d+)$#', $key, $matches) != 0) {
                    $place = post_param_string('place_file_' . $matches[1]);

                    $file = post_param_string('description_file_' . $matches[1]);
                    $files[] = array($file, $place);

                    if ($files_str != '') {
                        $files_str .= ', ';
                    }
                    $files_str .= $file;

                    $description = post_param_string('description_value_' . $matches[1], '');
                    $descriptions[$place . $file] = $description;
                }
            }

            foreach (array_keys($_POST) as $key) {
                $matches = array();
                if (preg_match('#^filename_file_(\d+)$#', $key, $matches) != 0) {
                    $place = post_param_string('place_file_' . $matches[1]);

                    $old_filename = post_param_string('filename_file_' . $matches[1]);
                    $new_filename = post_param_string('filename_value_' . $matches[1]);
                    if (($new_filename != '') && ($old_filename != $new_filename)) {
                        $owner = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'the_member', array('name' => cms_mb_substr($old_filename, 0, 80), 'path' => cms_mb_substr($place, 0, 80)));
                        if (((!is_null($owner)) && ($owner == get_member())) || (has_privilege(get_member(), 'delete_anything_filedump'))) {
                            $old_filepath = get_custom_file_base() . '/uploads/filedump' . $place . $old_filename;
                            $new_filepath = get_custom_file_base() . '/uploads/filedump' . $place . $new_filename;

                            if (file_exists($new_filepath)) {
                                warn_exit(do_lang_tempcode('OVERWRITE_ERROR'));
                            }
                            rename($old_filepath, $new_filepath);
                            sync_file_move($old_filepath, $new_filepath);
                            $GLOBALS['SITE_DB']->query_update('filedump', array('name' => cms_mb_substr($new_filename, 0, 80)), array('name' => cms_mb_substr($old_filename, 0, 80), 'path' => cms_mb_substr($place, 0, 80)), '', 1);

                            foreach ($files as $i => $_file) {
                                if ($_file[1] . $_file[0] == $place . $old_filename) {
                                    $files[$i][0] = $new_filename;
                                }
                            }

                            foreach ($descriptions as $filepath => $description) {
                                if ($filepath == $place . $old_filename) {
                                    unset($descriptions[$place . $old_filename]);
                                    $descriptions[$place . $new_filename] = $description;
                                }
                            }
                        }
                    }
                }
            }
        }

        if ($action != 'edit') {
            if (count($files) == 0) {
                warn_exit(do_lang_tempcode('NOTHING_SELECTED'));
            }
        }

        // Confirm
        if ((post_param_integer('confirmed', 0) != 1) && ($action != 'zip') && ($action != 'edit'/*edit too trivial/specific to need a confirm*/)) {
            $url = get_self_url();

            switch ($action) {
                case 'delete':
                    $text = do_lang_tempcode('CONFIRM_DELETE', escape_html($files_str));
                    break;

                case 'move':
                    $text = do_lang_tempcode('CONFIRM_MOVE', escape_html($files_str), $target);
                    break;
            }

            $hidden = build_keep_post_fields();
            $hidden->attach(form_input_hidden('confirmed', '1'));

            return do_template('CONFIRM_SCREEN', array('_GUID' => '19503cf5dc795b9c85d26702b79e3202', 'TITLE' => $this->title, 'FIELDS' => $hidden, 'PREVIEW' => $text, 'URL' => $url));
        }

        // Perform action(s)
        foreach ($files as $_file) {
            list($file, $place) = $_file;

            $where = array('name' => cms_mb_substr($file, 0, 80), 'path' => cms_mb_substr($place, 0, 80));

            $owner = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'the_member', $where);
            if (((!is_null($owner)) && ($owner == get_member())) || (has_privilege(get_member(), 'delete_anything_filedump'))) {
                $is_directory = is_dir(get_custom_file_base() . '/uploads/filedump' . $place . $file);
                $path = get_custom_file_base() . '/uploads/filedump' . $place . $file;

                switch ($action) {
                    case 'zip':
                        if ($is_directory) {
                            require_code('files2');
                            foreach (get_directory_contents($path) as $d_path) {
                                $file_array[] = array(
                                    'time' => filemtime($path . '/' . $d_path),
                                    'full_path' => $path . '/' . $d_path,
                                    'name' => ltrim($place . $file, '/') . '/' . $d_path,
                                );
                            }
                        } else {
                            $file_array[] = array(
                                'time' => filemtime($path),
                                'full_path' => $path,
                                'name' => ltrim($place . $file, '/'),
                            );
                        }
                        break;

                    case 'edit':
                        $description = $descriptions[$place . $file];
                        $test = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'description', $where);
                        if (!is_null($test)) {
                            $map = lang_remap('description', $test, $description);
                            $GLOBALS['SITE_DB']->query_update('filedump', $map, $where);
                        } else {
                            $map = array(
                                'name' => cms_mb_substr($file, 0, 80),
                                'path' => cms_mb_substr($place, 0, 80),
                                'the_member' => get_member(),
                            );
                            $map += insert_lang('description', $description, 3);
                            $GLOBALS['SITE_DB']->query_insert('filedump', $map);
                        }
                        break;

                    case 'delete':
                        $test = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'description', $where);
                        if (!is_null($test)) {
                            delete_lang($test);
                        }

                        if ($is_directory) {
                            deldir_contents($path);
                            @rmdir($path) or warn_exit(do_lang_tempcode('FOLDER_DELETE_ERROR'));

                            log_it('FILEDUMP_DELETE_FOLDER', $file, $place);
                        } else {
                            @unlink($path) or intelligent_write_error($path);

                            log_it('FILEDUMP_DELETE_FILE', $file, $place);
                        }
                        sync_file($path);

                        break;

                    case 'move':
                        $path_target = get_custom_file_base() . '/uploads/filedump' . $target . $file;
                        if (file_exists($path_target)) {
                            warn_exit(do_lang_tempcode('ALREADY_EXISTS', escape_html($path_target)));
                        }
                        @rename($path, $path_target) or intelligent_write_error($path);
                        sync_file_move($path, $path_target);

                        $test = $GLOBALS['SITE_DB']->query_update('filedump', array('path' => cms_mb_substr($target, 0, 80)), $where, '', 1);

                        update_filedump_links($place . $file, $target . $file);

                        log_it('FILEDUMP_MOVE', $place . $file, $target . $file);

                        break;
                }
            } else {
                access_denied('I_ERROR');
            }
        }

        if ($action == 'zip') {
            header('Content-Type: application/octet-stream' . '; authoritative=true;');
            header('Content-Disposition: attachment; filename="filedump-selection.zip"');

            create_zip_file($file_array, true);
            exit();
        }

        $redirect_url = get_param_string('redirect');

        return redirect_screen($this->title, $redirect_url, do_lang_tempcode('SUCCESS'));
    }

    /**
     * The actualiser for adding a folder.
     *
     * @return Tempcode The UI.
     */
    public function do_add_folder()
    {
        if (!has_privilege(get_member(), 'upload_filedump')) {
            access_denied('I_ERROR');
        }

        $name = filter_naughty(post_param_string('name'));
        $place = filter_naughty(post_param_string('place'));

        if (file_exists(get_custom_file_base() . '/uploads/filedump' . $place . $name)) {
            warn_exit(do_lang_tempcode('FOLDER_OVERWRITE_ERROR'));
        }

        $full_path = get_custom_file_base() . '/uploads/filedump' . $place . $name;
        cms_file_put_contents_safe($full_path . '/index.html', '', FILE_WRITE_FIX_PERMISSIONS | FILE_WRITE_SYNC_FILE);

        $redirect_url = build_url(array('page' => '_SELF', 'type' => 'browse', 'place' => $place), '_SELF');

        // Add description
        $test = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'description', array('name' => cms_mb_substr($name, 0, 80), 'path' => cms_mb_substr($place, 0, 80)));
        if (!is_null($test)) {
            delete_lang($test);
            $GLOBALS['SITE_DB']->query_delete('filedump', array('name' => cms_mb_substr($name, 0, 80), 'path' => cms_mb_substr($place, 0, 80)), '', 1);
        }
        $description = post_param_string('description', '');
        $map = array(
            'name' => cms_mb_substr($name, 0, 80),
            'path' => cms_mb_substr($place, 0, 80),
            'the_member' => get_member(),
        );
        $map += insert_lang('description', $description, 3);
        $GLOBALS['SITE_DB']->query_insert('filedump', $map);

        log_it('FILEDUMP_CREATE_FOLDER', $name, $place);

        return redirect_screen($this->title, $redirect_url, do_lang_tempcode('SUCCESS'));
    }

    /**
     * The actualiser for uploading a file.
     *
     * @return Tempcode The UI.
     */
    public function do_upload()
    {
        if (!has_privilege(get_member(), 'upload_filedump')) {
            access_denied('I_ERROR');
        }

        if (php_function_allowed('set_time_limit')) {
            @set_time_limit(0); // Slowly uploading a file can trigger time limit, on some servers
        }

        $place = filter_naughty(post_param_string('place'));

        require_code('uploads');
        is_plupload(true);

        $new_files = array();

        foreach ($_FILES as $file) {
            // Error?
            if ((!is_plupload()) && (!is_uploaded_file($file['tmp_name']))) {
                $max_size = get_max_file_size();
                if (($file['error'] == 1) || ($file['error'] == 2)) {
                    warn_exit(do_lang_tempcode('FILE_TOO_BIG', escape_html(integer_format($max_size))));
                } elseif ((isset($file)) && (($file['error'] == 3) || ($file['error'] == 6) || ($file['error'] == 7))) {
                    warn_exit(do_lang_tempcode('ERROR_UPLOADING_' . strval($file['error'])));
                } else {
                    warn_exit(do_lang_tempcode('ERROR_UPLOADING'));
                }
            }

            $filename = $file['name'];
            if (@get_magic_quotes_gpc()) {
                $filename = stripslashes($filename);
            }

            // Security
            if ((!has_privilege(get_member(), 'upload_anything_filedump')) || (get_file_base() != get_custom_file_base()/*demonstratr*/)) {
                check_extension($filename);
            }
            // Don't allow double file extensions, huge security risk with Apache
            $filename = str_replace('.', '-', basename($filename, '.' . get_file_extension($filename))) . '.' . get_file_extension($filename);

            // Too big?
            $max_size = get_max_file_size();
            if ($file['size'] > $max_size) {
                attach_message(do_lang_tempcode('FILE_TOO_BIG', escape_html(integer_format(intval($max_size)))), 'warn');
                continue;
            }

            // Conflict?
            if (file_exists(get_custom_file_base() . '/uploads/filedump' . $place . $filename)) {
                attach_message(do_lang_tempcode('OVERWRITE_ERROR'), 'warn');
                continue;
            }

            // Save in file
            $full = get_custom_file_base() . '/uploads/filedump' . $place . $filename;
            if (is_plupload()) {
                @rename($file['tmp_name'], $full) or warn_exit(do_lang_tempcode('FILE_MOVE_ERROR', escape_html($filename), escape_html('uploads/filedump' . $place)));
            } else {
                @move_uploaded_file($file['tmp_name'], $full) or warn_exit(do_lang_tempcode('FILE_MOVE_ERROR', escape_html($filename), escape_html('uploads/filedump' . $place)));
            }
            fix_permissions($full);
            sync_file($full);
            $new_files[] = $filename;

            // Add description
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('filedump', 'description', array('name' => cms_mb_substr($filename, 0, 80), 'path' => cms_mb_substr($place, 0, 80)));
            if (!is_null($test)) {
                delete_lang($test);
                $GLOBALS['SITE_DB']->query_delete('filedump', array('name' => cms_mb_substr($filename, 0, 80), 'path' => cms_mb_substr($place, 0, 80)), '', 1);
            }
            $description = post_param_string('description', '');
            $map = array(
                'name' => cms_mb_substr($filename, 0, 80),
                'path' => cms_mb_substr($place, 0, 80),
                'the_member' => get_member(),
            );
            $map += insert_lang('description', $description, 3);
            $GLOBALS['SITE_DB']->query_insert('filedump', $map);

            // Logging etc
            require_code('notifications');
            $subject = do_lang('FILEDUMP_NOTIFICATION_MAIL_SUBJECT', get_site_name(), $filename, $place);
            $mail = do_notification_lang('FILEDUMP_NOTIFICATION_MAIL', comcode_escape(get_site_name()), comcode_escape($filename), array(comcode_escape($place), comcode_escape($description)));
            dispatch_notification('filedump', $place, $subject, $mail);
            log_it('FILEDUMP_UPLOAD', $filename, $place);
            require_code('users2');
            if (has_actual_page_access(get_modal_user(), get_page_name(), get_zone_name())) {
                require_code('activities');
                syndicate_described_activity('filedump:ACTIVITY_FILEDUMP_UPLOAD', $place . '/' . $filename, '', '', '', '', '', 'filedump');
            }
        }

        // Done
        $url_map = array('page' => '_SELF', 'place' => $place);
        if (count($new_files) == 1) {
            $url_map['filename'] = $new_files[0];
        }

        $redirect_url = build_url($url_map, '_SELF');
        return redirect_screen($this->title, $redirect_url, do_lang_tempcode('SUCCESS'));
    }

    /**
     * Find URLs referenced that are broken.
     *
     * @return Tempcode The UI.
     */
    public function broken()
    {
        if (!$GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())) {
            access_denied('ADMIN_ONLY');
        }

        $broken = find_broken_filedump_links();

        require_code('form_templates');

        $hidden = new Tempcode();

        $fields = new Tempcode();
        $i = 0;
        foreach ($broken as $from => $to) {
            $pretty = do_lang_tempcode('FILEDUMP_BROKEN', escape_html(basename($from)));
            $description = do_lang_tempcode('DESCRIPTION_FILEDUMP_BROKEN', escape_html($from));
            $name = 'to_' . strval($i);

            $fields->attach(form_input_line($pretty, $description, $name, $to, false));

            $hidden->attach(form_input_hidden('from_' . strval($i), $from));

            $i++;
        }

        if (count($broken) == 0) {
            inform_exit(do_lang_tempcode('NO_ENTRIES'));
        }

        $url = build_url(array('page' => '_SELF', 'type' => '_broken'), '_SELF');

        return do_template('FORM_SCREEN', array(
            '_GUID' => '1b13a7aaf187f10a077df5b2b79098c7',
            'TITLE' => $this->title,
            'FIELDS' => $fields,
            'HIDDEN' => $hidden,
            'URL' => $url,
            'TEXT' => '',
            'SUBMIT_NAME' => do_lang_tempcode('FIX_BROKEN_FILEDUMP_LINKS'),
            'SUBMIT_ICON' => 'menu__adminzone__tools__cleanup',
        ));
    }

    /**
     * Fix URLs referenced that are broken.
     *
     * @return Tempcode The UI.
     */
    public function _broken()
    {
        if (!$GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())) {
            access_denied('ADMIN_ONLY');
        }

        foreach (array_keys($_POST) as $key) {
            $matches = array();
            if (preg_match('#^to\_(\d+)$#', $key, $matches) != 0) {
                $from = post_param_string('from_' . $matches[1]);
                $to = post_param_string('to_' . $matches[1]);
                if ($to != '') {
                    update_filedump_links($from, $to);
                }
            }
        }

        return inform_screen($this->title, do_lang_tempcode('SUCCESS'));
    }
}
