/**
 * Deliver the download file
 *
 * If enabled, the file is symlinked to better support large file downloads
 *
 * @access   public
 * @param    string    $file
 * @param    bool      $redirect True if we should perform a header redirect instead of calling edd_readfile_chunked()
 * @return   void
 */
function edd_deliver_download($file = '', $redirect = false)
{
    /*
     * If symlinks are enabled, a link to the file will be created
     * This symlink is used to hide the true location of the file, even when the file URL is revealed
     * The symlink is deleted after it is used
     */
    if (edd_symlink_file_downloads() && edd_is_local_file($file)) {
        $file = edd_get_local_path_from_url($file);
        // Generate a symbolic link
        $ext = edd_get_file_extension($file);
        $parts = explode('.', $file);
        $name = basename($parts[0]);
        $md5 = md5($file);
        $file_name = $name . '_' . substr($md5, 0, -15) . '.' . $ext;
        $path = edd_get_symlink_dir() . '/' . $file_name;
        $url = edd_get_symlink_url() . '/' . $file_name;
        // Set a transient to ensure this symlink is not deleted before it can be used
        set_transient(md5($file_name), '1', 30);
        // Schedule deletion of the symlink
        if (!wp_next_scheduled('edd_cleanup_file_symlinks')) {
            wp_schedule_single_event(current_time('timestamp') + 60, 'edd_cleanup_file_symlinks');
        }
        // Make sure the symlink doesn't already exist before we create it
        if (!file_exists($path)) {
            $link = @symlink(realpath($file), $path);
        } else {
            $link = true;
        }
        if ($link) {
            // Send the browser to the file
            header('Location: ' . $url);
        } else {
            edd_readfile_chunked($file);
        }
    } elseif ($redirect) {
        header('Location: ' . $file);
    } else {
        // Read the file and deliver it in chunks
        edd_readfile_chunked($file);
    }
}
/**
 * Delete symbolic links after they have been used
 *
 * @access public
 * @since  1.5
 * @return void
 */
function edd_cleanup_file_symlinks()
{
    $path = edd_get_symlink_dir();
    $dir = opendir($path);
    while (($file = readdir($dir)) !== false) {
        if ($file == '.' || $file == '..') {
            continue;
        }
        $transient = get_transient(md5($file));
        if ($transient === false) {
            @unlink($path . '/' . $file);
        }
    }
}
/**
 * Deliver the download file
 *
 * If enabled, the file is symlinked to better support large file downloads
 *
 * @access   public
 * @param    string    file
 * @return   void
 */
function edd_deliver_download($file = '')
{
    global $edd_options;
    $symlink = apply_filters('edd_symlink_file_downloads', isset($edd_options['symlink_file_downloads']));
    /*
     * If symlinks are enabled, a link to the file will be created
     * This symlink is used to hide the true location of the file, even when the file URL is revealed
     * The symlink is deleted after it is used
     */
    if ($symlink && function_exists('symlink')) {
        // Generate a symbolic link
        $ext = edd_get_file_extension($file);
        $parts = explode('.', $file);
        $name = basename($parts[0]);
        $md5 = md5($file);
        $file_name = $name . '_' . substr($md5, 0, -15) . '.' . $ext;
        $path = edd_get_symlink_dir() . '/' . $file_name;
        $url = edd_get_symlink_url() . '/' . $file_name;
        // Set a transient to ensure this symlink is not deleted before it can be used
        set_transient(md5($file_name), '1', 30);
        // Schedule deletion of the symlink
        if (!wp_next_scheduled('edd_cleanup_file_symlinks')) {
            wp_schedule_single_event(time() + 60, 'edd_cleanup_file_symlinks');
        }
        // Make sure the symlink doesn't already exist before we create it
        if (!file_exists($path)) {
            $link = symlink($file, $path);
        } else {
            $link = true;
        }
        if ($link) {
            // Send the browser to the file
            header('Location: ' . $url);
        } else {
            @edd_readfile_chunked($file);
        }
    } else {
        // Read the file and deliver it in chunks
        @edd_readfile_chunked($file);
    }
}