[ Index ]

PHP Cross Reference of phpBB-3.2.0-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: public');
 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 ($category == ATTACHMENT_CATEGORY_FLASH && $request->variable('view', 0) === 1)
 210      {
 211          // We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline
 212          header('Content-Disposition: inline');
 213      }
 214      else
 215      {
 216          if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
 217          {
 218              header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
 219              if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
 220              {
 221                  header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
 222              }
 223          }
 224          else
 225          {
 226              header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
 227              if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
 228              {
 229                  header('X-Download-Options: noopen');
 230              }
 231          }
 232      }
 233  
 234      // Close the db connection before sending the file etc.
 235      file_gc(false);
 236  
 237      if (!set_modified_headers($attachment['filetime'], $user->browser))
 238      {
 239          // We make sure those have to be enabled manually by defining a constant
 240          // because of the potential disclosure of full attachment path
 241          // in case support for features is absent in the webserver software.
 242          if (defined('PHPBB_ENABLE_X_ACCEL_REDIRECT') && PHPBB_ENABLE_X_ACCEL_REDIRECT)
 243          {
 244              // X-Accel-Redirect - http://wiki.nginx.org/XSendfile
 245              header('X-Accel-Redirect: ' . $user->page['root_script_path'] . $upload_dir . '/' . $attachment['physical_filename']);
 246              exit;
 247          }
 248          else if (defined('PHPBB_ENABLE_X_SENDFILE') && PHPBB_ENABLE_X_SENDFILE && !phpbb_http_byte_range($size))
 249          {
 250              // X-Sendfile - http://blog.lighttpd.net/articles/2006/07/02/x-sendfile
 251              // Lighttpd's X-Sendfile does not support range requests as of 1.4.26
 252              // and always requires an absolute path.
 253              header('X-Sendfile: ' . dirname(__FILE__) . "/../$upload_dir/{$attachment['physical_filename']}");
 254              exit;
 255          }
 256  
 257          if ($size)
 258          {
 259              header("Content-Length: $size");
 260          }
 261  
 262          // Try to deliver in chunks
 263          @set_time_limit(0);
 264  
 265          $fp = @fopen($filename, 'rb');
 266  
 267          if ($fp !== false)
 268          {
 269              // Deliver file partially if requested
 270              if ($range = phpbb_http_byte_range($size))
 271              {
 272                  fseek($fp, $range['byte_pos_start']);
 273  
 274                  send_status_line(206, 'Partial Content');
 275                  header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
 276                  header('Content-Length: ' . $range['bytes_requested']);
 277  
 278                  // First read chunks
 279                  while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192)
 280                  {
 281                      echo fread($fp, 8192);
 282                  }
 283                  // Then, read the remainder
 284                  echo fread($fp, $range['bytes_requested'] % 8192);
 285              }
 286              else
 287              {
 288                  while (!feof($fp))
 289                  {
 290                      echo fread($fp, 8192);
 291                  }
 292              }
 293              fclose($fp);
 294          }
 295          else
 296          {
 297              @readfile($filename);
 298          }
 299  
 300          flush();
 301      }
 302  
 303      exit;
 304  }
 305  
 306  /**
 307  * Get a browser friendly UTF-8 encoded filename
 308  */
 309  function header_filename($file)
 310  {
 311      global $request;
 312  
 313      $user_agent = $request->header('User-Agent');
 314  
 315      // There be dragons here.
 316      // Not many follows the RFC...
 317      if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Konqueror') !== false)
 318      {
 319          return "filename=" . rawurlencode($file);
 320      }
 321  
 322      // follow the RFC for extended filename for the rest
 323      return "filename*=UTF-8''" . rawurlencode($file);
 324  }
 325  
 326  /**
 327  * Check if downloading item is allowed
 328  */
 329  function download_allowed()
 330  {
 331      global $config, $user, $db, $request;
 332  
 333      if (!$config['secure_downloads'])
 334      {
 335          return true;
 336      }
 337  
 338      $url = htmlspecialchars_decode($request->header('Referer'));
 339  
 340      if (!$url)
 341      {
 342          return ($config['secure_allow_empty_referer']) ? true : false;
 343      }
 344  
 345      // Split URL into domain and script part
 346      $url = @parse_url($url);
 347  
 348      if ($url === false)
 349      {
 350          return ($config['secure_allow_empty_referer']) ? true : false;
 351      }
 352  
 353      $hostname = $url['host'];
 354      unset($url);
 355  
 356      $allowed = ($config['secure_allow_deny']) ? false : true;
 357      $iplist = array();
 358  
 359      if (($ip_ary = @gethostbynamel($hostname)) !== false)
 360      {
 361          foreach ($ip_ary as $ip)
 362          {
 363              if ($ip)
 364              {
 365                  $iplist[] = $ip;
 366              }
 367          }
 368      }
 369  
 370      // Check for own server...
 371      $server_name = $user->host;
 372  
 373      // Forcing server vars is the only way to specify/override the protocol
 374      if ($config['force_server_vars'] || !$server_name)
 375      {
 376          $server_name = $config['server_name'];
 377      }
 378  
 379      if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
 380      {
 381          $allowed = true;
 382      }
 383  
 384      // Get IP's and Hostnames
 385      if (!$allowed)
 386      {
 387          $sql = 'SELECT site_ip, site_hostname, ip_exclude
 388              FROM ' . SITELIST_TABLE;
 389          $result = $db->sql_query($sql);
 390  
 391          while ($row = $db->sql_fetchrow($result))
 392          {
 393              $site_ip = trim($row['site_ip']);
 394              $site_hostname = trim($row['site_hostname']);
 395  
 396              if ($site_ip)
 397              {
 398                  foreach ($iplist as $ip)
 399                  {
 400                      if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
 401                      {
 402                          if ($row['ip_exclude'])
 403                          {
 404                              $allowed = ($config['secure_allow_deny']) ? false : true;
 405                              break 2;
 406                          }
 407                          else
 408                          {
 409                              $allowed = ($config['secure_allow_deny']) ? true : false;
 410                          }
 411                      }
 412                  }
 413              }
 414  
 415              if ($site_hostname)
 416              {
 417                  if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
 418                  {
 419                      if ($row['ip_exclude'])
 420                      {
 421                          $allowed = ($config['secure_allow_deny']) ? false : true;
 422                          break;
 423                      }
 424                      else
 425                      {
 426                          $allowed = ($config['secure_allow_deny']) ? true : false;
 427                      }
 428                  }
 429              }
 430          }
 431          $db->sql_freeresult($result);
 432      }
 433  
 434      return $allowed;
 435  }
 436  
 437  /**
 438  * Check if the browser has the file already and set the appropriate headers-
 439  * @returns false if a resend is in order.
 440  */
 441  function set_modified_headers($stamp, $browser)
 442  {
 443      global $request;
 444  
 445      // let's see if we have to send the file at all
 446      $last_load     =  $request->header('If-Modified-Since') ? strtotime(trim($request->header('If-Modified-Since'))) : false;
 447  
 448      if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
 449      {
 450          if ($last_load !== false && $last_load >= $stamp)
 451          {
 452              send_status_line(304, 'Not Modified');
 453              // seems that we need those too ... browsers
 454              header('Cache-Control: public');
 455              header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
 456              return true;
 457          }
 458          else
 459          {
 460              header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
 461          }
 462      }
 463      return false;
 464  }
 465  
 466  /**
 467  * Garbage Collection
 468  *
 469  * @param bool $exit        Whether to die or not.
 470  *
 471  * @return null
 472  */
 473  function file_gc($exit = true)
 474  {
 475      global $cache, $db;
 476  
 477      if (!empty($cache))
 478      {
 479          $cache->unload();
 480      }
 481  
 482      $db->sql_close();
 483  
 484      if ($exit)
 485      {
 486          exit;
 487      }
 488  }
 489  
 490  /**
 491  * HTTP range support (RFC 2616 Section 14.35)
 492  *
 493  * Allows browsers to request partial file content
 494  * in case a download has been interrupted.
 495  *
 496  * @param int $filesize        the size of the file in bytes we are about to deliver
 497  *
 498  * @return mixed        false if the whole file has to be delivered
 499  *                    associative array on success
 500  */
 501  function phpbb_http_byte_range($filesize)
 502  {
 503      // Only call find_range_request() once.
 504      static $request_array;
 505  
 506      if (!$filesize)
 507      {
 508          return false;
 509      }
 510  
 511      if (!isset($request_array))
 512      {
 513          $request_array = phpbb_find_range_request();
 514      }
 515  
 516      return (empty($request_array)) ? false : phpbb_parse_range_request($request_array, $filesize);
 517  }
 518  
 519  /**
 520  * Searches for HTTP range request in request headers.
 521  *
 522  * @return mixed        false if no request found
 523  *                    array of strings containing the requested ranges otherwise
 524  *                    e.g. array(0 => '0-0', 1 => '123-125')
 525  */
 526  function phpbb_find_range_request()
 527  {
 528      global $request;
 529  
 530      $value = $request->header('Range');
 531  
 532      // Make sure range request starts with "bytes="
 533      if (strpos($value, 'bytes=') === 0)
 534      {
 535          // Strip leading 'bytes='
 536          // Multiple ranges can be separated by a comma
 537          return explode(',', substr($value, 6));
 538      }
 539  
 540      return false;
 541  }
 542  
 543  /**
 544  * Analyses a range request array.
 545  *
 546  * A range request can contain multiple ranges,
 547  * we however only handle the first request and
 548  * only support requests from a given byte to the end of the file.
 549  *
 550  * @param array    $request_array    array of strings containing the requested ranges
 551  * @param int    $filesize        the full size of the file in bytes that has been requested
 552  *
 553  * @return mixed        false if the whole file has to be delivered
 554  *                    associative array on success
 555  *                        byte_pos_start        the first byte position, can be passed to fseek()
 556  *                        byte_pos_end        the last byte position
 557  *                        bytes_requested        the number of bytes requested
 558  *                        bytes_total            the full size of the file
 559  */
 560  function phpbb_parse_range_request($request_array, $filesize)
 561  {
 562      $first_byte_pos    = -1;
 563      $last_byte_pos    = -1;
 564  
 565      // Go through all ranges
 566      foreach ($request_array as $range_string)
 567      {
 568          $range = explode('-', trim($range_string));
 569  
 570          // "-" is invalid, "0-0" however is valid and means the very first byte.
 571          if (sizeof($range) != 2 || $range[0] === '' && $range[1] === '')
 572          {
 573              continue;
 574          }
 575  
 576          // Substitute defaults
 577          if ($range[0] === '')
 578          {
 579              $range[0] = 0;
 580          }
 581  
 582          if ($range[1] === '')
 583          {
 584              $range[1] = $filesize - 1;
 585          }
 586  
 587          if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
 588          {
 589              // We only support contiguous ranges, no multipart stuff :(
 590              return false;
 591          }
 592  
 593          if ($range[1] && $range[1] < $range[0])
 594          {
 595              // The requested range contains 0 bytes.
 596              continue;
 597          }
 598  
 599          // Return bytes from $range[0] to $range[1]
 600          if ($first_byte_pos < 0)
 601          {
 602              $first_byte_pos    = (int) $range[0];
 603          }
 604  
 605          $last_byte_pos    = (int) $range[1];
 606  
 607          if ($first_byte_pos >= $filesize)
 608          {
 609              // Requested range not satisfiable
 610              return false;
 611          }
 612  
 613          // Adjust last-byte-pos if it is absent or greater than the content.
 614          if ($range[1] === '' || $last_byte_pos >= $filesize)
 615          {
 616              $last_byte_pos = $filesize - 1;
 617          }
 618      }
 619  
 620      if ($first_byte_pos < 0 || $last_byte_pos < 0)
 621      {
 622          return false;
 623      }
 624  
 625      return array(
 626          'byte_pos_start'    => $first_byte_pos,
 627          'byte_pos_end'        => $last_byte_pos,
 628          'bytes_requested'    => $last_byte_pos - $first_byte_pos + 1,
 629          'bytes_total'        => $filesize,
 630      );
 631  }
 632  
 633  /**
 634  * Increments the download count of all provided attachments
 635  *
 636  * @param \phpbb\db\driver\driver_interface $db The database object
 637  * @param array|int $ids The attach_id of each attachment
 638  *
 639  * @return null
 640  */
 641  function phpbb_increment_downloads($db, $ids)
 642  {
 643      if (!is_array($ids))
 644      {
 645          $ids = array($ids);
 646      }
 647  
 648      $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
 649          SET download_count = download_count + 1
 650          WHERE ' . $db->sql_in_set('attach_id', $ids);
 651      $db->sql_query($sql);
 652  }
 653  
 654  /**
 655  * Handles authentication when downloading attachments from a post or topic
 656  *
 657  * @param \phpbb\db\driver\driver_interface $db The database object
 658  * @param \phpbb\auth\auth $auth The authentication object
 659  * @param int $topic_id The id of the topic that we are downloading from
 660  *
 661  * @return null
 662  */
 663  function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
 664  {
 665      $sql_array = array(
 666          'SELECT'    => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id',
 667          'FROM'        => array(
 668              TOPICS_TABLE => 't',
 669              FORUMS_TABLE => 'f',
 670          ),
 671          'WHERE'    => 't.topic_id = ' . (int) $topic_id . '
 672              AND t.forum_id = f.forum_id',
 673      );
 674  
 675      $sql = $db->sql_build_query('SELECT', $sql_array);
 676      $result = $db->sql_query($sql);
 677      $row = $db->sql_fetchrow($result);
 678      $db->sql_freeresult($result);
 679  
 680      if ($row && $row['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id']))
 681      {
 682          send_status_line(404, 'Not Found');
 683          trigger_error('ERROR_NO_ATTACHMENT');
 684      }
 685      else if ($row && $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']))
 686      {
 687          if ($row['forum_password'])
 688          {
 689              // Do something else ... ?
 690              login_forum_box($row);
 691          }
 692      }
 693      else
 694      {
 695          send_status_line(403, 'Forbidden');
 696          trigger_error('SORRY_AUTH_VIEW_ATTACH');
 697      }
 698  }
 699  
 700  /**
 701  * Handles authentication when downloading attachments from PMs
 702  *
 703  * @param \phpbb\db\driver\driver_interface $db The database object
 704  * @param \phpbb\auth\auth $auth The authentication object
 705  * @param int $user_id The user id
 706  * @param int $msg_id The id of the PM that we are downloading from
 707  *
 708  * @return null
 709  */
 710  function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id)
 711  {
 712      global $phpbb_dispatcher;
 713  
 714      if (!$auth->acl_get('u_pm_download'))
 715      {
 716          send_status_line(403, 'Forbidden');
 717          trigger_error('SORRY_AUTH_VIEW_ATTACH');
 718      }
 719  
 720      $allowed = phpbb_download_check_pm_auth($db, $user_id, $msg_id);
 721  
 722      /**
 723      * Event to modify PM attachments download auth
 724      *
 725      * @event core.modify_pm_attach_download_auth
 726      * @var    bool    allowed        Whether the user is allowed to download from that PM or not
 727      * @var    int        msg_id        The id of the PM to download from
 728      * @var    int        user_id        The user id for auth check
 729      * @since 3.1.11-RC1
 730      */
 731      $vars = array('allowed', 'msg_id', 'user_id');
 732      extract($phpbb_dispatcher->trigger_event('core.modify_pm_attach_download_auth', compact($vars)));
 733  
 734      if (!$allowed)
 735      {
 736          send_status_line(403, 'Forbidden');
 737          trigger_error('ERROR_NO_ATTACHMENT');
 738      }
 739  }
 740  
 741  /**
 742  * Checks whether a user can download from a particular PM
 743  *
 744  * @param \phpbb\db\driver\driver_interface $db The database object
 745  * @param int $user_id The user id
 746  * @param int $msg_id The id of the PM that we are downloading from
 747  *
 748  * @return bool Whether the user is allowed to download from that PM or not
 749  */
 750  function phpbb_download_check_pm_auth($db, $user_id, $msg_id)
 751  {
 752      // Check if the attachment is within the users scope...
 753      $sql = 'SELECT msg_id
 754          FROM ' . PRIVMSGS_TO_TABLE . '
 755          WHERE msg_id = ' . (int) $msg_id . '
 756              AND (
 757                  user_id = ' . (int) $user_id . '
 758                  OR author_id = ' . (int) $user_id . '
 759              )';
 760      $result = $db->sql_query_limit($sql, 1);
 761      $allowed = (bool) $db->sql_fetchfield('msg_id');
 762      $db->sql_freeresult($result);
 763  
 764      return $allowed;
 765  }
 766  
 767  /**
 768  * Check if the browser is internet explorer version 7+
 769  *
 770  * @param string $user_agent    User agent HTTP header
 771  * @param int $version IE version to check against
 772  *
 773  * @return bool true if internet explorer version is greater than $version
 774  */
 775  function phpbb_is_greater_ie_version($user_agent, $version)
 776  {
 777      if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
 778      {
 779          $ie_version = (int) $matches[1];
 780          return ($ie_version > $version);
 781      }
 782      else
 783      {
 784          return false;
 785      }
 786  }


Generated: Sun Feb 19 19:47:08 2017 Cross-referenced by PHPXref 0.7.1