Пример #1
0
/**
 * Find file meta information for adding to a zip file
 *
 * @param  PATH			The full path to the folder to add
 * @param  PATH			The subpath relative to the path (should be left as the default '', as this is used for the recursion to distinguish the adding base path from where it's currently looking)
 * @return array			A list of maps that stores time,full_path,name, for each file
 */
function zip_scan_folder($path, $subpath = '')
{
    $_full = $path == '' ? $subpath : $path . '/' . $subpath;
    if ($_full == '') {
        $_full = '.';
    }
    $info = array();
    $dh = @opendir($_full);
    if ($dh !== false) {
        while (($entry = readdir($dh)) !== false) {
            $_subpath = $subpath == '' ? $entry : $subpath . '/' . $entry;
            if (!should_ignore_file($_subpath) && $entry != 'backups') {
                $full = $path == '' ? $_subpath : $path . '/' . $_subpath;
                if (!is_readable($full)) {
                    continue;
                }
                if (is_dir($full)) {
                    $info2 = zip_scan_folder($path, $_subpath);
                    $info = array_merge($info, $info2);
                } else {
                    $mtime = filemtime($full);
                    $info[] = array('full_path' => $full, 'name' => $_subpath, 'time' => $mtime);
                }
            }
        }
        closedir($dh);
    }
    return $info;
}
Пример #2
0
/**
 * Get an array of all the installed languages that can be found in root/lang/ and root/lang_custom/
 *
 * @param  boolean			Whether to even find empty languages
 * @return array				The installed languages (map, lang=>type)
 */
