Your IP : 216.73.217.143


Current Path : /home/ereika83/public_html/wp-content/plugins/secure-downloads/core/
Upload File :
Current File : /home/ereika83/public_html/wp-content/plugins/secure-downloads/core/opsd-download.php

<?php 
/**
 * @version 1.0
 * @package File Download
 * @subpackage Support Download Functions
 * @category Functions
 * 
 * @author wpdevelop
 * @link https://oplugins.com/
 * @email info@oplugins.com
 *
 * @modified 29.09.2015
 */

if ( ! defined( 'ABSPATH' ) ) exit;                                             // Exit if accessed directly


////////////////////////////////////////////////////////////////////////////////
// Force File Download in Browser
////////////////////////////////////////////////////////////////////////////////

/** Class for force File Downloading in Browser.
 *  Usage:
 * 
    $file_link = 'http://serer.com/XXXXXXXXXX/some_product_name.zip';
	$result = OPSD_Download::start_download_process( $file_link );
	
	if ( $result['error'] === 0 ) {  Success } else { Parse error code }
 * 
 *  Return:
 *			array( 'file' => array(
								[url] => http://serer.com/XXXXXXXXXX/some_product_name.zip
								[local_path] => Z:\home\new\serer.com/XXXXXXXXXX/some_product_name.zip
								[name] => some_product_name.zip
								[extension] => zip
								[size] => 114480888
								[readable_size] => 109.18 MB
								[is_local] => 0
								[content_type] => application/octet-stream
						 )
				, 'error' => 0		// 0 | 'file_not_exist' | 'error_opening_file'
			)	
 */
class OPSD_Download {
	
	
	/** Start Download Process in browser
	 * 
	 * @param string $file_url - real URL to file
	 * @return array		   - array( 'file' => array(
														[url] => http://serer.com/XXXXXXXXXX/some_product_name.zip
														[local_path] => Z:\home\new\serer.com/XXXXXXXXXX/some_product_name.zip
														[name] => some_product_name.zip
														[extension] => zip
														[size] => 114480888
														[readable_size] => 109.18 MB
														[is_local] => 0
														[content_type] => application/octet-stream
												 )
										, 'error' => 0		// 0 | 'file_not_exist' | 'error_opening_file'
									)	
	 */
	public static function start_download_process( $file_url = '' ) {

		$file = array();
		
		$file[ 'url' ] = $file_url;

		$file[ 'local_path' ] = self::get_local_path_from_real_link( $file[ 'url' ] );

		// If File Exist
		if ( ! file_exists( $file[ 'local_path' ] ) ) {
			return array( 'file' => $file, 'error' => 'file_not_exist' );
		}

		$file[ 'name' ] = self::get_file_name_from_path( $file[ 'local_path' ] );		// product_premium.zip

		$file[ 'extension' ] = self::get_file_extension( $file[ 'name' ] );				// zip

		$file[ 'size' ] = self::get_file_size( $file[ 'local_path' ] );					// XXX bytes

		$file[ 'readable_size' ] = self::readable_format_file_size( $file[ 'size' ] );	// 2.93 MB

		$file[ 'is_local' ] = (int) self::is_file_local( $file[ 'url' ] );				// 1 | 0

		$file[ 'content_type' ] = self::get_file_content_type( $file[ 'extension' ] );	// application/zip

		
		$headers = self::get_all_headers();		// May be resume download
		
		if ( in_array( $file[ 'extension' ], array( 'php' ) ) ) {		
			return array( 'file' => $file, 'error' => 'file_not_permit' );	
			/*
			// Probabaly  its does not secure way  of including PHP files in such  way,  so do  not permit it.
			 include $file['local_path'];
			 return array( 'file' => $file, 'error' => 0 );
			 */
		}
		
		if ( headers_sent() ){
			return array( 'file' => $file, 'error' => 'headers_sent_before_download' );
		}
		
		
		if (  isset( $headers[ "Range" ] ) ) {	// Resume file download
						
			self::prepare_system_before_download_file();								// Prepeare system				// set time limits, server output options,  etc...

			$file_read_is_success = self::file_resume_download( $file , $headers );		// Set  headers and Output file

		} else {								// Ususal file download
			
			$file['url'] = str_replace( " ", "%20", $file['url'] );
			
			self::prepare_system_before_download_file();								// Prepeare system				// set time limits, server output options,  etc...
						
			self::set_headers_for_file_download( $file );								// H E A D E R S
			
			$file_read_is_success = self::readfile_by_parts( $file['local_path'] );			// Output file
		}
		

		if ( ! $file_read_is_success ) {
			return array( 'file' => $file, 'error' => 'error_opening_file' );
		}
							
		return array( 'file' => $file, 'error' => 0 );
	}
	

	/** Resume download of file,  in case if connection was aborted	- "header: 206 Partial content"
	 * 
	 * @param array $file
	 * @param array $headers
	 * @return boolean - TRUE on success or FALSE on failure.
	 */
	public static function file_resume_download( $file, $headers ) {

		// H E A D E R S
		@header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 206 Partial content' . "\n" );

		//nocache_headers();		
		header( "Robots: none" . "\n" );
		header( "Content-Type: " . $file['content_type'] . "\n" );
		header( "Content-Description: File Transfer" . "\n" );
		header( "Content-Disposition: attachment; filename=\"" . $file['name'] . "\"" . "\n" );
		header( "Content-Transfer-Encoding: binary" . "\n" );

		if ( 1 ) {
			$content_length = '';
			$val = split( "=", $headers[ "Range" ] );
			if ( ereg( "^-", $val[ 1 ] ) ) {
				$slen = ereg_replace( "-", "", $val[ 1 ] );
				$file_seek_offset = $file['size'] - $slen;
				$content_length = $slen;
			} else if ( ereg( "-$", $val[ 1 ] ) ) {
				$file_seek_offset = ereg_replace( "-", "", $val[ 1 ] );
				$slen = $file['size'] - $file_seek_offset;
				$content_length = (string) ((int) $file['size'] - (int) $file_seek_offset);
			} else if ( is_integer( strpos( $val[ 1 ], "-" ) ) ) {
				$ranges = split( "-", $val[ 1 ] );
				$file_seek_offset = $ranges[ 0 ];
				$slen = $ranges[ 1 ] - $ranges[ 0 ];
				$content_length = (string) ((int) $file['size'] - (int) $file_seek_offset);
			}
		}	
		header( "Content-Length: " . $content_length . "\n" );

		$br = $file_seek_offset . "-" . (string) ($file['size'] - 1) . "/" . $file['size'];
		header( "Content-Range: bytes " . $br . "\n" );
		header( "Connection: close" );

		// Important! During Resume downloading instead of URL we need to open file with local path, 
		// otherwsie fseek will not work  and generate an error.	
		
		if ( true ) {
			
			$file_read_status = self::readfile_by_parts( $file['local_path'],  $file_seek_offset );
			
		} else {		
			// Alternative way  of outputting data
			$file_read_status = self::readfile_by_fpassthru( $file['local_path'],  $file_seek_offset );
		}
		
		return $file_read_status;
	}
	
	
	/** Output all remaining data on a file pointer
	 * 
	 * @param string $file_url
	 * @return boolean	- TRUE on success or FALSE on failure.
	 */
	public static function readfile_by_parts( $file_url , $file_seek_offset = false ) {

		/** @fopen( $file_url, 'rb' );
		 *  Windows offers a text-mode translation flag ('t') which will transparently translate \n to \r\n when working with the file. 
		 *  In contrast, you can also use 'b' to force binary mode, which will not translate your data. 
		 *  To use these flags, specify either 'b' or 't' as the last character of the mode parameter. 
		 */

		// Open
		$handle    = @fopen( $file_url, 'rb' );																				
		if ( false === $handle ) {
			return false;
		}

		// If we resume download,  so  then set file pointer to  specific position
		if ( $file_seek_offset !== false ) {
			$seek_result = @fseek( $handle, $file_seek_offset );		// Upon success, returns 0; otherwise, returns -1. 
		}
		
		// Read
		$buffer    = '';
		$part_size = 1024 * 1024;
// $part_size = 1024 * 8;	// Read by  8 Kbytes
// $e=0;																												// Simulation! 		
		while ( ! @feof( $handle ) ) {
			$buffer = @fread( $handle, $part_size );
			echo $buffer;
// $e++; if ( $e > 10 ) { exit; }																						// Simulation! generate connection  error after receiving 10 Mb 
		}

		// Close
		$status = @fclose( $handle );

		return $status;
	}
	

