Commit 9ef80dfd authored by Richard Mansfield's avatar Richard Mansfield

Believe the declared mime type of uploads instead of using the 'file' command

parent 9efe9ec8
......@@ -42,22 +42,18 @@
This table only keeps track of files that are specifically uploaded for a
blog post, not ones that have been uploaded already some other way, that
the user wants to associate with a blog post.
Hopefully this table is unnecessary; we just store all temporary
stuff in the javascript.
the user wants to associate with a blog post. -->
<TABLE NAME="artefact_blog_blogpost_file_pending">
<FIELDS>
<FIELD NAME="file" TYPE="int" LENGTH="10" NOTNULL="true" />
<FIELD NAME="when" TYPE="datetime" NOTNULL="true" />
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" />
<FIELD NAME="oldextension" TYPE="text" NOTNULL="false" />
<FIELD NAME="filetype" TYPE="text" NOTNULL="false" />
</FIELDS>
<KEYS>
<KEY NAME="blogpost_file_pending_pk" TYPE="primary" FIELDS="file" />
<KEY NAME="filefk" TYPE="foreign" FIELDS="file" REFTABLE="artefact" REFFIELDS="id" />
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
</KEYS>
</TABLE>
-->
</TABLES>
</XMLDB>
......@@ -114,6 +114,17 @@ function xmldb_artefact_blog_upgrade($oldversion=0) {
execute_sql('ALTER TABLE {artefact_blog_blogpost} ADD CONSTRAINT {arteblogblog_blo_fk} FOREIGN KEY (blogpost) REFERENCES {artefact}(id)');
}
}
if ($oldversion < 2008101600) {
$table = new XMLDBTable('artefact_blog_blogpost_file_pending');
$table->addFieldInfo('id', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
$table->addFieldInfo('oldextension', XMLDB_TYPE_TEXT, null);
$table->addFieldInfo('filetype', XMLDB_TYPE_TEXT, null);
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
create_table($table);
}
return $status;
}
......
......@@ -28,11 +28,10 @@ define('INTERNAL', 1);
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
require_once('file.php');
$uploadnumber = param_integer('uploadnumber');
$createid = param_variable('createid');
$uploadnumber = param_integer('tempfile');
safe_require('artefact', 'blog');
$path = ArtefactTypeBlogPost::get_temp_file_path($createid, $uploadnumber);
serve_file($path, '');
$path = ArtefactTypeBlogPost::get_temp_file_path($uploadnumber);
serve_file($path, '', get_field('artefact_blog_blogpost_file_pending', 'filetype', 'id', $uploadnumber));
?>
......@@ -600,35 +600,49 @@ class ArtefactTypeBlogPost extends ArtefactType {
static $blogattachmentroot = 'artefact/blog/uploads/';
public static function get_temp_file_path($createid, $uploadnumber) {
return get_config('dataroot') . self::$blogattachmentroot
. session_id() . $createid . '/' . $uploadnumber;
public static function get_temp_file_path($uploadnumber) {
return get_config('dataroot') . self::$blogattachmentroot . ($uploadnumber % 256) . '/' . $uploadnumber;
}
/**
* Returns the size of a temporary attachment
*/
public static function temp_attachment_size($createid, $uploadnumber) {
return filesize(self::get_temp_file_path($createid, $uploadnumber));
public static function temp_attachment_size($uploadnumber) {
return filesize(self::get_temp_file_path($uploadnumber));
}
/**
* This function saves an uploaded file to a temporary directory in dataroot
*
* and saves the mime type info in the db for downloadtemp.php to read from.
*/
public static function save_attachment_temporary($inputname, $dirname, $filename) {
public static function save_attachment_temporary($inputname) {
require_once('uploadmanager.php');
$um = new upload_manager($inputname);
db_begin();
$record = new StdClass;
$result = new StdClass;
$tempdir = self::$blogattachmentroot . $dirname;
$result->error = $um->process_file_upload($tempdir, $filename);
$result->oldextension = $um->original_filename_extension();
$result->filetype = $um->file['type'];
$tempfile = $tempdir . '/' . $filename;
$result->tempfilename = insert_record('artefact_blog_blogpost_file_pending', $record, 'id', true);
$tempdir = self::$blogattachmentroot . ($result->tempfilename % 256);
$result->error = $um->process_file_upload($tempdir, $result->tempfilename);
if ($result->error) {
delete_records('artefact_blog_blogpost_file_pending', 'id', $result->tempfilename);
}
else {
$record = (object) array(
'id' => $result->tempfilename,
'oldextension' => $um->original_filename_extension(),
'filetype' => $um->file['type'],
);
update_record('artefact_blog_blogpost_file_pending', $record);
}
db_commit();
safe_require('artefact', 'file');
$result->type = ArtefactTypeFile::detect_artefact_type($tempfile);
$result->type = ArtefactTypeFile::detect_artefact_type($um->file['type']);
return $result;
}
......@@ -636,7 +650,7 @@ class ArtefactTypeBlogPost extends ArtefactType {
/**
* Save a temporary uploaded file to the myfiles area.
*/
public function save_attachment($directory, $filename, $uploaddata) {
public function save_attachment($uploaddata) {
// Create the blogfiles folder if it doesn't exist yet.
$blogfilesid = self::blogfiles_folder_id();
......@@ -654,16 +668,19 @@ class ArtefactTypeBlogPost extends ArtefactType {
$data->tags = $uploaddata->tags;
$data->owner = $USER->get('id');
$data->parent = $blogfilesid;
$data->oldextension = $uploaddata->oldextension;
$data->filetype = $uploaddata->filetype;
$filedata = get_record('artefact_blog_blogpost_file_pending', 'id', $uploaddata->tempfilename);
$data->oldextension = $filedata->oldextension;
$data->filetype = $filedata->filetype;
$path = self::$blogattachmentroot . $directory . '/' . $filename;
$path = self::$blogattachmentroot . ($uploaddata->tempfilename % 256) . '/' . $uploaddata->tempfilename;
if (!$fileid = ArtefactTypeFile::save_file($path, $data)) {
return false;
}
$this->attach_file($fileid);
delete_records('artefact_blog_blogpost_file_pending', 'id', $uploaddata->tempfilename);
return $fileid;
}
......
......@@ -31,19 +31,6 @@ require_once('pieforms/pieform.php');
safe_require('artefact', 'blog');
/*
* Files uploaded to blog posts will be stored temporarily in the
* artefact/blog directory under the dataroot until the blog post is
* saved. This createid is used to ensure that all of these newly
* uploaded files get unique filenames.
*/
$createid = $SESSION->get('createid');
if (empty($createid)) {
$createid = 1;
}
$SESSION->set('createid', $createid + 1);
/*
* For a new post, the 'blog' parameter will be set to the blog's
* artefact id. For an existing post, the 'blogpost' parameter will
......@@ -175,8 +162,6 @@ var copyrightnotice = '{$copyright}';
// "Uploading file to blog post" in the upload status line.
var uploader = new FileUploader('uploader', 'upload.php', null, {$getstring['blogpost']}, false,
attachtopost, fileattached);
uploader.createid = {$createid};
// File browser instance allows users to attach files from the my files area
......@@ -257,11 +242,10 @@ var uploaddata = {};
// files list. This should be done here if names of attached files
// need to be unique.
function attachtopost(data) {
var rowid = data.uploadnumber ? 'uploaded:' + data.uploadnumber : 'artefact:' + data.id;
var rowid = data.tempfilename ? 'uploaded:' + data.tempfilename : 'artefact:' + data.id;
if (fileattached_id(rowid) || data.error) {
return;
}
var ext = data.oldextension ? data.oldextension : '';
var tags;
if (typeof(data.tags) == "string") {
tags = data.tags;
......@@ -320,7 +304,6 @@ function saveblogpost() {
}
var data = {'title' : $('editpost_title').value,
'draft' : $('draftpost_thisisdraft').checked,
'createid' : {$createid},
'blog' : {$blog},
'blogpost' : {$blogpost}};
// attachments
......@@ -470,8 +453,7 @@ function imageSrcFromId(imageid) {
return config.wwwroot + 'artefact/file/download.php?file=' + idparts[1];
}
if (idparts[0] == 'uploaded') {
return config.wwwroot + 'artefact/blog/downloadtemp.php?uploadnumber=' + idparts[1] +
'&createid=' + {$createid};
return config.wwwroot + 'artefact/blog/downloadtemp.php?tempfile=' + idparts[1];
}
return '';
}
......@@ -482,7 +464,7 @@ function imageIdFromSrc(src) {
if (ind != -1) {
return 'artefact:' + src.substring(ind+artefactstring.length, src.length);
}
var uploadstring = 'downloadtemp.php?uploadnumber=';
var uploadstring = 'downloadtemp.php?tempfile=';
ind = src.indexOf(uploadstring);
if (ind != -1) {
return 'uploaded:' + src.substring(ind+uploadstring.length, src.length).split('&')[0];
......
......@@ -34,7 +34,6 @@ json_headers();
$title = param_variable('title');
$draft = param_boolean('draft');
$createid = param_integer('createid');
$blog = param_integer('blog');
$blogpost = param_integer('blogpost');
$uploads = json_decode(param_variable('uploads'));
......@@ -56,7 +55,7 @@ safe_require('artefact', 'blog');
if (!empty($uploads)) {
$uploadsize = 0;
foreach ($uploads as $upload) {
$uploadsize += ArtefactTypeBlogPost::temp_attachment_size($createid, $upload->id);
$uploadsize += ArtefactTypeBlogPost::temp_attachment_size($upload->data->tempfilename);
}
if (!$USER->quota_allowed($uploadsize)) {
json_reply('local', get_string('newattachmentsexceedquota', 'artefact.blog'));
......@@ -115,7 +114,7 @@ $uploadartefact = array();
if (!empty($uploads)) {
foreach ($uploads as $upload) {
if (!$fileid = $postobj->save_attachment(session_id() . $createid, $upload->id, $upload->data)) {
if (!$fileid = $postobj->save_attachment($upload->data)) {
json_reply('local', get_string('errorsavingattachments', 'artefact.blog'));
// Things could be in a bad state.
}
......@@ -130,7 +129,7 @@ if (!empty($uploads)) {
if (!empty($uploadartefact)) {
$originalbody = $body;
foreach ($uploadartefact as $k => $v) {
$regexps = array('/<img([^>]+)src="([^>]+)downloadtemp.php\?uploadnumber=' . $k .'&amp;createid=\d+/',
$regexps = array('/<img([^>]+)src="([^>]+)downloadtemp.php\?tempfile=' . $k .'/',
'/alt="uploaded:' . $k . '"/');
$subs = array('<img$1src="' . get_config('wwwroot') . 'artefact/file/download.php?file=' . $v,
'alt="artefact:' . $v . '"');
......
......@@ -36,19 +36,16 @@ $result->title = param_variable('title');
$result->description = param_variable('description', null);
$result->tags = param_variable('tags', null);
$result->uploadnumber = param_integer('uploadnumber'); // id of target iframe
$createid = param_variable('createid');
// Ignore possible file name clashes; they should be dealt with in the
// javascript on the edit blog post page.
safe_require('artefact', 'blog');
$attach = ArtefactTypeBlogPost::save_attachment_temporary('userfile', session_id() . $createid,
$result->uploadnumber);
$attach = ArtefactTypeBlogPost::save_attachment_temporary('userfile');
if (!$attach->error) {
$result->error = false;
$result->artefacttype = $attach->type;
$result->oldextension = $attach->oldextension;
$result->filetype = $attach->filetype;
$result->tempfilename = $attach->tempfilename;
$result->message = get_string('uploadoffilecomplete', 'artefact.file', $result->title);
}
else {
......
......@@ -27,7 +27,7 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2008020700;
$config->version = 2008101600;
$config->release = '0.1.1';
?>
......@@ -266,7 +266,7 @@ class PluginBlocktypeInternalmedia extends PluginBlocktype {
$url = self::get_download_link($artefact, $block);
require_once('file.php');
$mimetype = get_mime_type($artefact->get_path());
$mimetype = $artefact->get('filetype');
$autostart = 'false';
return '<a href="' . $url . '">' . hsc($artefact->get('title')) . '</a><br>'
......@@ -339,7 +339,7 @@ class PluginBlocktypeInternalmedia extends PluginBlocktype {
$size = 'width="' . $width . '" height="' . $height . '"';
require_once('file.php');
$mimetype = get_mime_type($artefact->get_path());
$mimetype = $artefact->get('filetype');
$autostart = 'false';
return '<a href="' . $url . '">' . hsc($artefact->get('title')) . '</a><br>'
......
......@@ -95,6 +95,6 @@ if ($contenttype = $file->override_content_type()) {
$options['overridecontenttype'] = $contenttype;
}
$options['owner'] = $file->get('owner');
serve_file($path, $title, $options);
serve_file($path, $title, $file->get('filetype'), $options);
?>
......@@ -719,11 +719,6 @@ function FileUploader(element, uploadscript, statevars, foldername, folderid, up
appendChildNodes(self.form,
INPUT({'type':'hidden', 'name':'parentfolder', 'value':self.folderid}));
if (self.createid) {
appendChildNodes(self.form,
INPUT({'type':'hidden', 'name':'createid', 'value':self.createid}));
}
if (group) {
appendChildNodes(self.form, INPUT({
'type':'hidden',
......
......@@ -694,9 +694,9 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
return get_config('dataroot') . self::get_file_directory($this->fileid) . '/' . $this->fileid;
}
public static function detect_artefact_type($file) {
public static function detect_artefact_type($mimetype) {
require_once('file.php');
if (ArtefactTypeImage::is_image_mime_type(get_mime_type(get_config('dataroot') . $file))) {
if (is_image_mime_type($mimetype)) {
return 'image';
}
return 'file';
......@@ -706,9 +706,7 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
* Test file type and return a new Image or File.
*/
public static function new_file($path, $data) {
require_once('file.php');
$type = get_mime_type($path);
if (ArtefactTypeImage::is_image_mime_type($type)) {
if ($data->filetype && self::detect_artefact_type($data->filetype) == 'image') {
list($data->width, $data->height) = getimagesize($path);
return new ArtefactTypeImage(0, $data);
}
......@@ -775,10 +773,10 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
if (!$USER->quota_allowed($size) && !$data->institution) {
return get_string('uploadexceedsquota', 'artefact.file');
}
$data->size = $size;
$data->filetype = $um->file['type'];
$data->oldextension = $um->original_filename_extension();
$f = self::new_file($um->file['tmp_name'], $data);
$f->set('size', $size);
$f->set('oldextension', $um->original_filename_extension());
$f->set('filetype', $um->file['type']);
$f->commit();
$id = $f->get('id');
// Save the file using its id as the filename, and use its id modulo
......
......@@ -207,15 +207,18 @@ function upload_submit(Pieform $form, $values) {
}
// Entry in artefact table
$artefact = new ArtefactTypeProfileIcon();
$artefact->set('owner', $USER->id);
$artefact->set('title', ($values['title']) ? $values['title'] : $values['file']['name']);
$artefact->set('note', $values['file']['name']);
$artefact->set('filetype', $values['file']['type']);
$data = (object) array(
'owner' => $USER->id,
'title' => $values['title'] ? $values['title'] : $values['file']['name'],
'note' => $values['file']['name'],
'filetype' => $values['file']['type'],
'size' => $filesize,
);
list($data->width, $data->height) = getimagesize($values['file']['tmp_name']);
$artefact = new ArtefactTypeProfileIcon(0, $data);
if (preg_match("/\.([^\.]+)$/", $values['file']['name'], $saved)) {
$artefact->set('oldextension', $saved[1]);
}
$artefact->set('size', $filesize);
$artefact->commit();
$id = $artefact->get('id');
......
......@@ -300,12 +300,14 @@ class AuthXmlrpc extends Auth {
}
require_once('file.php');
$mime = get_mime_type($filename);
$imagesize = getimagesize($filename);
$mime = $imagesize['mime'];
if (!is_image_mime_type($mime)) {
$error = get_string('filenotimage');
}
list($width, $height) = getimagesize($filename);
$width = $imagesize[0];
$height = $imagesize[1];
$imagemaxwidth = get_config('imagemaxwidth');
$imagemaxheight = get_config('imagemaxheight');
if ($width > $imagemaxwidth || $height > $imagemaxheight) {
......@@ -327,6 +329,10 @@ class AuthXmlrpc extends Auth {
$artefact->set('owner', $user->id);
$artefact->set('title', 'Profile Icon');
$artefact->set('note', 'Profile Icon');
$artefact->set('size', $filesize);
$artefact->set('filetype', $mime);
$artefact->set('width', $width);
$artefact->set('height', $height);
$artefact->commit();
$id = $artefact->get('id');
......
......@@ -43,13 +43,14 @@ define('BYTESERVING_BOUNDARY', 'm1i2k3e40516'); //unique string constant
* @param string $path The file to send. Must include the dataroot path.
* @param string $filename The name of the file as the browser should use to
* serve it.
* @param string $mimetype Mime type to be sent in header
* @param array $options Any options to use when serving the file. Currently
* lifetime = 0 for no cache
* forcedownload - force application rather than inline
* overridecontenttype - send this instead of the mimetype
* there are none.
*/
function serve_file($path, $filename, $options=array()) {
function serve_file($path, $filename, $mimetype, $options=array()) {
$dataroot = get_config('dataroot');
$path = realpath($path);
$options = array_merge(array(
......@@ -66,7 +67,6 @@ function serve_file($path, $filename, $options=array()) {
session_write_close(); // unlock session during fileserving
$mimetype = get_mime_type($path);
$lastmodified = filemtime($path);
$filesize = filesize($path);
......@@ -278,6 +278,14 @@ function byteserving_send_file($filename, $mimetype, $ranges) {
* Sometimes file will be unable to detect the mimetype, in which case
* it will return the empty string.
*
*
* This function should no longer be required. Mime types are now
* stored along with files in the artefact tables, and passed directly
* to serve_file. Left in place for the upgrade to initially populate
* the mime type of existing files.
* See htdocs/artefact/file/db/upgrade.php.
*
*
* @param string $file The file to check
* @return string The mime type of the file, or false if file is not available.
*/
......@@ -397,7 +405,8 @@ function get_dataroot_image_path($path, $id, $size=null) {
// it, we can make one however.
if (is_readable($originalimage)) {
$originalmimetype = get_mime_type($originalimage);
$imageinfo = getimagesize($originalimage);
$originalmimetype = $imageinfo['mime'];
switch ($originalmimetype) {
case 'image/jpeg':
case 'image/jpg':
......
......@@ -83,13 +83,8 @@ class upload_manager {
return get_string('notphpuploadedfile');
}
// Check the file type is allowed. If the type cannot be detected,
// then the file is ALLOWED through (the type can often not be detected
// for MS word documents). Maybe later that can be configurable. If
// the path to the file program is empty in the configuration, the file
// will not be checked.
require_once('file.php');
$type = get_mime_type($file['tmp_name']);
// Check the file type is allowed.
$type = $file['type'];
if ($type) {
if ($type != 'application/x-empty' && substr($type, 0, 5) != 'text/') {
$validtypes = get_column_sql('SELECT mimetype
......
......@@ -39,12 +39,21 @@ switch ($type) {
if ($type == 'profileicon') {
// Convert ID of user to the ID of a profileicon
$id = get_field('usr', 'profileicon', 'id', $id);
$data = get_record_sql('
SELECT u.profileicon, f.filetype
FROM {usr} u INNER JOIN {artefact_file_files} f ON u.profileicon = f.artefact
WHERE u.id = ?', array($id));
if ($data) {
$id = $data->profileicon;
$mimetype = $data->filetype;
}
}
else {
$mimetype = get_field('artefact_file_files', 'filetype', 'artefact', $id);
}
if ($id) {
if ($path = get_dataroot_image_path('artefact/file/profileicons', $id, $size)) {
$mimetype = get_mime_type($path);
if ($mimetype) {
header('Content-type: ' . $mimetype);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment