Ejemplo n.º 1
0
 /**
  * Check if the given file is capable of being imported by this plugin.
  * As {@link file_storage::mimetype()} now uses finfo PHP extension if available,
  * the value returned by $file->get_mimetype for a .dat file is not the same on all servers.
  * So we must made 2 checks to verify if the plugin can import the file.
  * @param stored_file $file the file to check
  * @return bool whether this plugin can import the file
  */
 public function can_import_file($file) {
     $mimetypes = array(
         mimeinfo('type', '.dat'),
         mimeinfo('type', '.zip')
     );
     return in_array($file->get_mimetype(), $mimetypes) || in_array(mimeinfo('type', $file->get_filename()), $mimetypes);
 }
Ejemplo n.º 2
0
 /**
  * Generates a preview image for the stored file
  *
  * @param stored_file $file the file we want to preview
  * @param string $mode preview mode, eg. 'thumb'
  * @return stored_file|bool the newly created preview file or false
  */
 protected function create_file_preview(stored_file $file, $mode)
 {
     $mimetype = $file->get_mimetype();
     if ($mimetype === 'image/gif' or $mimetype === 'image/jpeg' or $mimetype === 'image/png') {
         // make a preview of the image
         $data = $this->create_imagefile_preview($file, $mode);
     } else {
         // unable to create the preview of this mimetype yet
         return false;
     }
     if (empty($data)) {
         return false;
     }
     $context = context_system::instance();
     $record = array('contextid' => $context->id, 'component' => 'core', 'filearea' => 'preview', 'itemid' => 0, 'filepath' => '/' . trim($mode, '/') . '/', 'filename' => $file->get_contenthash());
     $imageinfo = getimagesizefromstring($data);
     if ($imageinfo) {
         $record['mimetype'] = $imageinfo['mime'];
     }
     return $this->create_file_from_string($record, $data);
 }
Ejemplo n.º 3
0
 /**
  * Check if the given file is capable of being imported by this plugin.
  *
  * Note that expensive or detailed integrity checks on the file should
  * not be performed by this method. Simple file type or magic-number tests
  * would be suitable.
  *
  * @param stored_file $file the file to check
  * @return bool whether this plugin can import the file
  */
 public function can_import_file($file)
 {
     return $file->get_mimetype() == $this->mime_type();
 }
 /**
  * if we already know we have exactly one file,
  * bypass set_formats and just pass the file
  * so we can detect the formats by mimetype.
  *
  * @param stored_file $file         file to set the format from
  * @param mixed       $extraformats any additional formats other than by mimetype
  *                                  eg leap2a etc
  */
 public function set_format_by_file(stored_file $file, $extraformats = null)
 {
     $this->file = $file;
     $fileformat = portfolio_format_from_mimetype($file->get_mimetype());
     if (is_string($extraformats)) {
         $extraformats = array($extraformats);
     } else {
         if (!is_array($extraformats)) {
             $extraformats = array();
         }
     }
     $this->set_formats(array_merge(array($fileformat), $extraformats));
 }
Ejemplo n.º 5
0
/**
* Deduce export format from file mimetype
*
* This function returns the revelant portfolio export format
* which is used to determine which portfolio plugins can be used
* for exporting this content
* according to the mime type of the given file
* this only works when exporting exactly <b>one</b> file
*
* @param stored_file $file file to check mime type for
*
* @return string the format constant (see PORTFOLIO_FORMAT_XXX constants)
*/
function portfolio_format_from_file(stored_file $file)
{
    static $alreadymatched;
    if (empty($alreadymatched)) {
        $alreadymatched = array();
    }
    if (!$file instanceof stored_file) {
        throw new portfolio_exception('invalidfileargument', 'portfolio');
    }
    $mimetype = $file->get_mimetype();
    if (array_key_exists($mimetype, $alreadymatched)) {
        return $alreadymatched[$mimetype];
    }
    $allformats = portfolio_supported_formats();
    foreach ($allformats as $format => $classname) {
        $supportedmimetypes = call_user_func(array($classname, 'mimetypes'));
        if (!is_array($supportedmimetypes)) {
            debugging("one of the portfolio format classes, {$classname}, said it supported something funny for mimetypes, should have been array...");
            debugging(print_r($supportedmimetypes, true));
            continue;
        }
        if (in_array($mimetype, $supportedmimetypes)) {
            $alreadymatched[$mimetype] = $format;
            return $format;
        }
    }
    return PORTFOLIO_FORMAT_FILE;
    // base case for files...
}
Ejemplo n.º 6
0
 /**
  * Checks to see if a passed file is indexable.
  *
  * @param \stored_file $file The file to check
  * @return bool True if the file can be indexed
  */
 protected function file_is_indexable($file)
 {
     if (!empty($this->config->maxindexfilekb) && $file->get_filesize() > $this->config->maxindexfilekb * 1024) {
         // The file is too big to index.
         return false;
     }
     $mime = $file->get_mimetype();
     if ($mime == 'application/vnd.moodle.backup') {
         // We don't index Moodle backup files. There is nothing usefully indexable in them.
         return false;
     }
     return true;
 }