			/** Alternative  way  of outputting data,  currently  does not used!
			 *  Output remaining data during file resume downloading
			 * 
			 * @param string $file_url
			 * @return boolean - TRUE on success or FALSE on failure.
			 */
			public static function readfile_by_fpassthru( $file_local_path,  $file_seek_offset ) {

				// Open
				$handle    = @fopen( $file_local_path, 'rb' );		

				if ( false === $handle ) {
					return false;
				}

				$seek_result = @fseek( $handle, $file_seek_offset );		// Upon success, returns 0; otherwise, returns -1. 

				global $downloadbuffer;

				if ( $downloadbuffer > 0 ) {
					//@set_time_limit( 86400 );
					while ( ! @feof( $handle ) ) {
						print( @fread( $handle, $downloadbuffer ) );
						ob_flush();
						flush();
						sleep( 1 );
					}
					$status = @fclose( $handle );
				} else {
					$status = @fpassthru( $handle );
				}
				return (bool) $status;
			}

	
	//   P r e p a r e     S y s t e m
			
	/** Set Headers before file download 
	 * 
	 * @param array $file  array( 'content_type' => '...', 'name' => '...', 'size' => '...' )
	 */
	public static function set_headers_for_file_download( $file ) {

		nocache_headers();		
		header( "Robots: none" . "\n" );
		@header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 200 OK' . "\n" );
		header( "Content-Type: " . $file['content_type'] . "\n" );
		header( "Content-Description: File Transfer" . "\n" );
		header( "Content-Disposition: attachment; filename=\"" . $file['name'] . "\"" . "\n" );
		header( "Content-Transfer-Encoding: binary" . "\n" );

		if ( (int) $file['size'] > 0 )
			header( "Content-Length: " . $file['size'] . "\n" );
	}


	/** Prepare system before downloading 
	 *  set time limits, server output options 
	 */
	public static function prepare_system_before_download_file() {

		$disabled = explode( ',', ini_get( 'disable_functions' ) );
		$is_func_disabled = in_array( 'set_time_limit', $disabled );
		if ( ! $is_func_disabled && ! ini_get( 'safe_mode' ) ) {
			@set_time_limit( 0 );
		}
		//FixIn: 1.2.3
//		if ( function_exists( 'get_magic_quotes_runtime' ) && get_magic_quotes_runtime() && version_compare( phpversion(), '5.4', '<' ) ) {
//			set_magic_quotes_runtime( 0 );
//		}

		@session_write_close();
		if ( function_exists( 'apache_setenv' ) ) {
			@apache_setenv( 'no-gzip', 1 );
		}
		@ini_set( 'zlib.output_compression', 'Off' );
		
		@ob_end_clean();	// In case,  if somewhere opeded output buffer, may be  required for working fpassthru with  large files 
	}
	
	
	//   S u p p o r t     F u n c t i o n s

	/** Get local path to file from real link to file
	 * 
	 * @param string $file_link
	 */
	public static function get_local_path_from_real_link( $file_url ) {

		$file_local_path = str_replace( site_url(), '', $file_url );

		$file_local_path = trailingslashit( ABSPATH ) . ltrim( $file_local_path, '/\\' );

		return $file_local_path;
	}


	/** Get file name from path or URL
	 * 
	 * @param string $file_path		- Local path or URL
	 * @return string
	 */
	public static function get_file_name_from_path( $file_path ) {

		$file_name = str_replace( '\\', '/', $file_path );	
		$file_name = explode( '/', $file_name );
		$file_name = end( $file_name );

		return $file_name;
	}


	/** Get file extension from  file name
	 * 
	 * @param string $file_name
	 * @return string
	 */
	public static function get_file_extension( $file_name ) {

		$file_extension = explode( '.', $file_name );
		$file_extension = end( $file_extension );

		return $file_extension;
	}


	/** Get file size if not defined
	* 
	* @param string $url
	* @return int
	*/
	public static function get_file_size( $url ) {

		$size = 0;

		$pos1 = strpos( strtolower( $url ), "http://" );
		$pos2 = strpos( strtolower( $url ), "https://" );

		if ( is_integer( $pos1 ) ||  is_integer( $pos2 ) ) {
			$s = self::get_file_size_remote( $url );
			if ( is_integer( $s ) )
				$size = $s;
		} else {
			$size = @filesize( $url );
		}
		return $size;

	}


	/** Get file size in URL
	 * 
	 * @param string $url
	 * @return int | false
	 */
	public static function get_file_size_remote( $url ) {

		$url = parse_url( $url );
		if ( $fp = @fsockopen( $url[ 'host' ], ($url[ 'port' ] ? $url[ 'port' ] : 80 ), $errno, $errstr, $timeout ) ) {
			fwrite( $fp, 'HEAD ' . $url[ 'path' ] . ( ( !empty( $url[ 'query' ] ) ) ? $url[ 'query' ] : '' ) . " HTTP/1.0\r\nHost: " . $url[ 'host' ] . "\r\n\r\n" );
			@stream_set_timeout( $fp, $timeout );
			while ( ! feof( $fp ) ) {
				$size = fgets( $fp, 4096 );
				if ( stristr( $size, 'Content-Length' ) !== false ) {
					$size = trim( substr( $size, 16 ) );
					break;
				}
			}
			fclose( $fp );
		}
		return is_numeric( $size ) ? intval( $size ) : false;
	}


