pdfemb_secure = $pdfemb_secure; $this->pdfemb_cacheencrypted = $pdfemb_cacheencrypted; } /** * Undocumented function * * @return void */ public function intercept_uploads() { // Called in admin_init. add_filter( 'wp_handle_upload_prefilter', array( $this, 'custom_upload_filter' ) ); } /** * Undocumented function * * @return void */ public function handle_downloads() { // Called in init. if ( ! isset( $_GET['pdfemb-serveurl'] ) && ! isset( $_GET['pdfemb-nonce'] ) ) { return; } if ( 'POST' !== $_SERVER['REQUEST_METHOD'] && ! isset( $_GET['pdfemb-nonce'] ) ) { return; } $direct_download = false; if ( isset( $_GET['pdfemb-nonce'] ) ) { if ( ! wp_verify_nonce( $_GET['pdfemb-nonce'], 'pdfemb-secure-download-' . $_GET['pdfemb-serveurl'] ) ) { return; } else { $direct_download = true; } } $pdfurl = $_GET['pdfemb-serveurl']; $filepath = $this->get_secure_path( $pdfurl ); if ( '' !== $filepath && file_exists( $filepath ) ) { $filename = basename( $filepath ); if ( ! $this->is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) { // @codingStandardsIgnoreLine @set_time_limit( 0 ); // @codingStandardsIgnoreLine } if ( function_exists( 'get_magic_quotes_runtime' ) && get_magic_quotes_runtime() && version_compare( phpversion(), '5.4', '<' ) ) { // @codingStandardsIgnoreLine set_magic_quotes_runtime( 0 ); // @codingStandardsIgnoreLine } @session_write_close(); // @codingStandardsIgnoreLine if ( function_exists( 'apache_setenv' ) ) { @apache_setenv( 'no-gzip', 1 ); // @codingStandardsIgnoreLine } @ini_set( 'zlib.output_compression', 'Off' ); // @codingStandardsIgnoreLine if ( ob_get_length() ) { ob_clean(); // Clear output buffer in case Unicode BOM was added by a PHP file saved in wrong encoding. } nocache_headers(); header( 'Robots: none' ); header( 'Content-Type: application/octet-stream' ); header( 'Content-Description: File Transfer' ); header( 'Content-Disposition: attachment; filename="' . $filename . ( $direct_download ? '' : '.binary' ) . '"' ); header( 'Content-Transfer-Encoding: binary' ); if ( ! class_exists( 'WP_PDF_SimpleRC4' ) ) { include_once dirname( __FILE__ ) . '/rc4_simple.php'; } $sk = $this->get_secret_key(); $filetime = filemtime( $filepath ); $cache_to_file = ( false !== $filetime && ! $direct_download && $this->pdfemb_cacheencrypted ? $filepath . '.encrypted-cache.' . md5( $filetime . '-' . $sk ) . '.pdf' : '' ); $myrc4 = $direct_download ? new WP_PDF_DirectRC4( '' ) : new WP_PDF_SimpleRC4( $sk ); $this->readfile_chunked( $filepath, true, $myrc4, $cache_to_file ); } else { header( 'Location: ' . $pdfurl ); } exit(); } /** * Helper Method to get secure * * @param string $pdfurl PDF Url. * @return string */ public function get_secure_path( $pdfurl ) { $upload_dir = wp_upload_dir(); $basedir = trailingslashit( $upload_dir['basedir'] ) . 'securepdfs/'; $baseurl = trailingslashit( set_url_scheme( $upload_dir['baseurl'] ) ) . 'securepdfs/'; $regex = '|^' . $baseurl . '(([^/]+/)*([^/]+\.pdf))$|'; $matches = array(); if ( preg_match( $regex, set_url_scheme( $pdfurl ), $matches ) ) { // Check for .. tricks. if ( ! preg_match( '|[\\\/]\.\.[\\\/]|', $pdfurl ) && strpos( $pdfurl, '\\' ) === false ) { return $basedir . $matches[1]; } } return ''; // Wasn't a secure PDF. } /** * Hash * * @var string */ protected $myrc4; /** * Read Chunk file * * @param string $file File. * @param bool $retbytes Retbytes. * @param bool $myrc4 RC4. * @param string $cache_to_file file to cache. * @return mixed */ protected function readfile_chunked( $file, $retbytes = true, $myrc4 = false, $cache_to_file = '' ) { $chunksize = 1024 * 1024; $buffer = ''; $cnt = 0; $reading_from_cache = false; $handle = false; $cache_handle = false; if ( '' !== $cache_to_file ) { $cache_handle = @fopen( $cache_to_file, 'r' ); // @codingStandardsIgnoreLine if ( false === $cache_handle ) { $cache_handle = @fopen( $cache_to_file, 'w' ); // @codingStandardsIgnoreLine } else { // Read from cache. $reading_from_cache = true; $handle = $cache_handle; $cache_handle = false; } } $size = @filesize( $file ); // @codingStandardsIgnoreLine if ( $reading_from_cache && @filesize( $cache_to_file ) != $size ) { // @codingStandardsIgnoreLine // Revert back to non-cached version since can't be trusted. error_log( 'Cached encrypted PDF was not of correct filesize: ' . $cache_to_file ); $handle = false; $reading_from_cache = false; $cache_handle = false; } if ( false === $handle ) { $handle = @fopen( $file, 'r' ); // @codingStandardsIgnoreLine } if ( false === $handle ) { return false; } if ( $size = @filesize( $file ) ) { // @codingStandardsIgnoreLine header( 'Content-Length: ' . $size ); } while ( ! @feof( $handle ) ) { // @codingStandardsIgnoreLine $buffer = @fread( $handle, $chunksize ); // @codingStandardsIgnoreLine if ( ! $reading_from_cache ) { $buffer = $myrc4->rc4_encrypt_block( $buffer ); } echo $buffer; // @codingStandardsIgnoreLine if ( ! $reading_from_cache && false !== $cache_handle ) { // Write to cache. @fwrite( $cache_handle, $buffer ); // @codingStandardsIgnoreLine } if ( $retbytes ) { $cnt += strlen( $buffer ); } } $status = @fclose( $handle ); // @codingStandardsIgnoreLine if ( false !== $cache_handle ) { @fclose( $cache_handle ); // @codingStandardsIgnoreLine } if ( $retbytes && $status ) { return $cnt; } return $status; } /** * Helper method for Secret Key * * @return string */ public function get_secret_key() { $sk = get_site_option( 'pdfemb-sk' ); if ( false === $sk ) { $sk = md5( sprintf( 'pdfemb-%d-%d', wp_rand(), time() ) ); update_site_option( 'pdfemb-sk', $sk, 60 * 60 * 12 ); } return $sk; } /** * Helper Method for Custom Upload Filter. * * @param string $file Upload File. * @return string */ public function custom_upload_filter( $file ) { if ( 'application/pdf' === $file['type'] && $this->pdfemb_secure ) { add_filter( 'upload_dir', array( $this, 'custom_upload_dir' ) ); } return $file; } /** * Undocumented function * * @param string $function Function. * @return bool */ protected function is_func_disabled( $function ) { $disabled = explode( ',', ini_get( 'disable_functions' ) ); return in_array( $function, $disabled, true ); } /** * Undocumented function * * @param array $upload Upload. * @return array */ public function custom_upload_dir( $upload ) { // Override the year / month being based on the post publication date, if year/month organization is enabled. if ( get_option( 'uploads_use_yearmonth_folders' ) ) { // Generate the yearly and monthly dirs. $time = current_time( 'mysql' ); $y = substr( $time, 0, 4 ); $m = substr( $time, 5, 2 ); $upload['subdir'] = "/$y/$m"; } $upload['subdir'] = '/securepdfs' . $upload['subdir']; $upload['path'] = $upload['basedir'] . $upload['subdir']; $upload['url'] = $upload['baseurl'] . $upload['subdir']; return $upload; } /** * Helper Method to create protected files * * @param bool $force Force Upload. * @param string $method Protected method. * @return void */ public function create_protection_files( $force = false, $method = false ) { if ( false === get_transient( 'pdfemb_check_protection_files' ) || $force ) { $wp_upload_dir = wp_upload_dir(); $upload_path = $wp_upload_dir['basedir'] . '/securepdfs'; wp_mkdir_p( $upload_path ); // Make sure the /edd folder is created. wp_mkdir_p( $upload_path ); // Top level .htaccess file. $rules = $this->get_htaccess_rules( $method ); if ( file_exists( $upload_path . '/.htaccess' ) ) { $contents = @file_get_contents( $upload_path . '/.htaccess' ); // @codingStandardsIgnoreLine if ( $contents !== $rules ) { // Update the .htaccess rules if they don't match. @file_put_contents( $upload_path . '/.htaccess', $rules ); // @codingStandardsIgnoreLine } } elseif ( wp_is_writable( $upload_path ) ) { // Create the file if it doesn't exist. @file_put_contents( $upload_path . '/.htaccess', $rules ); // @codingStandardsIgnoreLine } // Top level blank index.php. if ( ! file_exists( $upload_path . '/index.php' ) && wp_is_writable( $upload_path ) ) { @file_put_contents( $upload_path . '/index.php', 'scan_folders( $upload_path, $folders ); foreach ( $folders as $folder ) { // Create index.php, if it doesn't exist. if ( ! file_exists( $folder . 'index.php' ) && wp_is_writable( $folder ) ) { @file_put_contents( $folder . 'index.php', '\n"; $rules .= " \n"; $rules .= " Order Deny,Allow\n"; $rules .= " Deny from all\n"; $rules .= " \n"; $rules .= " Order Allow,Deny\n"; $rules .= " Allow from all\n"; $rules .= " \n"; $rules .= " \n"; $rules .= " = 2.4>\n"; $rules .= " Require all denied\n"; $rules .= " \n"; $rules .= " Require all granted\n"; $rules .= " \n"; $rules .= " \n"; $rules .= "\n"; $rules .= "\n"; $rules .= " \n"; $rules .= " Order Deny,Allow\n"; $rules .= " Deny from all\n"; $rules .= " \n"; $rules .= " Order Allow,Deny\n"; $rules .= " Allow from all\n"; $rules .= " \n"; $rules .= " \n"; $rules .= " \n"; $rules .= " Require all denied\n"; $rules .= " \n"; $rules .= " Require all granted\n"; $rules .= " \n"; $rules .= " \n"; $rules .= "\n"; break; } return $rules; } /** * Helper Method to scan folders * * @param string $path Path. * @param string $return Return Path. * @return void */ protected function scan_folders( $path, &$return ) { $lists = @scandir( $path ); // @codingStandardsIgnoreLine if ( ! empty( $lists ) ) { foreach ( $lists as $f ) { if ( is_dir( $path . DIRECTORY_SEPARATOR . $f ) && '.' !== $f && '..' !== $f ) { $finaldirpath = trailingslashit( $path . DIRECTORY_SEPARATOR . $f ); if ( ! in_array( $finaldirpath, $return, true ) ) { $return[] = $finaldirpath; } $this->scan_folders( $path . DIRECTORY_SEPARATOR . $f, $return ); } } } } }