function _find_all_langs($even_empty_langs = false)
{
    $_dir = opendir(get_file_base() . '/lang/');
    $_langs = array();
    while (false !== ($file = readdir($_dir))) {
        if (!should_ignore_file('lang/' . $file, IGNORE_ACCESS_CONTROLLERS) && strlen($file) <= 5) {
            if (is_dir(get_file_base() . '/lang/' . $file)) {
                $_langs[$file] = 'lang';
            }
        }
    }
    closedir($_dir);
    if (!in_safe_mode()) {
        $_dir = @opendir(get_custom_file_base() . '/lang_custom/');
        if ($_dir !== false) {
            while (false !== ($file = readdir($_dir))) {
                if (!should_ignore_file('lang_custom/' . $file, IGNORE_ACCESS_CONTROLLERS) && strlen($file) <= 5) {
                    if (is_dir(get_custom_file_base() . '/lang_custom/' . $file)) {
                        if ($even_empty_langs || is_file(get_custom_file_base() . '/lang_custom/' . $file . '/global.ini')) {
                            $_langs[$file] = 'lang_custom';
                        } else {
                            $_dir2 = opendir(get_custom_file_base() . '/lang_custom/' . $file);
                            while (false !== ($file2 = readdir($_dir2))) {
                                if (substr($file2, -4) == '.ini' || substr($file2, -3) == '.po') {
                                    $_langs[$file] = 'lang_custom';
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            closedir($_dir);
        }
        if (get_custom_file_base() != get_file_base()) {
            $_dir = opendir(get_file_base() . '/lang_custom/');
            while (false !== ($file = readdir($_dir))) {
                if (!should_ignore_file('lang_custom/' . $file, IGNORE_ACCESS_CONTROLLERS) && strlen($file) <= 5) {
                    if ($even_empty_langs) {
                        $_langs[$file] = 'lang_custom';
                    } else {
                        $_dir2 = opendir(get_file_base() . '/lang_custom/' . $file);
                        while (false !== ($file2 = readdir($_dir2))) {
                            if (substr($file2, -4) == '.ini' || substr($file2, -3) == '.po') {
                                $_langs[$file] = 'lang_custom';
                                break;
                            }
                        }
                    }
                }
            }
            closedir($_dir);
        }
    }
    return $_langs;
}
Пример #3
0
 /**
  * Standard modular run function for do_next_menu hooks. They find links to put on standard navigation menus of the system.
  *
  * @return array			Array of links and where to show
  */
 function run()
 {
     $has_langs = false;
     $_dir = opendir(get_file_base() . '/lang/');
     $_langs = array();
     while (false !== ($file = readdir($_dir))) {
         if ($file == fallback_lang()) {
             continue;
         }
         if (!should_ignore_file('lang/' . $file, IGNORE_ACCESS_CONTROLLERS) && strlen($file) <= 5) {
             if (is_dir(get_file_base() . '/lang/' . $file)) {
                 $has_langs = true;
             }
         }
     }
     closedir($_dir);
     if (!in_safe_mode()) {
         $_dir = @opendir(get_custom_file_base() . '/lang_custom/');
         if ($_dir !== false) {
             while (false !== ($file = readdir($_dir))) {
                 if ($file == fallback_lang()) {
                     continue;
                 }
                 if (!should_ignore_file('lang_custom/' . $file, IGNORE_ACCESS_CONTROLLERS) && strlen($file) <= 5) {
                     if (is_dir(get_custom_file_base() . '/lang_custom/' . $file)) {
                         $has_langs = true;
                     }
                 }
             }
             closedir($_dir);
         }
         if (get_custom_file_base() != get_file_base()) {
             $_dir = opendir(get_file_base() . '/lang_custom/');
             while (false !== ($file = readdir($_dir))) {
                 if ($file == fallback_lang()) {
                     continue;
                 }
                 if (!should_ignore_file('lang_custom/' . $file, IGNORE_ACCESS_CONTROLLERS) && strlen($file) <= 5) {
                     $has_langs = true;
                 }
             }
             closedir($_dir);
         }
     }
     return array(array('style', 'language', array('admin_lang', array('type' => 'misc'), get_module_zone('admin_lang')), do_lang_tempcode('TRANSLATE_CODE'), 'DOC_TRANSLATE'), multi_lang() ? array('style', 'language', array('admin_lang', array('type' => 'content'), get_module_zone('admin_lang')), do_lang_tempcode('TRANSLATE_CONTENT'), 'DOC_TRANSLATE_CONTENT') : NULL, !$has_langs ? NULL : array('style', 'criticise_language', array('admin_lang', array('type' => 'criticise'), get_module_zone('admin_lang')), do_lang_tempcode('CRITICISE_LANGUAGE_PACK'), 'DOC_CRITICISE_LANGUAGE_PACK'));
 }
Пример #4
0
 /**
  * Standard modular listing function for OcCLE FS hooks.
  *
  * @param	array			The current meta-directory path
  * @param	string		The root node of the current meta-directory
  * @param	array			The current directory listing
  * @param	array			A reference to the OcCLE filesystem object
  * @return  ~array 	The final directory listing (false: failure)
  */
 function listing($meta_dir, $meta_root_node, $current_dir, &$occle_fs)
 {
     $path = get_custom_file_base() . '/uploads/filedump';
     foreach ($meta_dir as $meta_dir_section) {
         $path .= '/' . filter_naughty($meta_dir_section);
     }
     $listing = array();
     if (is_dir($path)) {
         $dh = opendir($path);
         while (($file = readdir($dh)) !== false) {
             if (!should_ignore_file($file, IGNORE_ACCESS_CONTROLLERS)) {
                 if (is_dir($path . '/' . $file)) {
                     $listing[$file] = array();
                 } else {
                     $listing[] = $file;
                 }
             }
         }
         return $listing;
     }
     return false;
     //Directory doesn't exist
 }
Пример #5
0
 /**
  * Scan a directory for files, and put them into the tempcode as an entry in the visual list.
  *
  * @param  PATH				The directory path
  * @return tempcode			The visual list of files
  */
 function do_dir($path)
 {
     $out = new ocp_tempcode();
     $files_here = array();
     $dirs_here = array();
     $handle = @opendir($path);
     if ($handle !== false) {
         while (false !== ($file = readdir($handle))) {
             if (!should_ignore_file($file, IGNORE_ACCESS_CONTROLLERS | IGNORE_HIDDEN_FILES)) {
                 if (is_file($path . '/' . $file)) {
                     $filefull = substr($path, strlen(get_file_base() . '/')) . '/' . $file;
                     $files_here[] = $filefull;
                 } else {
                     $dirs_here[] = $path . '/' . $file;
                 }
             }
         }
         closedir($handle);
     } else {
         warn_exit(do_lang_tempcode('DIRECTORY_NOT_FOUND', escape_html($path)));
     }
     sort($files_here);
     foreach ($files_here as $filefull) {
         $out->attach(do_template('BULK_HELPER_ENTRY', array('_GUID' => 'f57ec94c57b0ef0096c80a6c463f31d3', 'FILEFULL' => $filefull)));
     }
     sort($dirs_here);
     foreach ($dirs_here as $dir) {
         $out->attach($this->do_dir($dir));
     }
     return $out;
 }
Пример #6
0
 /**
  * The main user interface for the file dump.
  *
  * @return tempcode	The UI.
  */
 function module_do_gui()
 {
     $title = get_page_title('FILE_DUMP');
     $place = filter_naughty(get_param('place', '/'));
     if (substr($place, -1, 1) != '/') {
         $place .= '/';
     }
     $GLOBALS['FEED_URL'] = find_script('backend') . '?mode=filedump&filter=' . $place;
     // Show tree
     $dirs = explode('/', substr($place, 0, strlen($place) - 1));
     $i = 0;
     $pre = '';
     $file_tree = new ocp_tempcode();
     while (array_key_exists($i, $dirs)) {
         if ($i > 0) {
             $d = $dirs[$i];
         } else {
             $d = do_lang('FILE_DUMP');
         }
         if (array_key_exists($i + 1, $dirs)) {
             $tree_url = build_url(array('page' => '_SELF', 'place' => $pre . $dirs[$i] . '/'), '_SELF');
             if (!$file_tree->is_empty()) {
                 $file_tree->attach(do_template('BREADCRUMB', array('_GUID' => '7ee62e230d53344a7d9667dc59be21c6')));
             }
             $file_tree->attach(hyperlink($tree_url, $d));
         }
         $pre .= $dirs[$i] . '/';
         $i++;
     }
     if (!$file_tree->is_empty()) {
         breadcrumb_add_segment($file_tree, $d);
     } else {
         breadcrumb_set_self($i == 1 ? do_lang_tempcode('FILE_DUMP') : make_string_tempcode(escape_html($d)));
     }
     // Check directory exists
     $fullpath = get_custom_file_base() . '/uploads/filedump' . $place;
     if (!file_exists(get_custom_file_base() . '/uploads/filedump' . $place)) {
         if (has_specific_permission(get_member(), 'upload_filedump')) {
             @mkdir($fullpath, 0777) or warn_exit(do_lang_tempcode('WRITE_ERROR_DIRECTORY', escape_html($fullpath), escape_html(dirname($fullpath))));
             fix_permissions($fullpath, 0777);
             sync_file($fullpath);
         }
     }
     // Find all files in the incoming directory
     $handle = opendir(get_custom_file_base() . '/uploads/filedump' . $place);
     $i = 0;
     $filename = array();
     $description = array();
     $filesize = array();
     $filetime = array();
     $directory = array();
     $deletable = array();
     while (false !== ($file = readdir($handle))) {
         if (!should_ignore_file('uploads/filedump' . $place . $file, IGNORE_ACCESS_CONTROLLERS | IGNORE_HIDDEN_FILES)) {
             $directory[$i] = !is_file(get_custom_file_base() . '/uploads/filedump' . $place . $file);
             $filename[$i] = $directory[$i] ? $file . '/' : $file;
             if ($directory[$i]) {
                 $filesize[$i] = do_lang_tempcode('NA_EM');
             }
             $dbrows = $GLOBALS['SITE_DB']->query_select('filedump', array('description', 'the_member'), array('name' => $file, 'path' => $place));
             if (!array_key_exists(0, $dbrows)) {
                 $description[$i] = $directory[$i] ? do_lang_tempcode('NA_EM') : do_lang_tempcode('NONE_EM');
             } else {
                 $description[$i] = make_string_tempcode(escape_html(get_translated_text($dbrows[0]['description'])));
             }
             if ($description[$i]->is_empty()) {
                 $description[$i] = do_lang_tempcode('NONE_EM');
             }
             $deletable[$i] = array_key_exists(0, $dbrows) && $dbrows[0]['the_member'] == get_member() || has_specific_permission(get_member(), 'delete_anything_filedump');
             if ($directory[$i]) {
                 $size = get_directory_size(get_custom_file_base() . '/uploads/filedump' . $place . $file);
                 $timestamp = NULL;
             } else {
                 $size = filesize(get_custom_file_base() . '/uploads/filedump' . $place . $file);
                 $timestamp = filemtime(get_custom_file_base() . '/uploads/filedump' . $place . $file);
             }
             $filesize[$i] = clean_file_size($size);
             $filetime[$i] = is_null($timestamp) ? NULL : get_timezoned_date($timestamp);
             $i++;
         }
     }
     closedir($handle);
     if ($i != 0) {
         require_code('templates_table_table');
         $header_row = table_table_header_row(array(do_lang_tempcode('FILENAME'), do_lang_tempcode('DESCRIPTION'), do_lang_tempcode('SIZE'), do_lang_tempcode('DATE_TIME'), do_lang_tempcode('ACTIONS')));
         $rows = new ocp_tempcode();
         for ($a = 0; $a < $i; $a++) {
             if ($directory[$a]) {
                 $link = build_url(array('page' => '_SELF', 'place' => $place . $filename[$a]), '_SELF');
             } else {
                 $link = make_string_tempcode(get_custom_base_url() . '/uploads/filedump' . str_replace('%2F', '/', rawurlencode($place . $filename[$a])));
             }
             if (!$directory[$a]) {
                 if ($deletable[$a]) {
                     $delete_url = build_url(array('page' => '_SELF', 'type' => 'ed', 'file' => $filename[$a], 'place' => $place), '_SELF');
                     $actions = do_template('TABLE_TABLE_ACTION_DELETE_ENTRY', array('_GUID' => '9b91e485d80417b1664145f9bca5a2f5', 'NAME' => $filename[$a], 'URL' => $delete_url));
                 } else {
                     $actions = new ocp_tempcode();
                 }
             } else {
                 $delete_url = build_url(array('page' => '_SELF', 'type' => 'ec', 'file' => $filename[$a], 'place' => $place), '_SELF');
                 $actions = do_template('TABLE_TABLE_ACTION_DELETE_CATEGORY', array('_GUID' => '0fa7d4090c6195328191399a14799169', 'NAME' => $filename[$a], 'URL' => $delete_url));
             }
             $rows->attach(table_table_row(array(hyperlink($link, escape_html($filename[$a]), !$directory[$a]), escape_html($description[$a]), escape_html($filesize[$a]), is_null($filetime[$a]) ? do_lang_tempcode('NA') : make_string_tempcode(escape_html($filetime[$a])), $actions)));
         }
         $files = do_template('TABLE_TABLE', array('_GUID' => '1c0a91d47c5fc8a7c2b35c7d9b36132f', 'HEADER_ROW' => $header_row, 'ROWS' => $rows));
     } else {
         $files = new ocp_tempcode();
     }
     // Do a form so people can upload their own stuff
     if (has_specific_permission(get_member(), 'upload_filedump')) {
         $post_url = build_url(array('page' => '_SELF', 'type' => 'ad', 'uploading' => 1), '_SELF');
         $submit_name = do_lang_tempcode('FILEDUMP_UPLOAD');
         $max = floatval(get_max_file_size());
         $text = new ocp_tempcode();
         if ($max < 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 > 10.0 ? integer_format(intval($max)) : float_format($max / 1024.0 / 1024.0)), escape_html(is_null($config_url) ? '' : $config_url)));
         }
         require_code('form_templates');
         $fields = form_input_upload(do_lang_tempcode('UPLOAD'), do_lang_tempcode('_DESCRIPTION_UPLOAD'), 'file', true);
         $fields->attach(form_input_line(do_lang_tempcode('DESCRIPTION'), do_lang_tempcode('DESCRIPTION_DESCRIPTION'), 'description', '', false));
         $hidden = new ocp_tempcode();
         $hidden->attach(form_input_hidden('place', $place));
         handle_max_file_size($hidden);
         $upload_form = do_template('FORM', array('TABINDEX' => strval(get_form_field_tabindex()), 'SKIP_REQUIRED' => true, 'HIDDEN' => $hidden, 'TEXT' => $text, 'FIELDS' => $fields, 'SUBMIT_NAME' => $submit_name, 'URL' => $post_url));
     } else {
         $upload_form = new ocp_tempcode();
     }
     // Do a form so people can make folders
     if (get_option('is_on_folder_create') == '1') {
         $post_url = build_url(array('page' => '_SELF', 'type' => 'ac'), '_SELF');
         require_code('form_templates');
         $fields = form_input_line(do_lang_tempcode('NAME'), do_lang_tempcode('DESCRIPTION_NAME'), 'name', '', true);
         $hidden = form_input_hidden('place', $place);
         $submit_name = do_lang_tempcode('FILEDUMP_CREATE_FOLDER');
         $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, 'URL' => $post_url));
     } else {
         $create_folder_form = new ocp_tempcode();
     }
     return do_template('FILE_DUMP_SCREEN', array('_GUID' => '3f49a8277a11f543eff6488622949c84', 'TITLE' => $title, 'PLACE' => $place, 'FILES' => $files, 'UPLOAD_FORM' => $upload_form, 'CREATE_FOLDER_FORM' => $create_folder_form));
 }
Пример #7
0
/**
 * Get all the themes image codes. THIS DOES NOT SEARCH THE DB - DO NOT USE UNLESS IT'S ON A PURE PACKAGED THEME
 *
 * @param  PATH			The base-path to where we are searching for images
 * @param  PATH			The path to search under, relative to the base-path. This is not the same as the base-path, as we are cropping paths to the base-path
 * @param  boolean		Whether to search recursively from the given directory
 * @return array			A list of image codes
 */
function get_all_image_codes($base_path, $search_under, $recurse = true)
{
    $out = array();
    require_code('images');
    if (!file_exists($base_path . '/' . $search_under)) {
        return array();
    }
    $handle = @opendir($base_path . '/' . $search_under);
    if ($handle !== false) {
        while (false !== ($file = readdir($handle))) {
            if (!should_ignore_file($file, IGNORE_ACCESS_CONTROLLERS)) {
                $full_path = $base_path . '/' . $search_under . '/' . $file;
                if (is_file($full_path)) {
                    if (is_image($file)) {
                        $dot_pos = strrpos($file, '.');
                        if ($dot_pos === false) {
                            $dot_pos = strlen($file);
                        }
                        $_file = substr($file, 0, $dot_pos);
                        $short_path = $search_under == '' ? $_file : $search_under . '/' . $_file;
                        $out[$short_path] = 1;
                    }
                } elseif (strlen($file) != 2 || strtoupper($file) != $file) {
                    if ($recurse) {
                        $out += get_all_image_codes($base_path, $search_under . '/' . $file);
                    }
                }
            }
        }
        closedir($handle);
    }
    return $out;
}
Пример #8
0
 /**
  * Find a script file.
  *
  * @param  string					Script name
  * @param  ?string				Directory (NULL: OcCLE module data dir)
  * @return ~string				Path or failure (false: failure)
  */
 function _find_script_file($script_name, $dir = NULL)
 {
     if (is_null($dir)) {
         $dir = get_custom_file_base() . '/data/modules/admin_occle/';
     }
     $dh = @opendir($dir);
     if ($dh !== false) {
         while (($file = readdir($dh)) !== false) {
             if ($file == $script_name) {
                 return $dir . $script_name;
             }
             if (is_dir($dir . $file) && $file != '.' && !should_ignore_file('data/modules/admin_occle/' . $file, IGNORE_ACCESS_CONTROLLERS)) {
                 $return = $this->_find_script_file($script_name, $dir . $file . '/');
                 if ($return) {
                     return $return;
                 }
             }
         }
         closedir($dh);
     }
     return false;
 }
Пример #9
0
/**
 * Get the contents of a directory, recursively. It is assumed that the directory exists.
 *
 * @param  PATH			The path to search
 * @param  PATH			The path we prepend to everything we find (intended to be used inside the recursion)
 * @param  boolean		Whether to also get special files
 * @param  boolean		Whether to recurse (if not, will return directories as files)
 * @return array			The contents of the directory
 */
function get_directory_contents($path, $rel_path = '', $special_too = false, $recurse = true)
{
    $out = array();
    $d = opendir($path);
    while (($file = readdir($d)) !== false) {
        if (!$special_too) {
            if (should_ignore_file($rel_path . ($rel_path == '' ? '' : '/') . $file, IGNORE_ACCESS_CONTROLLERS)) {
                continue;
            }
        } elseif ($file == '.' || $file == '..') {
            continue;
        }
        if (is_file($path . '/' . $file) || !$recurse) {
            $out[] = $rel_path . ($rel_path == '' ? '' : '/') . $file;
        } elseif (is_dir($path . '/' . $file)) {
            $out = array_merge($out, get_directory_contents($path . '/' . $file, $rel_path . ($rel_path == '' ? '' : '/') . $file, $special_too, $recurse));
        }
    }
    closedir($d);
    return $out;
}
Пример #10
0
/**
 * Get an array containing new comcode, and tempcode. The function wraps the normal comcode_to_tempcode function. The function will do attachment management, including deleting of attachments that have become unused due to editing of some comcode and removing of the reference.
 *
 * @param  LONG_TEXT		The unparsed comcode that references the attachments
 * @param  ID_TEXT		The type the attachment will be used for (e.g. download)
 * @param  ID_TEXT		The ID the attachment will be used for
 * @param  boolean		Whether we are only previewing the attachments (i.e. don't store them!)
 * @param  ?object		The database connection to use (NULL: standard site connection)
 * @param  ?boolean		Whether to insert it as an admin (any comcode parsing will be carried out with admin privileges) (NULL: autodetect)
 * @param  ?MEMBER		The member to use for ownership permissions (NULL: current member)
 * @return array			A map containing 'comcode' (after substitution for tying down the new attachments) and 'tempcode'
 */
function do_comcode_attachments($original_comcode, $type, $id, $previewing_only = false, $connection = NULL, $insert_as_admin = NULL, $for_member = NULL)
{
    require_lang('comcode');
    global $COMCODE_ATTACHMENTS;
    unset($COMCODE_ATTACHMENTS[$id]);
    // In case we have some kind of conflict
    if (is_null($connection)) {
        $connection = $GLOBALS['SITE_DB'];
    }
    if ($for_member !== NULL) {
        $member = $for_member;
        if (is_null($insert_as_admin)) {
            $insert_as_admin = false;
        }
    } else {
        if (function_exists('get_member')) {
            $member = get_member();
            if (is_null($insert_as_admin)) {
                $insert_as_admin = false;
            }
        } else {
            $member = 0;
            if (is_null($insert_as_admin)) {
                $insert_as_admin = true;
            }
        }
    }
    $comcode_text = substr($original_comcode, 0, 8) != '<comcode';
    // Handle data URLs for attachment embedding
    if (function_exists('imagecreatefromstring')) {
        $matches = array();
        $matches2 = array();
        $num_matches = preg_match_all('#<img[^<>]*src="data:image/\\w+;base64,([^"]*)"[^<>]*>#', $original_comcode, $matches);
        $num_matches2 = preg_match_all('#\\[img[^\\[\\]]*\\]data:image/\\w+;base64,([^"]*)\\[/img\\]#', $original_comcode, $matches2);
        for ($i = 0; $i < $num_matches2; $i++) {
            $matches[0][$num_matches] = $matches2[0][$i];
            $matches[1][$num_matches] = $matches2[1][$i];
            $num_matches++;
        }
        for ($i = 0; $i < $num_matches; $i++) {
            if (strpos($original_comcode, $matches[0][$i]) !== false) {
                $data = @base64_decode($matches[1][$i]);
                if ($data !== false && function_exists('imagepng')) {
                    $image = @imagecreatefromstring($data);
                    if ($image !== false) {
                        do {
                            $new_filename = uniqid('', true) . '.png';
                            $new_path = get_custom_file_base() . '/uploads/attachments/' . $new_filename;
                        } while (file_exists($new_path));
                        imagepng($image, $new_path);
                        $attachment_id = $GLOBALS['SITE_DB']->query_insert('attachments', array('a_member_id' => get_member(), 'a_file_size' => strlen($data), 'a_url' => 'uploads/attachments/' . $new_filename, 'a_thumb_url' => '', 'a_original_filename' => basename($new_filename), 'a_num_downloads' => 0, 'a_last_downloaded_time' => time(), 'a_description' => '', 'a_add_time' => time()), true);
                        $GLOBALS['SITE_DB']->query_insert('attachment_refs', array('r_referer_type' => $type, 'r_referer_id' => $id, 'a_id' => $attachment_id));
                        $original_comcode = str_replace($matches[0][$i], '[attachment type="inline" thumb="0"]' . strval($attachment_id) . '[/attachment]', $original_comcode);
                    }
                }
            }
        }
    }
    global $ATTACHMENTS_ALREADY_REFERENCED;
    $old_already = $ATTACHMENTS_ALREADY_REFERENCED;
    $ATTACHMENTS_ALREADY_REFERENCED = array();
    $before = $connection->query_select('attachment_refs', array('a_id', 'id'), array('r_referer_type' => $type, 'r_referer_id' => $id));
    foreach ($before as $ref) {
        $ATTACHMENTS_ALREADY_REFERENCED[$ref['a_id']] = 1;
    }
    $has_one = false;
    $may_have_one = false;
    foreach ($_POST as $key => $value) {
        if (preg_match('#^hidFileID\\_#i', $key) != 0) {
            require_code('uploads');
            $may_have_one = is_swf_upload();
        }
    }
    if ($may_have_one) {
        require_code('uploads');
        is_swf_upload(true);
        require_code('comcode_from_html');
        $original_comcode = preg_replace_callback('#<input [^>]*class="ocp_keep_ui_controlled" [^>]*title="([^"]*)" [^>]*type="text" [^>]*value="[^"]*"[^>]*/?' . '>#siU', 'debuttonise', $original_comcode);
    }
    $myfile = mixed();
    foreach ($_FILES as $key => $file) {
        $matches = array();
        if (($may_have_one && is_swf_upload() || is_uploaded_file($file['tmp_name'])) && preg_match('#file(\\d+)#', $key, $matches) != 0) {
            $has_one = true;
            $atype = post_param('attachmenttype' . $matches[1], '');
            $is_extract = preg_match('#\\[attachment [^\\]]*type="\\w+_extract"[^\\]]*\\]new_' . $matches[1] . '\\[/#', $original_comcode) != 0 || preg_match('#<attachment [^>]*type="\\w+_extract"[^>]*>new_' . $matches[1] . '</#', $original_comcode) != 0;
            if (substr($atype, -8) == '_extract' || $is_extract) {
                require_code('uploads');
                require_code('files');
                require_code('files2');
                $thumb = preg_match('#\\[(attachment|attachment_safe) [^\\]]*thumb="1"[^\\]]*\\]new_' . $matches[1] . '\\[/#', $original_comcode) != 0 || preg_match('#<(attachment|attachment_safe) [^>]*thumb="1"[^>]*>new_' . $matches[1] . '</#', $original_comcode) != 0;
                $arcext = get_file_extension($_FILES[$key]['name']);
                if ($arcext == 'tar' || $arcext == 'zip') {
                    if ($arcext == 'tar') {
                        require_code('tar');
                        $myfile = tar_open($file['tmp_name'], 'rb');
                        $dir = tar_get_directory($myfile, true);
                    } elseif ($arcext == 'zip') {
                        if (!function_exists('zip_open') && get_option('unzip_cmd') == '') {
                            warn_exit(do_lang_tempcode('ZIP_NOT_ENABLED'));
                        }
                        if (!function_exists('zip_open')) {
                            require_code('m_zip');
                            $mzip = true;
                        } else {
                            $mzip = false;
                        }
                        $myfile = zip_open($file['tmp_name']);
                        if (is_integer($myfile)) {
                            require_code('failure');
                            warn_exit(zip_error($myfile, $mzip));
                        }
                        $dir = array();
                        while (($zip_entry = zip_read($myfile)) !== false) {
                            $dir[] = array('zip_entry' => $zip_entry, 'path' => zip_entry_name($zip_entry), 'size' => zip_entry_filesize($zip_entry));
                        }
                    }
                    if (count($dir) > 100) {
                        require_code('site');
                        attach_message(do_lang_tempcode('TOO_MANY_FILES_TO_EXTRACT'), 'warn');
                    } else {
                        foreach ($dir as $entry) {
                            if (substr($entry['path'], -1) == '/') {
                                continue;
                            }
                            // Ignore folders
                            $_file = preg_replace('#\\..*\\.#', '.', basename($entry['path']));
                            if (!check_extension($_file, false, NULL, true)) {
                                continue;
                            }
                            if (should_ignore_file($entry['path'], IGNORE_ACCESS_CONTROLLERS | IGNORE_HIDDEN_FILES)) {
                                continue;
                            }
                            $place = get_custom_file_base() . '/uploads/attachments/' . $_file;
                            $i = 2;
                            // Hunt with sensible names until we don't get a conflict
                            while (file_exists($place)) {
                                $_file = strval($i) . basename($entry['path']);
                                $place = get_custom_file_base() . '/uploads/attachments/' . $_file;
                                $i++;
                            }
                            $i = 2;
                            $_file_thumb = basename($entry['path']);
                            $place_thumb = get_custom_file_base() . '/uploads/attachments_thumbs/' . $_file_thumb;
                            // Hunt with sensible names until we don't get a conflict
                            while (file_exists($place_thumb)) {
                                $_file_thumb = strval($i) . basename($entry['path']);
                                $place_thumb = get_custom_file_base() . '/uploads/attachments_thumbs/' . $_file_thumb;
                                $i++;
                            }
                            if ($arcext == 'tar') {
                                $file_details = tar_get_file($myfile, $entry['path'], false, $place);
                            } elseif ($arcext == 'zip') {
                                zip_entry_open($myfile, $entry['zip_entry']);
                                $file_details = array('size' => $entry['size']);
                                $out_file = @fopen($place, 'wb') or intelligent_write_error($place);
                                $more = mixed();
                                do {
                                    $more = zip_entry_read($entry['zip_entry']);
                                    if ($more !== false) {
                                        if (fwrite($out_file, $more) < strlen($more)) {
                                            warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
                                        }
                                    }
                                } while ($more !== false && $more != '');
                                fclose($out_file);
                                zip_entry_close($entry['zip_entry']);
                            }
                            $description = do_lang('EXTRACTED_FILE');
                            if (strpos($entry['path'], '/') !== false) {
                                $description = do_lang('EXTRACTED_FILE_PATH', dirname($entry['path']));
                            }
                            // Thumbnail
                            $thumb_url = '';
                            require_code('images');
                            if (is_image($_file)) {
                                $gd = get_option('is_on_gd') == '1' && function_exists('imagetypes');
                                if ($gd) {
                                    require_code('images');
                                    if (!is_saveable_image($_file)) {
                                        $ext = '.png';
                                    } else {
                                        $ext = '.' . get_file_extension($_file);
                                    }
                                    $thumb_url = 'uploads/attachments_thumbs/' . $_file_thumb;
                                    convert_image(get_custom_base_url() . '/uploads/attachments/' . $_file, $place_thumb, -1, -1, intval(get_option('thumb_width')), true, NULL, false, true);
                                    if ($connection->connection_write != $GLOBALS['SITE_DB']->connection_write) {
                                        $thumb_url = get_custom_base_url() . '/' . $thumb_url;
                                    }
                                } else {
                                    $thumb_url = 'uploads/attachments/' . $_file;
                                }
                            }
                            $url = 'uploads/attachments/' . $_file;
                            if (addon_installed('galleries')) {
                                require_code('images');
                                if (is_video($url) && $connection->connection_read == $GLOBALS['SITE_DB']->connection_read) {
                                    require_code('transcoding');
                                    $url = transcode_video($url, 'attachments', 'a_url', 'a_original_filename', NULL, NULL);
                                }
                            }
                            $attachment_id = $connection->query_insert('attachments', array('a_member_id' => get_member(), 'a_file_size' => $file_details['size'], 'a_url' => $url, 'a_thumb_url' => $thumb_url, 'a_original_filename' => basename($entry['path']), 'a_num_downloads' => 0, 'a_last_downloaded_time' => time(), 'a_description' => $description, 'a_add_time' => time()), true);
                            $connection->query_insert('attachment_refs', array('r_referer_type' => $type, 'r_referer_id' => $id, 'a_id' => $attachment_id));
                            if ($comcode_text) {
                                $original_comcode .= chr(10) . chr(10) . '[attachment type="' . comcode_escape(str_replace('_extract', '', $atype)) . '" description="' . comcode_escape($description) . '" thumb="' . ($thumb ? '1' : '0') . '"]' . strval($attachment_id) . '[/attachment]';
                            } else {
                                require_code('comcode_xml');
                                //$original_comcode.=chr(10).chr(10).'<attachment type="'.comcode_escape(str_replace('_extract','',$atype)).'" thumb="'.($thumb?'1':'0').'"><attachmentDescription>'.comcode_text__to__comcode_xml($description).'</attachmentDescription>'.strval($attachment_id).'</attachment>';			Would go in bad spot
                            }
                        }
                    }
                    if ($arcext == 'tar') {
                        tar_close($myfile);
                    } elseif ($arcext == 'zip') {
                        zip_close($myfile);
                    }
                }
            } else {
                if (strpos($original_comcode, ']new_' . $matches[1] . '[/attachment]') === false && strpos($original_comcode, '>new_' . $matches[1] . '</attachment>') === false && strpos($original_comcode, ']new_' . $matches[1] . '[/attachment_safe]') === false && strpos($original_comcode, '>new_' . $matches[1] . '</attachment_safe>') === false) {
                    if (preg_match('#\\]\\d+\\[/attachment\\]#', $original_comcode) == 0 && preg_match('#>\\d+</attachment>#', $original_comcode) == 0) {
                        if ($comcode_text) {
                            $original_comcode .= chr(10) . chr(10) . '[attachment]new_' . $matches[1] . '[/attachment]';
                        } else {
                            //$original_comcode.=chr(10).chr(10).'<attachment>new_'.$matches[1].'</attachment>';		Would go in bad spot
                        }
                    }
                }
            }
        }
    }
    global $LAX_COMCODE;
    $temp = $LAX_COMCODE;
    if ($has_one) {
        $LAX_COMCODE = true;
    }
    // We don't want a simple syntax error to cause us to lose our attachments
    $tempcode = comcode_to_tempcode($original_comcode, $member, $insert_as_admin, 60, $id, $connection, false, false, false, false, false, NULL, $for_member);
    $LAX_COMCODE = $temp;
    $ATTACHMENTS_ALREADY_REFERENCED = $old_already;
    /*if ((array_key_exists($id,$COMCODE_ATTACHMENTS)) && (array_key_exists(0,$COMCODE_ATTACHMENTS[$id])))
    	{
    		$original_comcode=$COMCODE_ATTACHMENTS[$id][0]['comcode'];
    	}*/
    $new_comcode = $original_comcode;
    if (array_key_exists($id, $COMCODE_ATTACHMENTS)) {
        $ids_present = array();
        for ($i = 0; $i < count($COMCODE_ATTACHMENTS[$id]); $i++) {
            $attachment = $COMCODE_ATTACHMENTS[$id][$i];
            // If it's a new one, we need to change the comcode to reference the ID we made for it
            if ($attachment['type'] == 'new') {
                $marker = $attachment['marker'];
                //				echo $marker.'!'.$new_comcode;
                $a_id = $attachment['id'];
                $old_length = strlen($new_comcode);
                // Search backwards from $marker
                $tag_end_start = $marker - strlen('[/' . $attachment['tag_type'] . ']');
                // </attachment> would be correct if it is Comcode-XML, but they have the same length, so it's irrelevant
                $tag_start_end = $tag_end_start;
                while ($tag_start_end > 1 && (!isset($new_comcode[$tag_start_end - 1]) || $new_comcode[$tag_start_end - 1] != ']' && $new_comcode[$tag_start_end - 1] != '>')) {
                    $tag_start_end--;
                }
                $param_keep = substr($new_comcode, 0, $tag_start_end - 1);
                $end_keep = substr($new_comcode, $tag_end_start);
                if ($comcode_text) {
                    $new_comcode = $param_keep;
                    if (strpos(substr($param_keep, strrpos($param_keep, '[')), ' type=') === false) {
                        $new_comcode .= ' type="' . comcode_escape($attachment['attachmenttype']) . '"';
                    }
                    if (strpos(substr($param_keep, strrpos($param_keep, '[')), ' description=') === false) {
                        $new_comcode .= ' description="' . comcode_escape($attachment['description']) . '"';
                    }
                    $new_comcode .= ']' . strval($a_id) . $end_keep;
                } else {
                    require_code('comcode_xml');
                    $new_comcode = $param_keep;
                    if (strpos(substr($param_keep, strrpos($param_keep, '<')), ' type=') === false) {
                        $new_comcode .= ' type="' . comcode_escape($attachment['attachmenttype']);
                    }
                    $new_comcode .= '">';
                    if (strpos(substr($param_keep, strrpos($param_keep, '<')), ' description=') === false) {
                        require_code('comcode_xml');
                        $new_comcode .= '<attachmentDescription>' . comcode_text__to__comcode_xml($attachment['description'], true) . '</attachmentDescription>';
                    }
                    $new_comcode .= strval($a_id) . $end_keep;
                }
                //				echo $new_comcode.'<br />!<br />';
                // Update other attachment markers
                $dif = strlen($new_comcode) - $old_length;
                for ($j = $i + 1; $j < count($COMCODE_ATTACHMENTS[$id]); $j++) {
                    //					echo $COMCODE_ATTACHMENTS[$id][$i]['marker'].'!';
                    $COMCODE_ATTACHMENTS[$id][$j]['marker'] += $dif;
                }
                if (!is_null($type)) {
                    $connection->query_insert('attachment_refs', array('r_referer_type' => $type, 'r_referer_id' => $id, 'a_id' => $a_id));
                }
            } else {
                // (Re-)Reference it
                $connection->query_delete('attachment_refs', array('r_referer_type' => $type, 'r_referer_id' => $id, 'a_id' => $attachment['id']), '', 1);
                $connection->query_insert('attachment_refs', array('r_referer_type' => $type, 'r_referer_id' => $id, 'a_id' => $attachment['id']));
            }
            $ids_present[] = $attachment['id'];
        }
        if (!$previewing_only && get_value('disable_attachment_cleanup') !== '1') {
            // Clear any de-referenced attachments
            foreach ($before as $ref) {
                if (!in_array($ref['a_id'], $ids_present) && strpos($new_comcode, 'attachment.php?id=') === false && !multi_lang()) {
                    // Delete reference (as it's not actually in the new comcode!)
                    $connection->query_delete('attachment_refs', array('id' => $ref['id']), '', 1);
                    // Was that the last reference to this attachment? (if so -- delete attachment)
                    $test = $connection->query_value_null_ok('attachment_refs', 'id', array('a_id' => $ref['a_id']));
                    if (is_null($test)) {
                        require_code('attachments3');
                        _delete_attachment($ref['a_id'], $connection);
                    }
                }
            }
        }
    }
    return array('comcode' => $new_comcode, 'tempcode' => $tempcode);
}
Пример #11
0
/**
 * Check for alien files.
 *
 * @param  array			List of files from old version
 * @param  array			List of verbatim files
 * @param  SHORT_TEXT	The directory we are scanning relative to
 * @param  SHORT_TEXT	The directory (relative) we are scanning
 * @param  boolean		Whether to give raw output (no UI)
 * @return string			HTML list of alien files
 */
function check_alien($old_files, $files, $dir, $rela = '', $raw = false)
{
    $alien = '';
    $dh = @opendir($dir);
    if ($dh !== false) {
        if ($rela == '') {
            $old_addons_now_gone = array('sources/hooks/systems/addon_registry/core_installation_uninstallation.php');
            $modules_moved_intentionally = array('collaboration/pages/modules/filedump.php');
            foreach (array_merge($old_addons_now_gone, $modules_moved_intentionally) as $x) {
                if (file_exists(get_file_base() . '/' . $x)) {
                    $alien .= '<li>';
                    if (!$raw) {
                        $alien .= '<input checked="checked" type="checkbox" name="' . uniqid('', true) . '" value="delete:' . escape_html($x) . '" /> ';
                    }
                    $alien .= '<kbd>' . escape_html($x) . '</kbd></li>';
                }
            }
        }
        while (($file = readdir($dh)) !== false) {
            if (should_ignore_file($rela . $file, IGNORE_ACCESS_CONTROLLERS | IGNORE_THEMES | IGNORE_USER_CUSTOMISE)) {
                continue;
            }
            if ($rela . $file == 'data/images') {
                continue;
            }
            if ($rela . $file == 'data/areaedit/plugins/SpellChecker/aspell') {
                continue;
            }
            $is_dir = @is_dir($dir . $file);
            if (!is_readable($dir . $file)) {
                continue;
            }
            if ($file == 'index.php') {
                continue;
            }
            // New zone
            if ($is_dir) {
                if (!file_exists($dir . $file . '/info.php')) {
                    if ($rela == '' && !file_exists($dir . $file . '/pages')) {
                        $ok = false;
                        foreach (array_keys($files) as $f) {
                            if (substr($f, 0, strlen($rela . $file . '/')) == $rela . $file . '/') {
                                $ok = true;
                                break;
                            }
                        }
                        if (!$ok) {
                            continue;
                        }
                    }
                    $alien .= check_alien($old_files, $files, $dir . $file . '/', $rela . $file . '/', $raw);
                }
            } else {
                if (!array_key_exists($rela . $file, $files)) {
                    if (strpos($rela, 'pages/modules') !== false) {
                        $zones = find_all_zones();
                        $matches = array();
                        preg_match('#(.*)pages/modules#', $rela, $matches);
                        $current_zone = str_replace('/', '', $matches[1]);
                        foreach ($zones as $zone) {
                            if (array_key_exists(str_replace($current_zone . '/', $zone . '/', $rela . $file), $files)) {
                                continue 2;
                            }
                        }
                    }
                    $disabled = '';
                    //if ((is_dir($dir.'/'.$file=='')) && ()) Not needed as this is only for files
                    $checked = '';
                    if (array_key_exists($rela . $file, $old_files)) {
                        $checked = 'checked="checked" ';
                    }
                    $alien .= '<li>';
                    if (!$raw) {
                        $alien .= '<input ' . $disabled . $checked . 'type="checkbox" name="' . uniqid('', true) . '" value="delete:' . escape_html($rela . $file) . '" /> ';
                    }
                    if (strlen($alien) <= 100000) {
                        // Reasonable limit
                        $alien .= '<kbd>' . escape_html($rela . $file) . '</kbd></li>';
                    }
                }
            }
        }
    }
    if (strlen($alien) > 100000) {
        $alien = '';
    }
    // Reasonable limit
    return $alien;
}
Пример #12
0
/**
 * Add a folder to the TAR archive
 *
 * @param  array			The TAR file handle
 * @param  ?resource		The logfile to write to (NULL: no logging)
 * @param  PATH			The full path to the folder to add
 * @param  ?integer		The maximum file size to add (NULL: no limit)
 * @param  PATH			The subpath relative to the path (should be left as the default '', as this is used for the recursion to distinguish the adding base path from where it's currently looking)
 * @param  ?array			A map (filename=>1) of files to not back up (NULL: none)
 * @param  ?array			A list of directories ONLY to back up from the root (NULL: no restriction)
 * @param  boolean		Whether to output spaces as we go to keep the connection alive
 * @param  boolean		Whether to not skip "special files" (ones not normally archive)
 */
function tar_add_folder(&$resource, $logfile, $path, $max_size = NULL, $subpath = '', $avoid_backing_up = NULL, $root_only_dirs = NULL, $tick = false, $all_files = false)
{
    require_code('files');
    $_full = $path == '' ? $subpath : $path . '/' . $subpath;
    if ($_full == '') {
        $_full = '.';
    }
    if (!is_null($logfile)) {
        $dh = @opendir($_full);
        if ($dh === false) {
            if (fwrite($logfile, 'Could not access ' . $_full . ' [case 2]' . "\n") == 0) {
                warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
            }
        }
    } else {
        $dh = opendir($_full);
    }
    if ($dh !== false) {
        while (($entry = readdir($dh)) !== false) {
            if ($entry == '.' || $entry == '..') {
                continue;
            }
            if ($tick) {
                @(print ' ');
            }
            $_subpath = $subpath == '' ? $entry : $subpath . '/' . $entry;
            if (($all_files || !should_ignore_file($_subpath)) && $entry != 'backups') {
                $full = $path == '' ? $_subpath : $path . '/' . $_subpath;
                if (!is_readable($full)) {
                    if (fwrite($logfile, 'Could not access ' . $full . "\n") == 0) {
                        warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
                    }
                    continue;
                }
                if (is_dir($full)) {
                    if (is_null($root_only_dirs) || in_array($entry, $root_only_dirs)) {
                        tar_add_folder($resource, $logfile, $path, $max_size, $_subpath, $avoid_backing_up, NULL, $tick, $all_files);
                    }
                } else {
                    if ($full != $resource['full'] && (is_null($max_size) || filesize($full) < $max_size * 1024 * 1024) && (is_null($avoid_backing_up) || !array_key_exists($_subpath, $avoid_backing_up))) {
                        //echo $_subpath.'<br />';
                        tar_add_file($resource, $_subpath, $full, fileperms($full), filemtime($full), true);
                        if (!is_null($logfile) && fwrite($logfile, 'Backed up file ' . $full . ' (' . clean_file_size(filesize($full)) . ')' . "\n") == 0) {
                            warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
                        }
                    }
                }
            }
        }
        closedir($dh);
    }
}
                            $matches = array();
                            if (preg_match('#\\n(\\t*)function install(\\_ocf)?\\([^\\n]*\\)\\n\\1\\{\\n(.*)\\n\\1\\}#sU', $old, $matches) != 0) {
                                $old_install_code = $matches[3];
                                $new_install_code = '';
                                if (preg_match('#\\n(\\t*)function install(\\_ocf)?\\([^\\n]*\\)\\n\\1\\{\\n(.*)\\n\\1\\}#sU', $new, $matches) != 0) {
                                    $new_install_code = $matches[3];
                                }
                                if ($new_install_code != $old_install_code) {
                                    $manual_changes['install_diff'][$file] = diff_simple_2($old_install_code, $new_install_code, true);
                                }
                            }
                        }
                    }
                }
            } else {
                if (!should_ignore_file($file, IGNORE_CUSTOM_DIR_CONTENTS | IGNORE_HIDDEN_FILES | IGNORE_THEMES | IGNORE_CUSTOM_ZONES | IGNORE_REVISION_FILES | IGNORE_EDITFROM_FILES)) {
                    $manual_changes['maybe_delete'][$file] = NULL;
                }
            }
        }
        echo '
			<h2>Advice</h2>
		';
        foreach (array('maybe_delete' => 'The following files might need deleting', 'css_diff' => 'The following CSS/tpl changes have happened (diff; may need applying to overridden templates)', 'install_diff' => 'The following install code changes have happened (diff) &ndash; isolate to <kbd>data_custom/execute_temp.php</kbd> to make an adhoc upgrader') as $d => $message) {
            echo '
				<p>
					' . $message . '&hellip;
				</p>
			';
            if (count($manual_changes[$d]) != 0) {
                echo '<ul>';
Пример #14
0
 /**
  * (Recursively) find all files we can choose to export.
  *
  * @param  PATH				The directory to search
  * @return array				A map, path=>1 (inverted list)
  */
 function do_dir($dir)
 {
     $full = get_file_base() . '/' . ($dir == '' ? '' : $dir . '/');
     $temp = array();
     $_dir = @opendir($full);
     if ($_dir !== false) {
         while (false !== ($file = readdir($_dir))) {
             if ($dir == '' && $file == '_tests') {
                 continue;
             }
             if (!should_ignore_file(($dir == '' ? '' : $dir . '/') . $file, IGNORE_EDITFROM_FILES | IGNORE_REVISION_FILES)) {
                 $temp[$file] = 1;
             }
         }
         closedir($_dir);
     }
     $out = array();
     foreach (array_keys($temp) as $file) {
         if (is_dir($full . $file)) {
             if (!array_key_exists($file . '_custom', $temp) || substr($dir, 0, 7) == 'themes/') {
                 $under = $this->do_dir($dir . '/' . $file);
                 if (count($under) != 1 || !array_key_exists(($dir == '' ? '' : $dir . '/') . $file . '/index.html', $under) || substr($dir, 0, 7) == 'themes/') {
                     $out = array_merge($out, $under);
                 }
             }
         } else {
             $out[$dir . '/' . $file] = 1;
         }
     }
     return $out;
 }