	/** Show File Size in readable format
	 * 
	 * @param int $bytes
	 * @return string
	 */
	public static function readable_format_file_size( $bytes ) {
		if ( $bytes >= 1073741824 ) {
			$bytes = number_format( $bytes / 1073741824, 2 ) . ' GB';
		} elseif ( $bytes >= 1048576 ) {
			$bytes = number_format( $bytes / 1048576, 2 ) . ' MB';
		} elseif ( $bytes >= 1024 ) {
			$bytes = number_format( $bytes / 1024, 2 ) . ' kB';
		} elseif ( $bytes > 1 ) {
			$bytes = $bytes . ' bytes';
		} elseif ( $bytes == 1 ) {
			$bytes = $bytes . ' byte';
		} else {
			$bytes = '0 bytes';
		}

		return $bytes;
	}


	/** Check if this file local or URL
	 *  
	 * @param type $file - file path or url
	 * @return bool
	 */
	public static function is_file_local( $file ) {

		$file = strtolower( $file );

		$is_found_url = preg_match( '#https?://#', $file, $matches, PREG_OFFSET_CAPTURE );

		return ! $is_found_url;
	}


	/** Get Content type of file
	 * 
	 * @param string $ext	- zip
	 * @return string		- 'application/octet-stream'
	 */
	public static function get_file_content_type( $ext ) {

		$c_types = array();
		if ( 1 ) {
			$c_types[ 'ac' ] = "application/pkix-attr-cert";
			$c_types[ 'adp' ] = "audio/adpcm";
			$c_types[ 'ai' ] = "application/postscript";
			$c_types[ 'aif' ] = "audio/x-aiff";
			$c_types[ 'aifc' ] = "audio/x-aiff";
			$c_types[ 'aiff' ] = "audio/x-aiff";
			$c_types[ 'air' ] = "application/vnd.adobe.air-application-installer-package+zip";
			$c_types[ 'apk' ] = "application/vnd.android.package-archive";
			$c_types[ 'asc' ] = "application/pgp-signature";
			$c_types[ 'atom' ] = "application/atom+xml";
			$c_types[ 'atomcat' ] = "application/atomcat+xml";
			$c_types[ 'atomsvc' ] = "application/atomsvc+xml";
			$c_types[ 'au' ] = "audio/basic";
			$c_types[ 'aw' ] = "application/applixware";
			$c_types[ 'avi' ] = "video/x-msvideo";
			$c_types[ 'bcpio' ] = "application/x-bcpio";
			$c_types[ 'bin' ] = "application/octet-stream";
			$c_types[ 'bmp' ] = "image/bmp";
			$c_types[ 'boz' ] = "application/x-bzip2";
			$c_types[ 'bpk' ] = "application/octet-stream";
			$c_types[ 'bz' ] = "application/x-bzip";
			$c_types[ 'bz2' ] = "application/x-bzip2";
			$c_types[ 'ccxml' ] = "application/ccxml+xml";
			$c_types[ 'cdmia' ] = "application/cdmi-capability";
			$c_types[ 'cdmic' ] = "application/cdmi-container";
			$c_types[ 'cdmid' ] = "application/cdmi-domain";
			$c_types[ 'cdmio' ] = "application/cdmi-object";
			$c_types[ 'cdmiq' ] = "application/cdmi-queue";
			$c_types[ 'cdf' ] = "application/x-netcdf";
			$c_types[ 'cer' ] = "application/pkix-cert";
			$c_types[ 'cgm' ] = "image/cgm";
			$c_types[ 'class' ] = "application/octet-stream";
			$c_types[ 'cpio' ] = "application/x-cpio";
			$c_types[ 'cpt' ] = "application/mac-compactpro";
			$c_types[ 'crl' ] = "application/pkix-crl";
			$c_types[ 'csh' ] = "application/x-csh";
			$c_types[ 'css' ] = "text/css";
			$c_types[ 'cu' ] = "application/cu-seeme";
			$c_types[ 'davmount' ] = "application/davmount+xml";
			$c_types[ 'dbk' ] = "application/docbook+xml";
			$c_types[ 'dcr' ] = "application/x-director";
			$c_types[ 'deploy' ] = "application/octet-stream";
			$c_types[ 'dif' ] = "video/x-dv";
			$c_types[ 'dir' ] = "application/x-director";
			$c_types[ 'dist' ] = "application/octet-stream";
			$c_types[ 'distz' ] = "application/octet-stream";
			$c_types[ 'djv' ] = "image/vnd.djvu";
			$c_types[ 'djvu' ] = "image/vnd.djvu";
			$c_types[ 'dll' ] = "application/octet-stream";
			$c_types[ 'dmg' ] = "application/octet-stream";
			$c_types[ 'dms' ] = "application/octet-stream";
			$c_types[ 'doc' ] = "application/msword";
			$c_types[ 'docx' ] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
			$c_types[ 'dotx' ] = "application/vnd.openxmlformats-officedocument.wordprocessingml.template";
			$c_types[ 'dssc' ] = "application/dssc+der";
			$c_types[ 'dtd' ] = "application/xml-dtd";
			$c_types[ 'dump' ] = "application/octet-stream";
			$c_types[ 'dv' ] = "video/x-dv";
			$c_types[ 'dvi' ] = "application/x-dvi";
			$c_types[ 'dxr' ] = "application/x-director";
			$c_types[ 'ecma' ] = "application/ecmascript";
			$c_types[ 'elc' ] = "application/octet-stream";
			$c_types[ 'emma' ] = "application/emma+xml";
			$c_types[ 'eps' ] = "application/postscript";
			$c_types[ 'epub' ] = "application/epub+zip";
			$c_types[ 'etx' ] = "text/x-setext";
			$c_types[ 'exe' ] = "application/octet-stream";
			$c_types[ 'exi' ] = "application/exi";
			$c_types[ 'ez' ] = "application/andrew-inset";
			$c_types[ 'f4v' ] = "video/x-f4v";
			$c_types[ 'fli' ] = "video/x-fli";
			$c_types[ 'flv' ] = "video/x-flv";
			$c_types[ 'gif' ] = "image/gif";
			$c_types[ 'gml' ] = "application/srgs";
			$c_types[ 'gpx' ] = "application/gml+xml";
			$c_types[ 'gram' ] = "application/gpx+xml";
			$c_types[ 'grxml' ] = "application/srgs+xml";
			$c_types[ 'gtar' ] = "application/x-gtar";
			$c_types[ 'gxf' ] = "application/gxf";
			$c_types[ 'hdf' ] = "application/x-hdf";
			$c_types[ 'hqx' ] = "application/mac-binhex40";
			$c_types[ 'htm' ] = "text/html";
			$c_types[ 'html' ] = "text/html";
			$c_types[ 'ice' ] = "x-conference/x-cooltalk";
			$c_types[ 'ico' ] = "image/x-icon";
			$c_types[ 'ics' ] = "text/calendar";
			$c_types[ 'ief' ] = "image/ief";
			$c_types[ 'ifb' ] = "text/calendar";
			$c_types[ 'iges' ] = "model/iges";
			$c_types[ 'igs' ] = "model/iges";
			$c_types[ 'ink' ] = "application/inkml+xml";
			$c_types[ 'inkml' ] = "application/inkml+xml";
			$c_types[ 'ipfix' ] = "application/ipfix";
			$c_types[ 'jar' ] = "application/java-archive";
			$c_types[ 'jnlp' ] = "application/x-java-jnlp-file";
			$c_types[ 'jp2' ] = "image/jp2";
			$c_types[ 'jpe' ] = "image/jpeg";
			$c_types[ 'jpeg' ] = "image/jpeg";
			$c_types[ 'jpg' ] = "image/jpeg";
			$c_types[ 'js' ] = "application/javascript";
			$c_types[ 'json' ] = "application/json";
			$c_types[ 'jsonml' ] = "application/jsonml+json";
			$c_types[ 'kar' ] = "audio/midi";
			$c_types[ 'latex' ] = "application/x-latex";
			$c_types[ 'lha' ] = "application/octet-stream";
			$c_types[ 'lrf' ] = "application/octet-stream";
			$c_types[ 'lzh' ] = "application/octet-stream";
			$c_types[ 'lostxml' ] = "application/lost+xml";
			$c_types[ 'm3u' ] = "audio/x-mpegurl";
			$c_types[ 'm4a' ] = "audio/mp4a-latm";
			$c_types[ 'm4b' ] = "audio/mp4a-latm";
			$c_types[ 'm4p' ] = "audio/mp4a-latm";
			$c_types[ 'm4u' ] = "video/vnd.mpegurl";
			$c_types[ 'm4v' ] = "video/x-m4v";
			$c_types[ 'm21' ] = "application/mp21";
			$c_types[ 'ma' ] = "application/mathematica";
			$c_types[ 'mac' ] = "image/x-macpaint";
			$c_types[ 'mads' ] = "application/mads+xml";
			$c_types[ 'man' ] = "application/x-troff-man";
			$c_types[ 'mar' ] = "application/octet-stream";
			$c_types[ 'mathml' ] = "application/mathml+xml";
			$c_types[ 'mbox' ] = "application/mbox";
			$c_types[ 'me' ] = "application/x-troff-me";
			$c_types[ 'mesh' ] = "model/mesh";
			$c_types[ 'metalink' ] = "application/metalink+xml";
			$c_types[ 'meta4' ] = "application/metalink4+xml";
			$c_types[ 'mets' ] = "application/mets+xml";
			$c_types[ 'mid' ] = "audio/midi";
			$c_types[ 'midi' ] = "audio/midi";
			$c_types[ 'mif' ] = "application/vnd.mif";
			$c_types[ 'mods' ] = "application/mods+xml";
			$c_types[ 'mov' ] = "video/quicktime";
			$c_types[ 'movie' ] = "video/x-sgi-movie";
			$c_types[ 'm1v' ] = "video/mpeg";
			$c_types[ 'm2v' ] = "video/mpeg";
			$c_types[ 'mp2' ] = "audio/mpeg";
			$c_types[ 'mp2a' ] = "audio/mpeg";
			$c_types[ 'mp21' ] = "application/mp21";
			$c_types[ 'mp3' ] = "audio/mpeg";
			$c_types[ 'mp3a' ] = "audio/mpeg";
			$c_types[ 'mp4' ] = "video/mp4";
			$c_types[ 'mp4s' ] = "application/mp4";
			$c_types[ 'mpe' ] = "video/mpeg";
			$c_types[ 'mpeg' ] = "video/mpeg";
			$c_types[ 'mpg' ] = "video/mpeg";
			$c_types[ 'mpg4' ] = "video/mpeg";
			$c_types[ 'mpga' ] = "audio/mpeg";
			$c_types[ 'mrc' ] = "application/marc";
			$c_types[ 'mrcx' ] = "application/marcxml+xml";
			$c_types[ 'ms' ] = "application/x-troff-ms";
			$c_types[ 'mscml' ] = "application/mediaservercontrol+xml";
			$c_types[ 'msh' ] = "model/mesh";
			$c_types[ 'mxf' ] = "application/mxf";
			$c_types[ 'mxu' ] = "video/vnd.mpegurl";
			$c_types[ 'nc' ] = "application/x-netcdf";
			$c_types[ 'oda' ] = "application/oda";
			$c_types[ 'oga' ] = "application/ogg";
			$c_types[ 'ogg' ] = "application/ogg";
			$c_types[ 'ogx' ] = "application/ogg";
			$c_types[ 'omdoc' ] = "application/omdoc+xml";
			$c_types[ 'onetoc' ] = "application/onenote";
			$c_types[ 'onetoc2' ] = "application/onenote";
			$c_types[ 'onetmp' ] = "application/onenote";
			$c_types[ 'onepkg' ] = "application/onenote";
			$c_types[ 'opf' ] = "application/oebps-package+xml";
			$c_types[ 'oxps' ] = "application/oxps";
			$c_types[ 'p7c' ] = "application/pkcs7-mime";
			$c_types[ 'p7m' ] = "application/pkcs7-mime";
			$c_types[ 'p7s' ] = "application/pkcs7-signature";
			$c_types[ 'p8' ] = "application/pkcs8";
			$c_types[ 'p10' ] = "application/pkcs10";
			$c_types[ 'pbm' ] = "image/x-portable-bitmap";
			$c_types[ 'pct' ] = "image/pict";
			$c_types[ 'pdb' ] = "chemical/x-pdb";
			$c_types[ 'pdf' ] = "application/pdf";
			$c_types[ 'pki' ] = "application/pkixcmp";
			$c_types[ 'pkipath' ] = "application/pkix-pkipath";
			$c_types[ 'pfr' ] = "application/font-tdpfr";
			$c_types[ 'pgm' ] = "image/x-portable-graymap";
			$c_types[ 'pgn' ] = "application/x-chess-pgn";
			$c_types[ 'pgp' ] = "application/pgp-encrypted";
			$c_types[ 'pic' ] = "image/pict";
			$c_types[ 'pict' ] = "image/pict";
			$c_types[ 'pkg' ] = "application/octet-stream";
			$c_types[ 'png' ] = "image/png";
			$c_types[ 'pnm' ] = "image/x-portable-anymap";
			$c_types[ 'pnt' ] = "image/x-macpaint";
			$c_types[ 'pntg' ] = "image/x-macpaint";
			$c_types[ 'pot' ] = "application/vnd.ms-powerpoint";
			$c_types[ 'potx' ] = "application/vnd.openxmlformats-officedocument.presentationml.template";
			$c_types[ 'ppm' ] = "image/x-portable-pixmap";
			$c_types[ 'pps' ] = "application/vnd.ms-powerpoint";
			$c_types[ 'ppsx' ] = "application/vnd.openxmlformats-officedocument.presentationml.slideshow";
			$c_types[ 'ppt' ] = "application/vnd.ms-powerpoint";
			$c_types[ 'pptx' ] = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
			$c_types[ 'prf' ] = "application/pics-rules";
			$c_types[ 'ps' ] = "application/postscript";
			$c_types[ 'psd' ] = "image/photoshop";
			$c_types[ 'qt' ] = "video/quicktime";
			$c_types[ 'qti' ] = "image/x-quicktime";
			$c_types[ 'qtif' ] = "image/x-quicktime";
			$c_types[ 'ra' ] = "audio/x-pn-realaudio";
			$c_types[ 'ram' ] = "audio/x-pn-realaudio";
			$c_types[ 'ras' ] = "image/x-cmu-raster";
			$c_types[ 'rdf' ] = "application/rdf+xml";
			$c_types[ 'rgb' ] = "image/x-rgb";
			$c_types[ 'rm' ] = "application/vnd.rn-realmedia";
			$c_types[ 'rmi' ] = "audio/midi";
			$c_types[ 'roff' ] = "application/x-troff";
			$c_types[ 'rss' ] = "application/rss+xml";
			$c_types[ 'rtf' ] = "text/rtf";
			$c_types[ 'rtx' ] = "text/richtext";
			$c_types[ 'sgm' ] = "text/sgml";
			$c_types[ 'sgml' ] = "text/sgml";
			$c_types[ 'sh' ] = "application/x-sh";
			$c_types[ 'shar' ] = "application/x-shar";
			$c_types[ 'sig' ] = "application/pgp-signature";
			$c_types[ 'silo' ] = "model/mesh";
			$c_types[ 'sit' ] = "application/x-stuffit";
			$c_types[ 'skd' ] = "application/x-koan";
			$c_types[ 'skm' ] = "application/x-koan";
			$c_types[ 'skp' ] = "application/x-koan";
			$c_types[ 'skt' ] = "application/x-koan";
			$c_types[ 'sldx' ] = "application/vnd.openxmlformats-officedocument.presentationml.slide";
			$c_types[ 'smi' ] = "application/smil";
			$c_types[ 'smil' ] = "application/smil";
			$c_types[ 'snd' ] = "audio/basic";
			$c_types[ 'so' ] = "application/octet-stream";
			$c_types[ 'spl' ] = "application/x-futuresplash";
			$c_types[ 'spx' ] = "audio/ogg";
			$c_types[ 'src' ] = "application/x-wais-source";
			$c_types[ 'stk' ] = "application/hyperstudio";
			$c_types[ 'sv4cpio' ] = "application/x-sv4cpio";
			$c_types[ 'sv4crc' ] = "application/x-sv4crc";
			$c_types[ 'svg' ] = "image/svg+xml";
			$c_types[ 'swf' ] = "application/x-shockwave-flash";
			$c_types[ 't' ] = "application/x-troff";
			$c_types[ 'tar' ] = "application/x-tar";
			$c_types[ 'tcl' ] = "application/x-tcl";
			$c_types[ 'tex' ] = "application/x-tex";
			$c_types[ 'texi' ] = "application/x-texinfo";
			$c_types[ 'texinfo' ] = "application/x-texinfo";
			$c_types[ 'tif' ] = "image/tiff";
			$c_types[ 'tiff' ] = "image/tiff";
			$c_types[ 'torrent' ] = "application/x-bittorrent";
			$c_types[ 'tr' ] = "application/x-troff";
			$c_types[ 'tsv' ] = "text/tab-separated-values";
			$c_types[ 'txt' ] = "text/plain";
			$c_types[ 'ustar' ] = "application/x-ustar";
			$c_types[ 'vcd' ] = "application/x-cdlink";
			$c_types[ 'vrml' ] = "model/vrml";
			$c_types[ 'vsd' ] = "application/vnd.visio";
			$c_types[ 'vss' ] = "application/vnd.visio";
			$c_types[ 'vst' ] = "application/vnd.visio";
			$c_types[ 'vsw' ] = "application/vnd.visio";
			$c_types[ 'vxml' ] = "application/voicexml+xml";
			$c_types[ 'wav' ] = "audio/x-wav";
			$c_types[ 'wbmp' ] = "image/vnd.wap.wbmp";
			$c_types[ 'wbmxl' ] = "application/vnd.wap.wbxml";
			$c_types[ 'wm' ] = "video/x-ms-wm";
			$c_types[ 'wml' ] = "text/vnd.wap.wml";
			$c_types[ 'wmlc' ] = "application/vnd.wap.wmlc";
			$c_types[ 'wmls' ] = "text/vnd.wap.wmlscript";
			$c_types[ 'wmlsc' ] = "application/vnd.wap.wmlscriptc";
			$c_types[ 'wmv' ] = "video/x-ms-wmv";
			$c_types[ 'wmx' ] = "video/x-ms-wmx";
			$c_types[ 'wrl' ] = "model/vrml";
			$c_types[ 'xbm' ] = "image/x-xbitmap";
			$c_types[ 'xdssc' ] = "application/dssc+xml";
			$c_types[ 'xer' ] = "application/patch-ops-error+xml";
			$c_types[ 'xht' ] = "application/xhtml+xml";
			$c_types[ 'xhtml' ] = "application/xhtml+xml";
			$c_types[ 'xla' ] = "application/vnd.ms-excel";
			$c_types[ 'xlam' ] = "application/vnd.ms-excel.addin.macroEnabled.12";
			$c_types[ 'xlc' ] = "application/vnd.ms-excel";
			$c_types[ 'xlm' ] = "application/vnd.ms-excel";
			$c_types[ 'xls' ] = "application/vnd.ms-excel";
			$c_types[ 'xlsx' ] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
			$c_types[ 'xlsb' ] = "application/vnd.ms-excel.sheet.binary.macroEnabled.12";
			$c_types[ 'xlt' ] = "application/vnd.ms-excel";
			$c_types[ 'xltx' ] = "application/vnd.openxmlformats-officedocument.spreadsheetml.template";
			$c_types[ 'xlw' ] = "application/vnd.ms-excel";
			$c_types[ 'xml' ] = "application/xml";
			$c_types[ 'xpm' ] = "image/x-xpixmap";
			$c_types[ 'xsl' ] = "application/xml";
			$c_types[ 'xslt' ] = "application/xslt+xml";
			$c_types[ 'xul' ] = "application/vnd.mozilla.xul+xml";
			$c_types[ 'xwd' ] = "image/x-xwindowdump";
			$c_types[ 'xyz' ] = "chemical/x-xyz";
			$c_types[ 'zip' ] = "application/zip";
		}

		if ( wp_is_mobile() ) {
			return 'application/octet-stream';
		}

		if ( isset( $c_types[ $ext ] ) )
			return $c_types[ $ext ];
		else
			return 'application/force-download';
	}

	
	/** Ger all heders from $_SERVER
	 * 
	 * @return array
	 */
	public static function get_all_headers() {

		$headers = array();
		//FixIn: 1.2.2
		foreach ( (array) $_SERVER as $key => $value ) {
		//while ( list($key, $value) = each( $_SERVER ) ) {
			if ( strncmp( $key, "HTTP_", 5 ) == 0 ) {
				$key = strtr( ucwords( strtolower( strtr( substr( $key, 5 ), "_", " " ) ) ), " ", "-" );
				$headers[ $key ] = $value;
			}
		}
		return $headers;
	}
	

