[ Index ]

PHP Cross Reference of MyBB 1.8.37

title

Body

[close]

/inc/ -> functions_upload.php (source)

   1  <?php
   2  /**
   3   * MyBB 1.8
   4   * Copyright 2014 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://www.mybb.com
   7   * License: http://www.mybb.com/about/license
   8   *
   9   */
  10  
  11  /**
  12   * Get maximum upload filesize limit set in PHP
  13   * @since MyBB 1.8.27
  14   * @return int maximum allowed filesize
  15   */
  16  function get_php_upload_limit()
  17  {    
  18      $maxsize = array(return_bytes(ini_get('upload_max_filesize')), return_bytes(ini_get('post_max_size')));
  19      $maxsize = array_filter($maxsize); // Remove empty values
  20  
  21      if(empty($maxsize))
  22      {
  23          return 0;
  24      }
  25      else
  26      {
  27          return (int)min($maxsize);
  28      }
  29  }
  30  
  31  /**
  32   * Remove an attachment from a specific post
  33   *
  34   * @param int $pid The post ID
  35   * @param string $posthash The posthash if available
  36   * @param int $aid The attachment ID
  37   */
  38  function remove_attachment($pid, $posthash, $aid)
  39  {
  40      global $db, $mybb, $plugins;
  41      $aid = (int)$aid;
  42      $posthash = $db->escape_string($posthash);
  43      if(!empty($posthash))
  44      {
  45          $query = $db->simple_select("attachments", "aid, attachname, thumbnail, visible", "aid='{$aid}' AND posthash='{$posthash}'");
  46          $attachment = $db->fetch_array($query);
  47      }
  48      else
  49      {
  50          $query = $db->simple_select("attachments", "aid, attachname, thumbnail, visible", "aid='{$aid}' AND pid='{$pid}'");
  51          $attachment = $db->fetch_array($query);
  52      }
  53  
  54      $plugins->run_hooks("remove_attachment_do_delete", $attachment);
  55  
  56      if($attachment === false)
  57      {
  58          // no attachment found with the given details
  59          return;
  60      }
  61  
  62      $db->delete_query("attachments", "aid='{$attachment['aid']}'");
  63  
  64      $uploadspath_abs = mk_path_abs($mybb->settings['uploadspath']);
  65  
  66      // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file.
  67      $query = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($attachment['attachname'])."'");
  68      if($db->fetch_field($query, "numreferences") == 0)
  69      {
  70          delete_uploaded_file($uploadspath_abs."/".$attachment['attachname']);
  71          if($attachment['thumbnail'] && $attachment['thumbnail'] !== 'SMALL')
  72          {
  73              delete_uploaded_file($uploadspath_abs."/".$attachment['thumbnail']);
  74          }
  75  
  76          $date_directory = explode('/', $attachment['attachname']);
  77          $query_indir = $db->simple_select("attachments", "COUNT(aid) as indir", "attachname LIKE '".$db->escape_string_like($date_directory[0])."/%'");
  78          if($db->fetch_field($query_indir, 'indir') == 0 && @is_dir($uploadspath_abs."/".$date_directory[0]))
  79          {
  80              delete_upload_directory($uploadspath_abs."/".$date_directory[0]);
  81          }
  82      }
  83  
  84      if($attachment['visible'] == 1 && $pid)
  85      {
  86          $post = get_post($pid);
  87          update_thread_counters($post['tid'], array("attachmentcount" => "-1"));
  88      }
  89  }
  90  
  91  /**
  92   * Remove all of the attachments from a specific post
  93   *
  94   * @param int $pid The post ID
  95   * @param string $posthash The posthash if available
  96   */
  97  function remove_attachments($pid, $posthash="")
  98  {
  99      global $db, $mybb, $plugins;
 100  
 101      if($pid)
 102      {
 103          $post = get_post($pid);
 104      }
 105      $posthash = $db->escape_string($posthash);
 106      if($posthash != "" && !$pid)
 107      {
 108          $query = $db->simple_select("attachments", "*", "posthash='$posthash'");
 109      }
 110      else
 111      {
 112          $query = $db->simple_select("attachments", "*", "pid='$pid'");
 113      }
 114  
 115      $uploadspath_abs = mk_path_abs($mybb->settings['uploadspath']);
 116  
 117      $num_attachments = 0;
 118      while($attachment = $db->fetch_array($query))
 119      {
 120          if($attachment['visible'] == 1)
 121          {
 122              $num_attachments++;
 123          }
 124  
 125          $plugins->run_hooks("remove_attachments_do_delete", $attachment);
 126  
 127          $db->delete_query("attachments", "aid='".$attachment['aid']."'");
 128  
 129          // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file.
 130          $query2 = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($attachment['attachname'])."'");
 131          if($db->fetch_field($query2, "numreferences") == 0)
 132          {
 133              delete_uploaded_file($uploadspath_abs."/".$attachment['attachname']);
 134              if($attachment['thumbnail'])
 135              {
 136                  delete_uploaded_file($uploadspath_abs."/".$attachment['thumbnail']);
 137              }
 138  
 139              $date_directory = explode('/', $attachment['attachname']);
 140              $query_indir = $db->simple_select("attachments", "COUNT(aid) as indir", "attachname LIKE '".$db->escape_string_like($date_directory[0])."/%'");
 141              if($db->fetch_field($query_indir, 'indir') == 0 && @is_dir($uploadspath_abs."/".$date_directory[0]))
 142              {
 143                  delete_upload_directory($uploadspath_abs."/".$date_directory[0]);
 144              }
 145          }
 146      }
 147  
 148      if($post['tid'])
 149      {
 150          update_thread_counters($post['tid'], array("attachmentcount" => "-{$num_attachments}"));
 151      }
 152  }
 153  
 154  /**
 155   * Remove any matching avatars for a specific user ID
 156   *
 157   * @param int $uid The user ID
 158   * @param string $exclude A file name to be excluded from the removal
 159   */
 160  function remove_avatars($uid, $exclude="")
 161  {
 162      global $mybb, $plugins;
 163  
 164      if(defined('IN_ADMINCP'))
 165      {
 166          $avatarpath = '../'.$mybb->settings['avataruploadpath'];
 167      }
 168      else
 169      {
 170          $avatarpath = $mybb->settings['avataruploadpath'];
 171      }
 172  
 173      $dir = opendir($avatarpath);
 174      if($dir)
 175      {
 176          while($file = @readdir($dir))
 177          {
 178              $plugins->run_hooks("remove_avatars_do_delete", $file);
 179  
 180              if(preg_match("#avatar_".$uid."\.#", $file) && is_file($avatarpath."/".$file) && $file != $exclude)
 181              {
 182                  delete_uploaded_file($avatarpath."/".$file);
 183              }
 184          }
 185  
 186          @closedir($dir);
 187      }
 188  }
 189  
 190  /**
 191   * Create the attachment directory index file.
 192   * 
 193   * @param string $path The path to the attachment directory to create the file in.
 194   */
 195  function create_attachment_index($path)
 196  {
 197      $index = @fopen(rtrim($path, '/').'/index.html', 'w');
 198      @fwrite($index, '<html>\n<head>\n<title></title>\n</head>\n<body>\n&nbsp;\n</body>\n</html>');
 199      @fclose($index);
 200  }
 201  
 202  /**
 203   * Upload a new avatar in to the file system
 204   *
 205   * @param array $avatar Incoming FILE array, if we have one - otherwise takes $_FILES['avatarupload']
 206   * @param int $uid User ID this avatar is being uploaded for, if not the current user
 207   * @return array Array of errors if any, otherwise filename of successful.
 208   */
 209  function upload_avatar($avatar=array(), $uid=0)
 210  {
 211      global $db, $mybb, $lang, $plugins, $cache;
 212  
 213      $ret = array();
 214  
 215      if(!$uid)
 216      {
 217          $uid = $mybb->user['uid'];
 218      }
 219  
 220      if(empty($avatar['name']) || empty($avatar['tmp_name']))
 221      {
 222          $avatar = $_FILES['avatarupload'];
 223      }
 224  
 225      if(!is_uploaded_file($avatar['tmp_name']))
 226      {
 227          $ret['error'] = $lang->error_uploadfailed;
 228          return $ret;
 229      }
 230  
 231      // Check we have a valid extension
 232          $ext = get_extension(my_strtolower($avatar['name']));
 233          if(!preg_match("#^(gif|jpg|jpeg|jpe|bmp|png)$#i", $ext))
 234          {
 235              $ret['error'] = $lang->error_avatartype;
 236              return $ret;
 237          }
 238  
 239      if(defined('IN_ADMINCP'))
 240      {
 241          $avatarpath = '../'.$mybb->settings['avataruploadpath'];
 242          $lang->load("messages", true);
 243      }
 244      else
 245      {
 246          $avatarpath = $mybb->settings['avataruploadpath'];
 247      }
 248  
 249      $filename = "avatar_".$uid.".".$ext;
 250      $file = upload_file($avatar, $avatarpath, $filename);
 251      if(!empty($file['error']))
 252      {
 253          delete_uploaded_file($avatarpath."/".$filename);
 254          $ret['error'] = $lang->error_uploadfailed;
 255          return $ret;
 256      }
 257  
 258      // Lets just double check that it exists
 259      if(!file_exists($avatarpath."/".$filename))
 260      {
 261          $ret['error'] = $lang->error_uploadfailed;
 262          delete_uploaded_file($avatarpath."/".$filename);
 263          return $ret;
 264      }
 265  
 266      // Check if this is a valid image or not
 267      $img_dimensions = @getimagesize($avatarpath."/".$filename);
 268      if(!is_array($img_dimensions))
 269      {
 270          delete_uploaded_file($avatarpath."/".$filename);
 271          $ret['error'] = $lang->error_uploadfailed;
 272          return $ret;
 273      }
 274  
 275      // Check avatar dimensions
 276      if($mybb->settings['maxavatardims'] != '')
 277      {
 278          list($maxwidth, $maxheight) = @preg_split('/[|x]/', $mybb->settings['maxavatardims']);
 279          if(($maxwidth && $img_dimensions[0] > $maxwidth) || ($maxheight && $img_dimensions[1] > $maxheight))
 280          {
 281              // Automatic resizing enabled?
 282              if($mybb->settings['avatarresizing'] == "auto" || ($mybb->settings['avatarresizing'] == "user" && $mybb->input['auto_resize'] == 1))
 283              {
 284                  require_once  MYBB_ROOT."inc/functions_image.php";
 285                  $thumbnail = generate_thumbnail($avatarpath."/".$filename, $avatarpath, $filename, $maxheight, $maxwidth);
 286                  if(empty($thumbnail['filename']))
 287                  {
 288                      $ret['error'] = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight);
 289                      $ret['error'] .= "<br /><br />".$lang->error_avatarresizefailed;
 290                      delete_uploaded_file($avatarpath."/".$filename);
 291                      return $ret;
 292                  }
 293                  else
 294                  {
 295                      // Copy scaled image to CDN
 296                      copy_file_to_cdn($avatarpath . '/' . $thumbnail['filename']);
 297                      // Reset filesize
 298                      $avatar['size'] = filesize($avatarpath."/".$filename);
 299                      // Reset dimensions
 300                      $img_dimensions = @getimagesize($avatarpath."/".$filename);
 301                  }
 302              }
 303              else
 304              {
 305                  $ret['error'] = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight);
 306                  if($mybb->settings['avatarresizing'] == "user")
 307                  {
 308                      $ret['error'] .= "<br /><br />".$lang->error_avataruserresize;
 309                  }
 310                  delete_uploaded_file($avatarpath."/".$filename);
 311                  return $ret;
 312              }
 313          }
 314      }
 315  
 316      // Check a list of known MIME types to establish what kind of avatar we're uploading
 317      $attachtypes = (array)$cache->read('attachtypes');
 318  
 319      $allowed_mime_types = array();
 320      foreach($attachtypes as $attachtype)
 321      {
 322          if(defined('IN_ADMINCP') || is_member($attachtype['groups']) && $attachtype['avatarfile'])
 323          {
 324              $allowed_mime_types[$attachtype['mimetype']] = $attachtype['maxsize'];
 325          }
 326      }
 327  
 328      $avatar['type'] = my_strtolower($avatar['type']);
 329  
 330      switch($avatar['type'])
 331      {
 332          case "image/gif":
 333              $img_type =  1;
 334              break;
 335          case "image/jpeg":
 336          case "image/x-jpg":
 337          case "image/x-jpeg":
 338          case "image/pjpeg":
 339          case "image/jpg":
 340              $img_type = 2;
 341              break;
 342          case "image/png":
 343          case "image/x-png":
 344              $img_type = 3;
 345              break;
 346          case "image/bmp":
 347          case "image/x-bmp":
 348          case "image/x-windows-bmp":
 349              $img_type = 6;
 350              break;
 351          default:
 352              $img_type = 0;
 353      }
 354  
 355      // Check if the uploaded file type matches the correct image type (returned by getimagesize)
 356      if(empty($allowed_mime_types[$avatar['type']]) || $img_dimensions[2] != $img_type || $img_type == 0)
 357      {
 358          $ret['error'] = $lang->error_uploadfailed;
 359          delete_uploaded_file($avatarpath."/".$filename);
 360          return $ret;
 361      }
 362  
 363      // Next check the file size
 364      if(($mybb->settings['avatarsize'] > 0 && $avatar['size'] > ($mybb->settings['avatarsize']*1024)) || $avatar['size'] > ($allowed_mime_types[$avatar['type']]*1024))
 365      {
 366          delete_uploaded_file($avatarpath."/".$filename);
 367          $ret['error'] = $lang->error_uploadsize;
 368          return $ret;
 369      }
 370  
 371      // Everything is okay so lets delete old avatars for this user
 372      remove_avatars($uid, $filename);
 373  
 374      $ret = array(
 375          "avatar" => $mybb->settings['avataruploadpath']."/".$filename,
 376          "width" => (int)$img_dimensions[0],
 377          "height" => (int)$img_dimensions[1]
 378      );
 379      $ret = $plugins->run_hooks("upload_avatar_end", $ret);
 380      return $ret;
 381  }
 382  
 383  /**
 384   * Upload an attachment in to the file system
 385   *
 386   * @param array $attachment Attachment data (as fed by PHPs $_FILE)
 387   * @param boolean $update_attachment Whether or not we are updating a current attachment or inserting a new one
 388   * @return array Array of attachment data if successful, otherwise array of error data
 389   */
 390  function upload_attachment($attachment, $update_attachment=false)
 391  {
 392      global $mybb, $db, $theme, $templates, $posthash, $pid, $tid, $forum, $mybb, $lang, $plugins, $cache;
 393  
 394      $posthash = $db->escape_string($mybb->get_input('posthash'));
 395      $pid = (int)$pid;
 396  
 397      if(!is_uploaded_file($attachment['tmp_name']) || empty($attachment['tmp_name']))
 398      {
 399          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_php4;
 400          return $ret;
 401      }
 402  
 403      $attachtypes = (array)$cache->read('attachtypes');
 404      $attachment = $plugins->run_hooks("upload_attachment_start", $attachment);
 405  
 406      $allowed_mime_types = array();
 407      foreach($attachtypes as $ext => $attachtype)
 408      {
 409          if(!is_member($attachtype['groups']) || ($attachtype['forums'] != -1 && strpos(','.$attachtype['forums'].',', ','.$forum['fid'].',') === false))
 410          {
 411              unset($attachtypes[$ext]);
 412          }
 413      }
 414  
 415      $ext = get_extension($attachment['name']);
 416      // Check if we have a valid extension
 417      if(!isset($attachtypes[$ext]))
 418      {
 419          $ret['error'] = $lang->error_attachtype;
 420          return $ret;
 421      }
 422      else
 423      {
 424          $attachtype = $attachtypes[$ext];
 425      }
 426  
 427      // check the length of the filename
 428      $maxFileNameLength = 255;
 429      if(my_strlen($attachment['name']) > $maxFileNameLength)
 430      {
 431          $ret['error'] = $lang->sprintf($lang->error_attach_filename_length, htmlspecialchars_uni($attachment['name']), $maxFileNameLength);
 432          return $ret;
 433      }
 434  
 435      // Check the size
 436      if($attachment['size'] > $attachtype['maxsize']*1024 && $attachtype['maxsize'] != "")
 437      {
 438          $ret['error'] = $lang->sprintf($lang->error_attachsize, htmlspecialchars_uni($attachment['name']), $attachtype['maxsize']);
 439          return $ret;
 440      }
 441  
 442      // Double check attachment space usage
 443      if($mybb->usergroup['attachquota'] > 0)
 444      {
 445          $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='".$mybb->user['uid']."'");
 446          $usage = $db->fetch_array($query);
 447          $usage = $usage['ausage']+$attachment['size'];
 448          if($usage > ($mybb->usergroup['attachquota']*1024))
 449          {
 450              $friendlyquota = get_friendly_size($mybb->usergroup['attachquota']*1024);
 451              $ret['error'] = $lang->sprintf($lang->error_reachedattachquota, $friendlyquota);
 452              return $ret;
 453          }
 454      }
 455  
 456      // Gather forum permissions
 457      $forumpermissions = forum_permissions($forum['fid']);
 458  
 459      // Check if an attachment with this name is already in the post
 460      if($pid != 0)
 461      {
 462          $uploaded_query = "pid='{$pid}'";
 463      }
 464      else
 465      {
 466          $uploaded_query = "posthash='{$posthash}'";
 467      }
 468      $query = $db->simple_select("attachments", "*", "filename='".$db->escape_string($attachment['name'])."' AND ".$uploaded_query);
 469      $prevattach = $db->fetch_array($query);
 470      if($prevattach && $update_attachment == false)
 471      {
 472          if(!$mybb->usergroup['caneditattachments'] && !$forumpermissions['caneditattachments'])
 473          {
 474              $ret['error'] = $lang->error_alreadyuploaded_perm;
 475              return $ret;
 476          }
 477  
 478          $ret['error'] = $lang->sprintf($lang->error_alreadyuploaded, htmlspecialchars_uni($attachment['name']));
 479          return $ret;
 480      }
 481  
 482      // Check to see how many attachments exist for this post already
 483      if($mybb->settings['maxattachments'] > 0 && $update_attachment == false)
 484      {
 485          $query = $db->simple_select("attachments", "COUNT(aid) AS numattachs", $uploaded_query);
 486          $attachcount = $db->fetch_field($query, "numattachs");
 487          if($attachcount >= $mybb->settings['maxattachments'])
 488          {
 489              $ret['error'] = $lang->sprintf($lang->error_maxattachpost, $mybb->settings['maxattachments']);
 490              return $ret;
 491          }
 492      }
 493  
 494      $uploadspath_abs = mk_path_abs($mybb->settings['uploadspath']);
 495      $month_dir = '';
 496      if($mybb->safemode == false)
 497      {
 498          // Check if the attachment directory (YYYYMM) exists, if not, create it
 499          $month_dir = gmdate("Ym");
 500          if(!@is_dir($uploadspath_abs."/".$month_dir))
 501          {
 502              @mkdir($uploadspath_abs."/".$month_dir);
 503              // Still doesn't exist - oh well, throw it in the main directory
 504              if(!@is_dir($uploadspath_abs."/".$month_dir))
 505              {
 506                  $month_dir = '';
 507              }
 508              else
 509              {
 510                  create_attachment_index($uploadspath_abs."/".$month_dir);
 511              }
 512          }
 513      }
 514  
 515      // All seems to be good, lets move the attachment!
 516      $filename = "post_".$mybb->user['uid']."_".TIME_NOW."_".md5(random_str()).".attach";
 517  
 518      $file = upload_file($attachment, $uploadspath_abs."/".$month_dir, $filename);
 519  
 520      // Failed to create the attachment in the monthly directory, just throw it in the main directory
 521      if(!empty($file['error']) && $month_dir)
 522      {
 523          $file = upload_file($attachment, $uploadspath_abs.'/', $filename);
 524      }
 525      elseif($month_dir)
 526      {
 527          $filename = $month_dir."/".$filename;
 528      }
 529  
 530      if(!empty($file['error']))
 531      {
 532          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail;
 533          switch($file['error'])
 534          {
 535              case 1:
 536                  $ret['error'] .= $lang->error_uploadfailed_nothingtomove;
 537                  break;
 538              case 2:
 539                  $ret['error'] .= $lang->error_uploadfailed_movefailed;
 540                  break;
 541          }
 542          return $ret;
 543      }
 544  
 545      // Lets just double check that it exists
 546      if(!file_exists($uploadspath_abs."/".$filename))
 547      {
 548          $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail.$lang->error_uploadfailed_lost;
 549          return $ret;
 550      }
 551  
 552      // Generate the array for the insert_query
 553      $attacharray = array(
 554          "pid" => $pid,
 555          "posthash" => $posthash,
 556          "uid" => $mybb->user['uid'],
 557          "filename" => $db->escape_string($file['original_filename']),
 558          "filetype" => $db->escape_string($file['type']),
 559          "filesize" => (int)$file['size'],
 560          "attachname" => $filename,
 561          "downloads" => 0,
 562          "dateuploaded" => TIME_NOW
 563      );
 564  
 565      // If we're uploading an image, check the MIME type compared to the image type and attempt to generate a thumbnail
 566      if($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe")
 567      {
 568          // Check a list of known MIME types to establish what kind of image we're uploading
 569          switch(my_strtolower($file['type']))
 570          {
 571              case "image/gif":
 572                  $img_type =  1;
 573                  break;
 574              case "image/jpeg":
 575              case "image/x-jpg":
 576              case "image/x-jpeg":
 577              case "image/pjpeg":
 578              case "image/jpg":
 579                  $img_type = 2;
 580                  break;
 581              case "image/png":
 582              case "image/x-png":
 583                  $img_type = 3;
 584                  break;
 585              default:
 586                  $img_type = 0;
 587          }
 588  
 589          $supported_mimes = array();
 590          foreach($attachtypes as $attachtype)
 591          {
 592              if(!empty($attachtype['mimetype']))
 593              {
 594                  $supported_mimes[] = $attachtype['mimetype'];
 595              }
 596          }
 597  
 598          // Check if the uploaded file type matches the correct image type (returned by getimagesize)
 599          $img_dimensions = @getimagesize($uploadspath_abs."/".$filename);
 600  
 601          $mime = "";
 602          $file_path = $uploadspath_abs."/".$filename;
 603          if(function_exists("finfo_open"))
 604          {
 605              $file_info = finfo_open(FILEINFO_MIME);
 606              list($mime, ) = explode(';', finfo_file($file_info, $file_path), 1);
 607              finfo_close($file_info);
 608          }
 609          else if(function_exists("mime_content_type"))
 610          {
 611              $mime = mime_content_type($file_path);
 612          }
 613  
 614          if(!is_array($img_dimensions) || ($img_dimensions[2] != $img_type && !in_array($mime, $supported_mimes)))
 615          {
 616              delete_uploaded_file($uploadspath_abs."/".$filename);
 617              $ret['error'] = $lang->error_uploadfailed;
 618              return $ret;
 619          }
 620          require_once  MYBB_ROOT."inc/functions_image.php";
 621          $thumbname = str_replace(".attach", "_thumb.$ext", $filename);
 622  
 623          $attacharray = $plugins->run_hooks("upload_attachment_thumb_start", $attacharray);
 624  
 625          $thumbnail = generate_thumbnail($uploadspath_abs."/".$filename, $uploadspath_abs, $thumbname, $mybb->settings['attachthumbh'], $mybb->settings['attachthumbw']);
 626  
 627          if(!empty($thumbnail['filename']))
 628          {
 629              $attacharray['thumbnail'] = $thumbnail['filename'];
 630          }
 631          elseif($thumbnail['code'] == 4)
 632          {
 633              $attacharray['thumbnail'] = "SMALL";
 634          }
 635      }
 636      if($forumpermissions['modattachments'] == 1 && !is_moderator($forum['fid'], "canapproveunapproveattachs"))
 637      {
 638          $attacharray['visible'] = 0;
 639      }
 640      else
 641      {
 642          $attacharray['visible'] = 1;
 643      }
 644  
 645      $attacharray = $plugins->run_hooks("upload_attachment_do_insert", $attacharray);
 646  
 647      if($prevattach && $update_attachment == true)
 648      {
 649          unset($attacharray['downloads']); // Keep our download count if we're updating an attachment
 650          $db->update_query("attachments", $attacharray, "aid='".$db->escape_string($prevattach['aid'])."'");
 651  
 652          // Remove old attachment file
 653          // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file.
 654          $query = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($prevattach['attachname'])."'");
 655          if($db->fetch_field($query, "numreferences") == 0)
 656          {
 657              delete_uploaded_file($uploadspath_abs."/".$prevattach['attachname']);
 658              if($prevattach['thumbnail'])
 659              {
 660                  delete_uploaded_file($uploadspath_abs."/".$prevattach['thumbnail']);
 661              }
 662  
 663              $date_directory = explode('/', $prevattach['attachname']);
 664              $query_indir = $db->simple_select("attachments", "COUNT(aid) as indir", "attachname LIKE '".$db->escape_string_like($date_directory[0])."/%'");
 665              if($db->fetch_field($query_indir, 'indir') == 0 && @is_dir($uploadspath_abs."/".$date_directory[0]))
 666              {
 667                  delete_upload_directory($uploadspath_abs."/".$date_directory[0]);
 668              }
 669          }
 670  
 671          $aid = $prevattach['aid'];
 672      }
 673      else
 674      {
 675          $aid = $db->insert_query("attachments", $attacharray);
 676          if($pid)
 677          {
 678              update_thread_counters($tid, array("attachmentcount" => "+1"));
 679          }
 680      }
 681      $ret['aid'] = $aid;
 682      return $ret;
 683  }
 684  
 685  /**
 686   * Check whether the input $FILE variable indicates a PHP file upload error,
 687   * and if so, return an appropriate user-friendly error message.
 688   *
 689   * @param array $FILE File data (as fed by PHP's $_FILE).
 690   *
 691   * @return string Error message or empty if no error detected.
 692   */
 693  function check_parse_php_upload_err($FILE)
 694  {
 695      global $lang;
 696  
 697      $err = '';
 698  
 699      if(isset($FILE['error']) && $FILE['error'] != 0 && ($FILE['error'] != UPLOAD_ERR_NO_FILE || $FILE['name']))
 700      {
 701          $err = $lang->error_uploadfailed.$lang->error_uploadfailed_detail;
 702          switch($FILE['error'])
 703          {
 704              case 1: // UPLOAD_ERR_INI_SIZE
 705                  $err .= $lang->error_uploadfailed_php1;
 706                  break;
 707              case 2: // UPLOAD_ERR_FORM_SIZE
 708                  $err .= $lang->error_uploadfailed_php2;
 709                  break;
 710              case 3: // UPLOAD_ERR_PARTIAL
 711                  $err .= $lang->error_uploadfailed_php3;
 712                  break;
 713              case 4: // UPLOAD_ERR_NO_FILE
 714                  $err .= $lang->error_uploadfailed_php4;
 715                  break;
 716              case 6: // UPLOAD_ERR_NO_TMP_DIR
 717                  $err .= $lang->error_uploadfailed_php6;
 718                  break;
 719              case 7: // UPLOAD_ERR_CANT_WRITE
 720                  $err .= $lang->error_uploadfailed_php7;
 721                  break;
 722              default:
 723                  $err .= $lang->sprintf($lang->error_uploadfailed_phpx, $FILE['error']);
 724                  break;
 725          }
 726      }
 727  
 728      return $err;
 729  }
 730  
 731  /**
 732   * Process adding attachment(s) when the "Add Attachment" button is pressed.
 733   *
 734   * @param int $pid The ID of the post.
 735   * @param array $forumpermission The permissions for the forum.
 736   * @param string $attachwhere Search string "pid='$pid'" or "posthash='".$db->escape_string($mybb->get_input('posthash'))."'"
 737   * @param string $action Where called from: "newthread", "newreply", or "editpost"
 738   *
 739   * @return array Array of errors if any, empty array otherwise
 740   */
 741  function add_attachments($pid, $forumpermissions, $attachwhere, $action=false)
 742  {
 743      global $db, $mybb, $editdraftpid, $lang;
 744  
 745      $ret = array();
 746  
 747      if($forumpermissions['canpostattachments'])
 748      {
 749          $attachments = array();
 750          $fields = array ('name', 'type', 'tmp_name', 'error', 'size');
 751          $aid = array();
 752  
 753          $total = isset($_FILES['attachments']['name']) ? count($_FILES['attachments']['name']) : 0;
 754          $filenames = "";
 755          $delim = "";
 756          for($i=0; $i<$total; ++$i)
 757          {
 758              foreach($fields as $field)
 759              {
 760                  $attachments[$i][$field] = $_FILES['attachments'][$field][$i];
 761              }
 762  
 763              $FILE = $attachments[$i];
 764              if(!empty($FILE['name']) && !empty($FILE['type']) && $FILE['size'] > 0)
 765              {
 766                  $filenames .= $delim . "'" . $db->escape_string($FILE['name']) . "'";
 767                  $delim = ",";
 768              }
 769          }
 770  
 771          if ($filenames != '')
 772          {
 773              $query = $db->simple_select("attachments", "filename", "{$attachwhere} AND filename IN (".$filenames.")");
 774  
 775              while ($row = $db->fetch_array($query))
 776              {
 777                  $aid[$row['filename']] = true;
 778              }
 779          }
 780  
 781          foreach($attachments as $FILE)
 782          {
 783              if($err = check_parse_php_upload_err($FILE))
 784              {
 785                  $ret['errors'][] = $err;
 786                  $mybb->input['action'] = $action;
 787              }
 788              else if(!empty($FILE['name']) && !empty($FILE['type']))
 789              {
 790                  if($FILE['size'] > 0)
 791                  {
 792                      $filename = $db->escape_string($FILE['name']);
 793                      $exists = !empty($aid[$filename]);
 794  
 795                      $update_attachment = false;
 796                      if($action == "editpost")
 797                      {
 798                          if($exists && $mybb->get_input('updateattachment') && ($mybb->usergroup['caneditattachments'] || $forumpermissions['caneditattachments']))
 799                          {
 800                              $update_attachment = true;
 801                          }
 802                      }
 803                      else
 804                      {
 805                          if($exists && $mybb->get_input('updateattachment'))
 806                          {
 807                              $update_attachment = true;
 808                          }
 809                      }
 810                      
 811                      if(!$exists && $mybb->get_input('updateattachment') && $mybb->get_input('updateconfirmed', MyBB::INPUT_INT) != 1)
 812                      {
 813                          $ret['errors'][] = $lang->sprintf($lang->error_updatefailed, $filename);
 814                      }
 815                      else
 816                      {
 817                          $attachedfile = upload_attachment($FILE, $update_attachment);
 818  
 819                          if(!empty($attachedfile['error']))
 820                          {
 821                              $ret['errors'][] = $attachedfile['error'];
 822                              $mybb->input['action'] = $action;
 823                          }
 824                          else if(isset($attachedfile['aid']) && $mybb->get_input('ajax', MyBB::INPUT_INT) == 1)
 825                          {
 826                              $ret['success'][] = array($attachedfile['aid'], get_attachment_icon(get_extension($filename)), htmlspecialchars_uni($filename), get_friendly_size($FILE['size']));
 827                          }
 828                      }
 829                  }
 830                  else
 831                  {
 832                      $ret['errors'][] = $lang->sprintf($lang->error_uploadempty, htmlspecialchars_uni($FILE['name']));
 833                      $mybb->input['action'] = $action;
 834                  }
 835              }
 836          }
 837      }
 838  
 839      return $ret;
 840  }
 841  
 842  /**
 843   * Delete an uploaded file both from the relative path and the CDN path if a CDN is in use.
 844   *
 845   * @param string $path The relative path to the uploaded file.
 846   *
 847   * @return bool Whether the file was deleted successfully.
 848   */
 849  function delete_uploaded_file($path = '')
 850  {
 851      global $mybb, $plugins;
 852  
 853      $deleted = false;
 854  
 855      $deleted = @unlink($path);
 856  
 857      $cdn_base_path = rtrim($mybb->settings['cdnpath'], '/');
 858      $path = ltrim($path, '/');
 859      $cdn_path = realpath($cdn_base_path . '/' . $path);
 860  
 861      if(!empty($mybb->settings['usecdn']) && !empty($cdn_base_path))
 862      {
 863          $deleted = $deleted && @unlink($cdn_path);
 864      }
 865  
 866      $hook_params = array(
 867          'path' => &$path,
 868          'deleted' => &$deleted,
 869      );
 870  
 871      $plugins->run_hooks('delete_uploaded_file', $hook_params);
 872  
 873      return $deleted;
 874  }
 875  
 876  /**
 877   * Delete an upload directory on both the local filesystem and the CDN filesystem.
 878   *
 879   * @param string $path The directory to delete.
 880   *
 881   * @return bool Whether the directory was deleted.
 882   */
 883  function delete_upload_directory($path = '')
 884  {
 885      global $mybb, $plugins;
 886  
 887      $deleted = false;
 888  
 889      $deleted_index = @unlink(rtrim($path, '/').'/index.html');
 890  
 891      $deleted = @rmdir($path);
 892  
 893      $cdn_base_path = rtrim($mybb->settings['cdnpath'], '/');
 894      $path = ltrim($path, '/');
 895      $cdn_path = rtrim(realpath($cdn_base_path . '/' . $path), '/');
 896  
 897      if(!empty($mybb->settings['usecdn']) && !empty($cdn_base_path))
 898      {
 899          $deleted = $deleted && @rmdir($cdn_path);
 900      }
 901  
 902      $hook_params = array(
 903          'path' => &$path,
 904          'deleted' => &$deleted,
 905      );
 906  
 907      $plugins->run_hooks('delete_upload_directory', $hook_params);
 908  
 909      // If not successfully deleted then reinstante the index file
 910      if(!$deleted && $deleted_index)
 911      {
 912          create_attachment_index($path);
 913      }
 914  
 915      return $deleted;
 916  }
 917  
 918  /**
 919   * Actually move a file to the uploads directory
 920   *
 921   * @param array $file The PHP $_FILE array for the file
 922   * @param string $path The path to save the file in
 923   * @param string $filename The filename for the file (if blank, current is used)
 924   * @return array The uploaded file
 925   */
 926  function upload_file($file, $path, $filename="")
 927  {
 928      global $plugins, $mybb;
 929  
 930      $upload = array();
 931  
 932      if(empty($file['name']) || $file['name'] == "none" || $file['size'] < 1)
 933      {
 934          $upload['error'] = 1;
 935          return $upload;
 936      }
 937  
 938      if(!$filename)
 939      {
 940          $filename = $file['name'];
 941      }
 942  
 943      $upload['original_filename'] = preg_replace("#/$#", "", $file['name']); // Make the filename safe
 944      $filename = preg_replace("#/$#", "", $filename); // Make the filename safe
 945      $moved = @move_uploaded_file($file['tmp_name'], $path."/".$filename);
 946  
 947      $cdn_path = '';
 948  
 949      $moved_cdn = copy_file_to_cdn($path."/".$filename, $cdn_path);
 950  
 951      if(!$moved)
 952      {
 953          $upload['error'] = 2;
 954          return $upload;
 955      }
 956      @my_chmod($path."/".$filename, '0644');
 957      $upload['filename'] = $filename;
 958      $upload['path'] = $path;
 959      $upload['type'] = $file['type'];
 960      $upload['size'] = $file['size'];
 961      $upload = $plugins->run_hooks("upload_file_end", $upload);
 962  
 963      if($moved_cdn)
 964      {
 965          $upload['cdn_path'] = $cdn_path;
 966      }
 967  
 968      return $upload;
 969  }


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref