<?php  // vim:set et ts=4 sw=4 sts=4:
# Copyright (C) 2003-2014 hipplay Inc.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE OF hipplay Inc.
# The copyright notice above does not evidence any actual or intended
# publication of such source code. The contents of this file may not
# be disclosed to third parties, copied or duplicated in any form, in
# whole or in part, without the prior written permission of
# hipplay Inc.
#
namespace HipPlayConnect\FileSystem;


use HipPlayConnect\REST\AxRESTController;
use HipPlayConnect\AxRecoverableErrorException;

class AxDownloadManager
{
    const DEBUG_DOWNLOADS = FALSE;

    public static function getToken( array $files )
    {
        if ( count( $files ) == 0 )
            throw new AxRecoverableErrorException( 'empty list of files to download', AxRecoverableErrorException::ERR_CANNOT_PARSE_XML );

        // find the highest common ancestor of all the files to tar from there
        $commonDir = self::findCommonPath($files);

        if (self::DEBUG_DOWNLOADS)
            error_log("Download common dir: $commonDir");

        $filename = tempnam( '/tmp', 'AxDownloadManagerToken-getToken-' );
        $handle = fopen( $filename, 'w' );
        $commonDirLen = strlen( $commonDir );
        foreach ( $files as $file ) {
            $fileSubpath = substr( $file, $commonDirLen );
            fwrite( $handle, $fileSubpath . "\n" );
            if (self::DEBUG_DOWNLOADS)
                error_log("++ $fileSubpath");
        }
        fclose( $handle );
        
        $handle = fopen( $filename . '-root', 'w' );
        fwrite( $handle, $commonDir );
        fclose( $handle );        
        
        return substr( $filename, strlen( '/tmp/AxDownloadManagerToken-getToken-' ) );
    }

    protected static function findCommonPath(array $files) {
        $commonPath = '/';

        // loop on the folders of the first file
        foreach ( explode( '/', substr( $files[ 0 ], 1 ) ) as $dir )
        {
            $testCommonDir = $commonPath .  $dir . '/';
            $testCommonDirLen = strlen( $testCommonDir );

            foreach ( $files as $file )
            {
                if ( $testCommonDir != substr( $file, 0, $testCommonDirLen ) )
                    break 2;
            }

            $commonPath = $testCommonDir;
        }

        return $commonPath;
    }

    protected static function isAgentMSIE() {
        if (!isset($_SERVER['HTTP_USER_AGENT']))
            return FALSE;
        return ereg( 'MSIE ([0-9]+\.[0-9]+[a-z]*);(.*)', $_SERVER[ 'HTTP_USER_AGENT' ] );
    }

    public static function downloadForToken( $token )
    {
        $rootDir = NULL;
        $filesList = "/tmp/AxDownloadManagerToken-getToken-$token";

        if (
            !file_exists( $filesList ) ||
            ( false === ( $rootDir = file_get_contents( "$filesList-root" ) ) )
        ) {
            if (self::DEBUG_DOWNLOADS)
                error_log("Download file not found: ");

            AxRESTController::error( 404 );
        }

        // mandatory otherwise you end up with out of memory errors
        ob_end_clean();

        // UN-localized name with date
        $name = 'Download ' . date( 'Y-m-d H.i.s' ) . '.tgz';

        //force download dialog
        header('Content-type: application/gzip' );
        header('Content-Disposition: attachment; filename="'. ( self::isAgentMSIE() ? rawurlencode( $name ) : $name ) .'"' ); // SFN 20087022 bug 11969

        // These headers are ***REQUIRED*** for MS Internet Explorer to download the files.
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');

        header( 'Content-transfer-encoding: binary' );

        $rootDir = escapeshellarg($rootDir);
        $filesList = "/tmp/AxDownloadManagerToken-getToken-$token";
        $outputFile = "/tmp/AxDownloadManagerToken-getToken-$token.tar.gz";
        $logFile = "/tmp/AxDownloadManagerToken-getToken-$token.log";
        $outputFileEsc = escapeshellarg($outputFile);
        $filesListEsc = escapeshellarg($filesList);

        if (MC_PLATFORM == 'Full') {
            $command = 'cd ' . $rootDir . ' && ' .
                       'tar -czf ' . $outputFileEsc . ' -T ' . $filesListEsc . ' 2>' . $logFile;
            system($command);
            readfile($outputFile);
        } else {
            // tar options:
            // c : create archive
            // f  : output file
            // -  : stdout
            // T : file with names to include

            $command = 'cd ' . $rootDir . " && " .
                       "/bin/nice -n 20 " .
                       "/bin/tar cf - -T " .
                            $filesListEsc .
                       " | /bin/gzip -c ";

            $handle = popen( $command, 'r' );

            // TODO: Consider using fpassthru on $handle
            while( !feof( $handle ) && connection_status() == CONNECTION_NORMAL )
                print( fread( $handle, 1024*1024 ) );
            pclose($handle);
        }

        unlink( $filesList );
        unlink( "/tmp/AxDownloadManagerToken-getToken-$token-root" );

        exit;
    }
}