		/** Convert Seconds to  readable view, like 1 day 3 hours 15 min
		 * 
		 * @param int $seconds
		 * @return string
		 */
		public static function readable_format_seconds_to_words( $seconds ) {
			$ret = "";

			$days = intval( intval( $seconds ) / (3600 * 24) );
			if ( $days > 0 ) {
				$ret .= $days . ' ' . ( ( $days > 1 ) ? __( 'days', 'secure-downloads' ) : __( 'day', 'secure-downloads' ) ) . ' ';
			}

			$hours = (intval( $seconds ) / 3600) % 24;
			if ( $hours > 0 ) {
				$ret .= $hours . ' ' . ( ( $hours > 1 ) ? __( 'hours', 'secure-downloads' ) : __( 'hour', 'secure-downloads' ) ) . ' ';
			}

			$minutes = (intval( $seconds ) / 60) % 60;
			if ( $minutes > 0 ) {
				$ret .= $minutes . ' ' . ( ( $minutes > 1 ) ? __( 'minutes', 'secure-downloads' ) : __( 'minute', 'secure-downloads' ) ) . ' ';
			}

			$seconds = intval( $seconds ) % 60;
			if ( $seconds > 0 ) {
				$ret .= $seconds . ' ' . ( ( $seconds > 1 ) ? __( 'seconds', 'secure-downloads' ) : __( 'second', 'secure-downloads' ) ) . ' ';
			}

			return trim( $ret );
		}

}


