class-simple-job-board-resume-download-handler.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <?php if (!defined('ABSPATH')) { exit; } // Exit if accessed directly
  2. /**
  3. * Simple_Job_Board_Resume_Download_Handler Class
  4. *
  5. * Functions to download
  6. * @link https://wordpress.org/plugins/simple-job-board
  7. * @since 2.4.3
  8. * @since 2.4.4 Fixed the "File not found error" & verified the authentication before resume download
  9. * @since 2.4.5 Resolved the resume downloading issue
  10. *
  11. * @package Simple_Job_Board
  12. * @subpackage Simple_Job_Board/includes
  13. * @author PressTigers <support@presstigers.com>
  14. */
  15. class Simple_Job_Board_Resume_Download_Handler {
  16. /**
  17. * Initialize the class and set its properties.
  18. *
  19. * @since 1.0.0
  20. */
  21. public function __construct() {
  22. // Fire on Resume Download
  23. if ( isset( $_GET['resume_id'] ) || isset( $_GET['sjb_file'] ) ) {
  24. add_action('init', array( $this, 'download_resume' ) );
  25. }
  26. }
  27. /**
  28. * Download Resume
  29. *
  30. * @since 2.4.3
  31. */
  32. public function download_resume() {
  33. // Check for User login & its capabilities
  34. $this->check_user_login();
  35. // Resume Path
  36. if (isset($_GET['resume_id'])) {
  37. $file_path = get_post_meta(intval($_GET['resume_id']), 'resume_path', TRUE);
  38. } elseif (isset($_GET['sjb_file'])) {
  39. // Get Multiple Attachments Path
  40. $files = get_post_meta(intval($_GET['post']), 'attachments_meta', TRUE);
  41. $file_path = $files['base_dir'] . '/' . esc_attr($_GET['sjb_file']);
  42. }
  43. if ( file_exists( $file_path ) ) {
  44. // Resume Name
  45. $filename = basename($file_path);
  46. if ( !$filename ) {
  47. wp_die(__('File not found', 'simple-job-board'), '', array('response' => 404));
  48. }
  49. // Set Server Configuration
  50. $this->set_server_config();
  51. // Clear all Buffers
  52. $this->clean_buffers();
  53. // Set the headers to prevent caching for the different browsers
  54. nocache_headers();
  55. // Download Headers
  56. header("X-Robots-Tag: noindex, nofollow", TRUE);
  57. header("Content-Type: " . $this->get_resume_content_type($file_path));
  58. header("Content-Description: File Transfer");
  59. header("Content-Disposition: attachment; filename=\"" . $filename . "\";");
  60. header("Content-Transfer-Encoding: binary");
  61. // Get File Size & Set Content Header
  62. if ($size = @filesize($file_path)) {
  63. header("Content-Length: " . $size);
  64. }
  65. if (!$this->readfile_chunked($file_path)) {
  66. header('Location: ' . $file_path);
  67. }
  68. } else {
  69. wp_die(__('File not found', 'simple-job-board'), '', array('response' => 404));
  70. }
  71. exit;
  72. }
  73. /**
  74. * Check login first before download file.
  75. *
  76. * @access private
  77. * @since 2.4.4
  78. */
  79. private function check_user_login() {
  80. if (!is_user_logged_in()) {
  81. wp_die( __('You must be logged in to download files.', 'simple-job-board') . ' <a href="' . esc_url(wp_login_url()) . '" >' . __('Login', 'simple-job-board') . '</a>', 403);
  82. } elseif (!current_user_can('download_resume' ) ) {
  83. wp_die(__('This is not your download link.', 'simple-job-board' ) . ' <a href="' . esc_url(get_admin_url()) . '" >' . __('Go to Dashboard', 'simple-job-board') . '</a>', 403);
  84. }
  85. }
  86. /**
  87. * Set Sever Config variables
  88. *
  89. * Check and set certain server config variables to ensure downloads work as intended.
  90. *
  91. * @since 2.4.3
  92. */
  93. private function set_server_config() {
  94. $this->set_time_limit(0); // No Time Limit
  95. // Sets the current active configuration's setting of magic_quotes_runtime
  96. if (function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime() && version_compare(phpversion(), '5.4', '<')) {
  97. set_magic_quotes_runtime(0);
  98. }
  99. // Disable mod_deflate
  100. if (function_exists('apache_setenv')) {
  101. @apache_setenv('no-gzip', 1);
  102. }
  103. @ini_set('zlib.output_compression', 'Off');
  104. // Write session data and end session
  105. @session_write_close();
  106. }
  107. /**
  108. * Clean all output buffers.
  109. *
  110. * Can prevent errors, for example: transfer closed with 3 bytes remaining to read.
  111. *
  112. * @since 2.4.3
  113. *
  114. * @access private
  115. */
  116. private function clean_buffers() {
  117. if (ob_get_level()) {
  118. $levels = ob_get_level();
  119. for ($i = 0; $i < $levels; $i++) {
  120. @ob_end_clean();
  121. }
  122. } else {
  123. @ob_end_clean();
  124. }
  125. }
  126. /**
  127. * Set execution time to no limit
  128. *
  129. * @since 2.4.3
  130. */
  131. private function set_time_limit($limit = 0) {
  132. if (function_exists('set_time_limit') && FALSE === strpos(ini_get('disable_functions'), 'set_time_limit') && !ini_get('safe_mode')) {
  133. @set_time_limit($limit);
  134. }
  135. }
  136. /**
  137. * Get Content Type of Resume
  138. *
  139. * @since 2.4.3
  140. * @access private
  141. *
  142. * @param string $file_path Resume Path
  143. * @return string
  144. */
  145. private function get_resume_content_type($file_path) {
  146. $file_extension = strtolower(substr(strrchr($file_path, "."), 1));
  147. $ctype = "application/force-download";
  148. // Checked for Allowed Mime Type
  149. foreach (get_allowed_mime_types() as $mime => $type) {
  150. $mimes = explode('|', $mime);
  151. if (in_array($file_extension, $mimes)) {
  152. $ctype = $type;
  153. break;
  154. }
  155. }
  156. return $ctype;
  157. }
  158. /**
  159. * readfile_chunked.
  160. *
  161. * Reads file in chunks so big downloads are possible without changing PHP.INI - http://codeigniter.com/wiki/Download_helper_for_large_files/.
  162. *
  163. * @since 2.4.3
  164. * @access private
  165. *
  166. * @param string $file
  167. * @return bool Success or fail
  168. */
  169. private function readfile_chunked($file) {
  170. $chunksize = 1024 * 1024;
  171. // Open Resume
  172. $handle = @fopen($file, 'r');
  173. if (false === $handle) {
  174. return FALSE;
  175. }
  176. while (!@feof($handle)) {
  177. echo @fread($handle, $chunksize);
  178. if (ob_get_length()) {
  179. ob_flush();
  180. flush();
  181. }
  182. }
  183. return @fclose($handle);
  184. }
  185. }
  186. new Simple_Job_Board_Resume_Download_Handler();