Avatar.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. /**
  3. * This file handles the avatar requests. The whole point of this file is to reduce the loaded stuff to show an image
  4. *
  5. * Simple Machines Forum (SMF)
  6. *
  7. * @package SMF
  8. * @author Simple Machines
  9. *
  10. * @copyright 2012 Simple Machines
  11. * @license http://www.simplemachines.org/about/smf/license.php BSD
  12. *
  13. * @version 2.1 Alpha 1
  14. */
  15. if (!defined('SMF'))
  16. die('Hacking attempt...');
  17. // Make sure we have the attachment ID
  18. $temp = explode(';', $_SERVER['QUERY_STRING']);
  19. foreach($temp as $tmp)
  20. if(substr($tmp, 0, 6) == 'attach')
  21. {
  22. @list(, $_GET['attach']) = explode('=', $tmp);
  23. break;
  24. }
  25. // We need a valid ID
  26. if(empty($_GET['attach']) || (string)$_GET['attach'] != (string)(int)$_GET['attach'])
  27. die;
  28. // Load the only files we need
  29. require($sourcedir. '/Load.php');
  30. require($sourcedir. '/Subs.php');
  31. // No access in strict maintenance mode
  32. if(!empty($maintenance) && $maintenance == 2)
  33. die;
  34. $smcFunc = array();
  35. // Load the database.
  36. loadDatabase();
  37. // Load the settings
  38. reloadSettings();
  39. // This is done to clear any output that was made before now.
  40. if(!empty($modSettings['enableCompressedOutput']) && !headers_sent() && ob_get_length() == 0)
  41. {
  42. if(@ini_get('zlib.output_compression') == '1' || @ini_get('output_handler') == 'ob_gzhandler')
  43. $modSettings['enableCompressedOutput'] = 0;
  44. else
  45. ob_start('ob_gzhandler');
  46. }
  47. if(empty($modSettings['enableCompressedOutput']))
  48. {
  49. ob_start();
  50. header('Content-Encoding: none');
  51. }
  52. // Better handling
  53. $id_attach = (int)$_GET['attach'];
  54. // Use cache when possible
  55. if(($cache = cache_get_data('avatar_lookup_id-'. $id_attach)) != null)
  56. $file = $cache;
  57. // Get the info from the DB
  58. else
  59. {
  60. $request = $smcFunc['db_query']('', '
  61. SELECT id_folder, filename AS real_filename, file_hash, fileext, id_attach, attachment_type, mime_type, approved, id_member
  62. FROM {db_prefix}attachments
  63. WHERE id_attach = {int:id_attach}
  64. AND id_member > {int:blank_id_member}
  65. LIMIT 1',
  66. array(
  67. 'id_attach' => $id_attach,
  68. 'blank_id_member' => 0,
  69. )
  70. );
  71. $file = $smcFunc['db_fetch_assoc']($request);
  72. // Update the download counter (unless it's a thumbnail).
  73. if ($file['attachment_type'] != 3)
  74. $smcFunc['db_query']('attach_download_increase', '
  75. UPDATE LOW_PRIORITY {db_prefix}attachments
  76. SET downloads = downloads + 1
  77. WHERE id_attach = {int:id_attach}',
  78. array(
  79. 'id_attach' => $id_attach,
  80. )
  81. );
  82. $file['filename'] = getAttachmentFilename($file['real_filename'], $id_attach, $file['id_folder'], false, $file['file_hash']);
  83. // ETag time
  84. $file['etag'] = '"'. function_exists('md5_file') ? md5_file($file['filename']) : md5(file_get_contents($file['filename'])). '"';
  85. // Cache it... (Why do I randomly select a length at which to expire? Search around for RIP_JITTER :P)
  86. cache_put_data('avatar_lookup_id-'. $id_attach, $file, mt_rand(850, 900));
  87. }
  88. // The file does not exists
  89. if(!file_exists($file['filename']))
  90. {
  91. header('HTTP/1.0 404 File Not Found');
  92. die('404 File Not Found');
  93. }
  94. // If it hasn't been modified since the last time this attachement was retrieved, there's no need to display it again.
  95. if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
  96. {
  97. list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
  98. if (strtotime($modified_since) >= filemtime($file['filename']))
  99. {
  100. ob_end_clean();
  101. // Answer the question - no, it hasn't been modified ;).
  102. header('HTTP/1.1 304 Not Modified');
  103. exit;
  104. }
  105. }
  106. header('Pragma: ');
  107. header('Expires: '. gmdate('D, d M Y H:i:s', time() + 31536000). ' GMT');
  108. header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($file['filename'])). ' GMT');
  109. header('Accept-Ranges: bytes');
  110. header('Connection: close');
  111. header('ETag: '. $file['etag']);
  112. header('Content-Type: '. $file['mime_type']);
  113. // Since we don't do output compression for files this large...
  114. if (filesize($file['filename']) > 4194304)
  115. {
  116. // Forcibly end any output buffering going on.
  117. while (@ob_get_level() > 0)
  118. @ob_end_clean();
  119. $fp = fopen($file['filename'], 'rb');
  120. while (!feof($fp))
  121. {
  122. print fread($fp, 8192);
  123. flush();
  124. }
  125. fclose($fp);
  126. }
  127. // On some of the less-bright hosts, readfile() is disabled. It's just a faster, more byte safe, version of what's in the if.
  128. elseif (@readfile($file['filename']) === null)
  129. print file_get_contents($file['filename']);
  130. exit;