Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_download.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 18.24 KiB


 001  <?php
 002  /**
 003  *
 004  * This file is part of the phpBB Forum Software package.
 005  *
 006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 007  * @license GNU General Public License, version 2 (GPL-2.0)
 008  *
 009  * For full copyright and license information, please see
 010  * the docs/CREDITS.txt file.
 011  *
 012  */
 013   
 014  /**
 015  * @ignore
 016  */
 017  if (!defined('IN_PHPBB'))
 018  {
 019      exit;
 020  }
 021   
 022  /**
 023  * A simplified function to deliver avatars
 024  * The argument needs to be checked before calling this function.
 025  */
 026  function send_avatar_to_browser($file, $browser)
 027  {
 028      global $config, $phpbb_root_path;
 029   
 030      $prefix = $config['avatar_salt'] . '_';
 031      $image_dir = $config['avatar_path'];
 032   
 033      // Adjust image_dir path (no trailing slash)
 034      if (substr($image_dir, -1, 1) == '/' || substr($image_dir, -1, 1) == '\\')
 035      {
 036          $image_dir = substr($image_dir, 0, -1) . '/';
 037      }
 038      $image_dir = str_replace(array('../', '..\\', './', '.\\'), '', $image_dir);
 039   
 040      if ($image_dir && ($image_dir[0] == '/' || $image_dir[0] == '\\'))
 041      {
 042          $image_dir = '';
 043      }
 044      $file_path = $phpbb_root_path . $image_dir . '/' . $prefix . $file;
 045   
 046      if ((@file_exists($file_path) && @is_readable($file_path)) && !headers_sent())
 047      {
 048          header('Cache-Control: public');
 049   
 050          $image_data = @getimagesize($file_path);
 051          header('Content-Type: ' . image_type_to_mime_type($image_data[2]));
 052   
 053          if ((strpos(strtolower($browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7))
 054          {
 055              header('Content-Disposition: attachment; ' . header_filename($file));
 056   
 057              if (strpos(strtolower($browser), 'msie 6.0') !== false)
 058              {
 059                  header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
 060              }
 061              else
 062              {
 063                  header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
 064              }
 065          }
 066          else
 067          {
 068              header('Content-Disposition: inline; ' . header_filename($file));
 069              header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
 070          }
 071   
 072          $size = @filesize($file_path);
 073          if ($size)
 074          {
 075              header("Content-Length: $size");
 076          }
 077   
 078          if (@readfile($file_path) == false)
 079          {
 080              $fp = @fopen($file_path, 'rb');
 081   
 082              if ($fp !== false)
 083              {
 084                  while (!feof($fp))
 085                  {
 086                      echo fread($fp, 8192);
 087                  }
 088                  fclose($fp);
 089              }
 090          }
 091   
 092          flush();
 093      }
 094      else
 095      {
 096          header('HTTP/1.0 404 Not Found');
 097      }
 098  }
 099   
 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 '<title>' . $title . '</title>';
 112      echo '</head>';
 113      echo '<body>';
 114      echo '<div>';
 115      echo '<img src="' . $src . '" alt="' . $title . '" />';
 116      echo '</div>';
 117      echo '</body>';
 118      echo '</html>';
 119  }
 120   
 121  /**
 122  * Send file to browser
 123  */
 124  function send_file_to_browser($attachment, $upload_dir, $category)
 125  {
 126      global $user, $db, $config, $phpbb_root_path;
 127   
 128      $filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename'];
 129   
 130      if (!@file_exists($filename))
 131      {
 132          send_status_line(404, 'Not Found');
 133          trigger_error('ERROR_NO_ATTACHMENT');
 134      }
 135   
 136      // Correct the mime type - we force application/octetstream for all files, except images
 137      // Please do not change this, it is a security precaution
 138      if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0)
 139      {
 140          $attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream';
 141      }
 142   
 143      if (@ob_get_length())
 144      {
 145          @ob_end_clean();
 146      }
 147   
 148      // Now send the File Contents to the Browser
 149      $size = @filesize($filename);
 150   
 151      // To correctly display further errors we need to make sure we are using the correct headers for both (unsetting content-length may not work)
 152   
 153      // Check if headers already sent or not able to get the file contents.
 154      if (headers_sent() || !@file_exists($filename) || !@is_readable($filename))
 155      {
 156          // PHP track_errors setting On?
 157          if (!empty($php_errormsg))
 158          {
 159              send_status_line(500, 'Internal Server Error');
 160              trigger_error($user->lang['UNABLE_TO_DELIVER_FILE'] . '<br />' . sprintf($user->lang['TRACKED_PHP_ERROR'], $php_errormsg));
 161          }
 162   
 163          send_status_line(500, 'Internal Server Error');
 164          trigger_error('UNABLE_TO_DELIVER_FILE');
 165      }
 166   
 167      // Make sure the database record for the filesize is correct
 168      if ($size > 0 && $size != $attachment['filesize'])
 169      {
 170          // Update database record
 171          $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
 172              SET filesize = ' . (int) $size . '
 173              WHERE attach_id = ' . (int) $attachment['attach_id'];
 174          $db->sql_query($sql);
 175      }
 176   
 177      // Now the tricky part... let's dance
 178      header('Cache-Control: public');
 179   
 180      // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
 181      header('Content-Type: ' . $attachment['mimetype']);
 182   
 183      if (phpbb_is_greater_ie_version($user->browser, 7))
 184      {
 185          header('X-Content-Type-Options: nosniff');
 186      }
 187   
 188      if ($category == ATTACHMENT_CATEGORY_FLASH && request_var('view', 0) === 1)
 189      {
 190          // 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
 191          header('Content-Disposition: inline');
 192      }
 193      else
 194      {
 195          if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
 196          {
 197              header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
 198              if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
 199              {
 200                  header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
 201              }
 202          }
 203          else
 204          {
 205              header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
 206              if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
 207              {
 208                  header('X-Download-Options: noopen');
 209              }
 210          }
 211      }
 212   
 213      if ($size)
 214      {
 215          header("Content-Length: $size");
 216      }
 217   
 218      // Close the db connection before sending the file etc.
 219      file_gc(false);
 220   
 221      if (!set_modified_headers($attachment['filetime'], $user->browser))
 222      {
 223          // We make sure those have to be enabled manually by defining a constant
 224          // because of the potential disclosure of full attachment path
 225          // in case support for features is absent in the webserver software.
 226          if (defined('PHPBB_ENABLE_X_ACCEL_REDIRECT') && PHPBB_ENABLE_X_ACCEL_REDIRECT)
 227          {
 228              // X-Accel-Redirect - http://wiki.nginx.org/XSendfile
 229              header('X-Accel-Redirect: ' . $user->page['root_script_path'] . $upload_dir . '/' . $attachment['physical_filename']);
 230              exit;
 231          }
 232          else if (defined('PHPBB_ENABLE_X_SENDFILE') && PHPBB_ENABLE_X_SENDFILE && !phpbb_http_byte_range($size))
 233          {
 234              // X-Sendfile - http://blog.lighttpd.net/articles/2006/07/02/x-sendfile
 235              // Lighttpd's X-Sendfile does not support range requests as of 1.4.26
 236              // and always requires an absolute path.
 237              header('X-Sendfile: ' . dirname(__FILE__) . "/../$upload_dir/{$attachment['physical_filename']}");
 238              exit;
 239          }
 240   
 241          // Try to deliver in chunks
 242          @set_time_limit(0);
 243   
 244          $fp = @fopen($filename, 'rb');
 245   
 246          if ($fp !== false)
 247          {
 248              // Deliver file partially if requested
 249              if ($range = phpbb_http_byte_range($size))
 250              {
 251                  fseek($fp, $range['byte_pos_start']);
 252   
 253                  send_status_line(206, 'Partial Content');
 254                  header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
 255                  header('Content-Length: ' . $range['bytes_requested']);
 256              }
 257   
 258              while (!feof($fp))
 259              {
 260                  echo fread($fp, 8192);
 261              }
 262              fclose($fp);
 263          }
 264          else
 265          {
 266              @readfile($filename);
 267          }
 268   
 269          flush();
 270      }
 271   
 272      exit;
 273  }
 274   
 275  /**
 276  * Get a browser friendly UTF-8 encoded filename
 277  */
 278  function header_filename($file)
 279  {
 280      global $request;
 281   
 282      $user_agent = $request->header('User-Agent');
 283   
 284      // There be dragons here.
 285      // Not many follows the RFC...
 286      if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Safari') !== false || strpos($user_agent, 'Konqueror') !== false)
 287      {
 288          return "filename=" . rawurlencode($file);
 289      }
 290   
 291      // follow the RFC for extended filename for the rest
 292      return "filename*=UTF-8''" . rawurlencode($file);
 293  }
 294   
 295  /**
 296  * Check if downloading item is allowed
 297  */
 298  function download_allowed()
 299  {
 300      global $config, $user, $db, $request;
 301   
 302      if (!$config['secure_downloads'])
 303      {
 304          return true;
 305      }
 306   
 307      $url = htmlspecialchars_decode($request->header('Referer'));
 308   
 309      if (!$url)
 310      {
 311          return ($config['secure_allow_empty_referer']) ? true : false;
 312      }
 313   
 314      // Split URL into domain and script part
 315      $url = @parse_url($url);
 316   
 317      if ($url === false)
 318      {
 319          return ($config['secure_allow_empty_referer']) ? true : false;
 320      }
 321   
 322      $hostname = $url['host'];
 323      unset($url);
 324   
 325      $allowed = ($config['secure_allow_deny']) ? false : true;
 326      $iplist = array();
 327   
 328      if (($ip_ary = @gethostbynamel($hostname)) !== false)
 329      {
 330          foreach ($ip_ary as $ip)
 331          {
 332              if ($ip)
 333              {
 334                  $iplist[] = $ip;
 335              }
 336          }
 337      }
 338   
 339      // Check for own server...
 340      $server_name = $user->host;
 341   
 342      // Forcing server vars is the only way to specify/override the protocol
 343      if ($config['force_server_vars'] || !$server_name)
 344      {
 345          $server_name = $config['server_name'];
 346      }
 347   
 348      if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
 349      {
 350          $allowed = true;
 351      }
 352   
 353      // Get IP's and Hostnames
 354      if (!$allowed)
 355      {
 356          $sql = 'SELECT site_ip, site_hostname, ip_exclude
 357              FROM ' . SITELIST_TABLE;
 358          $result = $db->sql_query($sql);
 359   
 360          while ($row = $db->sql_fetchrow($result))
 361          {
 362              $site_ip = trim($row['site_ip']);
 363              $site_hostname = trim($row['site_hostname']);
 364   
 365              if ($site_ip)
 366              {
 367                  foreach ($iplist as $ip)
 368                  {
 369                      if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
 370                      {
 371                          if ($row['ip_exclude'])
 372                          {
 373                              $allowed = ($config['secure_allow_deny']) ? false : true;
 374                              break 2;
 375                          }
 376                          else
 377                          {
 378                              $allowed = ($config['secure_allow_deny']) ? true : false;
 379                          }
 380                      }
 381                  }
 382              }
 383   
 384              if ($site_hostname)
 385              {
 386                  if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
 387                  {
 388                      if ($row['ip_exclude'])
 389                      {
 390                          $allowed = ($config['secure_allow_deny']) ? false : true;
 391                          break;
 392                      }
 393                      else
 394                      {
 395                          $allowed = ($config['secure_allow_deny']) ? true : false;
 396                      }
 397                  }
 398              }
 399          }
 400          $db->sql_freeresult($result);
 401      }
 402   
 403      return $allowed;
 404  }
 405   
 406  /**
 407  * Check if the browser has the file already and set the appropriate headers-
 408  * @returns false if a resend is in order.
 409  */
 410  function set_modified_headers($stamp, $browser)
 411  {
 412      global $request;
 413   
 414      // let's see if we have to send the file at all
 415      $last_load     =  $request->header('Modified-Since') ? strtotime(trim($request->header('Modified-Since'))) : false;
 416   
 417      if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
 418      {
 419          if ($last_load !== false && $last_load >= $stamp)
 420          {
 421              send_status_line(304, 'Not Modified');
 422              // seems that we need those too ... browsers
 423              header('Cache-Control: public');
 424              header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
 425              return true;
 426          }
 427          else
 428          {
 429              header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
 430          }
 431      }
 432      return false;
 433  }
 434   
 435  /**
 436  * Garbage Collection
 437  *
 438  * @param bool $exit        Whether to die or not.
 439  *
 440  * @return null
 441  */
 442  function file_gc($exit = true)
 443  {
 444      global $cache, $db;
 445   
 446      if (!empty($cache))
 447      {
 448          $cache->unload();
 449      }
 450   
 451      $db->sql_close();
 452   
 453      if ($exit)
 454      {
 455          exit;
 456      }
 457  }
 458   
 459  /**
 460  * HTTP range support (RFC 2616 Section 14.35)
 461  *
 462  * Allows browsers to request partial file content
 463  * in case a download has been interrupted.
 464  *
 465  * @param int $filesize        the size of the file in bytes we are about to deliver
 466  *
 467  * @return mixed        false if the whole file has to be delivered
 468  *                    associative array on success
 469  */
 470  function phpbb_http_byte_range($filesize)
 471  {
 472      // Only call find_range_request() once.
 473      static $request_array;
 474   
 475      if (!$filesize)
 476      {
 477          return false;
 478      }
 479   
 480      if (!isset($request_array))
 481      {
 482          $request_array = phpbb_find_range_request();
 483      }
 484   
 485      return (empty($request_array)) ? false : phpbb_parse_range_request($request_array, $filesize);
 486  }
 487   
 488  /**
 489  * Searches for HTTP range request in request headers.
 490  *
 491  * @return mixed        false if no request found
 492  *                    array of strings containing the requested ranges otherwise
 493  *                    e.g. array(0 => '0-0', 1 => '123-125')
 494  */
 495  function phpbb_find_range_request()
 496  {
 497      global $request;
 498   
 499      $value = $request->header('Range');
 500   
 501      // Make sure range request starts with "bytes="
 502      if (strpos($value, 'bytes=') === 0)
 503      {
 504          // Strip leading 'bytes='
 505          // Multiple ranges can be separated by a comma
 506          return explode(',', substr($value, 6));
 507      }
 508   
 509      return false;
 510  }
 511   
 512  /**
 513  * Analyses a range request array.
 514  *
 515  * A range request can contain multiple ranges,
 516  * we however only handle the first request and
 517  * only support requests from a given byte to the end of the file.
 518  *
 519  * @param array    $request_array    array of strings containing the requested ranges
 520  * @param int    $filesize        the full size of the file in bytes that has been requested
 521  *
 522  * @return mixed        false if the whole file has to be delivered
 523  *                    associative array on success
 524  *                        byte_pos_start        the first byte position, can be passed to fseek()
 525  *                        byte_pos_end        the last byte position
 526  *                        bytes_requested        the number of bytes requested
 527  *                        bytes_total            the full size of the file
 528  */
 529  function phpbb_parse_range_request($request_array, $filesize)
 530  {
 531      // Go through all ranges
 532      foreach ($request_array as $range_string)
 533      {
 534          $range = explode('-', trim($range_string));
 535   
 536          // "-" is invalid, "0-0" however is valid and means the very first byte.
 537          if (sizeof($range) != 2 || $range[0] === '' && $range[1] === '')
 538          {
 539              continue;
 540          }
 541   
 542          if ($range[0] === '')
 543          {
 544              // Return last $range[1] bytes.
 545   
 546              if (!$range[1])
 547              {
 548                  continue;
 549              }
 550   
 551              if ($range[1] >= $filesize)
 552              {
 553                  return false;
 554              }
 555   
 556              $first_byte_pos    = $filesize - (int) $range[1];
 557              $last_byte_pos    = $filesize - 1;
 558          }
 559          else
 560          {
 561              // Return bytes from $range[0] to $range[1]
 562   
 563              $first_byte_pos    = (int) $range[0];
 564              $last_byte_pos    = (int) $range[1];
 565   
 566              if ($last_byte_pos && $last_byte_pos < $first_byte_pos)
 567              {
 568                  // The requested range contains 0 bytes.
 569                  continue;
 570              }
 571   
 572              if ($first_byte_pos >= $filesize)
 573              {
 574                  // Requested range not satisfiable
 575                  return false;
 576              }
 577   
 578              // Adjust last-byte-pos if it is absent or greater than the content.
 579              if ($range[1] === '' || $last_byte_pos >= $filesize)
 580              {
 581                  $last_byte_pos = $filesize - 1;
 582              }
 583          }
 584   
 585          // We currently do not support range requests that end before the end of the file
 586          if ($last_byte_pos != $filesize - 1)
 587          {
 588              continue;
 589          }
 590   
 591          return array(
 592              'byte_pos_start'    => $first_byte_pos,
 593              'byte_pos_end'        => $last_byte_pos,
 594              'bytes_requested'    => $last_byte_pos - $first_byte_pos + 1,
 595              'bytes_total'        => $filesize,
 596          );
 597      }
 598  }
 599   
 600  /**
 601  * Increments the download count of all provided attachments
 602  *
 603  * @param \phpbb\db\driver\driver_interface $db The database object
 604  * @param array|int $ids The attach_id of each attachment
 605  *
 606  * @return null
 607  */
 608  function phpbb_increment_downloads($db, $ids)
 609  {
 610      if (!is_array($ids))
 611      {
 612          $ids = array($ids);
 613      }
 614   
 615      $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
 616          SET download_count = download_count + 1
 617          WHERE ' . $db->sql_in_set('attach_id', $ids);
 618      $db->sql_query($sql);
 619  }
 620   
 621  /**
 622  * Handles authentication when downloading attachments from a post or topic
 623  *
 624  * @param \phpbb\db\driver\driver_interface $db The database object
 625  * @param \phpbb\auth\auth $auth The authentication object
 626  * @param int $topic_id The id of the topic that we are downloading from
 627  *
 628  * @return null
 629  */
 630  function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
 631  {
 632      $sql_array = array(
 633          'SELECT'    => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id',
 634          'FROM'        => array(
 635              TOPICS_TABLE => 't',
 636              FORUMS_TABLE => 'f',
 637          ),
 638          'WHERE'    => 't.topic_id = ' . (int) $topic_id . '
 639              AND t.forum_id = f.forum_id',
 640      );
 641   
 642      $sql = $db->sql_build_query('SELECT', $sql_array);
 643      $result = $db->sql_query($sql);
 644      $row = $db->sql_fetchrow($result);
 645      $db->sql_freeresult($result);
 646   
 647      if ($row && $row['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id']))
 648      {
 649          send_status_line(404, 'Not Found');
 650          trigger_error('ERROR_NO_ATTACHMENT');
 651      }
 652      else if ($row && $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']))
 653      {
 654          if ($row['forum_password'])
 655          {
 656              // Do something else ... ?
 657              login_forum_box($row);
 658          }
 659      }
 660      else
 661      {
 662          send_status_line(403, 'Forbidden');
 663          trigger_error('SORRY_AUTH_VIEW_ATTACH');
 664      }
 665  }
 666   
 667  /**
 668  * Handles authentication when downloading attachments from PMs
 669  *
 670  * @param \phpbb\db\driver\driver_interface $db The database object
 671  * @param \phpbb\auth\auth $auth The authentication object
 672  * @param int $user_id The user id
 673  * @param int $msg_id The id of the PM that we are downloading from
 674  *
 675  * @return null
 676  */
 677  function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id)
 678  {
 679      if (!$auth->acl_get('u_pm_download'))
 680      {
 681          send_status_line(403, 'Forbidden');
 682          trigger_error('SORRY_AUTH_VIEW_ATTACH');
 683      }
 684   
 685      $allowed = phpbb_download_check_pm_auth($db, $user_id, $msg_id);
 686   
 687      if (!$allowed)
 688      {
 689          send_status_line(403, 'Forbidden');
 690          trigger_error('ERROR_NO_ATTACHMENT');
 691      }
 692  }
 693   
 694  /**
 695  * Checks whether a user can download from a particular PM
 696  *
 697  * @param \phpbb\db\driver\driver_interface $db The database object
 698  * @param int $user_id The user id
 699  * @param int $msg_id The id of the PM that we are downloading from
 700  *
 701  * @return bool Whether the user is allowed to download from that PM or not
 702  */
 703  function phpbb_download_check_pm_auth($db, $user_id, $msg_id)
 704  {
 705      // Check if the attachment is within the users scope...
 706      $sql = 'SELECT msg_id
 707          FROM ' . PRIVMSGS_TO_TABLE . '
 708          WHERE msg_id = ' . (int) $msg_id . '
 709              AND (
 710                  user_id = ' . (int) $user_id . '
 711                  OR author_id = ' . (int) $user_id . '
 712              )';
 713      $result = $db->sql_query_limit($sql, 1);
 714      $allowed = (bool) $db->sql_fetchfield('msg_id');
 715      $db->sql_freeresult($result);
 716   
 717      return $allowed;
 718  }
 719   
 720  /**
 721  * Check if the browser is internet explorer version 7+
 722  *
 723  * @param string $user_agent    User agent HTTP header
 724  * @param int $version IE version to check against
 725  *
 726  * @return bool true if internet explorer version is greater than $version
 727  */
 728  function phpbb_is_greater_ie_version($user_agent, $version)
 729  {
 730      if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
 731      {
 732          $ie_version = (int) $matches[1];
 733          return ($ie_version > $version);
 734      }
 735      else
 736      {
 737          return false;
 738      }
 739  }
 740