////////////////////////////////////////////////////////////////////////////////
// Secret Links
////////////////////////////////////////////////////////////////////////////////

/** Secret Link CLASS  */
class OPSD_sLink {
    
    const DOWNLOAD_URL_TAG    = 'product';
    
    // unlike a const, static property values can be changed
    public static $settings = array( 
                                    'is_show_file_name' => true 
                                  , 'is_send_email_notification' => true 
                                  , 'hash_type' => 'phpass'                     // 'phpass' - hashin using WP Portable PHP password hashing framework instance.
                                                                                // 'wp' - using standard WP pasword functions
                                                                                // 'md5' (simple hashing using md5,  not recommended)                                                                                 
                                );             
    private $secret_key;

    
    /** Load Secret HASH from DB */
    function __construct() {                                                    //TODO: generate here KEY and HASH based on different symbols        
    
		// Load Pass class
		require_once( ABSPATH . 'wp-includes/class-phpass.php');
		
		// SECRET KEY - key for checking valid links
		$opsd_secret_key = get_opsd_option( 'opsd_secret_key' );
		if ( empty( $opsd_secret_key ) ) {
			update_opsd_option( 'opsd_secret_key', wp_generate_password( 30, false, false ) );
		}
		$this->secret_key = get_opsd_option( 'opsd_secret_key' );
	}
    
	
	/** Get Url Path,  like '/download/product' - checking for start redirection and download of product.
	 *  Note, we have starting '/' symbol here
	 * 
	 * @return string
	 */
	public function get_url_path() {
		
		$download_url_path = get_opsd_option( 'opsd_download_url_path' );
		$download_url_path = trim( $download_url_path );
		if ( ! empty( $download_url_path ) ) {
			$download_url_path = '/' . trim( $download_url_path, '/' );
		}
		return $download_url_path;		
	}	
    
	
    /** Get secret link for download of specific product
     * 
     * @param array $product = Array (
                                [id] => bcbs
                                [order] => 0
                                [ip] => 0.0.0.0
                                [ipl] => 0
                                [expire] => +1440 seconds
                                [title] => Title
                                [description] => Some version
                                [path] => /wp-content/fhjdfjvbdvbhjsbe4hg8wn934g8nv87hw4gnvq89o8phgnv8whsv47w8hg7548whubgh87rsbi/product.zip
                            )
     * @param array $opt - optional array with  parameters, which redefined default product values   array(             
                                                                                                        'expire' => '+1 day'            
                                                                                                        'ip' => '149.10.0.1'                                                                                                                  
                                                                                                      )
     * @return string = http://new/download/?product=YmNicywxNDg4MTg2ODE4LDAsMC4wLjAuMCwwLDgwM2FlNTk0YjQ3NzMwNzg3NDlmZTQ0NjdiOWM0MDg4/product.bs.zip
     */
    public function generate_secret_link( $product = array() , $opt = array() ) {    
//debuge($product , $opt)		;die;
		if (	   ( empty( $product[ 'path' ] ) ) 
				|| ( empty( $product[ 'id' ]   ) ) 
			)
			return false;
		
		if ( isset( $opt[ 'expire' ] ) )	{			                                                                //FixIn: 1.2.2.2
			$product[ 'expire' ] = $opt[ 'expire' ];
		} 
			
		if ( opsd_is_valid_timestamp( $product[ 'expire' ] ) ) {
			$product[ 'expire' ] = $product[ 'expire' ];				
		} else {
			$product[ 'expire' ] = strtotime( $product[ 'expire' ] , current_time( 'timestamp' ) );
		}			
		
		
		
		if ( ! empty( $opt[ 'ip' ] ) )		
			$product[ 'ip' ] = $opt[ 'ip' ];
		
		if ( ! empty( $opt[ 'order' ] ) )		
			$product[ 'order' ] = $opt[ 'order' ];	// ITs can  be email,  where we are sending this link
		
//debuge($product[ 'order' ]);die;

		// Verify Hash        
		$hash_for_verification = $this->generate_one_way_hash( $this->secret_key . $product[ 'id' ] . $product[ 'expire' ] . $product[ 'order' ] . $product[ 'ip' ] );

		$auth = $product[ 'id' ] . ',' . $product[ 'expire' ] . ',' . $product[ 'order' ] . ',' . $product[ 'ip' ] . ',' . $hash_for_verification;
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Encode URL
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		// This encoding is designed to make binary data survive transport 
		// through transport layers that are not 8-bit clean, such as mail bodies.
		$auth = base64_encode( $auth );			
		// Returns a string in which all non-alphanumeric characters except -_.~ 
		// have been replaced with a percent (%) sign followed by two hex digits.
		$auth = rawurlencode( $auth );			
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		$secret_link = rtrim( get_site_url(), '/' ) . $this->get_url_path() . '/?' . self::DOWNLOAD_URL_TAG . '=' . $auth;
		
		// If use file name at  the end of url
        if ( self::$settings[ 'is_show_file_name' ] ) {	

            $file_name = OPSD_Download::get_file_name_from_path( $product['path'] );

            $secret_link .= '/' . $file_name;
        }

        return $secret_link;        
    }
    
	
    /** Check if the url for download valid, and return error key or valid path  to file
	 * 
	 * @param string $url
	 * @return mixed	-	return  string error code key,  or download array with path key to the file: array( 
																												[id] => 1
																												[expire] => 1491983082
																												[order] => 0
																												[ip] => 127.0
																												[path] => XXXXXXXXXX/pro/pro.zip
	*/
	public function check_secret_link( $url ) {
		
		// Check if we have parameter for downloading,  and hash  of this parameter  is correct,  otherwsie skip all this
		$my_parsed_url		 = wp_parse_url( $_SERVER[ 'REQUEST_URI' ] );
		$my_parsed_url_path	 = trim( $my_parsed_url[ 'path' ] );
		$my_parsed_url_path	 = trim( $my_parsed_url_path, '/' );
		
		$download_url_path = $this->get_url_path();
		$download_url_path = trim( $download_url_path, '/' );
		
		// Wrong initial path. Its will  show not found page 
		if ( $download_url_path != $my_parsed_url_path ) {		  
			return 'wrong_url_path';
		}
	
				
		// Get  product HASH and then check  if we can download it.
		if ( empty( $_GET[ self::DOWNLOAD_URL_TAG ] ) ) {
			
			return 'wrong_url_path'; 
			
		} else {
			$auth = $_GET[ self::DOWNLOAD_URL_TAG ];

			// Remove any /filename.zip from end
			$pos = strpos( $auth, "/" );
			if ( is_integer( $pos ) ) {
				$auth = substr( $auth, 0, $pos );
			}

			////////////////////////////////////////////////////////////////////
			// Decode URL
			////////////////////////////////////////////////////////////////////

			// percent (%) signs with two hex digits replace to symbols:: 'foo%20bar%40baz' => foo bar@baz
			$auth = rawurldecode( $auth );

			//    2,    1486134709, 1486048303,     176.102.54.50   ,0  ,2c70a0c65a2f8a84c649bd6e957151e5
			// bcbs,    1488185523,          0,     0.0.0.0         ,0  ,6ef85ddb126dfde4f0cf6dd1b1afc4bf
			$auth = base64_decode( $auth );

			////////////////////////////////////////////////////////////////////

			
			// Get Download parameters /////////////////////////////////////////
			$download = array();
			$download[ 'id' ]		= strtok( $auth, "," );							// bcbs
			$download[ 'expire' ]	= strtok( "," );								// 1486134709
			$download[ 'order' ]	= strtok( "," );								// 1486048303
			$download[ 'ip' ]		= strtok( "," );								// 176.102.54.50        - IP 
			$verifyhash				= strtok( "," );								// 2c70a0c65a2f8a84c649bd6e957151e5
			$verifyhash				= trim( $verifyhash );


			////////////////////////////////////////////////////////////////////
			// Checking
			////////////////////////////////////////////////////////////////////

			
			// Check  Hash /////////////////////////////////////////////////////

			// Generate Hash based on secret key,  
			// for recehcking about verification of this link             
			$hash = $this->secret_key . $download[ 'id' ] . $download[ 'expire' ] . $download[ 'order' ] . $download[ 'ip' ];
			if ( ! $this->verify_one_way_hash( $verifyhash, $hash ) ) {

				return 'wrong_hash_in_url';
			}
			
			// Check if link expired ////////////////////////////////////////////
			if ( $download[ 'expire' ] != 0 ) {
				$curtime = current_time( 'timestamp' );											  //current_time( 'timestamp' );
				
//debuge($curtime , $download[ 'expire' ]);
//debuge( '$download[ "expire" ]', $download[ 'expire' ],  date_i18n(                                     
//					get_opsd_option( 'opsd_date_format' ) . ' ' . get_opsd_option( 'opsd_time_format' )
//				  , $download[ 'expire' ]//current_time( 'timestamp' )
//				  ) );
//debuge( '$curtime', $curtime,  date_i18n(                                     
//					get_opsd_option( 'opsd_date_format' ) . ' ' . get_opsd_option( 'opsd_time_format' )
//				  , $curtime//current_time( 'timestamp' )
//				  ) );
//die;

				if ( $curtime > $download[ 'expire' ] ) {					
					return 'url_expired';
				}
			}

		
			// Check IP /////////////////////////////////////////////////////////
			$download[ 'ip' ] = apply_filters( 'opsd_define_ip_mask' , $download[ 'ip' ] );                             //FixIn: 1.1.4.2
			if ( ! is_array( $download['ip'] ) ) {

				if ( ! in_array( $download['ip'], array( '0', '0.0.0.0' ) ) ) {

					$ip_mask = explode( '.', $download['ip'] );
					$ip_real = explode( '.', opsd_get_user_ip() );

					foreach ( $ip_mask as $ip_k => $ip_v ) {
						if ( $ip_real[ $ip_k ] != $ip_v ) {
							return 'ip_not_valied';
						}
					}
				}
			} else {
				$is_ip_valid = false;
				$ip_real     = opsd_get_user_ip();
				foreach ( $download['ip'] as $ip_mask_single ) {
					if ( $ip_mask_single == $ip_real ) {
						$is_ip_valid = true;
					}
				}
				if ( ! $is_ip_valid ) {
					return 'ip_not_valied';
				}
			}

			// Check if Product Exist /////////////////////////////////////////////////////////

			$product = opsd_get_product( $download[ 'id' ] );
			if ( ( empty( $product ) ) || ( empty( $product[ 'path' ] ) ) ) {
				
				return 'product_not_exist';
							
			} else { 
				// Success! 
				$download['path'] = $product['path'];

				return $download;
			}
						
		}
		
	}
	
	
	/** Generate One Way  hash here 
     * 
     * @param string $known_string
     * @return string
     */
    function generate_one_way_hash( $known_string ) {
        
        switch ( self::$settings[ 'hash_type' ] ) {
            
            case 'phpass':
                /** https://roots.io/improving-wordpress-password-security/
                 * the 1st parameter can be from 8 to 30
                 * The 2nd parameter of true is the important one. That boolean flag tells phpass whether to use a "portable" hash. 
                 * If that flag was false then phpass would check for the existence of a strong hashing function such as bcrypt and use it.
                 */
                $hasher_obj	 = new PasswordHash( 12, false );
				$hash		 = $hasher_obj->HashPassword( wp_unslash( $known_string ) );
				break;
            case 'wp':
				$hash		 = wp_hash_password( $known_string );
				break;
			default:															// same as 'md5'
				$hash		 = md5( $known_string );
				break;
		}
         
        return $hash;        
    }
    
    
    /** Check if hash Valid
     * 
     * @param string $input_hash   - hash, which we need to check,  if its VALID
     * @param string $known_string - from which is generating HASH
     * @return boolean
     */
    function verify_one_way_hash( $hash, $known_string ) {
        
        $hash_is_correct = false;

		switch ( self::$settings[ 'hash_type' ] ) {

			case 'phpass':
				$hasher_obj		 = new PasswordHash( 12, false );
				$hash_is_correct = $hasher_obj->CheckPassword( $known_string, $hash );
				break;
			case 'wp':
				$hash_is_correct = wp_check_password( $known_string, $hash );
				break;
			default:															// same as 'md5'
				$known_hash		 = $this->generate_one_way_hash( $known_string );
				if ( $hash == $known_hash )
					$hash_is_correct = true;
				break;
		}

		return $hash_is_correct;
	}
    
}