Ejemplo n.º 7
0
/**
 * Resize the image, if required, then generate an img tag and, if required, a link to the full-size image
 * @param stored_file $file the image file to process
 * @param int $maxwidth the maximum width allowed for the image
 * @param int $maxheight the maximum height allowed for the image
 * @return string HTML fragment to add to the label
 */
function label_generate_resized_image(stored_file $file, $maxwidth, $maxheight)
{
    global $CFG;
    $fullurl = moodle_url::make_draftfile_url($file->get_itemid(), $file->get_filepath(), $file->get_filename());
    $link = null;
    $attrib = array('alt' => $file->get_filename(), 'src' => $fullurl);
    if ($imginfo = $file->get_imageinfo()) {
        // Work out the new width / height, bounded by maxwidth / maxheight
        $width = $imginfo['width'];
        $height = $imginfo['height'];
        if (!empty($maxwidth) && $width > $maxwidth) {
            $height *= (double) $maxwidth / $width;
            $width = $maxwidth;
        }
        if (!empty($maxheight) && $height > $maxheight) {
            $width *= (double) $maxheight / $height;
            $height = $maxheight;
        }
        $attrib['width'] = $width;
        $attrib['height'] = $height;
        // If the size has changed and the image is of a suitable mime type, generate a smaller version
        if ($width != $imginfo['width']) {
            $mimetype = $file->get_mimetype();
            if ($mimetype === 'image/gif' or $mimetype === 'image/jpeg' or $mimetype === 'image/png') {
                require_once $CFG->libdir . '/gdlib.php';
                $tmproot = make_temp_directory('mod_label');
                $tmpfilepath = $tmproot . '/' . $file->get_contenthash();
                $file->copy_content_to($tmpfilepath);
                $data = generate_image_thumbnail($tmpfilepath, $width, $height);
                unlink($tmpfilepath);
                if (!empty($data)) {
                    $fs = get_file_storage();
                    $record = array('contextid' => $file->get_contextid(), 'component' => $file->get_component(), 'filearea' => $file->get_filearea(), 'itemid' => $file->get_itemid(), 'filepath' => '/', 'filename' => 's_' . $file->get_filename());
                    $smallfile = $fs->create_file_from_string($record, $data);
                    // Replace the image 'src' with the resized file and link to the original
                    $attrib['src'] = moodle_url::make_draftfile_url($smallfile->get_itemid(), $smallfile->get_filepath(), $smallfile->get_filename());
                    $link = $fullurl;
                }
            }
        }
    } else {
        // Assume this is an image type that get_imageinfo cannot handle (e.g. SVG)
        $attrib['width'] = $maxwidth;
    }
    $img = html_writer::empty_tag('img', $attrib);
    if ($link) {
        return html_writer::link($link, $img);
    } else {
        return $img;
    }
}
Ejemplo n.º 8
0
 /**
  * Generates a preview image for the stored file
  *
  * @param stored_file $file the file we want to preview
  * @param string $mode preview mode, eg. 'thumb'
  * @return stored_file|bool the newly created preview file or false
  */
 protected function create_file_preview(stored_file $file, $mode)
 {
     $mimetype = $file->get_mimetype();
     if ($mimetype === 'image/gif' or $mimetype === 'image/jpeg' or $mimetype === 'image/png') {
         // make a preview of the image
         $data = $this->create_imagefile_preview($file, $mode);
     } else {
         // unable to create the preview of this mimetype yet
         return false;
     }
     if (empty($data)) {
         return false;
     }
     // getimagesizefromstring() is available from PHP 5.4 but we need to support
     // lower versions, so...
     $tmproot = make_temp_directory('thumbnails');
     $tmpfilepath = $tmproot . '/' . $file->get_contenthash() . '_' . $mode;
     file_put_contents($tmpfilepath, $data);
     $imageinfo = getimagesize($tmpfilepath);
     unlink($tmpfilepath);
     $context = context_system::instance();
     $record = array('contextid' => $context->id, 'component' => 'core', 'filearea' => 'preview', 'itemid' => 0, 'filepath' => '/' . trim($mode, '/') . '/', 'filename' => $file->get_contenthash());
     if ($imageinfo) {
         $record['mimetype'] = $imageinfo['mime'];
     }
     return $this->create_file_from_string($record, $data);
 }
