[ Index ] |
|
Code source de Drupal 5.3 |
1 <?php 2 // $Id: upload.module,v 1.148.2.2 2007/10/17 21:29:00 drumm Exp $ 3 4 /** 5 * @file 6 * File-handling and attaching files to nodes. 7 * 8 */ 9 10 /** 11 * Implementation of hook_help(). 12 */ 13 function upload_help($section) { 14 switch ($section) { 15 case 'admin/help#upload': 16 $output = '<p>'. t('The upload module allows users to upload files to the site. The ability to upload files to a site is important for members of a community who want to share work. It is also useful to administrators who want to keep uploaded files connected to a node or page.') .'</p>'; 17 $output .= '<p>'. t('Users with the upload files permission can upload attachments. You can choose which post types can take attachments on the content types settings page. Each user role can be customized for the file size of uploads, and the dimension of image files.') .'</p>'; 18 $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@upload">Upload page</a>.', array('@upload' => 'http://drupal.org/handbook/modules/upload/')) .'</p>'; 19 return $output; 20 case 'admin/settings/upload': 21 return '<p>'. t('Users with the <a href="@permissions">upload files permission</a> can upload attachments. Users with the <a href="@permissions">view uploaded files permission</a> can view uploaded attachments. You can choose which post types can take attachments on the <a href="@types">content types settings</a> page.', array('@permissions' => url('admin/user/access'), '@types' => url('admin/settings/types'))) .'</p>'; 22 } 23 } 24 25 /** 26 * Implementation of hook_perm(). 27 */ 28 function upload_perm() { 29 return array('upload files', 'view uploaded files'); 30 } 31 32 /** 33 * Implementation of hook_link(). 34 */ 35 function upload_link($type, $node = NULL, $teaser = FALSE) { 36 $links = array(); 37 38 // Display a link with the number of attachments 39 if ($teaser && $type == 'node' && isset($node->files) && user_access('view uploaded files')) { 40 $num_files = 0; 41 foreach ($node->files as $file) { 42 if ($file->list) { 43 $num_files++; 44 } 45 } 46 if ($num_files) { 47 $links['upload_attachments'] = array( 48 'title' => format_plural($num_files, '1 attachment', '@count attachments'), 49 'href' => "node/$node->nid", 50 'attributes' => array('title' => t('Read full article to view attachments.')), 51 'fragment' => 'attachments' 52 ); 53 } 54 } 55 56 return $links; 57 } 58 59 /** 60 * Implementation of hook_menu(). 61 */ 62 function upload_menu($may_cache) { 63 $items = array(); 64 65 if ($may_cache) { 66 $items[] = array( 67 'path' => 'upload/js', 68 'callback' => 'upload_js', 69 'access' => user_access('upload files'), 70 'type' => MENU_CALLBACK 71 ); 72 $items[] = array('path' => 'admin/settings/uploads', 73 'title' => t('File uploads'), 74 'description' => t('Control how files may be attached to content.'), 75 'callback' => 'drupal_get_form', 76 'callback arguments' => array('upload_admin_settings'), 77 'access' => user_access('administer site configuration'), 78 'type' => MENU_NORMAL_ITEM); 79 } 80 else { 81 // Add handlers for previewing new uploads. 82 if (isset($_SESSION['file_previews'])) { 83 foreach ($_SESSION['file_previews'] as $fid => $file) { 84 $filename = file_create_filename($file->filename, file_create_path()); 85 if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) { 86 // strip file_directory_path() from filename. @see file_create_url 87 if (strpos($filename, file_directory_path()) !== FALSE) { 88 $filename = trim(substr($filename, strlen(file_directory_path())), '\\/'); 89 } 90 $filename = 'system/files/' . $filename; 91 } 92 93 $items[] = array( 94 'path' => $filename, 'title' => t('File download'), 95 'callback' => 'upload_download', 96 'access' => user_access('view uploaded files'), 97 'type' => MENU_CALLBACK 98 ); 99 $_SESSION['file_previews'][$fid]->_filename = $filename; 100 } 101 } 102 } 103 104 return $items; 105 } 106 107 /** 108 * Form API callback to validate the upload settings form. 109 */ 110 function upload_admin_settings_validate($form_id, $form_values) { 111 if (($form_values['upload_max_resolution'] != '0')) { 112 if (!preg_match('/^[0-9]+x[0-9]+$/', $form_values['upload_max_resolution'])) { 113 form_set_error('upload_max_resolution', t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.')); 114 } 115 } 116 117 $default_uploadsize = $form_values['upload_uploadsize_default']; 118 $default_usersize = $form_values['upload_usersize_default']; 119 120 $exceed_max_msg = t('Your PHP settings limit the maximum file size per upload to %size MB.', array('%size' => file_upload_max_size())).'<br/>'; 121 $more_info = t("Depending on your sever environment, these settings may be changed in the system-wide php.ini file, a php.ini file in your Drupal root directory, in your Drupal site's settings.php file, or in the .htaccess file in your Drupal root directory."); 122 123 if (!is_numeric($default_uploadsize) || ($default_uploadsize <= 0)) { 124 form_set_error('upload_uploadsize_default', t('The %role file size limit must be a number and greater than zero.', array('%role' => t('default')))); 125 } 126 if (!is_numeric($default_usersize) || ($default_usersize <= 0)) { 127 form_set_error('upload_usersize_default', t('The %role file size limit must be a number and greater than zero.', array('%role' => t('default')))); 128 } 129 if ($default_uploadsize > file_upload_max_size()) { 130 form_set_error('upload_uploadsize_default', $exceed_max_msg . $more_info); 131 $more_info = ''; 132 } 133 if ($default_uploadsize > $default_usersize) { 134 form_set_error('upload_uploadsize_default', t('The %role maximum file size per upload is greater than the total file size allowed per user', array('%role' => t('default')))); 135 } 136 137 foreach ($form_values['roles'] as $rid => $role) { 138 $uploadsize = $form_values['upload_uploadsize_'. $rid]; 139 $usersize = $form_values['upload_usersize_'. $rid]; 140 141 if (!is_numeric($uploadsize) || ($uploadsize <= 0)) { 142 form_set_error('upload_uploadsize_'. $rid, t('The %role file size limit must be a number and greater than zero.', array('%role' => $role))); 143 } 144 if (!is_numeric($usersize) || ($usersize <= 0)) { 145 form_set_error('upload_usersize_'. $rid, t('The %role file size limit must be a number and greater than zero.', array('%role' => $role))); 146 } 147 if ($uploadsize > file_upload_max_size()) { 148 form_set_error('upload_uploadsize_'. $rid, $exceed_max_msg . $more_info); 149 $more_info = ''; 150 } 151 if ($uploadsize > $usersize) { 152 form_set_error('upload_uploadsize_'. $rid, t('The %role maximum file size per upload is greater than the total file size allowed per user', array('%role' => $role))); 153 } 154 } 155 } 156 157 /** 158 * Menu callback for the upload settings form. 159 */ 160 function upload_admin_settings() { 161 $upload_extensions_default = variable_get('upload_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'); 162 $upload_uploadsize_default = variable_get('upload_uploadsize_default', 1); 163 $upload_usersize_default = variable_get('upload_usersize_default', 1); 164 165 $form['settings_general'] = array( 166 '#type' => 'fieldset', 167 '#title' => t('General settings'), 168 '#collapsible' => TRUE, 169 ); 170 $form['settings_general']['upload_max_resolution'] = array( 171 '#type' => 'textfield', 172 '#title' => t('Maximum resolution for uploaded images'), 173 '#default_value' => variable_get('upload_max_resolution', 0), 174 '#size' => 15, 175 '#maxlength' => 10, 176 '#description' => t('The maximum allowed image size (e.g. 640x480). Set to 0 for no restriction.'), 177 '#field_suffix' => '<kbd>'. t('WIDTHxHEIGHT') .'</kbd>' 178 ); 179 $form['settings_general']['upload_list_default'] = array( 180 '#type' => 'select', 181 '#title' => t('List files by default'), 182 '#default_value' => variable_get('upload_list_default', 1), 183 '#options' => array(0 => t('No'), 1 => t('Yes')), 184 '#description' => t('Set whether files attached to nodes are listed or not in the node view by default.'), 185 ); 186 187 $form['settings_general']['upload_extensions_default'] = array( 188 '#type' => 'textfield', 189 '#title' => t('Default permitted file extensions'), 190 '#default_value' => $upload_extensions_default, 191 '#maxlength' => 255, 192 '#description' => t('Default extensions that users can upload. Separate extensions with a space and do not include the leading dot.'), 193 ); 194 $form['settings_general']['upload_uploadsize_default'] = array( 195 '#type' => 'textfield', 196 '#title' => t('Default maximum file size per upload'), 197 '#default_value' => $upload_uploadsize_default, 198 '#size' => 5, 199 '#maxlength' => 5, 200 '#description' => t('The default maximum file size a user can upload.'), 201 '#field_suffix' => t('MB') 202 ); 203 $form['settings_general']['upload_usersize_default'] = array( 204 '#type' => 'textfield', 205 '#title' => t('Default total file size per user'), 206 '#default_value' => $upload_usersize_default, 207 '#size' => 5, 208 '#maxlength' => 5, 209 '#description' => t('The default maximum size of all files a user can have on the site.'), 210 '#field_suffix' => t('MB') 211 ); 212 213 $form['settings_general']['upload_max_size'] = array('#value' => '<p>'. t('Your PHP settings limit the maximum file size per upload to %size.', array('%size' => format_size(file_upload_max_size()))).'</p>'); 214 215 $roles = user_roles(0, 'upload files'); 216 $form['roles'] = array('#type' => 'value', '#value' => $roles); 217 218 foreach ($roles as $rid => $role) { 219 $form['settings_role_'. $rid] = array( 220 '#type' => 'fieldset', 221 '#title' => t('Settings for @role', array('@role' => $role)), 222 '#collapsible' => TRUE, 223 '#collapsed' => TRUE, 224 ); 225 $form['settings_role_'. $rid]['upload_extensions_'. $rid] = array( 226 '#type' => 'textfield', 227 '#title' => t('Permitted file extensions'), 228 '#default_value' => variable_get('upload_extensions_'. $rid, $upload_extensions_default), 229 '#maxlength' => 255, 230 '#description' => t('Extensions that users in this role can upload. Separate extensions with a space and do not include the leading dot.'), 231 ); 232 $form['settings_role_'. $rid]['upload_uploadsize_'. $rid] = array( 233 '#type' => 'textfield', 234 '#title' => t('Maximum file size per upload'), 235 '#default_value' => variable_get('upload_uploadsize_'. $rid, $upload_uploadsize_default), 236 '#size' => 5, 237 '#maxlength' => 5, 238 '#description' => t('The maximum size of a file a user can upload (in megabytes).'), 239 ); 240 $form['settings_role_'. $rid]['upload_usersize_'. $rid] = array( 241 '#type' => 'textfield', 242 '#title' => t('Total file size per user'), 243 '#default_value' => variable_get('upload_usersize_'. $rid, $upload_usersize_default), 244 '#size' => 5, 245 '#maxlength' => 5, 246 '#description' => t('The maximum size of all files a user can have on the site (in megabytes).'), 247 ); 248 } 249 250 return system_settings_form($form); 251 } 252 253 function upload_download() { 254 foreach ($_SESSION['file_previews'] as $file) { 255 if ($file->_filename == $_GET['q']) { 256 file_transfer($file->filepath, array('Content-Type: '. mime_header_encode($file->filemime), 'Content-Length: '. $file->filesize)); 257 } 258 } 259 } 260 261 function upload_file_download($file) { 262 $file = file_create_path($file); 263 $result = db_query("SELECT f.* FROM {files} f WHERE filepath = '%s'", $file); 264 if ($file = db_fetch_object($result)) { 265 if (user_access('view uploaded files')) { 266 $node = node_load($file->nid); 267 if (node_access('view', $node)) { 268 $type = mime_header_encode($file->filemime); 269 return array( 270 'Content-Type: '. $type, 271 'Content-Length: '. $file->filesize, 272 ); 273 } 274 else { 275 return -1; 276 } 277 } 278 else { 279 return -1; 280 } 281 } 282 } 283 284 /** 285 * Save new uploads and attach them to the node object. 286 * append file_previews to the node object as well. 287 */ 288 function _upload_prepare(&$node) { 289 290 // Clean up old file previews if a post didn't get the user to this page. 291 // i.e. the user left the edit page, because they didn't want to upload anything. 292 if(count($_POST) == 0) { 293 if (is_array($_SESSION['file_previews']) && count($_SESSION['file_previews'])) { 294 foreach ($_SESSION['file_previews'] as $fid => $file) { 295 file_delete($file->filepath); 296 } 297 unset($_SESSION['file_previews']); 298 } 299 } 300 301 // $_SESSION['file_current_upload'] tracks the fid of the file submitted this page request. 302 // form_builder sets the value of file->list to 0 for checkboxes added to a form after 303 // it has been submitted. Since unchecked checkboxes have no return value and do not 304 // get a key in _POST form_builder has no way of knowing the difference between a check 305 // box that wasn't present on the last form build, and a checkbox that is unchecked. 306 307 unset($_SESSION['file_current_upload']); 308 309 global $user; 310 311 // Save new file uploads to tmp dir. 312 if (($file = file_check_upload()) && user_access('upload files')) { 313 314 // Scale image uploads. 315 $file = _upload_image($file); 316 317 $key = 'upload_'. count($_SESSION['file_previews']); 318 $file->fid = $key; 319 $file->source = $key; 320 $file->list = variable_get('upload_list_default',1); 321 $_SESSION['file_previews'][$key] = $file; 322 323 // Store the uploaded fid for this page request in case of submit without 324 // preview or attach. See earlier notes. 325 $_SESSION['file_current_upload'] = $key; 326 } 327 328 // Attach file previews to node object. 329 if (is_array($_SESSION['file_previews']) && count($_SESSION['file_previews'])) { 330 foreach ($_SESSION['file_previews'] as $fid => $file) { 331 if ($user->uid != 1) { 332 // Here something.php.pps becomes something.php_.pps 333 $file->filename = upload_munge_filename($file->filename, NULL, 0); 334 $file->description = $file->filename; 335 } 336 $node->files[$fid] = $file; 337 } 338 } 339 } 340 341 function upload_form_alter($form_id, &$form) { 342 if ($form_id == 'node_type_form' && isset($form['identity']['type'])) { 343 $form['workflow']['upload'] = array( 344 '#type' => 'radios', 345 '#title' => t('Attachments'), 346 '#default_value' => variable_get('upload_'. $form['#node_type']->type, 1), 347 '#options' => array(t('Disabled'), t('Enabled')), 348 ); 349 } 350 351 if (isset($form['type'])) { 352 $node = $form['#node']; 353 if ($form['type']['#value'] .'_node_form' == $form_id && variable_get("upload_$node->type", TRUE)) { 354 drupal_add_js('misc/progress.js'); 355 drupal_add_js('misc/upload.js'); 356 357 // Attachments fieldset 358 $form['attachments'] = array( 359 '#type' => 'fieldset', 360 '#access' => user_access('upload files'), 361 '#title' => t('File attachments'), 362 '#collapsible' => TRUE, 363 '#collapsed' => empty($node->files), 364 '#description' => t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.'), 365 '#prefix' => '<div class="attachments">', 366 '#suffix' => '</div>', 367 '#weight' => 30, 368 ); 369 370 // Wrapper for fieldset contents (used by upload JS). 371 $form['attachments']['wrapper'] = array( 372 '#prefix' => '<div id="attach-wrapper">', 373 '#suffix' => '</div>', 374 ); 375 376 // Make sure necessary directories for upload.module exist and are 377 // writable before displaying the attachment form. 378 $path = file_directory_path(); 379 $temp = file_directory_temp(); 380 // Note: pass by reference 381 if (!file_check_directory($path, FILE_CREATE_DIRECTORY) || !file_check_directory($temp, FILE_CREATE_DIRECTORY)) { 382 $form['attachments']['#description'] = t('File attachments are disabled. The file directories have not been properly configured.'); 383 if (user_access('administer site configuration')) { 384 $form['attachments']['#description'] .= ' '. t('Please visit the <a href="@admin-file-system">file system configuration page</a>.', array('@admin-file-system' => url('admin/settings/file-system'))); 385 } 386 else { 387 $form['attachments']['#description'] .= ' '. t('Please contact the site administrator.'); 388 } 389 } 390 else { 391 $form['attachments']['wrapper'] += _upload_form($node); 392 $form['#attributes']['enctype'] = 'multipart/form-data'; 393 } 394 } 395 } 396 } 397 398 function _upload_validate(&$node) { 399 // Accumulator for disk space quotas. 400 $filesize = 0; 401 402 // Check if node->files exists, and if it contains something. 403 if (is_array($node->files)) { 404 // Update existing files with form data. 405 foreach ($node->files as $fid => $file) { 406 // Convert file to object for compatibility 407 $file = (object)$file; 408 409 // Validate new uploads. 410 if (strpos($fid, 'upload') !== FALSE && !$file->remove) { 411 global $user; 412 413 // Bypass validation for uid = 1. 414 if ($user->uid != 1) { 415 // Update filesize accumulator. 416 $filesize += $file->filesize; 417 418 // Validate file against all users roles. 419 // Only denies an upload when all roles prevent it. 420 421 $total_usersize = upload_space_used($user->uid) + $filesize; 422 $error = array(); 423 foreach ($user->roles as $rid => $name) { 424 $extensions = variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp')); 425 $uploadsize = variable_get("upload_uploadsize_$rid", variable_get('upload_uploadsize_default', 1)) * 1024 * 1024; 426 $usersize = variable_get("upload_usersize_$rid", variable_get('upload_usersize_default', 1)) * 1024 * 1024; 427 428 $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i'; 429 430 if (!preg_match($regex, $file->filename)) { 431 $error['extension']++; 432 } 433 434 if ($uploadsize && $file->filesize > $uploadsize) { 435 $error['uploadsize']++; 436 } 437 438 if ($usersize && $total_usersize + $file->filesize > $usersize) { 439 $error['usersize']++; 440 } 441 } 442 443 $user_roles = count($user->roles); 444 $valid = TRUE; 445 if ($error['extension'] == $user_roles) { 446 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' => $file->filename, '%files-allowed' => $extensions))); 447 $valid = FALSE; 448 } 449 elseif ($error['uploadsize'] == $user_roles) { 450 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' => $file->filename, '%maxsize' => format_size($uploadsize)))); 451 $valid = FALSE; 452 } 453 elseif ($error['usersize'] == $user_roles) { 454 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' => $file->filename, '%quota' => format_size($usersize)))); 455 $valid = FALSE; 456 } 457 elseif (strlen($file->filename) > 255) { 458 form_set_error('upload', t('The selected file %name can not be attached to this post, because the filename is too long.', array('%name' => $file->filename))); 459 $valid = FALSE; 460 } 461 462 if (!$valid) { 463 unset($node->files[$fid], $_SESSION['file_previews'][$fid]); 464 file_delete($file->filepath); 465 } 466 } 467 } 468 } 469 } 470 } 471 472 /** 473 * Implementation of hook_nodeapi(). 474 */ 475 function upload_nodeapi(&$node, $op, $teaser) { 476 switch ($op) { 477 478 case 'load': 479 $output = ''; 480 if (variable_get("upload_$node->type", 1) == 1) { 481 $output['files'] = upload_load($node); 482 return $output; 483 } 484 break; 485 486 case 'prepare': 487 _upload_prepare($node); 488 break; 489 490 case 'validate': 491 _upload_validate($node); 492 break; 493 494 case 'view': 495 if (isset($node->files) && user_access('view uploaded files')) { 496 // Add the attachments list to node body with a heavy 497 // weight to ensure they're below other elements 498 if (count($node->files)) { 499 if (!$teaser && user_access('view uploaded files')) { 500 $node->content['files'] = array( 501 '#value' => theme('upload_attachments', $node->files), 502 '#weight' => 50, 503 ); 504 } 505 } 506 } 507 break; 508 case 'alter': 509 if (isset($node->files) && user_access('view uploaded files')) { 510 // Manipulate so that inline references work in preview 511 if (!variable_get('clean_url', 0)) { 512 $previews = array(); 513 foreach ($node->files as $file) { 514 if (strpos($file->fid, 'upload') !== FALSE) { 515 $previews[] = $file; 516 } 517 } 518 519 // URLs to files being previewed are actually Drupal paths. When Clean 520 // URLs are disabled, the two do not match. We perform an automatic 521 // replacement from temporary to permanent URLs. That way, the author 522 // can use the final URL in the body before having actually saved (to 523 // place inline images for example). 524 foreach ($previews as $file) { 525 $old = file_create_filename($file->filename, file_create_path()); 526 $new = url($old); 527 $node->body = str_replace($old, $new, $node->body); 528 $node->teaser = str_replace($old, $new, $node->teaser); 529 } 530 } 531 } 532 break; 533 case 'insert': 534 case 'update': 535 if (user_access('upload files')) { 536 upload_save($node); 537 } 538 break; 539 540 case 'delete': 541 upload_delete($node); 542 break; 543 544 case 'delete revision': 545 upload_delete_revision($node); 546 break; 547 548 case 'search result': 549 return is_array($node->files) ? format_plural(count($node->files), '1 attachment', '@count attachments') : NULL; 550 551 case 'rss item': 552 if (is_array($node->files)) { 553 $files = array(); 554 foreach ($node->files as $file) { 555 if ($file->list) { 556 $files[] = $file; 557 } 558 } 559 if (count($files) > 0) { 560 // RSS only allows one enclosure per item 561 $file = array_shift($files); 562 return array( 563 array( 564 'key' => 'enclosure', 565 'attributes' => array( 566 'url' => file_create_url($file->filepath), 567 'length' => $file->filesize, 568 'type' => $file->filemime 569 ) 570 ) 571 ); 572 } 573 } 574 return array(); 575 } 576 } 577 578 /** 579 * Displays file attachments in table 580 */ 581 function theme_upload_attachments($files) { 582 $header = array(t('Attachment'), t('Size')); 583 $rows = array(); 584 foreach ($files as $file) { 585 $file = (object)$file; 586 if ($file->list && !$file->remove) { 587 // Generate valid URL for both existing attachments and preview of new attachments (these have 'upload' in fid) 588 $href = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path()))); 589 $text = $file->description ? $file->description : $file->filename; 590 $rows[] = array(l($text, $href), format_size($file->filesize)); 591 } 592 } 593 if (count($rows)) { 594 return theme('table', $header, $rows, array('id' => 'attachments')); 595 } 596 } 597 598 /** 599 * Determine how much disk space is occupied by a user's uploaded files. 600 * 601 * @param $uid 602 * The integer user id of a user. 603 * @return 604 * The amount of disk space used by the user in bytes. 605 */ 606 function upload_space_used($uid) { 607 return db_result(db_query('SELECT SUM(filesize) FROM {files} f INNER JOIN {node} n ON f.nid = n.nid WHERE n.uid = %d', $uid)); 608 } 609 610 /** 611 * Determine how much disk space is occupied by uploaded files. 612 * 613 * @return 614 * The amount of disk space used by uploaded files in bytes. 615 */ 616 function upload_total_space_used() { 617 return db_result(db_query('SELECT SUM(filesize) FROM {files}')); 618 } 619 620 /** 621 * Munge the filename as needed for security purposes. 622 * 623 * @param $filename 624 * The name of a file to modify. 625 * @param $extensions 626 * A space separated list of valid extensions. If this is blank, we'll use 627 * the admin-defined defaults for the user role from upload_extensions_$rid. 628 * @param $alerts 629 * Whether alerts (watchdog, drupal_set_message()) should be displayed. 630 * @return $filename 631 * The potentially modified $filename. 632 */ 633 function upload_munge_filename($filename, $extensions = NULL, $alerts = 1) { 634 global $user; 635 636 $original = $filename; 637 638 // Allow potentially insecure uploads for very savvy users and admin 639 if (!variable_get('allow_insecure_uploads', 0)) { 640 641 if (!isset($extensions)) { 642 $extensions = ''; 643 foreach ($user->roles as $rid => $name) { 644 $extensions .= ' '. variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp')); 645 } 646 647 } 648 649 $whitelist = array_unique(explode(' ', trim($extensions))); 650 651 $filename_parts = explode('.', $filename); 652 653 $new_filename = array_shift($filename_parts); // Remove file basename. 654 $final_extension = array_pop($filename_parts); // Remove final extension. 655 656 foreach ($filename_parts as $filename_part) { 657 $new_filename .= ".$filename_part"; 658 if (!in_array($filename_part, $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) { 659 $new_filename .= '_'; 660 } 661 } 662 $filename = "$new_filename.$final_extension"; 663 } 664 665 if ($alerts && $original != $filename) { 666 $message = t('Your filename has been renamed to conform to site policy.'); 667 drupal_set_message($message); 668 } 669 670 return $filename; 671 } 672 673 /** 674 * Undo the effect of upload_munge_filename(). 675 */ 676 function upload_unmunge_filename($filename) { 677 return str_replace('_.', '.', $filename); 678 } 679 680 function upload_save(&$node) { 681 if (!is_array($node->files)) { 682 return; 683 } 684 685 foreach ($node->files as $fid => $file) { 686 // Convert file to object for compatibility 687 $file = (object)$file; 688 689 // Remove file. Process removals first since no further processing 690 // will be required. 691 if ($file->remove) { 692 // Remove file previews... 693 if (strpos($file->fid, 'upload') !== FALSE) { 694 file_delete($file->filepath); 695 } 696 697 // Remove managed files. 698 else { 699 db_query('DELETE FROM {file_revisions} WHERE fid = %d AND vid = %d', $fid, $node->vid); 700 // Only delete a file if it isn't used by any revision 701 $count = db_result(db_query('SELECT COUNT(fid) FROM {file_revisions} WHERE fid = %d', $fid)); 702 if ($count < 1) { 703 db_query('DELETE FROM {files} WHERE fid = %d', $fid); 704 file_delete($file->filepath); 705 } 706 } 707 } 708 709 // New file upload 710 elseif (strpos($file->fid, 'upload') !== FALSE) { 711 if ($file = file_save_upload($file, $file->filename)) { 712 $file->fid = db_next_id('{files}_fid'); 713 db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", $file->fid, $node->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize); 714 db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $node->vid, $file->list, $file->description); 715 // Tell other modules where the file was stored. 716 $node->files[$fid] = $file; 717 } 718 unset($_SESSION['file_previews'][$fid]); 719 } 720 721 // Create a new revision, as needed 722 elseif ($node->old_vid && is_numeric($fid)) { 723 db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $node->vid, $file->list, $file->description); 724 } 725 726 // Update existing revision 727 else { 728 db_query("UPDATE {file_revisions} SET list = %d, description = '%s' WHERE fid = %d AND vid = %d", $file->list, $file->description, $file->fid, $node->vid); 729 } 730 } 731 } 732 733 function upload_delete($node) { 734 $files = array(); 735 $result = db_query('SELECT * FROM {files} WHERE nid = %d', $node->nid); 736 while ($file = db_fetch_object($result)) { 737 $files[$file->fid] = $file; 738 } 739 740 foreach ($files as $fid => $file) { 741 // Delete all file revision information associated with the node 742 db_query('DELETE FROM {file_revisions} WHERE fid = %d', $fid); 743 file_delete($file->filepath); 744 } 745 746 // Delete all files associated with the node 747 db_query('DELETE FROM {files} WHERE nid = %d', $node->nid); 748 } 749 750 function upload_delete_revision($node) { 751 if (is_array($node->files)) { 752 foreach ($node->files as $file) { 753 // Check if the file will be used after this revision is deleted 754 $count = db_result(db_query('SELECT COUNT(fid) FROM {file_revisions} WHERE fid = %d', $file->fid)); 755 756 // if the file won't be used, delete it 757 if ($count < 2) { 758 db_query('DELETE FROM {files} WHERE fid = %d', $file->fid); 759 file_delete($file->filepath); 760 } 761 } 762 } 763 764 // delete the revision 765 db_query('DELETE FROM {file_revisions} WHERE vid = %d', $node->vid); 766 } 767 768 function _upload_form($node) { 769 770 $form['#theme'] = 'upload_form_new'; 771 772 if (is_array($node->files) && count($node->files)) { 773 $form['files']['#theme'] = 'upload_form_current'; 774 $form['files']['#tree'] = TRUE; 775 foreach ($node->files as $key => $file) { 776 // Generate valid URL for both existing attachments and preview of new attachments (these have 'upload' in fid) 777 $description = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path()))); 778 $description = "<small>". check_plain($description) ."</small>"; 779 $form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description ); 780 781 $form['files'][$key]['size'] = array('#value' => format_size($file->filesize)); 782 $form['files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => $file->remove); 783 $form['files'][$key]['list'] = array('#type' => 'checkbox', '#default_value' => $file->list); 784 // if the file was uploaded this page request, set value. this fixes the problem 785 // formapi has recognizing new checkboxes. see comments in _upload_prepare. 786 if ($_SESSION['file_current_upload'] == $file->fid) { 787 $form['files'][$key]['list']['#value'] = variable_get('upload_list_default',1); 788 } 789 $form['files'][$key]['filename'] = array('#type' => 'value', '#value' => $file->filename); 790 $form['files'][$key]['filepath'] = array('#type' => 'value', '#value' => $file->filepath); 791 $form['files'][$key]['filemime'] = array('#type' => 'value', '#value' => $file->filemime); 792 $form['files'][$key]['filesize'] = array('#type' => 'value', '#value' => $file->filesize); 793 $form['files'][$key]['fid'] = array('#type' => 'value', '#value' => $file->fid); 794 } 795 } 796 797 if (user_access('upload files')) { 798 // This div is hidden when the user uploads through JS. 799 $form['new'] = array( 800 '#prefix' => '<div id="attach-hide">', 801 '#suffix' => '</div>', 802 ); 803 $form['new']['upload'] = array('#type' => 'file', '#title' => t('Attach new file'), '#size' => 40); 804 $form['new']['attach'] = array('#type' => 'button', '#value' => t('Attach'), '#name' => 'attach', '#id' => 'attach-button'); 805 // The class triggers the js upload behaviour. 806 $form['attach-url'] = array('#type' => 'hidden', '#value' => url('upload/js', NULL, NULL, TRUE), '#attributes' => array('class' => 'upload')); 807 } 808 809 // Needed for JS 810 $form['current']['vid'] = array('#type' => 'hidden', '#value' => $node->vid); 811 return $form; 812 } 813 814 /** 815 * Theme the attachments list. 816 */ 817 function theme_upload_form_current(&$form) { 818 $header = array(t('Delete'), t('List'), t('Description'), t('Size')); 819 820 foreach (element_children($form) as $key) { 821 $row = array(); 822 $row[] = drupal_render($form[$key]['remove']); 823 $row[] = drupal_render($form[$key]['list']); 824 $row[] = drupal_render($form[$key]['description']); 825 $row[] = drupal_render($form[$key]['size']); 826 $rows[] = $row; 827 } 828 $output = theme('table', $header, $rows); 829 $output .= drupal_render($form); 830 return $output; 831 } 832 833 /** 834 * Theme the attachment form. 835 * Note: required to output prefix/suffix. 836 */ 837 function theme_upload_form_new($form) { 838 $output = drupal_render($form); 839 return $output; 840 } 841 842 function upload_load($node) { 843 $files = array(); 844 845 if ($node->vid) { 846 $result = db_query('SELECT * FROM {files} f INNER JOIN {file_revisions} r ON f.fid = r.fid WHERE r.vid = %d ORDER BY f.fid', $node->vid); 847 while ($file = db_fetch_object($result)) { 848 $files[$file->fid] = $file; 849 } 850 } 851 852 return $files; 853 } 854 855 /** 856 * Check an upload, if it is an image, make sure it fits within the 857 * maximum dimensions allowed. 858 */ 859 function _upload_image($file) { 860 $info = image_get_info($file->filepath); 861 862 if ($info) { 863 list($width, $height) = explode('x', variable_get('upload_max_resolution', 0)); 864 if ($width && $height) { 865 $result = image_scale($file->filepath, $file->filepath, $width, $height); 866 if ($result) { 867 $file->filesize = filesize($file->filepath); 868 drupal_set_message(t('The image was resized to fit within the maximum allowed resolution of %resolution pixels.', array('%resolution' => variable_get('upload_max_resolution', 0)))); 869 } 870 } 871 } 872 873 return $file; 874 } 875 876 /** 877 * Menu-callback for JavaScript-based uploads. 878 */ 879 function upload_js() { 880 // We only do the upload.module part of the node validation process. 881 $node = (object)$_POST; 882 883 // Load existing node files. 884 $node->files = upload_load($node); 885 886 // Handle new uploads, and merge tmp files into node-files. 887 _upload_prepare($node); 888 _upload_validate($node); 889 890 $form = _upload_form($node); 891 foreach (module_implements('form_alter') as $module) { 892 $function = $module .'_form_alter'; 893 $function('upload_js', $form); 894 } 895 $form = form_builder('upload_js', $form); 896 $output = theme('status_messages') . drupal_render($form); 897 // We send the updated file attachments form. 898 print drupal_to_js(array('status' => TRUE, 'data' => $output)); 899 exit; 900 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Nov 30 16:20:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |