/** * create a thumbnail * * @param string the full path to the original file * @param string the pull path to write the thumbnail * @param boolean TRUE to resize to 60x60 * @param boolean TRUE to see error messages, if any * @return TRUE on success, FALSE on error */ public static function shrink($original, $target, $fixed = FALSE, $verbose = TRUE) { global $context; $file_name = basename($original); $open = Image::open($original); if ($open === FALSE) { return FALSE; } list($image, $image_information) = $open; // actual width $width = $image_information[0]; // standard width if ($fixed) { $maximum_width = 60; } elseif (isset($context['thumbnail_width']) && $context['thumbnail_width'] >= 32) { $maximum_width = $context['thumbnail_width']; } else { $maximum_width = 60; } // actual height $height = $image_information[1]; // standard height if ($fixed) { $maximum_height = 60; } elseif (isset($context['thumbnail_height']) && $context['thumbnail_height'] >= 32) { $maximum_height = $context['thumbnail_height']; } else { $maximum_height = 60; } // assume resize is not necessary $thumbnail_height = $height; $thumbnail_width = $width; // the image is laid vertically if ($height > $width) { // set the thumbnail size if ($height > $maximum_height) { $thumbnail_height = $maximum_height; $thumbnail_width = $width * $thumbnail_height / $height; } // the image is laid horizontally } else { // set the thumbnail size if ($width > $maximum_width) { $thumbnail_width = $maximum_width; $thumbnail_height = $height * $thumbnail_width / $width; } } // create target folder for the thumbnail if ($target_path = dirname($target)) { Safe::make_path($target_path); } // we already have a small image if ($thumbnail_width == $width && $thumbnail_height == $height) { // copy file content to the thumbnail if (!copy($original, $target)) { if ($verbose) { Logger::error(sprintf(i18n::s('Cannot copy image to %s'), $target)); } return FALSE; } // this will be filtered by umask anyway Safe::chmod($target, $context['file_mask']); // job done return TRUE; } // create the thumbnail in memory $thumbnail = NULL; if (Image::use_magic()) { $thumbnail = $image->resizeImage($thumbnail_width, $thumbnail_height, Imagick::FILTER_POINT, 1); } else { if ($image_information[2] == 2 && is_callable('ImageCreateTrueColor') && ($thumbnail = ImageCreateTrueColor($thumbnail_width, $thumbnail_height))) { ImageCopyResampled($thumbnail, $image, 0, 0, 0, 0, $thumbnail_width, $thumbnail_height, $width, $height); } if (!$thumbnail && is_callable('ImageCreate') && ($thumbnail = ImageCreate($thumbnail_width, $thumbnail_height))) { ImageCopyResized($thumbnail, $image, 0, 0, 0, 0, $thumbnail_width, $thumbnail_height, $width, $height); } } // sanity check if (!$thumbnail) { if ($verbose) { Logger::error(sprintf(i18n::s('Impossible to skrink image %s'), $file_name)); } return FALSE; } // save the thumbnail in the file system $result = FALSE; if (Image::use_magic()) { $result = $image->writeImage($target); } else { if ($image_information[2] == 1 && is_callable('ImageGIF')) { ImageGIF($thumbnail, $target); } elseif ($image_information[2] == 2 && is_callable('ImageJPEG')) { ImageJPEG($thumbnail, $target, IMG_JPEG_QUALITY); } elseif (($image_information[2] == 1 || $image_information[2] == 3) && is_callable('ImagePNG')) { ImagePNG($thumbnail, $target); } else { if ($verbose) { Logger::error(sprintf(i18n::s('Impossible to write to %s.'), $target)); } return FALSE; } } // this will be filtered by umask anyway Safe::chmod($target, $context['file_mask']); // job done if (Image::use_magic()) { $image->destroy(); } else { ImageDestroy($thumbnail); } return TRUE; }
} elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'confirm') { // list running scripts $context['text'] .= '<p>' . i18n::s('Listing files...') . BR . "\n"; // locate script files starting at root $scripts = Scripts::list_scripts_at(NULL); if (is_array($scripts)) { $context['text'] .= BR . sprintf(i18n::s('%d scripts have been found.'), count($scripts)) . "\n"; } $context['text'] .= "</p>\n"; // chmod each file $context['text'] .= '<p>' . i18n::s('Updating file permissions...') . BR . "\n"; // analyse each script $count = 0; foreach ($scripts as $file) { // this will be filtered by umask anyway Safe::chmod($context['path_to_root'] . $file, $context['file_mask']); $count++; // avoid timeouts if (!($count % 50)) { Safe::set_time_limit(30); SQL::ping(); } } if ($count) { $context['text'] .= sprintf(i18n::s('%d files have been updated.'), $count) . "\n"; } $context['text'] .= "</p>\n"; // display the execution time $time = round(get_micro_time() - $context['start_time'], 2); $context['text'] .= '<p>' . sprintf(i18n::s('Script terminated in %.2f seconds.'), $time) . '</p>'; // forward to the index page
/** * process uploaded file * * This function processes files from the temporary directory, and put them at their definitive * place. * * It returns FALSE if there is a disk error, or if some virus has been detected, or if * the operation fails for some other reason (e.g., file size). * * @param array usually, $_FILES['upload'] * @param string target location for the file * @param mixed reference to the target anchor, of a function to parse every file individually * @return mixed file name or array of file names or FALSE if an error has occured */ public static function upload($input, $file_path, $target = NULL, $overlay = NULL) { global $context, $_REQUEST; // size exceeds php.ini settings -- UPLOAD_ERR_INI_SIZE if (isset($input['error']) && $input['error'] == 1) { Logger::error(i18n::s('The size of this file is over limit.')); } elseif (isset($input['error']) && $input['error'] == 2) { Logger::error(i18n::s('The size of this file is over limit.')); } elseif (isset($input['error']) && $input['error'] == 3) { Logger::error(i18n::s('No file has been transmitted.')); } elseif (isset($input['error']) && $input['error'] == 4) { Logger::error(i18n::s('No file has been transmitted.')); } elseif (!$input['size']) { Logger::error(i18n::s('No file has been transmitted.')); } // do we have a file? if (!isset($input['name']) || !$input['name'] || $input['name'] == 'none') { return FALSE; } // access the temporary uploaded file $file_upload = $input['tmp_name']; // $_FILES transcoding to utf8 is not automatic $input['name'] = utf8::encode($input['name']); // enhance file name $file_name = $input['name']; $file_extension = ''; $position = strrpos($input['name'], '.'); if ($position !== FALSE) { $file_name = substr($input['name'], 0, $position); $file_extension = strtolower(substr($input['name'], $position + 1)); } $input['name'] = $file_name; if ($file_extension) { $input['name'] .= '.' . $file_extension; } // ensure we have a file name $file_name = utf8::to_ascii($input['name']); // uploads are not allowed if (!Surfer::may_upload()) { Logger::error(i18n::s('You are not allowed to perform this operation.')); } elseif (!Files::is_authorized($input['name'])) { Logger::error(i18n::s('This type of file is not allowed.')); } elseif ($file_path && !Safe::is_uploaded_file($file_upload)) { Logger::error(i18n::s('Possible file attack.')); } else { // create folders if ($file_path) { Safe::make_path($file_path); } // sanity check if ($file_path && $file_path[strlen($file_path) - 1] != '/') { $file_path .= '/'; } // move the uploaded file if ($file_path && !Safe::move_uploaded_file($file_upload, $context['path_to_root'] . $file_path . $file_name)) { Logger::error(sprintf(i18n::s('Impossible to move the upload file to %s.'), $file_path . $file_name)); } else { // process the file where it is if (!$file_path) { $file_path = str_replace($context['path_to_root'], '', dirname($file_upload)); $file_name = basename($file_upload); } // check against viruses $result = Files::has_virus($context['path_to_root'] . $file_path . '/' . $file_name); // no virus has been found in this file if ($result == 'N') { $context['text'] .= Skin::build_block(i18n::s('No virus has been found.'), 'note'); } // this file has been infected! if ($result == 'Y') { // delete this file immediately Safe::unlink($file_path . '/' . $file_name); Logger::error(i18n::s('This file has been infected by a virus and has been rejected!')); return FALSE; } // explode a .zip file include_once $context['path_to_root'] . 'shared/zipfile.php'; if (preg_match('/\\.zip$/i', $file_name) && isset($_REQUEST['explode_files'])) { $zipfile = new zipfile(); // check files extracted from the archive file function explode_callback($name) { global $context; // reject all files put in sub-folders if (($path = substr($name, strlen($context['uploaded_path'] . '/'))) && strpos($path, '/') !== FALSE) { Safe::unlink($name); } elseif (!Files::is_authorized($name)) { Safe::unlink($name); } else { // make it easy to download $ascii = utf8::to_ascii(basename($name)); Safe::rename($name, $context['uploaded_path'] . '/' . $ascii); // remember this name $context['uploaded_files'][] = $ascii; } } // extract archive components and save them in mentioned directory $context['uploaded_files'] = array(); $context['uploaded_path'] = $file_path; if (!($count = $zipfile->explode($context['path_to_root'] . $file_path . '/' . $file_name, $file_path, '', 'explode_callback'))) { Logger::error(sprintf('Nothing has been extracted from %s.', $file_name)); return FALSE; } // one single file has been uploaded } else { $context['uploaded_files'] = array($file_name); } // ensure we know the surfer Surfer::check_default_editor($_REQUEST); // post-process all uploaded files foreach ($context['uploaded_files'] as $file_name) { // this will be filtered by umask anyway Safe::chmod($context['path_to_root'] . $file_path . $file_name, $context['file_mask']); // invoke post-processing function if ($target && is_callable($target)) { call_user_func($target, $file_name, $context['path_to_root'] . $file_path); // we have to update an anchor page } elseif ($target && is_string($target)) { $fields = array(); // update a file with the same name for this anchor if ($matching =& Files::get_by_anchor_and_name($target, $file_name)) { $fields['id'] = $matching['id']; } elseif (isset($input['id']) && ($matching = Files::get($input['id']))) { $fields['id'] = $matching['id']; // silently delete the previous version of the file if (isset($matching['file_name'])) { Safe::unlink($file_path . '/' . $matching['file_name']); } } // prepare file record $fields['file_name'] = $file_name; $fields['file_size'] = filesize($context['path_to_root'] . $file_path . $file_name); $fields['file_href'] = ''; $fields['anchor'] = $target; // change title if (isset($_REQUEST['title'])) { $fields['title'] = $_REQUEST['title']; } // change has been documented if (!isset($_REQUEST['version']) || !$_REQUEST['version']) { $_REQUEST['version'] = ''; } else { $_REQUEST['version'] = ' - ' . $_REQUEST['version']; } // always remember file uploads, for traceability $_REQUEST['version'] = $fields['file_name'] . ' (' . Skin::build_number($fields['file_size'], i18n::s('bytes')) . ')' . $_REQUEST['version']; // add to file history $fields['description'] = Files::add_to_history($matching, $_REQUEST['version']); // if this is an image, maybe we can derive a thumbnail for it? if (Files::is_image($file_name)) { include_once $context['path_to_root'] . 'images/image.php'; Image::shrink($context['path_to_root'] . $file_path . $file_name, $context['path_to_root'] . $file_path . 'thumbs/' . $file_name); if (file_exists($context['path_to_root'] . $file_path . 'thumbs/' . $file_name)) { $fields['thumbnail_url'] = $context['url_to_home'] . $context['url_to_root'] . $file_path . 'thumbs/' . rawurlencode($file_name); } } // change active_set if (isset($_REQUEST['active_set'])) { $fields['active_set'] = $_REQUEST['active_set']; } // change source if (isset($_REQUEST['source'])) { $fields['source'] = $_REQUEST['source']; } // change keywords if (isset($_REQUEST['keywords'])) { $fields['keywords'] = $_REQUEST['keywords']; } // change alternate_href if (isset($_REQUEST['alternate_href'])) { $fields['alternate_href'] = $_REQUEST['alternate_href']; } // overlay, if any if (is_object($overlay)) { // allow for change detection $overlay->snapshot(); // update the overlay from form content $overlay->parse_fields($_REQUEST); // save content of the overlay in this item $fields['overlay'] = $overlay->save(); $fields['overlay_id'] = $overlay->get_id(); } // create the record in the database if (!($fields['id'] = Files::post($fields))) { return FALSE; } // record surfer activity Activities::post('file:' . $fields['id'], 'upload'); } } // so far so good if (count($context['uploaded_files']) == 1) { return $context['uploaded_files'][0]; } else { return $context['uploaded_files']; } } } // some error has occured return FALSE; }
/** * duplicate all images for a given anchor * * This function duplicates records in the database, and changes anchors * to attach new records as per second parameter. * * @param string the source anchor * @param string the target anchor * @return int the number of duplicated records * * @see shared/anchors.php */ public static function duplicate_for_anchor($anchor_from, $anchor_to) { global $context; // look for records attached to this anchor $count = 0; $query = "SELECT * FROM " . SQL::table_name('images') . " WHERE anchor LIKE '" . SQL::escape($anchor_from) . "'"; if (($result = SQL::query($query)) && SQL::count($result)) { // create target folders $file_to = $context['path_to_root'] . Files::get_path($item['anchor'], 'images'); if (!Safe::make_path($file_to . '/thumbs')) { Logger::error(sprintf(i18n::s('Impossible to create path %s.'), $file_to . '/thumbs')); } $file_to = $context['path_to_root'] . $file_to . '/'; // the list of transcoded strings $transcoded = array(); // process all matching records one at a time $file_from = $context['path_to_root'] . Files::get_path($anchor_from, 'images'); while ($item = SQL::fetch($result)) { // sanity check if (!file_exists($context['path_to_root'] . $file_from . '/' . $item['image_name'])) { continue; } // duplicate image file if (!copy($context['path_to_root'] . $file_from . '/' . $item['image_name'], $file_to . $item['image_name'])) { Logger::error(sprintf(i18n::s('Impossible to copy file %s.'), $item['image_name'])); continue; } // this will be filtered by umask anyway Safe::chmod($file_to . $item['image_name'], $context['file_mask']); // copy the thumbnail as well Safe::copy($context['path_to_root'] . $file_from . '/' . $item['thumbnail_name'], $file_to . $item['thumbnail_name']); // this will be filtered by umask anyway Safe::chmod($file_to . $item['thumbnail_name'], $context['file_mask']); // a new id will be allocated $old_id = $item['id']; unset($item['id']); // target anchor $item['anchor'] = $anchor_to; // actual duplication if ($new_id = Images::post($item)) { // more pairs of strings to transcode --no automatic solution for [images=...] $transcoded[] = array('/\\[image=' . preg_quote($old_id, '/') . '/i', '[image=' . $new_id); // duplicate elements related to this item Anchors::duplicate_related_to('image:' . $old_id, 'image:' . $new_id); // stats $count++; } } // transcode in anchor if ($anchor = Anchors::get($anchor_to)) { $anchor->transcode($transcoded); } } // number of duplicated records return $count; }
continue; } // store the footprint for later use --number of lines, content hash $footprints[$file] = array($footprint[0], $footprint[1]); // ensure a clean reference store Safe::unlink($context['path_to_reference'] . $file); // create adequate path if (!Safe::make_path($context['path_to_reference'] . dirname($file))) { $context['text'] .= sprintf(i18n::s('Impossible to create path %s.'), $context['path_to_reference'] . dirname($file)) . BR . "\n"; } elseif (!Safe::copy($context['path_to_root'] . $file, $context['path_to_reference'] . $file)) { $context['text'] .= sprintf(i18n::s('Impossible to copy file %s.'), $file) . BR . "\n"; } else { // try to preserve the modification date Safe::touch($context['path_to_reference'] . $file, Safe::filemtime($context['path_to_root'] . $file)); // this will be filtered by umask anyway Safe::chmod($context['path_to_reference'] . $file, $context['file_mask']); } // avoid timeouts if (!(count($footprints) % 50)) { Safe::set_time_limit(30); SQL::ping(); } } if (count($footprints)) { $context['text'] .= sprintf(i18n::s('%d reference scripts have been copied.'), count($footprints)) . "\n"; } $context['text'] .= "</p>\n"; // purge documentation pages $context['text'] .= '<p>' . i18n::s('Purging the documentation pages...') . "</p>\n"; // get a parser include_once 'phpdoc.php';
function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path) { $v_result = true; $v_nb = 0; $v_extract_all = true; $v_listing = false; $p_path = $this->_translateWinPath($p_path, false); if ($p_path == '' || substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':')) { $p_path = "./" . $p_path; } $p_remove_path = $this->_translateWinPath($p_remove_path); // ----- Look for path to remove format (should end by /) if ($p_remove_path != '' && substr($p_remove_path, -1) != '/') { $p_remove_path .= '/'; } $p_remove_path_size = strlen($p_remove_path); switch ($p_mode) { case "complete": $v_extract_all = TRUE; $v_listing = FALSE; break; case "partial": $v_extract_all = FALSE; $v_listing = FALSE; break; case "list": $v_extract_all = FALSE; $v_listing = TRUE; break; default: $this->_error('Invalid extract mode (' . $p_mode . ')'); return false; } clearstatcache(); while (strlen($v_binary_data = $this->_readBlock()) != 0) { $v_extract_file = FALSE; $v_extraction_stopped = 0; if (!$this->_readHeader($v_binary_data, $v_header)) { return false; } if ($v_header['filename'] == '') { continue; } // ----- Look for long filename if ($v_header['typeflag'] == 'L') { if (!$this->_readLongHeader($v_header)) { return false; } } if (!$v_extract_all && is_array($p_file_list)) { // ----- By default no unzip if the file is not found $v_extract_file = false; for ($i = 0; $i < sizeof($p_file_list); $i++) { // ----- Look if it is a directory if (substr($p_file_list[$i], -1) == '/') { // ----- Look if the directory is in the filename path if (strlen($v_header['filename']) > strlen($p_file_list[$i]) && substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i]) { $v_extract_file = TRUE; break; } } elseif ($p_file_list[$i] == $v_header['filename']) { $v_extract_file = TRUE; break; } } } else { $v_extract_file = TRUE; } // ----- Look if this file need to be extracted if ($v_extract_file && !$v_listing) { if ($p_remove_path != '' && substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path) { $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size); } if ($p_path != './' && $p_path != '/') { while (substr($p_path, -1) == '/') { $p_path = substr($p_path, 0, strlen($p_path) - 1); } if (substr($v_header['filename'], 0, 1) == '/') { $v_header['filename'] = $p_path . $v_header['filename']; } else { $v_header['filename'] = $p_path . '/' . $v_header['filename']; } } if (file_exists($v_header['filename'])) { if (@is_dir($v_header['filename']) && $v_header['typeflag'] == '') { $this->_error('File ' . $v_header['filename'] . ' already exists as a directory'); return false; } if ($this->_isArchive($v_header['filename']) && $v_header['typeflag'] == "5") { $this->_error('Directory ' . $v_header['filename'] . ' already exists as a file'); return false; } if (!is_writeable($v_header['filename'])) { $this->_error('File ' . $v_header['filename'] . ' already exists and is write protected'); return false; } if (filemtime($v_header['filename']) > $v_header['mtime']) { // To be completed : An error or silent no replace ? } } elseif (($v_result = $this->_dirCheck($v_header['typeflag'] == "5" ? $v_header['filename'] : dirname($v_header['filename']))) != 1) { $this->_error('Unable to create path for ' . $v_header['filename']); return false; } if ($v_extract_file) { if ($v_header['typeflag'] == "5") { if (!@file_exists($v_header['filename'])) { global $context; if (!@mkdir($v_header['filename'], $context['directory_mask'])) { $this->_error('Unable to create directory {' . $v_header['filename'] . '}'); return false; } } } else { if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { $this->_error('Error while opening {' . $v_header['filename'] . '} in write binary mode'); return false; } else { $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_content = $this->_readBlock(); fwrite($v_dest_file, $v_content, 512); } if ($v_header['size'] % 512 != 0) { $v_content = $this->_readBlock(); fwrite($v_dest_file, $v_content, $v_header['size'] % 512); } @fclose($v_dest_file); // ----- Change the file mode, mtime @touch($v_header['filename'], $v_header['mtime']); // To be completed Safe::chmod($v_header['filename']); } // ----- Check the file size clearstatcache(); if (filesize($v_header['filename']) != $v_header['size']) { $this->_error('Extracted file ' . $v_header['filename'] . ' does not have the correct file size \'' . filesize($v_header['filename']) . '\' (' . $v_header['size'] . ' expected). Archive may be corrupted.'); return false; } } } else { $this->_jumpBlock(ceil($v_header['size'] / 512)); } } else { $this->_jumpBlock(ceil($v_header['size'] / 512)); } /* TBC : Seems to be unused ... if ($this->_compress) $v_end_of_file = @gzeof($this->_file); else $v_end_of_file = @feof($this->_file); */ if ($v_listing || $v_extract_file || $v_extraction_stopped) { // ----- Log extracted files if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) { $v_file_dir = ''; } if (substr($v_header['filename'], 0, 1) == '/' && $v_file_dir == '') { $v_file_dir = '/'; } $p_list_detail[$v_nb++] = $v_header; } Safe::set_time_limit(30); } return true; }
continue; } } // we should have an updated file in the staging directory if (file_exists($context['path_to_root'] . 'scripts/staging/' . $file)) { // we don't care about missing run-once scripts } elseif (preg_match('/\\brun_once\\b/i', $file)) { continue; // report on the missing file } else { $context['text'] .= sprintf(i18n::s('ERROR: File %s is missing or corrupted.'), $file) . BR . "\n"; $missing_files++; continue; } // this will be filtered by umask anyway Safe::chmod($context['path_to_root'] . 'scripts/staging/' . $file, $context['file_mask']); // maybe we have to update the front page if ($file == 'index.php' && isset($context['home_at_root']) && $context['home_at_root'] == 'Y') { if (Safe::copy($context['path_to_root'] . 'scripts/staging/index.php', $context['path_to_root'] . '../index.php')) { $context['text'] .= sprintf(i18n::s('%s has been updated'), '../index.php') . ' (' . $attributes[0] . ' ' . i18n::s('lines') . ')' . BR . "\n"; $updated_files++; // failed update } else { $context['text'] .= FAILURE_PREFIX . sprintf(i18n::s('Impossible to write to %s.'), '../index.php') . FAILURE_SUFFIX . BR . "\n"; $failures++; } } // ensure all folders exist if (!Safe::make_path(dirname($file))) { $context['text'] .= FAILURE_PREFIX . sprintf(i18n::s('Impossible to create path %s.'), dirname($file)) . FAILURE_SUFFIX . BR . "\n"; $failures++;