[ Index ]

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


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1