Index: database/database.mysql =================================================================== RCS file: /cvs/drupal/drupal/database/database.mysql,v retrieving revision 1.195 diff -u -F^f -r1.195 database.mysql --- database/database.mysql 30 Aug 2005 15:19:20 -0000 1.195 +++ database/database.mysql 1 Sep 2005 19:44:59 -0000 @@ -250,6 +250,7 @@ filemime varchar(255) NOT NULL default '', filesize int(10) unsigned NOT NULL default '0', list tinyint(1) unsigned NOT NULL default '0', + inline tinyint(1) unsigned NOT NULL default '0', KEY vid (vid), KEY fid (fid) ) TYPE=MyISAM; Index: database/database.pgsql =================================================================== RCS file: /cvs/drupal/drupal/database/database.pgsql,v retrieving revision 1.134 diff -u -F^f -r1.134 database.pgsql --- database/database.pgsql 30 Aug 2005 15:19:20 -0000 1.134 +++ database/database.pgsql 1 Sep 2005 19:44:59 -0000 @@ -245,7 +245,8 @@ filepath varchar(255) NOT NULL default '', filemime varchar(255) NOT NULL default '', filesize integer NOT NULL default '0', - list smallint NOT NULL default '0' + list smallint NOT NULL default '0', + inline tinyint(1) unsigned NOT NULL default '0' ); CREATE INDEX files_fid_idx ON files(fid); CREATE INDEX files_vid_idx ON files(vid); Index: database/updates.inc =================================================================== RCS file: /cvs/drupal/drupal/database/updates.inc,v retrieving revision 1.129 diff -u -F^f -r1.129 updates.inc --- database/updates.inc 30 Aug 2005 15:19:20 -0000 1.129 +++ database/updates.inc 1 Sep 2005 19:44:59 -0000 @@ -44,7 +44,8 @@ "2005-07-30" => "update_143", "2005-08-08" => "update_144", "2005-08-15" => "update_145", - "2005-08-25" => "update_146" + "2005-08-25" => "update_146", + "2005-08-25" => "update_147" ); function update_110() { @@ -778,6 +779,13 @@ function update_146() { return $ret; } +function update_147() { + $ret = array(); + $ret[] = update_sql("ALTER TABLE {files} ADD inline tinyint(1) unsigned default 0 not NULL"); + return $ret; +} + + function update_sql($sql) { $edit = $_POST["edit"]; $result = db_query($sql); Index: misc/drupal.css =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.css,v retrieving revision 1.116 diff -u -F^f -r1.116 drupal.css --- misc/drupal.css 31 Aug 2005 21:17:26 -0000 1.116 +++ misc/drupal.css 1 Sep 2005 19:44:59 -0000 @@ -455,6 +455,9 @@ form { .user-login-block { text-align: center; } +img.upload { + float:left; +} .more-help-link { font-size: 0.85em; text-align: right; Index: modules/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload.module,v retrieving revision 1.50 diff -u -F^f -r1.50 upload.module --- modules/upload.module 31 Aug 2005 18:37:30 -0000 1.50 +++ modules/upload.module 1 Sep 2005 19:44:59 -0000 @@ -89,7 +89,8 @@ function upload_menu($may_cache) { function upload_admin() { system_settings_save(); - $group .= form_textfield(t('Maximum resolution for uploaded images'), 'upload_max_resolution', variable_get('upload_max_resolution', 0), 15, 10, t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.')); + $group .= form_textfield(t('Maximum total file size'), 'upload_maxsize_total', variable_get('upload_maxsize_total', 0), 10, 10, t('The maximum size of a file a user can upload in megabytes. Enter 0 for unlimited.')); + $group .= form_textfield(t('Maximum resolution for uploaded images'), 'upload_max_resolution', variable_get('upload_max_resolution', 0), 10, 10, t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.')); $output = form_group(t('General settings'), $group); @@ -143,83 +144,7 @@ function upload_nodeapi(&$node, $op, $ar break; case 'validate': - $node->files = upload_load($node); - - // Double check existing files: - if (is_array($node->list)) { - foreach ($node->list as $key => $value) { - if ($file = file_check_upload($key)) { - $node->files[$file->source] = $file; - $node->files[$key]->list = $node->list[$key]; - $node->files[$key]->remove = $node->remove[$key]; - if ($file->source) { - $filesize += $file->filesize; - } - } - } - } - else { - foreach ($node->files as $key => $file) { - $node->list[$key] = $file->list; - } - } - - if (($file = file_check_upload('upload')) && user_access('upload files')) { - global $user; - - $file = _upload_image($file); - - // Don't do any checks for uid #1. - if ($user->uid != 1) { - // Validate file against all users roles. Only denies an upload when - // all roles prevent it. - $total_usersize = upload_space_used($user->uid) + $filesize; - foreach ($user->roles as $rid => $name) { - $extensions = variable_get("upload_extensions_$rid", 'jpg jpeg gif png txt html doc xls pdf ppt pps'); - $uploadsize = variable_get("upload_uploadsize_$rid", 1) * 1024 * 1024; - $usersize = variable_get("upload_usersize_$rid", 1) * 1024 * 1024; - - $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i'; - - if (!preg_match($regex, $file->filename)) { - $error['extension']++; - } - - if ($uploadsize && $file->filesize > $uploadsize) { - $error['uploadsize']++; - } - - if ($usersize && $total_usersize + $file->filesize > $usersize) { - $error['usersize']++; - } - } - } - - // Rename possibly executable scripts to prevent accidental execution. - // Uploaded files are attachments and should be shown in their original - // form, rather than run. - if (preg_match('/\.(php|pl|py|cgi|asp)$/i', $file->filename)) { - $file->filename .= '.txt'; - $file->filemime = 'text/plain'; - } - - if ($error['extension'] == count($user->roles) && $user->uid != 1) { - form_set_error('upload', t('The selected file %name can not be attached to this post, because it is only possible to attach files with the following extensions: %files-allowed.', array('%name' => theme('placeholder', $file->filename), '%files-allowed' => theme('placeholder', $extensions)))); - } - elseif ($error['uploadsize'] == count($user->roles) && $user->uid != 1) { - form_set_error('upload', t('The selected file %name can not be attached to this post, because it exceeded the maximum filesize of %maxsize.', array('%name' => theme('placeholder', $file->filename), '%maxsize' => theme('placeholder', format_size($uploadsize))))); - } - elseif ($error['usersize'] == count($user->roles) && $user->uid != 1) { - form_set_error('upload', t('The selected file %name can not be attached to this post, because the disk quota of %quota has been reached.', array('%name' => theme('placeholder', $file->filename), '%quota' => theme('placeholder', format_size($usersize))))); - } - else { - $key = 'upload_'. count($_SESSION['file_uploads']); - $file->source = $key; - $file->list = 1; - $file = file_save_upload($file); - $node->files[$key] = $file; - } - } + $node = _upload_validate($node); break; case 'form post': @@ -236,43 +161,8 @@ function upload_nodeapi(&$node, $op, $ar case 'view': if ($node->files && user_access('view uploaded files')) { - $header = array(t('Attachment'), t('Size')); - $rows = array(); - $previews = array(); - - // Build list of attached files - foreach ($node->files as $file) { - if ($file->list) { - $rows[] = array( - ''. check_plain($file->filename) .'', - format_size($file->filesize) - ); - // We save the list of files still in preview for later - if (!$file->fid) { - $previews[] = $file; - } - } - } - - // URLs to files being previewed are actually Drupal paths. When Clean - // URLs are disabled, the two do not match. We perform an automatic - // replacement from temporary to permanent URLs. That way, the author - // can use the final URL in the body before having actually saved (to - // place inline images for example). - if (!variable_get('clean_url', 0)) { - foreach ($previews as $file) { - $old = file_create_filename($file->filename, file_create_path()); - $new = url($old); - $node->body = str_replace($old, $new, $node->body); - $node->teaser = str_replace($old, $new, $node->teaser); - } - } - - $teaser = $arg; - // Add the attachments list - if (count($rows) && !$teaser) { - $node->body .= theme('table', $header, $rows, array('id' => 'attachments')); - } + $node = _upload_table($node); + $node = _upload_inline($node); } break; @@ -342,8 +232,8 @@ function upload_save($node) { // Insert new files: if ($file = file_save_upload($file, $file->filename)) { $fid = db_next_id('{files}_fid'); - db_query("INSERT INTO {files} (fid, nid, vid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, %d)", - $fid, $node->nid, $node->vid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $node->list[$key]); + db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize, list, inline) VALUES (%d, %d, '%s', '%s', '%s', %d, %d, %d)", + $fid, $node->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $node->list[$key], $node->inline[$key]); } } } @@ -360,15 +250,15 @@ function upload_save($node) { } foreach ((array)$node->list as $key => $value) { if (!$node->remove[$key]) { - db_query('UPDATE {files} SET list = %d WHERE fid = %d AND vid = %d', $node->list[$key], $key, $node->vid); + db_query('UPDATE {files} SET list = %d, inline = %d WHERE fid = %d AND vid = %d', $node->list[$key], $node->inline[$key], $key, $node->vid); } } if ($node->old_vid) { foreach ((array)$node->remove as $key => $remove) { if (!$remove) { $file = db_fetch_object(db_query('SELECT * FROM {files} WHERE vid = %d AND fid = %d', $node->old_vid, $key)); - db_query("INSERT INTO {files} (fid, nid, vid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, %d)", - $key, $node->nid, $node->vid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $file->list); + db_query("INSERT INTO {files} (fid, nid, vid, filename, filepath, filemime, filesize, list, inline) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, %d, %d)", + $key, $node->nid, $node->vid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $file->list, $file->inline); } } } @@ -393,15 +283,17 @@ function upload_form($node) { } function _upload_form($node) { - $header = array(t('Delete'), t('List'), t('Url'), t('Size')); + $header = array(t('Delete'), t('List'), t('Inline'), t('Url'), t('Size')); $rows = array(); $output = ''; if (is_array($node->files)) { foreach ($node->files as $key => $file) { + $is_image = ereg('^(image/)', $file->filemime); $rows[] = array( form_checkbox('', "remove][$key", 1, $file->remove), form_checkbox('', "list][$key", 1, $file->list), + form_checkbox('', "inline][$key", 1, $file->inline, '', $is_image ? '' : array('disabled'=>'disabled')), $file->filename ."
". file_create_url(($file->fid ? $file->filepath : file_create_filename($file->filename, file_create_path()))) ."", format_size($file->filesize) ); @@ -459,6 +351,188 @@ function _upload_image($file) { } /** + * Render the table under the node. + */ +function _upload_table($node) { + $header = array(t('Attachment'), t('Size')); + $rows = array(); + $previews = array(); + + // Build list of attached files + foreach ($node->files as $file) { + if ($file->list) { + $rows[] = array( + ''. check_plain($file->filename) .'', + format_size($file->filesize) + ); + // We save the list of files still in preview for later + if (!$file->fid) { + $previews[] = $file; + } + } + } + + // URLs to files being previewed are actually Drupal paths. When Clean + // URLs are disabled, the two do not match. We perform an automatic + // replacement from temporary to permanent URLs. That way, the author + // can use the final URL in the body before having actually saved (to + // place inline images for example). + if (!variable_get('clean_url', 0)) { + foreach ($previews as $file) { + $old = file_create_filename($file->filename, file_create_path()); + $new = url($old); + $node->body = str_replace($old, $new, $node->body); + $node->teaser = str_replace($old, $new, $node->teaser); + } + } + + $teaser = $arg; + // Add the attachments list + if (count($rows) && !$teaser) { + $node->body .= theme('table', $header, $rows, array('id' => 'attachments')); + } + return $node; +} + +/** + * Render inline link, or image. + */ +function _upload_inline($node) { + $previews = array(); + // Build list of attached files + foreach ($node->files as $file) { + if ($file->inline) { + $output .= theme('upload_inline', $file); + // We save the list of files still in preview for later + if (!$file->fid) { + $previews[] = $file; + } + } + } + + $node->body = "$output \n $node->body"; + $node->teaser = "$output \n $node->teaser"; + + // URLs to files being previewed are actually Drupal paths. When Clean + // URLs are disabled, the two do not match. We perform an automatic + // replacement from temporary to permanent URLs. That way, the author + // can use the final URL in the body before having actually saved (to + // place inline images for example). + if (!variable_get('clean_url', 0)) { + foreach ($previews as $file) { + $old = file_create_filename($file->filename, file_create_path()); + $new = url($old); + $node->body = str_replace($old, $new, $node->body); + $node->teaser = str_replace($old, $new, $node->teaser); + } + } + + return $node; +} + +/** + * Helper function for validating the uploads + */ +function _upload_validate($node) { + $node->files = upload_load($node); + // Double check existing files: + if (is_array($node->list)) { + foreach ($node->list as $key => $value) { + if ($file = file_check_upload($key)) { + $node->files[$file->source] = $file; + $node->files[$key]->list = $node->list[$key]; + $node->files[$key]->inline = $node->inline[$key]; + $node->files[$key]->remove = $node->remove[$key]; + if ($file->source) { + $filesize += $file->filesize; + } + } + } + } + else { + foreach ($node->files as $key => $file) { + $node->list[$key] = $file->list; + $node->inline[$key] = $node->inline; + } + } + + if (($file = file_check_upload('upload')) && user_access('upload files')) { + global $user; + + $file = _upload_image($file); + + $maxsize = variable_get("upload_maxsize_total", 0) * 1024 * 1024; + $total_size = upload_count_size() + $filesize; + $total_usersize = upload_count_size($user->uid) + $filesize; + + if ($maxsize && $total_size > $maxsize) { + form_set_error('upload', t('The selected file %name can not be attached to this post, because it exceeded the maximum filesize of %max-size', array('%name' => theme('placeholder', $file->filename), '%max-size' => theme('placeholder', format_size($maxsize))))); + break; + } + + // Don't do any checks for uid #1. + if ($user->uid != 1) { + // Validate file against all users roles. Only denies an upload when + // all roles prevent it. + foreach ($user->roles as $rid => $name) { + $extensions = variable_get("upload_extensions_$rid", 'jpg jpeg gif png txt html doc xls pdf ppt pps'); + $uploadsize = variable_get("upload_uploadsize_$rid", 1) * 1024 * 1024; + $usersize = variable_get("upload_usersize_$rid", 1) * 1024 * 1024; + + $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i'; + + if (!preg_match($regex, $file->filename)) { + $error['extension']++; + } + + if ($file->filesize > $uploadsize) { + $error['uploadsize']++; + } + + if ($total_usersize + $file->filesize > $usersize) { + $error['usersize']++; + } + } + } + + // Rename possibly executable scripts to prevent accidental execution. + // Uploaded files are attachments and should be shown in their original + // form, rather than run. + if (preg_match('/\.(php|pl|py|cgi|asp)$/i', $file->filename)) { + $file->filename .= '.txt'; + $file->filemime = 'text/plain'; + } + + if ($error['extension'] == count($user->roles) && $user->uid != 1) { + form_set_error('upload', t('The selected file %name can not be attached to this post, because it is only possible to attach files with the following extensions: %files-allowed', array('%name' => theme('placeholder', $file->filename), '%files-allowed' => theme('placeholder', $extensions)))); + } + elseif ($error['uploadsize'] == count($user->roles) && $user->uid != 1) { + form_set_error('upload', t('The selected file %name can not be attached to this post, because it exceeded the maximum filesize of %maxsize', array('%name' => theme('placeholder', $file->filename), '%maxsize' => theme('placeholder', format_size($uploadsize))))); + } + elseif ($error['usersize'] == count($user->roles) && $user->uid != 1) { + form_set_error('upload', t('The selected file %name can not be attached to this post, because the disk quota of %quota has been reached', array('%name' => theme('placeholder', $file->filename), '%quota' => theme('placeholder', format_size($usersize))))); + } + else { + $key = 'upload_'. count($_SESSION['file_uploads']); + $file->source = $key; + $file->list = 1; + $file = file_save_upload($file); + $node->files[$key] = $file; + } + } + return $node; +} + +/** + * Theme function for rendering of inline images + * @param $file a file object. + * @param $image a Boolean, indicating whether an img tag (TRUE) or an anchor tag (FALSE) should be used. + * @ingroup themable + */ +function theme_upload_inline($file) { + return ''.  check_plain($file->filename) .''; +} +/** * Menu-callback for JavaScript-based uploads. */ function upload_js() {