/** Get secret link for download of specific product
 * 
 * @param array $product = Array (
                            [id] => bcbs
                            [order] => 0
                            [ip] => 0.0.0.0
                            [ipl] => 0
                            [expire] => +1 day
                            [title] => Title
                            [description] => Some version
                            [path] => /wp-content/fhjdfjvbdvbhjsbe4hg8wn934g8nv87hw4gnvq89o8phgnv8whsv47w8hg7548whubgh87rsbi/product.bs.zip
                        )
  * @param array $opt - optional array with  parameters, which redefined default product values   array(             
                                                                                                        'expire' => '+1 day'            
                                                                                                        'ip' => '149.10.0.1'                                                                                                                   
                                                                                                      )
 * @return string = http://new/?opsd=922015&product=YmNicywxNDg4MTg2ODE4LDAsMC4wLjAuMCwwLDgwM2FlNTk0YjQ3NzMwNzg3NDlmZTQ0NjdiOWM0MDg4/product.bs.zip
 */
function opsd_get_secret_link( $product = array() , $opt = array() ) {
    
    $secret_link = '';
    
    if ( ! empty( $product ) ) {
        
        $opsd_link = new OPSD_sLink(); 

        $secret_link = $opsd_link->generate_secret_link( $product, $opt );
    }
    return $secret_link;
}


////////////////////////////////////////////////////////////////////////////////
// DOWNLOAD   REDIRECTION
////////////////////////////////////////////////////////////////////////////////

/** Check  if we need to star  download some product depend from URL parameters.
 *  If we need to download then make redirection.
 * 
 * @return type
 */
function opsd_download_link_redirect() {

	$opsd_link = new OPSD_sLink();
	
	$is_link_valid = $opsd_link->check_secret_link( $_SERVER[ 'REQUEST_URI' ] );

	if ( is_array( $is_link_valid ) ) {		// Success
		
		/**	array( 
					[id] => 1
					[expire] => 1491983082
					[order] => 0
					[ip] => 127.0
					[path] => XXXXXXXXXX/pro/pro.zip
		 */
		
		$product_path = ltrim( $is_link_valid['path'], '/\\' );

		$file_link = rtrim( get_site_url(), '/' ) . '/' . $product_path;		// Get real link  to downloading file	

		$result = OPSD_Download::start_download_process( $file_link );
		
		if ( $result[ 'error' ] !== 0 ) {

			switch ( $result[ 'error' ] ) {

				case 'file_not_exist':
					if ( wp_redirect( rtrim( get_site_url(), '/' ) . opsd_make_link_relative( get_opsd_option( 'opsd_url_file_not_exist' ) ) ) ) exit;

				case 'file_not_permit':
				case 'headers_sent_before_download':
				case 'error_opening_file':
					if ( wp_redirect( rtrim( get_site_url(), '/' ) . opsd_make_link_relative( get_opsd_option( 'opsd_url_error_opening_file' ) ) ) ) exit;

				default:
					break;
			}

		} else {	// Success!  Its seems evrything fine,  and doenload process was started !

			$products_id_arr = array( $is_link_valid['id'] );
			
			$opt			 = $is_link_valid;
			
			$replace = opsd_get_product_replace_shortcodes( $products_id_arr, $opt );
//TODO: incorrecrt ?????
// [product_expire_after] => 
//            [product_expire_date] => 2017/04/11 11:37		
//debuge( 'opt expire', $curtime,  date_i18n(                                     
//					get_opsd_option( 'opsd_date_format' ) . ' ' . get_opsd_option( 'opsd_time_format' )
//				  , $opt['expire']//current_time( 'timestamp' )
//				  ) );
//			
//debuge( $products_id_arr, $opt, $replace ); die;

			//TODO
			//$mail_api = opsd_send_email_to_user_notification( $replace, get_option( 'admin_email' ), $is_send_copy_to_admin = 'Off' );
			$mail_api = opsd_send_email_download_notification( $replace );

			exit;			
		}
		
	} else {								// Error
				
		switch ( $is_link_valid) {

			case 'wrong_url_path':	// Wrong initial path for download, so skip - return; - its means open this page,  or just  show 404 not found page			
				return;

			case 'wrong_hash_in_url':	// Hash  is Wrong, may be Hacking ???		- Redirect
				if ( wp_redirect( rtrim( get_site_url(), '/' ) . opsd_make_link_relative( get_opsd_option( 'opsd_url_wrong_hash' ) ) ) ) exit;

			case 'url_expired':			// Link Expired								- Redirect
				if ( wp_redirect( rtrim( get_site_url(), '/' ) . opsd_make_link_relative( get_opsd_option( 'opsd_url_download_expired' ) ) ) ) exit;

			case 'ip_not_valied':		// IP not permitted							- Redirect			
				if ( wp_redirect( rtrim( get_site_url(), '/' ) . opsd_make_link_relative( get_opsd_option( 'opsd_url_ip_not_valied' ) ) ) ) exit;

			case 'product_not_exist':	// Product  not exist						- Redirect		
				if ( wp_redirect( rtrim( get_site_url(), '/' ) . opsd_make_link_relative( get_opsd_option( 'opsd_url_file_not_exist' ) ) ) ) exit;

			default: 

				// Unknown error, or just opening some other page
				break;
		}
	
	}

}
add_action( 'template_redirect', 'opsd_download_link_redirect' );