[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/includes/ -> functions_download.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  /**
  15  * @ignore
  16  */
  17  if (!defined('IN_PHPBB'))
  18  {
  19      exit;
  20  }
  21  
  22  /**
  23  * A simplified function to deliver avatars
  24  * The argument needs to be checked before calling this function.
  25  */
  26  function send_avatar_to_browser($file, $browser)
  27  {
  28      global $config, $phpbb_root_path;
  29  
  30      $prefix = $config['avatar_salt'] . '_';
  31      $image_dir = $config['avatar_path'];
  32  
  33      // Adjust image_dir path (no trailing slash)
  34      if (substr($image_dir, -1, 1) == '/' || substr($image_dir, -1, 1) == '\\')
  35      {
  36          $image_dir = substr($image_dir, 0, -1) . '/';
  37      }
  38      $image_dir = str_replace(array('../', '..\\', './', '.\\'), '', $image_dir);
  39  
  40      if ($image_dir && ($image_dir[0] == '/' || $image_dir[0] == '\\'))
  41      {
  42          $image_dir = '';
  43      }
  44      $file_path = $phpbb_root_path . $image_dir . '/' . $prefix . $file;
  45  
  46      if ((@file_exists($file_path) && @is_readable($file_path)) && !headers_sent())
  47      {
  48          header('Cache-Control: public');
  49  
  50          $image_data = @getimagesize($file_path);
  51          header('Content-Type: ' . image_type_to_mime_type($image_data[2]));
  52  
  53          if ((strpos(strtolower($browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7))
  54          {
  55              header('Content-Disposition: attachment; ' . header_filename($file));
  56  
  57              if (strpos(strtolower($browser), 'msie 6.0') !== false)
  58              {
  59                  header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
  60              }
  61              else
  62              {
  63                  header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
  64              }
  65          }
  66          else
  67          {
  68              header('Content-Disposition: inline; ' . header_filename($file));
  69              header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
  70          }
  71  
  72          $size = @filesize($file_path);
  73          if ($size)
  74          {
  75              header("Content-Length: $size");
  76          }
  77  
  78          if (@readfile($file_path) == false)
  79          {
  80              $fp = @fopen($file_path, 'rb');
  81  
  82              if ($fp !== false)
  83              {
  84                  while (!feof($fp))
  85                  {
  86                      echo fread($fp, 8192);
  87                  }
  88                  fclose($fp);
  89              }
  90          }
  91  
  92          flush();
  93      }
  94      else
  95      {
  96          header('HTTP/1.0 404 Not Found');
  97      }
  98  }
  99  
 100  /**
 101  * Wraps an url into a simple html page. Used to display attachments in IE.
 102  * this is a workaround for now; might be moved to template system later
 103  * direct any complaints to 1 Microsoft Way, Redmond
 104  */
 105  function wrap_img_in_html($src, $title)
 106  {
 107      echo '<!DOCTYPE html>';
 108      echo '<html>';
 109      echo '<head>';
 110      echo '<meta charset="utf-8">';
 111      echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
 112      echo '<title>' . $title . '</title>';
 113      echo '</head>';
 114      echo '<body>';
 115      echo '<div>';
 116      echo '<img src="' . $src . '" alt="' . $title . '" />';
 117      echo '</div>';
 118      echo '</body>';
 119      echo '</html>';
 120  }
 121  
 122  /**
 123  * Send file to browser
 124  */
 125  function send_file_to_browser($attachment, $upload_dir, $category)
 126  {
 127      global $user, $db, $phpbb_dispatcher, $phpbb_root_path, $request;
 128  
 129      $filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename'];
 130  
 131      if (!@file_exists($filename))
 132      {
 133          send_status_line(404, 'Not Found');
 134          trigger_error('ERROR_NO_ATTACHMENT');
 135      }
 136  
 137      // Correct the mime type - we force application/octetstream for all files, except images
 138      // Please do not change this, it is a security precaution
 139      if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0)
 140      {
 141          $attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream';
 142      }
 143  
 144      if (@ob_get_length())
 145      {
 146          @ob_end_clean();
 147      }
 148  
 149      // Now send the File Contents to the Browser
 150      $size = @filesize($filename);
 151  
 152      /**
 153      * Event to alter attachment before it is sent to browser.
 154      *
 155      * @event core.send_file_to_browser_before
 156      * @var    array    attachment    Attachment data
 157      * @var    string    upload_dir    Relative path of upload directory
 158      * @var    int        category    Attachment category
 159      * @var    string    filename    Path to file, including filename
 160      * @var    int        size        File size
 161      * @since 3.1.11-RC1
 162      */
 163      $vars = array(
 164          'attachment',
 165          'upload_dir',
 166          'category',
 167          'filename',
 168          'size',
 169      );
 170      extract($phpbb_dispatcher->trigger_event('core.send_file_to_browser_before', compact($vars)));
 171  
 172      // To correctly display further errors we need to make sure we are using the correct headers for both (unsetting content-length may not work)
 173  
 174      // Check if headers already sent or not able to get the file contents.
 175      if (headers_sent() || !@file_exists($filename) || !@is_readable($filename))
 176      {
 177          // PHP track_errors setting On?
 178          if (!empty($php_errormsg))
 179          {
 180              send_status_line(500, 'Internal Server Error');
 181              trigger_error($user->lang['UNABLE_TO_DELIVER_FILE'] . '<br />' . sprintf($user->lang['TRACKED_PHP_ERROR'], $php_errormsg));
 182          }
 183  
 184          send_status_line(500, 'Internal Server Error');
 185          trigger_error('UNABLE_TO_DELIVER_FILE');
 186      }
 187  
 188      // Make sure the database record for the filesize is correct
 189      if ($size > 0 && $size != $attachment['filesize'] && strpos($attachment['physical_filename'], 'thumb_') === false)
 190      {
 191          // Update database record
 192          $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
 193              SET filesize = ' . (int) $size . '
 194              WHERE attach_id = ' . (int) $attachment['attach_id'];
 195          $db->sql_query($sql);
 196      }
 197  
 198      // Now the tricky part... let's dance
 199      header('Cache-Control: private');
 200  
 201      // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
 202      header('Content-Type: ' . $attachment['mimetype']);
 203  
 204      if (phpbb_is_greater_ie_version($user->browser, 7))
 205      {
 206          header('X-Content-Type-Options: nosniff');
 207      }
 208  
 209      if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
 210      {
 211          header('Content-Disposition: attachment; ' . header_filename(html_entity_decode($attachment['real_filename'], ENT_COMPAT)));
 212          if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
 213          {
 214              header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
 215          }
 216      }
 217      else
 218      {
 219          header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(html_entity_decode($attachment['real_filename'], ENT_COMPAT)));
 220          if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
 221          {
 222              header('X-Download-Options: noopen');
 223          }
 224      }
 225  
 226      // Close the db connection before sending the file etc.
 227      file_gc(false);
 228  
 229      if (!set_modified_headers($attachment['filetime'], $user->browser))
 230      {
 231          // We make sure those have to be enabled manually by defining a constant
 232          // because of the potential disclosure of full attachment path
 233          // in case support for features is absent in the webserver software.
 234          if (defined('PHPBB_ENABLE_X_ACCEL_REDIRECT') && PHPBB_ENABLE_X_ACCEL_REDIRECT)
 235          {
 236              // X-Accel-Redirect - http://wiki.nginx.org/XSendfile
 237              header('X-Accel-Redirect: ' . $user->page['root_script_path'] . $upload_dir . '/' . $attachment['physical_filename']);
 238              exit;
 239          }
 240          else if (defined('PHPBB_ENABLE_X_SENDFILE') && PHPBB_ENABLE_X_SENDFILE && !phpbb_http_byte_range($size))
 241          {
 242              // X-Sendfile - http://blog.lighttpd.net/articles/2006/07/02/x-sendfile
 243              // Lighttpd's X-Sendfile does not support range requests as of 1.4.26
 244              // and always requires an absolute path.
 245              header('X-Sendfile: ' . __DIR__ . "/../$upload_dir/{$attachment['physical_filename']}");
 246              exit;
 247          }
 248  
 249          if ($size)
 250          {
 251              header("Content-Length: $size");
 252          }
 253  
 254          // Try to deliver in chunks
 255          @set_time_limit(0);
 256  
 257          $fp = @fopen($filename, 'rb');
 258  
 259          if ($fp !== false)
 260          {
 261              // Deliver file partially if requested
 262              if ($range = phpbb_http_byte_range($size))
 263              {
 264                  fseek($fp, $range['byte_pos_start']);
 265  
 266                  send_status_line(206, 'Partial Content');
 267                  header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
 268                  header('Content-Length: ' . $range['bytes_requested']);
 269  
 270                  // First read chunks
 271                  while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192)
 272                  {
 273                      echo fread($fp, 8192);
 274                  }
 275                  // Then, read the remainder
 276                  echo fread($fp, $range['bytes_requested'] % 8192);
 277              }
 278              else
 279              {
 280                  while (!feof($fp))
 281                  {
 282                      echo fread($fp, 8192);
 283                  }
 284              }
 285              fclose($fp);
 286          }
 287          else
 288          {
 289              @readfile($filename);
 290          }
 291  
 292          flush();
 293      }
 294  
 295      exit;
 296  }
 297  
 298  /**
 299  * Get a browser friendly UTF-8 encoded filename
 300  */
 301  function header_filename($file)
 302  {
 303      global $request;
 304  
 305      $user_agent = $request->header('User-Agent');
 306  
 307      // There be dragons here.
 308      // Not many follows the RFC...
 309      if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Konqueror') !== false)
 310      {
 311          return "filename=" . rawurlencode($file);
 312      }
 313  
 314      // follow the RFC for extended filename for the rest
 315      return "filename*=UTF-8''" . rawurlencode($file);
 316  }
 317  
 318  /**
 319  * Check if downloading item is allowed
 320  */
 321  function download_allowed()
 322  {
 323      global $config, $user, $db, $request;
 324  
 325      if (!$config['secure_downloads'])
 326      {
 327          return true;
 328      }
 329  
 330      $url = html_entity_decode($request->header('Referer'), ENT_COMPAT);
 331  
 332      if (!$url)
 333      {
 334          return ($config['secure_allow_empty_referer']) ? true : false;
 335      }
 336  
 337      // Split URL into domain and script part
 338      $url = @parse_url($url);
 339  
 340      if ($url === false)
 341      {
 342          return ($config['secure_allow_empty_referer']) ? true : false;
 343      }
 344  
 345      $hostname = $url['host'];
 346      unset($url);
 347  
 348      $allowed = ($config['secure_allow_deny']) ? false : true;
 349      $iplist = array();
 350  
 351      if (($ip_ary = @gethostbynamel($hostname)) !== false)
 352      {
 353          foreach ($ip_ary as $ip)
 354          {
 355              if ($ip)
 356              {
 357                  $iplist[] = $ip;
 358              }
 359          }
 360      }
 361  
 362      // Check for own server...
 363      $server_name = $user->host;
 364  
 365      // Forcing server vars is the only way to specify/override the protocol
 366      if ($config['force_server_vars'] || !$server_name)
 367      {
 368          $server_name = $config['server_name'];
 369      }
 370  
 371      if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
 372      {
 373          $allowed = true;
 374      }
 375  
 376      // Get IP's and Hostnames
 377      if (!$allowed)
 378      {
 379          $sql = 'SELECT site_ip, site_hostname, ip_exclude
 380              FROM ' . SITELIST_TABLE;
 381          $result = $db->sql_query($sql);
 382  
 383          while ($row = $db->sql_fetchrow($result))
 384          {
 385              $site_ip = trim($row['site_ip']);
 386              $site_hostname = trim($row['site_hostname']);
 387  
 388              if ($site_ip)
 389              {
 390                  foreach ($iplist as $ip)
 391                  {
 392                      if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
 393                      {
 394                          if ($row['ip_exclude'])
 395                          {
 396                              $allowed = ($config['secure_allow_deny']) ? false : true;
 397                              break 2;
 398                          }
 399                          else
 400                          {
 401                              $allowed = ($config['secure_allow_deny']) ? true : false;
 402                          }
 403                      }
 404                  }
 405              }
 406  
 407              if ($site_hostname)
 408              {
 409                  if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
 410                  {
 411                      if ($row['ip_exclude'])
 412                      {
 413                          $allowed = ($config['secure_allow_deny']) ? false : true;
 414                          break;
 415                      }
 416                      else
 417                      {
 418                          $allowed = ($config['secure_allow_deny']) ? true : false;
 419                      }
 420                  }
 421              }
 422          }
 423          $db->sql_freeresult($result);
 424      }
 425  
 426      return $allowed;
 427  }
 428  
 429  /**
 430  * Check if the browser has the file already and set the appropriate headers-
 431  * @returns false if a resend is in order.
 432  */
 433  function set_modified_headers($stamp, $browser)
 434  {
 435      global $request;
 436  
 437      // let's see if we have to send the file at all
 438      $last_load     =  $request->header('If-Modified-Since') ? strtotime(trim($request->header('If-Modified-Since'))) : false;
 439  
 440      if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
 441      {
 442          if ($last_load !== false && $last_load >= $stamp)
 443          {
 444              send_status_line(304, 'Not Modified');
 445              // seems that we need those too ... browsers
 446              header('Cache-Control: private');
 447              header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
 448              return true;
 449          }
 450          else
 451          {
 452              header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
 453          }
 454      }
 455      return false;
 456  }
 457  
 458  /**
 459  * Garbage Collection
 460  *
 461  * @param bool $exit        Whether to die or not.
 462  *
 463  * @return null
 464  */
 465  function file_gc($exit = true)
 466  {
 467      global $cache, $db;
 468  
 469      if (!empty($cache))
 470      {
 471          $cache->unload();
 472      }
 473  
 474      $db->sql_close();
 475  
 476      if ($exit)
 477      {
 478          exit;
 479      }
 480  }
 481  
 482  /**
 483  * HTTP range support (RFC 2616 Section 14.35)
 484  *
 485  * Allows browsers to request partial file content
 486  * in case a download has been interrupted.
 487  *
 488  * @param int $filesize        the size of the file in bytes we are about to deliver
 489  *
 490  * @return mixed        false if the whole file has to be delivered
 491  *                    associative array on success
 492  */
 493  function phpbb_http_byte_range($filesize)
 494  {
 495      // Only call find_range_request() once.
 496      static $request_array;
 497  
 498      if (!$filesize)
 499      {
 500          return false;
 501      }
 502  
 503      if (!isset($request_array))
 504      {
 505          $request_array = phpbb_find_range_request();
 506      }
 507  
 508      return (empty($request_array)) ? false : phpbb_parse_range_request($request_array, $filesize);
 509  }
 510  
 511  /**
 512  * Searches for HTTP range request in request headers.
 513  *
 514  * @return mixed        false if no request found
 515  *                    array of strings containing the requested ranges otherwise
 516  *                    e.g. array(0 => '0-0', 1 => '123-125')
 517  */
 518  function phpbb_find_range_request()
 519  {
 520      global $request;
 521  
 522      $value = $request->header('Range');
 523  
 524      // Make sure range request starts with "bytes="
 525      if (strpos($value, 'bytes=') === 0)
 526      {
 527          // Strip leading 'bytes='
 528          // Multiple ranges can be separated by a comma
 529          return explode(',', substr($value, 6));
 530      }
 531  
 532      return false;
 533  }
 534  
 535  /**
 536  * Analyses a range request array.
 537  *
 538  * A range request can contain multiple ranges,
 539  * we however only handle the first request and
 540  * only support requests from a given byte to the end of the file.
 541  *
 542  * @param array    $request_array    array of strings containing the requested ranges
 543  * @param int    $filesize        the full size of the file in bytes that has been requested
 544  *
 545  * @return mixed        false if the whole file has to be delivered
 546  *                    associative array on success
 547  *                        byte_pos_start        the first byte position, can be passed to fseek()
 548  *                        byte_pos_end        the last byte position
 549  *                        bytes_requested        the number of bytes requested
 550  *                        bytes_total            the full size of the file
 551  */
 552  function phpbb_parse_range_request($request_array, $filesize)
 553  {
 554      $first_byte_pos    = -1;
 555      $last_byte_pos    = -1;
 556  
 557      // Go through all ranges
 558      foreach ($request_array as $range_string)
 559      {
 560          $range = explode('-', trim($range_string));
 561  
 562          // "-" is invalid, "0-0" however is valid and means the very first byte.
 563          if (count($range) != 2 || $range[0] === '' && $range[1] === '')
 564          {
 565              continue;
 566          }
 567  
 568          // Substitute defaults
 569          if ($range[0] === '')
 570          {
 571              $range[0] = 0;
 572          }
 573  
 574          if ($range[1] === '')
 575          {
 576              $range[1] = $filesize - 1;
 577          }
 578  
 579          if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
 580          {
 581              // We only support contiguous ranges, no multipart stuff :(
 582              return false;
 583          }
 584  
 585          if ($range[1] && $range[1] < $range[0])
 586          {
 587              // The requested range contains 0 bytes.
 588              continue;
 589          }
 590  
 591          // Return bytes from $range[0] to $range[1]
 592          if ($first_byte_pos < 0)
 593          {
 594              $first_byte_pos    = (int) $range[0];
 595          }
 596  
 597          $last_byte_pos    = (int) $range[1];
 598  
 599          if ($first_byte_pos >= $filesize)
 600          {
 601              // Requested range not satisfiable
 602              return false;
 603          }
 604  
 605          // Adjust last-byte-pos if it is absent or greater than the content.
 606          if ($range[1] === '' || $last_byte_pos >= $filesize)
 607          {
 608              $last_byte_pos = $filesize - 1;
 609          }
 610      }
 611  
 612      if ($first_byte_pos < 0 || $last_byte_pos < 0)
 613      {
 614          return false;
 615      }
 616  
 617      return array(
 618          'byte_pos_start'    => $first_byte_pos,
 619          'byte_pos_end'        => $last_byte_pos,
 620          'bytes_requested'    => $last_byte_pos - $first_byte_pos + 1,
 621          'bytes_total'        => $filesize,
 622      );
 623  }
 624  
 625  /**
 626  * Increments the download count of all provided attachments
 627  *
 628  * @param \phpbb\db\driver\driver_interface $db The database object
 629  * @param array|int $ids The attach_id of each attachment
 630  *
 631  * @return null
 632  */
 633  function phpbb_increment_downloads($db, $ids)
 634  {
 635      if (!is_array($ids))
 636      {
 637          $ids = array($ids);
 638      }
 639  
 640      $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
 641          SET download_count = download_count + 1
 642          WHERE ' . $db->sql_in_set('attach_id', $ids);
 643      $db->sql_query($sql);
 644  }
 645  
 646  /**
 647  * Handles authentication when downloading attachments from a post or topic
 648  *
 649  * @param \phpbb\db\driver\driver_interface $db The database object
 650  * @param \phpbb\auth\auth $auth The authentication object
 651  * @param int $topic_id The id of the topic that we are downloading from
 652  *
 653  * @return null
 654  */
 655  function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
 656  {
 657      global $phpbb_container;
 658  
 659      $sql_array = [
 660          'SELECT'    => 't.forum_id, t.topic_poster, t.topic_visibility, f.forum_name, f.forum_password, f.parent_id',
 661          'FROM'        => [
 662              TOPICS_TABLE => 't',
 663              FORUMS_TABLE => 'f',
 664          ],
 665          'WHERE'        => 't.topic_id = ' . (int) $topic_id . '
 666              AND t.forum_id = f.forum_id',
 667      ];
 668  
 669      $sql = $db->sql_build_query('SELECT', $sql_array);
 670      $result = $db->sql_query($sql);
 671      $row = $db->sql_fetchrow($result);
 672      $db->sql_freeresult($result);
 673  
 674      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 675  
 676      if ($row && !$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row))
 677      {
 678          send_status_line(404, 'Not Found');
 679          trigger_error('ERROR_NO_ATTACHMENT');
 680      }
 681      else if ($row && $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']))
 682      {
 683          if ($row['forum_password'])
 684          {
 685              // Do something else ... ?
 686              login_forum_box($row);
 687          }
 688      }
 689      else
 690      {
 691          send_status_line(403, 'Forbidden');
 692          trigger_error('SORRY_AUTH_VIEW_ATTACH');
 693      }
 694  }
 695  
 696  /**
 697  * Handles authentication when downloading attachments from PMs
 698  *
 699  * @param \phpbb\db\driver\driver_interface $db The database object
 700  * @param \phpbb\auth\auth $auth The authentication object
 701  * @param int $user_id The user id
 702  * @param int $msg_id The id of the PM that we are downloading from
 703  *
 704  * @return null
 705  */
 706  function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id)
 707  {
 708      global $phpbb_dispatcher;
 709  
 710      if (!$auth->acl_get('u_pm_download'))
 711      {
 712          send_status_line(403, 'Forbidden');
 713          trigger_error('SORRY_AUTH_VIEW_ATTACH');
 714      }
 715  
 716      $allowed = phpbb_download_check_pm_auth($db, $user_id, $msg_id);
 717  
 718      /**
 719      * Event to modify PM attachments download auth
 720      *
 721      * @event core.modify_pm_attach_download_auth
 722      * @var    bool    allowed        Whether the user is allowed to download from that PM or not
 723      * @var    int        msg_id        The id of the PM to download from
 724      * @var    int        user_id        The user id for auth check
 725      * @since 3.1.11-RC1
 726      */
 727      $vars = array('allowed', 'msg_id', 'user_id');
 728      extract($phpbb_dispatcher->trigger_event('core.modify_pm_attach_download_auth', compact($vars)));
 729  
 730      if (!$allowed)
 731      {
 732          send_status_line(403, 'Forbidden');
 733          trigger_error('ERROR_NO_ATTACHMENT');
 734      }
 735  }
 736  
 737  /**
 738  * Checks whether a user can download from a particular PM
 739  *
 740  * @param \phpbb\db\driver\driver_interface $db The database object
 741  * @param int $user_id The user id
 742  * @param int $msg_id The id of the PM that we are downloading from
 743  *
 744  * @return bool Whether the user is allowed to download from that PM or not
 745  */
 746  function phpbb_download_check_pm_auth($db, $user_id, $msg_id)
 747  {
 748      // Check if the attachment is within the users scope...
 749      $sql = 'SELECT msg_id
 750          FROM ' . PRIVMSGS_TO_TABLE . '
 751          WHERE msg_id = ' . (int) $msg_id . '
 752              AND (
 753                  user_id = ' . (int) $user_id . '
 754                  OR author_id = ' . (int) $user_id . '
 755              )';
 756      $result = $db->sql_query_limit($sql, 1);
 757      $allowed = (bool) $db->sql_fetchfield('msg_id');
 758      $db->sql_freeresult($result);
 759  
 760      return $allowed;
 761  }
 762  
 763  /**
 764  * Check if the browser is internet explorer version 7+
 765  *
 766  * @param string $user_agent    User agent HTTP header
 767  * @param int $version IE version to check against
 768  *
 769  * @return bool true if internet explorer version is greater than $version
 770  */
 771  function phpbb_is_greater_ie_version($user_agent, $version)
 772  {
 773      if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
 774      {
 775          $ie_version = (int) $matches[1];
 776          return ($ie_version > $version);
 777      }
 778      else
 779      {
 780          return false;
 781      }
 782  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1