Ejemplo n.º 9
0
 /**
  * Create portfolio tag
  *
  * @param stored_file $file file information object
  * @param string $path file path
  * @param array $attributes portfolio attributes
  * @return string
  */
 public static function make_tag($file, $path, $attributes)
 {
     $srcattr = 'href';
     $tag = 'a';
     $content = $file->get_filename();
     if (in_array($file->get_mimetype(), portfolio_format_image::mimetypes())) {
         $srcattr = 'src';
         $tag = 'img';
         $content = '';
     }
     $attributes[$srcattr] = $path;
     // this will override anything we might have been passed (which is good)
     $dom = new DomDocument();
     $elem = null;
     if ($content) {
         $elem = $dom->createElement($tag, $content);
     } else {
         $elem = $dom->createElement($tag);
     }
     foreach ($attributes as $key => $value) {
         $elem->setAttribute($key, $value);
     }
     $dom->appendChild($elem);
     return $dom->saveXML($elem);
 }
Ejemplo n.º 10
0
/**
 * Handles the sending of file data to the user's browser, including support for
 * byteranges etc.
 *
 * @category files
 * @global stdClass $CFG
 * @global stdClass $COURSE
 * @global moodle_session $SESSION
 * @param stored_file $stored_file local file object
 * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours)
 * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only
 * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin
 * @param string $filename Override filename
 * @param bool $dontdie - return control to caller afterwards. this is not recommended and only used for cleanup tasks.
 *                        if this is passed as true, ignore_user_abort is called.  if you don't want your processing to continue on cancel,
 *                        you must detect this case when control is returned using connection_aborted. Please not that session is closed
 *                        and should not be reopened.
 * @return null script execution stopped unless $dontdie is true
 */
function send_stored_file($stored_file, $lifetime = 86400, $filter = 0, $forcedownload = false, $filename = null, $dontdie = false)
{
    global $CFG, $COURSE, $SESSION;
    if (!$stored_file or $stored_file->is_directory()) {
        // nothing to serve
        if ($dontdie) {
            return;
        }
        die;
    }
    if ($dontdie) {
        ignore_user_abort(true);
    }
    session_get_instance()->write_close();
    // unlock session during fileserving
    // Use given MIME type if specified, otherwise guess it using mimeinfo.
    // IE, Konqueror and Opera open html file directly in browser from web even when directed to save it to disk :-O
    // only Firefox saves all files locally before opening when content-disposition: attachment stated
    $filename = is_null($filename) ? $stored_file->get_filename() : $filename;
    $isFF = check_browser_version('Firefox', '1.5');
    // only FF > 1.5 properly tested
    $mimetype = ($forcedownload and !$isFF) ? 'application/x-forcedownload' : ($stored_file->get_mimetype() ? $stored_file->get_mimetype() : mimeinfo('type', $filename));
    $lastmodified = $stored_file->get_timemodified();
    $filesize = $stored_file->get_filesize();
    if ($lifetime > 0 && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
        // get unixtime of request header; clip extra junk off first
        $since = strtotime(preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]));
        if ($since && $since >= $lastmodified) {
            header('HTTP/1.1 304 Not Modified');
            header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $lifetime) . ' GMT');
            header('Cache-Control: max-age=' . $lifetime);
            header('Content-Type: ' . $mimetype);
            if ($dontdie) {
                return;
            }
            die;
        }
    }
    //do not put '@' before the next header to detect incorrect moodle configurations,
    //error should be better than "weird" empty lines for admins/users
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastmodified) . ' GMT');
    // if user is using IE, urlencode the filename so that multibyte file name will show up correctly on popup
    if (check_browser_version('MSIE')) {
        $filename = rawurlencode($filename);
    }
    if ($forcedownload) {
        header('Content-Disposition: attachment; filename="' . $filename . '"');
    } else {
        header('Content-Disposition: inline; filename="' . $filename . '"');
    }
    if ($lifetime > 0) {
        header('Cache-Control: max-age=' . $lifetime);
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $lifetime) . ' GMT');
        header('Pragma: ');
        if (empty($CFG->disablebyteserving) && $mimetype != 'text/plain' && $mimetype != 'text/html') {
            header('Accept-Ranges: bytes');
            if (!empty($_SERVER['HTTP_RANGE']) && strpos($_SERVER['HTTP_RANGE'], 'bytes=') !== FALSE) {
                // byteserving stuff - for acrobat reader and download accelerators
                // see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
                // inspired by: http://www.coneural.org/florian/papers/04_byteserving.php
                $ranges = false;
                if (preg_match_all('/(\\d*)-(\\d*)/', $_SERVER['HTTP_RANGE'], $ranges, PREG_SET_ORDER)) {
                    foreach ($ranges as $key => $value) {
                        if ($ranges[$key][1] == '') {
                            //suffix case
                            $ranges[$key][1] = $filesize - $ranges[$key][2];
                            $ranges[$key][2] = $filesize - 1;
                        } else {
                            if ($ranges[$key][2] == '' || $ranges[$key][2] > $filesize - 1) {
                                //fix range length
                                $ranges[$key][2] = $filesize - 1;
                            }
                        }
                        if ($ranges[$key][2] != '' && $ranges[$key][2] < $ranges[$key][1]) {
                            //invalid byte-range ==> ignore header
                            $ranges = false;
                            break;
                        }
                        //prepare multipart header
                        $ranges[$key][0] = "\r\n--" . BYTESERVING_BOUNDARY . "\r\nContent-Type: {$mimetype}\r\n";
                        $ranges[$key][0] .= "Content-Range: bytes {$ranges[$key][1]}-{$ranges[$key][2]}/{$filesize}\r\n\r\n";
                    }
                } else {
                    $ranges = false;
                }
                if ($ranges) {
                    byteserving_send_file($stored_file->get_content_file_handle(), $mimetype, $ranges, $filesize);
                }
            }
        } else {
            /// Do not byteserve (disabled, strings, text and html files).
            header('Accept-Ranges: none');
        }
    } else {
        // Do not cache files in proxies and browsers
        if (strpos($CFG->wwwroot, 'https://') === 0) {
            //https sites - watch out for IE! KB812935 and KB316431
            header('Cache-Control: max-age=10');
            header('Expires: ' . gmdate('D, d M Y H:i:s', 0) . ' GMT');
            header('Pragma: ');
        } else {
            //normal http - prevent caching at all cost
            header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
            header('Expires: ' . gmdate('D, d M Y H:i:s', 0) . ' GMT');
            header('Pragma: no-cache');
        }
        header('Accept-Ranges: none');
        // Do not allow byteserving when caching disabled
    }
    if (empty($filter)) {
        if ($mimetype == 'text/plain') {
            header('Content-Type: Text/plain; charset=utf-8');
            //add encoding
        } else {
            header('Content-Type: ' . $mimetype);
        }
        header('Content-Length: ' . $filesize);
        //flush the buffers - save memory and disable sid rewrite
        //this also disables zlib compression
        prepare_file_content_sending();
        // send the contents
        $stored_file->readfile();
    } else {
        // Try to put the file through filters
        if ($mimetype == 'text/html') {
            $options = new stdClass();
            $options->noclean = true;
            $options->nocache = true;
            // temporary workaround for MDL-5136
            $text = $stored_file->get_content();
            $text = file_modify_html_header($text);
            $output = format_text($text, FORMAT_HTML, $options, $COURSE->id);
            header('Content-Length: ' . strlen($output));
            header('Content-Type: text/html');
            //flush the buffers - save memory and disable sid rewrite
            //this also disables zlib compression
            prepare_file_content_sending();
            // send the contents
            echo $output;
        } else {
            if ($mimetype == 'text/plain' and $filter == 1) {
                // only filter text if filter all files is selected
                $options = new stdClass();
                $options->newlines = false;
                $options->noclean = true;
                $text = $stored_file->get_content();
                $output = '<pre>' . format_text($text, FORMAT_MOODLE, $options, $COURSE->id) . '</pre>';
                header('Content-Length: ' . strlen($output));
                header('Content-Type: text/html; charset=utf-8');
                //add encoding
                //flush the buffers - save memory and disable sid rewrite
                //this also disables zlib compression
                prepare_file_content_sending();
                // send the contents
                echo $output;
            } else {
                // Just send it out raw
                header('Content-Length: ' . $filesize);
                header('Content-Type: ' . $mimetype);
                //flush the buffers - save memory and disable sid rewrite
                //this also disables zlib compression
                prepare_file_content_sending();
                // send the contents
                $stored_file->readfile();
            }
        }
    }
    if ($dontdie) {
        return;
    }
    die;
    //no more chars to output!!!
}