[ Index ]
 

Code source de b2evolution 2.1.0-beta

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/blogs/inc/files/ -> upload.ctrl.php (source)

   1  <?php
   2  /**

   3   * This file implements the UI controller for file upload.

   4   *

   5   * This file is part of the evoCore framework - {@link http://evocore.net/}

   6   * See also {@link http://sourceforge.net/projects/evocms/}.

   7   *

   8   * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/}

   9   * (dh please re-add)

  10   *

  11   * {@internal License choice

  12   * - If you have received this file as part of a package, please find the license.txt file in

  13   *   the same folder or the closest folder above for complete license terms.

  14   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)

  15   *   then you must choose one of the following licenses before using the file:

  16   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php

  17   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php

  18   * }}

  19   *

  20   * {@internal Open Source relicensing agreement:

  21   * (dh please re-add)

  22   * }}

  23   *

  24   * @package admin

  25   *

  26   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}

  27   * @author fplanque: Francois PLANQUE.

  28   * (dh please re-add)

  29   *

  30   * @version $Id: upload.ctrl.php,v 1.2 2007/09/26 23:32:39 fplanque Exp $

  31   */
  32  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  33  
  34  /**

  35   * Filelist

  36   * fp>> TODO: When the user is viewing details for a file he should (by default) not be presented with the filelist in addition to the file properties

  37   * In cases like that, we should try to avoid instanciating a Filelist.

  38   */
  39  load_class('files/model/_filelist.class.php');
  40  
  41  /**

  42   * @var User

  43   */
  44  global $current_User;
  45  
  46  // Check global access permissions:

  47  if( ! $Settings->get( 'fm_enabled' ) )
  48  {
  49      bad_request_die( 'The filemanager is disabled.' );
  50  }
  51  
  52  // Check permission:

  53  $current_User->check_perm( 'files', 'add', true );
  54  
  55  
  56  $AdminUI->set_path( 'files', 'upload' );
  57  
  58  // Params that may need to be passed through:

  59  param( 'fm_mode', 'string', NULL, true );
  60  param( 'item_ID', 'integer', NULL, true );
  61  
  62  $action = param_action();
  63  
  64  
  65  // INIT params:

  66  if( param( 'root_and_path', 'string', '', false ) /* not memorized (default) */ && strpos( $root_and_path, '::' ) )
  67  { // root and path together: decode and override (used by "radio-click-dirtree")
  68      list( $root, $path ) = explode( '::', $root_and_path, 2 );
  69      // Memorize new root:

  70      memorize_param( 'root', 'string', NULL );
  71      memorize_param( 'path', 'string', NULL );
  72  }
  73  else
  74  {
  75      param( 'root', 'string', NULL, true ); // the root directory from the dropdown box (user_X or blog_X; X is ID - 'user' for current user (default))

  76      param( 'path', 'string', '/', true );  // the path relative to the root dir

  77      if( param( 'new_root', 'string', '' )
  78          && $new_root != $root )
  79      { // We have changed root in the select list
  80          $root = $new_root;
  81          $path = '';
  82      }
  83  }
  84  
  85  // Get root:

  86  $ads_list_path = false; // false by default, gets set if we have a valid root

  87  /**

  88   * @var FileRoot

  89   */
  90  $fm_FileRoot = NULL;
  91  
  92  $FileRootCache = & get_Cache( 'FileRootCache' );
  93  
  94  $available_Roots = $FileRootCache->get_available_FileRoots();
  95  
  96  if( ! empty($root) )
  97  { // We have requested a root folder by string:
  98      $fm_FileRoot = & $FileRootCache->get_by_ID($root, true);
  99  
 100      if( ! $fm_FileRoot || ! isset( $available_Roots[$fm_FileRoot->ID] ) )
 101      { // Root not found or not in list of available ones
 102          $Messages->add( T_('You don\'t have access to the requested root directory.'), 'error' );
 103          $fm_FileRoot = false;
 104      }
 105  }
 106  
 107  if( ! $fm_FileRoot )
 108  { // No root requested (or the requested is invalid), get the first one available:
 109      if( $available_Roots
 110          && ( $tmp_keys = array_keys( $available_Roots ) )
 111          && $first_Root = & $available_Roots[ $tmp_keys[0] ] )
 112      { // get the first one
 113          $fm_FileRoot = & $first_Root;
 114      }
 115      else
 116      {
 117          $Messages->add( T_('You don\'t have access to any root directory.'), 'error' );
 118      }
 119  }
 120  
 121  if( $fm_FileRoot )
 122  { // We have access to a file root:
 123      if( empty($fm_FileRoot->ads_path) )
 124      {    // Not sure it's possible to get this far, but just in case...
 125          $Messages->add( sprintf( T_('The root directory &laquo;%s&raquo; does not exist.'), $fm_FileRoot->ads_path ), 'error' );
 126      }
 127      else
 128      { // Root exists
 129          // Let's get into requested list dir...

 130          $non_canonical_list_path = $fm_FileRoot->ads_path.$path;
 131  
 132          // Dereference any /../ just to make sure, and CHECK if directory exists:

 133          $ads_list_path = get_canonical_path( $non_canonical_list_path );
 134  
 135          if( !is_dir( $ads_list_path ) )
 136          { // This should never happen, but just in case the diretory does not exist:
 137              $Messages->add( sprintf( T_('The directory &laquo;%s&raquo; does not exist.'), $path ), 'error' );
 138              $path = '';        // fp> added

 139              $ads_list_path = NULL;
 140          }
 141          elseif( ! preg_match( '#^'.preg_quote($fm_FileRoot->ads_path, '#').'#', $ads_list_path ) )
 142          { // cwd is OUTSIDE OF root!
 143              $Messages->add( T_( 'You are not allowed to go outside your root directory!' ), 'error' );
 144              $path = '';        // fp> added

 145              $ads_list_path = $fm_FileRoot->ads_path;
 146          }
 147          elseif( $ads_list_path != $non_canonical_list_path )
 148          {    // We have reduced the absolute path, we should also reduce the relative $path (used in urls params)
 149              $path = get_canonical_path( $path );
 150          }
 151      }
 152  }
 153  
 154  
 155  // If there were errors, display them and exit (especially in case there's no valid FileRoot ($fm_FileRoot)):

 156  // TODO: dh> this prevents users from uploading if _any_ blog media directory is not writable.

 157  //           See http://forums.b2evolution.net/viewtopic.php?p=49001#49001

 158  if( $Messages->count('error') )
 159  {
 160      // Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)

 161      $AdminUI->disp_html_head();
 162  
 163      // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)

 164      $AdminUI->disp_body_top();
 165      $AdminUI->disp_payload_begin();
 166      $AdminUI->disp_payload_end();
 167  
 168      $AdminUI->disp_global_footer();
 169      exit();
 170  }
 171  
 172  
 173  $Debuglog->add( 'FM root: '.var_export( $fm_FileRoot, true ), 'files' );
 174  $Debuglog->add( 'FM _ads_list_path: '.var_export( $ads_list_path, true ), 'files' );
 175  
 176  
 177  if( empty($ads_list_path) )
 178  { // We have no Root / list path, there was an error. Unset any action.
 179      $action = '';
 180  }
 181  
 182  
 183  
 184  
 185  // Check permissions:

 186  if( ! $Settings->get('upload_enabled') )
 187  { // Upload is globally disabled
 188      $Messages->add( T_('Upload is disabled.'), 'error' );
 189  }
 190  
 191  if( ! $current_User->check_perm( 'files', 'add' ) )
 192  { // We do not have permission to add files
 193      $Messages->add( T_('You have no permission to add/upload files.'), 'error' );
 194  }
 195  
 196  
 197  // If there were errors, display them and exit (especially in case there's no valid FileRoot ($fm_FileRoot)):

 198  if( $Messages->count('error') )
 199  {
 200      $AdminUI->disp_html_head();
 201      // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)

 202      $AdminUI->disp_body_top();
 203      $AdminUI->disp_global_footer();
 204      exit();
 205  }
 206  
 207  
 208  // Quick mode means "just upload and leave mode when successful"

 209  param( 'upload_quickmode', 'integer', 0 );
 210  
 211  /**

 212   * Remember failed files (and the error messages)

 213   * @var array

 214   */
 215  $failedFiles = array();
 216  
 217  // Process uploaded files:

 218  if( isset($_FILES) && count( $_FILES ) )
 219  { // Some files have been uploaded:
 220      param( 'uploadfile_title', 'array', array() );
 221      param( 'uploadfile_alt', 'array', array() );
 222      param( 'uploadfile_desc', 'array', array() );
 223      param( 'uploadfile_name', 'array', array() );
 224  
 225      foreach( $_FILES['uploadfile']['name'] as $lKey => $lName )
 226      {
 227          if( empty( $lName ) )
 228          { // No file name
 229              if( $upload_quickmode
 230                   || !empty( $uploadfile_title[$lKey] )
 231                   || !empty( $uploadfile_alt[$lKey] )
 232                   || !empty( $uploadfile_desc[$lKey] )
 233                   || !empty( $uploadfile_name[$lKey] ) )
 234              { // User specified params but NO file!!!
 235                  // Remember the file as failed when additional info provided.

 236                  $failedFiles[$lKey] = T_( 'Please select a local file to upload.' );
 237              }
 238              // Abort upload for this file:

 239              continue;
 240          }
 241  
 242          if( $Settings->get( 'upload_maxkb' )
 243                  && $_FILES['uploadfile']['size'][$lKey] > $Settings->get( 'upload_maxkb' )*1024 )
 244          { // bigger than defined by blog
 245              $failedFiles[$lKey] = sprintf(
 246                      /* TRANS: %s will be replaced by the difference */ T_('The file is too large: %s but the maximum allowed is %s.'),
 247                      bytesreadable( $_FILES['uploadfile']['size'][$lKey] ),
 248                      bytesreadable($Settings->get( 'upload_maxkb' )*1024) );
 249              // Abort upload for this file:

 250              continue;
 251          }
 252  
 253          if( $_FILES['uploadfile']['error'][$lKey] )
 254          { // PHP has detected an error!:
 255              switch( $_FILES['uploadfile']['error'][$lKey] )
 256              {
 257                  case UPLOAD_ERR_FORM_SIZE:
 258                      // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form.

 259  
 260                      // This can easily be changed, so we do not use it.. file size gets checked for real just above.

 261                      break;
 262  
 263                  case UPLOAD_ERR_INI_SIZE: // bigger than allowed in php.ini
 264                      $failedFiles[$lKey] = T_('The file exceeds the upload_max_filesize directive in php.ini.');
 265                      // Abort upload for this file:

 266                      continue;
 267  
 268                  case UPLOAD_ERR_PARTIAL:
 269                      $failedFiles[$lKey] = T_('The file was only partially uploaded.');
 270                      // Abort upload for this file:

 271                      continue;
 272  
 273                  case UPLOAD_ERR_NO_FILE:
 274                      // Is probably the same as empty($lName) before.

 275                      $failedFiles[$lKey] = T_('No file was uploaded.');
 276                      // Abort upload for this file:

 277                      continue;
 278  
 279                  case 6: // numerical value of UPLOAD_ERR_NO_TMP_DIR
 280                  # (min_php: 4.3.10, 5.0.3) case UPLOAD_ERR_NO_TMP_DIR:

 281                      // Missing a temporary folder.

 282                      $failedFiles[$lKey] = T_('Missing a temporary folder (upload_tmp_dir in php.ini).');
 283                      // Abort upload for this file:

 284                      continue;
 285  
 286                  default:
 287                      $failedFiles[$lKey] = T_('Unknown error.').' #'.$_FILES['uploadfile']['error'][$lKey];
 288                      // Abort upload for this file:

 289                      continue;
 290              }
 291          }
 292  
 293          if( !is_uploaded_file( $_FILES['uploadfile']['tmp_name'][$lKey] ) )
 294          { // Ensure that a malicious user hasn't tried to trick the script into working on files upon which it should not be working.
 295              $failedFiles[$lKey] = T_('The file does not seem to be a valid upload! It may exceed the upload_max_filesize directive in php.ini.');
 296              // Abort upload for this file:

 297              continue;
 298          }
 299  
 300          // Use new name on server if specified:

 301          $newName = !empty( $uploadfile_name[ $lKey ] ) ? $uploadfile_name[ $lKey ] : $lName;
 302  
 303          if( $error_filename = validate_filename( $newName ) )
 304          { // Not a file name or not an allowed extension
 305              $failedFiles[$lKey] = $error_filename;
 306              // Abort upload for this file:

 307              continue;
 308          }
 309  
 310          // Get File object for requested target location:

 311          $FileCache = & get_Cache( 'FileCache' );
 312          $newFile = & $FileCache->get_by_root_and_path( $fm_FileRoot->type, $fm_FileRoot->in_type_ID, trailing_slash($path).$newName, true );
 313  
 314          if( $newFile->exists() )
 315          { // The file already exists in the target location!
 316              // TODO: Rename/Overwriting (save as filename_<numeric_extension> and provide interface to confirm, rename or overwrite)

 317              $failedFiles[$lKey] = sprintf( T_('The file &laquo;%s&raquo; already exists.'), $newFile->dget('name') );
 318              // Abort upload for this file:

 319              continue;
 320          }
 321  
 322          // Attempt to move the uploaded file to the requested target location:

 323          if( !move_uploaded_file( $_FILES['uploadfile']['tmp_name'][$lKey], $newFile->get_full_path() ) )
 324          {
 325              $failedFiles[$lKey] = T_('An unknown error occurred when moving the uploaded file on the server.');
 326              // Abort upload for this file:

 327              continue;
 328          }
 329  
 330          // change to default chmod settings

 331          if( $newFile->chmod( NULL ) === false )
 332          { // add a note, this is no error!
 333              $Messages->add( sprintf( T_('Could not change permissions of &laquo;%s&raquo; to default chmod setting.'), $newFile->dget('name') ), 'note' );
 334          }
 335  
 336          // Refreshes file properties (type, size, perms...)

 337          $newFile->load_properties();
 338  
 339          // Store extra info about the file into File Object:

 340          if( isset( $uploadfile_title[$lKey] ) )
 341          { // If a title text has been passed... (does not happen in quick upload mode)
 342              $newFile->set( 'title', trim( strip_tags($uploadfile_title[$lKey])) );
 343          }
 344          if( isset( $uploadfile_alt[$lKey] ) )
 345          { // If an alt text has been passed... (does not happen in quick upload mode)
 346              $newFile->set( 'alt', trim( strip_tags($uploadfile_alt[$lKey])) );
 347          }
 348          if( isset( $uploadfile_desc[$lKey] ) )
 349          { // If a desc text has been passed... (does not happen in quick upload mode)
 350              $newFile->set( 'desc', trim( strip_tags($uploadfile_desc[$lKey])) );
 351          }
 352  
 353          $success_msg = sprintf( T_('The file &laquo;%s&raquo; has been successfully uploaded.'), $newFile->dget('name') );
 354          if( $mode == 'upload' )
 355          {
 356              // TODO: Add plugin hook to allow generating JS insert code(s)

 357              $img_tag = format_to_output( $newFile->get_tag(), 'formvalue' );
 358              $success_msg .=
 359                  '<ul>'
 360                      .'<li>'.T_("Here's the code to display it:").' <input type="text" value="'.$img_tag.'" /></li>'
 361                      .'<li><a href="#" onclick="if( window.focus && window.opener ){ window.opener.focus(); textarea_wrap_selection( window.opener.document.getElementById(\'itemform_post_content\'), \''.format_to_output( $newFile->get_tag(), 'formvalue' ).'\', \'\', 1, window.opener.document ); } return false;">'.T_('Add the code to your post !').'</a></li>'
 362                  .'</ul>';
 363          }
 364  
 365          $Messages->add( $success_msg, 'success' );
 366  
 367          // Store File object into DB:

 368          $newFile->dbsave();
 369  
 370      }
 371  
 372      if( $upload_quickmode && !empty($failedFiles) )
 373      {    // Transmit file error to next page!
 374          $Messages->add( $failedFiles[0], 'error' );
 375          unset($failedFiles);
 376      }
 377      if( empty($failedFiles) )
 378      { // quick mode or no failed files, Go back to Browsing
 379          // header_redirect( 'admin.php?ctrl=files&root='.$fm_FileRoot->ID.'&path='.rawurlencode($path) );

 380          header_redirect( regenerate_url( 'ctrl', 'ctrl=files', '', '&' ) );
 381      }
 382  }
 383  
 384  
 385  // Update sub-menu:

 386  if( $current_User->check_perm( 'files', 'add' ) )
 387  { // Permission to upload: (no subtabs needed otherwise)
 388      $AdminUI->add_menu_entries(
 389              'files',
 390              array(
 391                      'browse' => array(
 392                          'text' => T_('Browse'),
 393                          'href' => regenerate_url( 'ctrl', 'ctrl=files' ) ),
 394                      'upload' => array(
 395                          'text' => T_('Upload multiple'),
 396                          'href' => regenerate_url( 'ctrl', 'ctrl=upload' ) ),
 397                  )
 398          );
 399  }
 400  
 401  
 402  // Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)

 403  $AdminUI->disp_html_head();
 404  
 405  // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)

 406  $AdminUI->disp_body_top();
 407  
 408  
 409  /*

 410   * Display payload:

 411   */
 412  $AdminUI->disp_view( 'files/views/_file_upload.view.php' );
 413  
 414  
 415  // Display body bottom, debug info and close </html>:

 416  $AdminUI->disp_global_footer();
 417  
 418  
 419  /*

 420   * $Log: upload.ctrl.php,v $

 421   * Revision 1.2  2007/09/26 23:32:39  fplanque

 422   * upload context saving

 423   *

 424   * Revision 1.1  2007/06/25 10:59:53  fplanque

 425   * MODULES (refactored MVC)

 426   *

 427   * Revision 1.10  2007/04/26 00:11:13  fplanque

 428   * (c) 2007

 429   *

 430   * Revision 1.9  2007/04/20 01:42:32  fplanque

 431   * removed excess javascript

 432   *

 433   * Revision 1.8  2007/02/22 18:36:57  fplanque

 434   * better error messages

 435   *

 436   * Revision 1.7  2007/01/24 13:44:56  fplanque

 437   * cleaned up upload

 438   *

 439   * Revision 1.6  2007/01/24 02:35:42  fplanque

 440   * refactoring

 441   *

 442   * Revision 1.5  2007/01/24 01:40:15  fplanque

 443   * Upload tab now stays in context

 444   *

 445   * Revision 1.4  2007/01/10 21:41:51  blueyed

 446   * todo: any "error" does not allow uploading and "blog media directory could not be created" is such an error, which may not be relevant

 447   *

 448   * Revision 1.3  2006/12/23 22:53:11  fplanque

 449   * extra security

 450   *

 451   * Revision 1.2  2006/12/22 01:09:30  fplanque

 452   * cleanup

 453   *

 454   * Revision 1.1  2006/12/22 00:51:34  fplanque

 455   * dedicated upload tab - proof of concept

 456   * (interlinking to be done)

 457   *

 458   */
 459  ?>


Généré le : Thu Nov 29 23:58:50 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics