[ Index ]

PHP Cross Reference of MyBB

title

Body

[close]

/inc/ -> functions_upload.php (source)

   1  <?php
   2  /**
   3   * MyBB 1.6
   4   * Copyright 2010 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://mybb.com
   7   * License: http://mybb.com/about/license
   8   *
   9   * $Id$
  10   */
  11  
  12  
  13  /**
  14   * Remove an attachment from a specific post
  15   *
  16   * @param int The post ID
  17   * @param string The posthash if available
  18   * @param int The attachment ID
  19   */
  20  function remove_attachment($pid, $posthash, $aid)
  21  {
  22      global $db, $mybb, $plugins;
  23      $aid = intval($aid);
  24      $posthash = $db->escape_string($posthash);
  25      if($posthash != "")
  26      {
  27          $query = $db->simple_select("attachments", "aid, attachname, thumbnail, visible", "aid='{$aid}' AND posthash='{$posthash}'");
  28          $attachment = $db->fetch_array($query);
  29      }
  30      else
  31      {
  32          $query = $db->simple_select("attachments", "aid, attachname, thumbnail, visible", "aid='{$aid}' AND pid='{$pid}'");
  33          $attachment = $db->fetch_array($query);
  34      }
  35  
  36      $plugins->run_hooks("remove_attachment_do_delete", $attachment);
  37  
  38      $db->delete_query("attachments", "aid='{$attachment['aid']}'");
  39  
  40      if(defined('IN_ADMINCP'))
  41      {
  42          $uploadpath = '../'.$mybb->settings['uploadspath'];
  43      }
  44      else
  45      {
  46          $uploadpath = $mybb->settings['uploadspath'];
  47      }
  48  
  49      // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file.
  50      $query = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($attachment['attachname'])."'");
  51      if($db->fetch_field($query, "numreferences") == 0)
  52      {
  53          @unlink($uploadpath."/".$attachment['attachname']);
  54          if($attachment['thumbnail'])
  55          {
  56              @unlink($uploadpath."/".$attachment['thumbnail']);
  57          }
  58  
  59          $date_directory = explode('/', $attachment['attachname']);
  60          if(@is_dir($uploadpath."/".$date_directory[0]))
  61          {
  62              @rmdir($uploadpath."/".$date_directory[0]);
  63          }
  64      }
  65  
  66      if($attachment['visible'] == 1 && $pid)
  67      {
  68          $post = get_post($pid);
  69          update_thread_counters($post['tid'], array("attachmentcount" => "-1"));
  70      }
  71  }
  72  
  73  /**
  74   * Remove all of the attachments from a specific post
  75   *
  76   * @param int The post ID
  77   * @param string The posthash if available
  78   */
  79  function remove_attachments($pid, $posthash="")
  80  {
  81      global $db, $mybb, $plugins;
  82  
  83      if($pid)
  84      {
  85          $post = get_post($pid);
  86      }
  87      $posthash = $db->escape_string($posthash);
  88      if($posthash != "" && !$pid)
  89      {
  90          $query = $db->simple_select("attachments", "*", "posthash='$posthash'");
  91      }
  92      else
  93      {
  94          $query = $db->simple_select("attachments", "*", "pid='$pid'");
  95      }
  96  
  97      if(defined('IN_ADMINCP'))
  98      {
  99          $uploadpath = '../'.$mybb->settings['uploadspath'];
 100      }
 101      else
 102      {
 103          $uploadpath = $mybb->settings['uploadspath'];
 104      }
 105  
 106      $num_attachments = 0;
 107      while($attachment = $db->fetch_array($query))
 108      {
 109          if($attachment['visible'] == 1)
 110          {
 111              $num_attachments++;
 112          }
 113  
 114          $plugins->run_hooks("remove_attachments_do_delete", $attachment);
 115  
 116          $db->delete_query("attachments", "aid='".$attachment['aid']."'");
 117  
 118          // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file.
 119          $query2 = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($attachment['attachname'])."'");
 120          if($db->fetch_field($query2, "numreferences") == 0)
 121          {
 122              @unlink($uploadpath."/".$attachment['attachname']);
 123              if($attachment['thumbnail'])
 124              {
 125                  @unlink($uploadpath."/".$attachment['thumbnail']);
 126              }
 127  
 128              $date_directory = explode('/', $attachment['attachname']);
 129              if(@is_dir($uploadpath."/".$date_directory[0]))
 130              {
 131                  @rmdir($uploadpath."/".$date_directory[0]);
 132              }
 133          }
 134      }
 135  
 136      if($post['tid'])
 137      {
 138          update_thread_counters($post['tid'], array("attachmentcount" => "-{$num_attachments}"));
 139      }
 140  }
 141  
 142  /**
 143   * Remove any matching avatars for a specific user ID
 144   *
 145   * @param int The user ID
 146   * @param string A file name to be excluded from the removal
 147   */
 148  function remove_avatars($uid, $exclude="")
 149  {
 150      global $mybb, $plugins;
 151  
 152      if(defined('IN_ADMINCP'))
 153      {
 154          $avatarpath = '../'.$mybb->settings['avataruploadpath'];
 155      }
 156      else
 157      {
 158          $avatarpath = $mybb->settings['avataruploadpath'];
 159      }
 160  
 161      $dir = opendir($avatarpath);
 162      if($dir)
 163      {
 164          while($file = @readdir($dir))
 165          {
 166              $plugins->run_hooks("remove_avatars_do_delete", $file);
 167  
 168              if(preg_match("#avatar_".$uid."\.#", $file) && is_file($avatarpath."/".$file) && $file != $exclude)
 169              {
 170                  @unlink($avatarpath."/".$file);
 171              }
 172          }
 173  
 174          @closedir($dir);
 175      }
 176  }
 177  
 178  /**
 179   * Upload a new avatar in to the file system
 180   *
 181   * @param srray incoming FILE array, if we have one - otherwise takes $_FILES['avatarupload']
 182   * @param string User ID this avatar is being uploaded for, if not the current user
 183   * @return array Array of errors if any, otherwise filename of successful.
 184   */
 185  function upload_avatar($avatar=array(), $uid=0)
 186  {
 187      global $db, $mybb, $lang, $plugins;
 188  
 189      if(!$uid)
 190      {
 191          $uid = $mybb->user['uid'];
 192      }
 193  
 194      if(!$avatar['name'] || !$avatar['tmp_name'])
 195      {
 196          $avatar = $_FILES['avatarupload'];
 197      }
 198  
 199      if(!is_uploaded_file($avatar['tmp_name']))
 200      {
 201          $ret['error'] = $lang->error_uploadfailed;
 202          return $ret;
 203      }
 204  
 205      // Check we have a valid extension
 206      $ext = get_extension(my_strtolower($avatar['name']));
 207      if(!preg_match("#^(gif|jpg|jpeg|jpe|bmp|png)$#i", $ext))
 208      {
 209          $ret['error'] = $lang->error_avatartype;
 210          return $ret;
 211      }
 212  
 213      if(defined('IN_ADMINCP'))
 214      {
 215          $avatarpath = '../'.$mybb->settings['avataruploadpath'];
 216          $lang->load("messages", true);
 217      }
 218      else
 219      {
 220          $avatarpath = $mybb->settings['avataruploadpath'];
 221      }
 222  
 223      $filename = "avatar_".$uid.".".$ext;
 224      $file = upload_file($avatar, $avatarpath, $filename);
 225      if($file['error'])
 226      {
 227          @unlink($avatarpath."/".$filename);
 228          $ret['error'] = $lang->error_uploadfailed;
 229          return $ret;
 230      }
 231  
 232  
 233      // Lets just double check that it exists
 234      if(!file_exists($avatarpath."/".$filename))
 235      {
 236          $ret['error'] = $lang->error_uploadfailed;
 237          @unlink($avatarpath."/".$filename);
 238          return $ret;
 239      }
 240  
 241      // Check if this is a valid image or not
 242      $img_dimensions = @getimagesize($avatarpath."/".$filename);
 243      if(!is_array($img_dimensions))
 244      {
 245          @unlink($avatarpath."/".$filename);
 246          $ret['error'] = $lang->error_uploadfailed;
 247          return $ret;
 248      }
 249  
 250      // Check avatar dimensions
 251      if($mybb->settings['maxavatardims'] != '')
 252      {
 253          list($maxwidth, $maxheight) = @explode("x", $mybb->settings['maxavatardims']);
 254          if(($maxwidth && $img_dimensions[0] > $maxwidth) || ($maxheight && $img_dimensions[1] > $maxheight))
 255          {
 256              // Automatic resizing enabled?
 257              if($mybb->settings['avatarresizing'] == "auto" || ($mybb->settings['avatarresizing'] == "user" && $mybb->input['auto_resize'] == 1))
 258              {
 259                  require_once  MYBB_ROOT."inc/functions_image.php";
 260                  $thumbnail = generate_thumbnail($avatarpath."/".$filename, $avatarpath, $filename, $maxheight, $maxwidth);
 261                  if(!$thumbnail['filename'])
 262                  {
 263                      $ret['error'] = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight);
 264                      $ret['error'] .= "<br /><br />".$lang->error_avatarresizefailed;
 265                      @unlink($avatarpath."/".$filename);
 266                      return $ret;
 267                  }
 268                  else
 269                  {
 270                      // Reset filesize
 271                      $avatar['size'] = filesize($avatarpath."/".$filename);
 272                      // Reset dimensions
 273                      $img_dimensions = @getimagesize($avatarpath."/".$filename);
 274                  }
 275              }
 276              else
 277              {
 278                  $ret['error'] = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight);
 279                  if($mybb->settings['avatarresizing'] == "user")
 280                  {
 281                      $ret['error'] .= "<br /><br />".$lang->error_avataruserresize;
 282                  }
 283                  @unlink($avatarpath."/".$filename);
 284                  return $ret;
 285              }
 286          }
 287      }
 288  
 289      // Next check the file size
 290      if($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0)
 291      {
 292          @unlink($avatarpath."/".$filename);
 293          $ret['error'] = $lang->error_uploadsize;
 294          return $ret;
 295      }
 296  
 297      // Check a list of known MIME types to establish what kind of avatar we're uploading
 298      switch(my_strtolower($avatar['type']))
 299      {
 300          case "image/gif":
 301              $img_type =  1;
 302              break;
 303          case "image/jpeg":
 304          case "image/x-jpg":
 305          case "image/x-jpeg":
 306          case "image/pjpeg":
 307          case "image/jpg":
 308              $img_type = 2;
 309              break;
 310          case "image/png":
 311          case "image/x-png":
 312              $img_type = 3;
 313              break;
 314          default:
 315              $img_type = 0;
 316      }
 317  
 318      // Check if the uploaded file type matches the correct image type (returned by getimagesize)
 319      if($img_dimensions[2] != $img_type || $img_type == 0)
 320      {
 321          $ret['error'] = $lang->error_uploadfailed;
 322          @unlink($avatarpath."/".$filename);
 323          return $ret;
 324      }
 325      // Everything is okay so lets delete old avatars for this user
 326      remove_avatars($uid, $filename);
 327  
 328      $ret = array(
 329          "avatar" => $mybb->settings['avataruploadpath']."/".$filename,
 330          "width" => intval($img_dimensions[0]),
 331          "height" => intval($img_dimensions[1])
 332      );
 333      $ret = $plugins->run_hooks("upload_avatar_end", $ret);
 334      return $ret;
 335  }
 336  
 337  /**
 338   * Upload an attachment in to the file system
 339   *
 340   * @param array Attachment data (as fed by PHPs $_FILE)
 341   * @param boolean Whether or not we are updating a current attachment or inserting a new one
 342   * @return array Array of attachment data if successful, otherwise array of error data
 343   */
 344  function upload_attachment($attachment, $update_attachment=false)
 345  {
 346      global $db, $theme, $templates, $posthash, $pid, $tid, $forum, $mybb, $lang, $plugins, $cache;
 347  
 348      $posthash = $db->escape_string($mybb->input['posthash']);
 349      $pid = intval($pid);
 350  
 351      if(isset($attachment['error']) && $attachment['error'] != 0)
 352      {
 353          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail;
 354          switch($attachment['error'])
 355          {
 356              case 1: // UPLOAD_ERR_INI_SIZE
 357                  $ret['error'] .= $lang->error_uploadfailed_php1;
 358                  break;
 359              case 2: // UPLOAD_ERR_FORM_SIZE
 360                  $ret['error'] .= $lang->error_uploadfailed_php2;
 361                  break;
 362              case 3: // UPLOAD_ERR_PARTIAL
 363                  $ret['error'] .= $lang->error_uploadfailed_php3;
 364                  break;
 365              case 4: // UPLOAD_ERR_NO_FILE
 366                  $ret['error'] .= $lang->error_uploadfailed_php4;
 367                  break;
 368              case 6: // UPLOAD_ERR_NO_TMP_DIR
 369                  $ret['error'] .= $lang->error_uploadfailed_php6;
 370                  break;
 371              case 7: // UPLOAD_ERR_CANT_WRITE
 372                  $ret['error'] .= $lang->error_uploadfailed_php7;
 373                  break;
 374              default:
 375                  $ret['error'] .= $lang->sprintf($lang->error_uploadfailed_phpx, $attachment['error']);
 376                  break;
 377          }
 378          return $ret;
 379      }
 380  
 381      if(!is_uploaded_file($attachment['tmp_name']) || empty($attachment['tmp_name']))
 382      {
 383          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_php4;
 384          return $ret;
 385      }
 386  
 387      $ext = get_extension($attachment['name']);
 388      // Check if we have a valid extension
 389      $query = $db->simple_select("attachtypes", "*", "extension='".$db->escape_string($ext)."'");
 390      $attachtype = $db->fetch_array($query);
 391      if(!$attachtype['atid'])
 392      {
 393          $ret['error'] = $lang->error_attachtype;
 394          return $ret;
 395      }
 396  
 397      // Check the size
 398      if($attachment['size'] > $attachtype['maxsize']*1024 && $attachtype['maxsize'] != "")
 399      {
 400          $ret['error'] = $lang->sprintf($lang->error_attachsize, $attachtype['maxsize']);
 401          return $ret;
 402      }
 403  
 404      // Double check attachment space usage
 405      if($mybb->usergroup['attachquota'] > 0)
 406      {
 407          $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='".$mybb->user['uid']."'");
 408          $usage = $db->fetch_array($query);
 409          $usage = $usage['ausage']+$attachment['size'];
 410          if($usage > ($mybb->usergroup['attachquota']*1024))
 411          {
 412              $friendlyquota = get_friendly_size($mybb->usergroup['attachquota']*1024);
 413              $ret['error'] = $lang->sprintf($lang->error_reachedattachquota, $friendlyquota);
 414              return $ret;
 415          }
 416      }
 417  
 418      // Gather forum permissions
 419      $forumpermissions = forum_permissions($forum['fid']);
 420  
 421      // Check if an attachment with this name is already in the post
 422      if($pid != 0)
 423      {
 424          $uploaded_query = "pid='{$pid}'";
 425      }
 426      else
 427      {
 428          $uploaded_query = "posthash='{$posthash}'";
 429      }
 430      $query = $db->simple_select("attachments", "*", "filename='".$db->escape_string($attachment['name'])."' AND ".$uploaded_query);
 431      $prevattach = $db->fetch_array($query);
 432      if($prevattach['aid'] && $update_attachment == false)
 433      {
 434          if(!$mybb->usergroup['caneditattachments'] && !$forumpermissions['caneditattachments'])
 435          {
 436              $ret['error'] = $lang->error_alreadyuploaded_perm;
 437              return $ret;
 438          }
 439  
 440          $ret['error'] = $lang->error_alreadyuploaded;
 441          return $ret;
 442      }
 443  
 444      $month_dir = '';
 445      if(ini_get('safe_mode') != 1 && strtolower(ini_get('safe_mode')) != 'on')
 446      {
 447          // Check if the attachment directory (YYYYMM) exists, if not, create it
 448          $month_dir = gmdate("Ym");
 449          if(!@is_dir($mybb->settings['uploadspath']."/".$month_dir))
 450          {
 451              @mkdir($mybb->settings['uploadspath']."/".$month_dir);
 452              // Still doesn't exist - oh well, throw it in the main directory
 453              if(!@is_dir($mybb->settings['uploadspath']."/".$month_dir))
 454              {
 455                  $month_dir = '';
 456              }
 457          }
 458      }
 459  
 460      // All seems to be good, lets move the attachment!
 461      $filename = "post_".$mybb->user['uid']."_".TIME_NOW."_".md5(random_str()).".attach";
 462  
 463      $file = upload_file($attachment, $mybb->settings['uploadspath']."/".$month_dir, $filename);
 464  
 465      // Failed to create the attachment in the monthly directory, just throw it in the main directory
 466      if($file['error'] && $month_dir)
 467      {
 468          $file = upload_file($attachment, $mybb->settings['uploadspath'].'/', $filename);
 469      }
 470  
 471      if($month_dir)
 472      {
 473          $filename = $month_dir."/".$filename;
 474      }
 475  
 476      if($file['error'])
 477      {
 478          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail;
 479          switch($file['error'])
 480          {
 481              case 1:
 482                  $ret['error'] .= $lang->error_uploadfailed_nothingtomove;
 483                  break;
 484              case 2:
 485                  $ret['error'] .= $lang->error_uploadfailed_movefailed;
 486                  break;
 487          }
 488          return $ret;
 489      }
 490  
 491      // Lets just double check that it exists
 492      if(!file_exists($mybb->settings['uploadspath']."/".$filename))
 493      {
 494          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail.$lang->error_uploadfailed_lost;
 495          return $ret;
 496      }
 497  
 498      // Generate the array for the insert_query
 499      $attacharray = array(
 500          "pid" => $pid,
 501          "posthash" => $posthash,
 502          "uid" => $mybb->user['uid'],
 503          "filename" => $db->escape_string($file['original_filename']),
 504          "filetype" => $db->escape_string($file['type']),
 505          "filesize" => intval($file['size']),
 506          "attachname" => $filename,
 507          "downloads" => 0,
 508          "dateuploaded" => TIME_NOW
 509      );
 510  
 511      // If we're uploading an image, check the MIME type compared to the image type and attempt to generate a thumbnail
 512      if($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe")
 513      {
 514          // Check a list of known MIME types to establish what kind of image we're uploading
 515          switch(my_strtolower($file['type']))
 516          {
 517              case "image/gif":
 518                  $img_type =  1;
 519                  break;
 520              case "image/jpeg":
 521              case "image/x-jpg":
 522              case "image/x-jpeg":
 523              case "image/pjpeg":
 524              case "image/jpg":
 525                  $img_type = 2;
 526                  break;
 527              case "image/png":
 528              case "image/x-png":
 529                  $img_type = 3;
 530                  break;
 531              default:
 532                  $img_type = 0;
 533          }
 534  
 535          $supported_mimes = array();
 536          $attachtypes = $cache->read("attachtypes");
 537          foreach($attachtypes as $attachtype)
 538          {
 539              if(!empty($attachtype['mimetype']))
 540              {
 541                  $supported_mimes[] = $attachtype['mimetype'];
 542              }
 543          }
 544  
 545          // Check if the uploaded file type matches the correct image type (returned by getimagesize)
 546          $img_dimensions = @getimagesize($mybb->settings['uploadspath']."/".$filename);
 547  
 548          $mime = "";
 549          $file_path = $mybb->settings['uploadspath']."/".$filename;
 550          if(function_exists("finfo_open"))
 551          {
 552              $file_info = finfo_open(FILEINFO_MIME);
 553              list($mime, ) = explode(';', finfo_file($file_info, MYBB_ROOT.$file_path), 1);
 554              finfo_close($file_info);
 555          }
 556          else if(function_exists("mime_content_type"))
 557          {
 558              $mime = mime_content_type(MYBB_ROOT.$file_path);
 559          }
 560  
 561          if(!is_array($img_dimensions) || ($img_dimensions[2] != $img_type && !in_array($mime, $supported_mimes)))
 562          {
 563              @unlink($mybb->settings['uploadspath']."/".$filename);
 564              $ret['error'] = $lang->error_uploadfailed;
 565              return $ret;
 566          }
 567          require_once  MYBB_ROOT."inc/functions_image.php";
 568          $thumbname = str_replace(".attach", "_thumb.$ext", $filename);
 569          $thumbnail = generate_thumbnail($mybb->settings['uploadspath']."/".$filename, $mybb->settings['uploadspath'], $thumbname, $mybb->settings['attachthumbh'], $mybb->settings['attachthumbw']);
 570  
 571          if($thumbnail['filename'])
 572          {
 573              $attacharray['thumbnail'] = $thumbnail['filename'];
 574          }
 575          elseif($thumbnail['code'] == 4)
 576          {
 577              $attacharray['thumbnail'] = "SMALL";
 578          }
 579      }
 580      if($forum['modattachments'] == 1 && !is_moderator($forum['fid'], "", $mybb->user['uid']))
 581      {
 582          $attacharray['visible'] = 0;
 583      }
 584      else
 585      {
 586          $attacharray['visible'] = 1;
 587      }
 588  
 589      $attacharray = $plugins->run_hooks("upload_attachment_do_insert", $attacharray);
 590  
 591      if($prevattach['aid'] && $update_attachment == true)
 592      {
 593          unset($attacharray['downloads']); // Keep our download count if we're updating an attachment
 594          $db->update_query("attachments", $attacharray, "aid='".$db->escape_string($prevattach['aid'])."'");
 595          $aid = $prevattach['aid'];
 596      }
 597      else
 598      {
 599          $aid = $db->insert_query("attachments", $attacharray);
 600          if($pid)
 601          {
 602              update_thread_counters($tid, array("attachmentcount" => "+1"));
 603          }
 604      }
 605      $ret['aid'] = $aid;
 606      return $ret;
 607  }
 608  
 609  /**
 610   * Actually move a file to the uploads directory
 611   *
 612   * @param array The PHP $_FILE array for the file
 613   * @param string The path to save the file in
 614   * @param string The filename for the file (if blank, current is used)
 615   */
 616  function upload_file($file, $path, $filename="")
 617  {
 618      global $plugins;
 619  
 620      if(empty($file['name']) || $file['name'] == "none" || $file['size'] < 1)
 621      {
 622          $upload['error'] = 1;
 623          return $upload;
 624      }
 625  
 626      if(!$filename)
 627      {
 628          $filename = $file['name'];
 629      }
 630  
 631      $upload['original_filename'] = preg_replace("#/$#", "", $file['name']); // Make the filename safe
 632      $upload['original_filename'] = utf8_handle_4byte_string($upload['original_filename']);
 633      $filename = preg_replace("#/$#", "", $filename); // Make the filename safe
 634      $moved = @move_uploaded_file($file['tmp_name'], $path."/".$filename);
 635  
 636      if(!$moved)
 637      {
 638          $upload['error'] = 2;
 639          return $upload;
 640      }
 641      @my_chmod($path."/".$filename, '0644');
 642      $upload['filename'] = $filename;
 643      $upload['path'] = $path;
 644      $upload['type'] = $file['type'];
 645      $upload['size'] = $file['size'];
 646      $upload = $plugins->run_hooks("upload_file_end", $upload);
 647      return $upload;
 648  }
 649  ?>


Generated: Tue Oct 8 19:19:50 2013 Cross-referenced by PHPXref 0.7.1