<?php
// $Revision: 1.1.2.10 $
// ------------------------------------------------------------------------- //
//  XooNIps - Neuroinformatics Base Platform System                          //
//  Copyright (C) 2005-2008 RIKEN, Japan All rights reserved.                //
//  http://xoonips.sourceforge.jp/                                           //
// ------------------------------------------------------------------------- //
//  This program is free software; you can redistribute it and/or modify     //
//  it under the terms of the GNU General Public License as published by     //
//  the Free Software Foundation; either version 2 of the License, or        //
//  (at your option) any later version.                                      //
//                                                                           //
//  You may not change or alter any portion of this comment or credits       //
//  of supporting developers from this source code or any supporting         //
//  source code which is considered copyrighted (c) material of the          //
//  original comment or credit authors.                                      //
//                                                                           //
//  This program is distributed in the hope that it will be useful,          //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of           //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
//  GNU General Public License for more details.                             //
//                                                                           //
//  You should have received a copy of the GNU General Public License        //
//  along with this program; if not, write to the Free Software              //
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
// ------------------------------------------------------------------------- //
if ( ! defined( 'XOOPS_ROOT_PATH' ) ) {
  exit();
}

/**
 * file download handling class
 *
 * @package xoonips_utility
 * @copyright copyright &copy; 2008 RIKEN Japan
 */
class XooNIpsUtilityDownload extends XooNIpsUtility {

  /**
   * HTTP_USER_AGENT
   * @access private
   * @var string HTTP_USER_AGENT environment variable
   */
  var $ua;

  /**
   * HTTP_ACCEPT_LANGUAGE
   * @access private
   * @var string HTTP_ACCEPT_LANGUAGE environment variable
   */
  var $al;

  /**
   * PATH_INFO
   * @access private
   * @var string PATH_INFO environment variable
   */
  var $pi;

  /**
   * client browser encoding
   * @access private
   * @var string client browser encoding
   */
  var $browser_encoding;

  /**
   * constractor
   *
   * @access public
   */
  function XooNIpsUtilityDownload() {
    $this->ua = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
    $this->al = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
    $this->pi = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : '';
    if ( ! preg_match( '/^\\/.*$/', $this->pi ) ) {
      $this->pi = '';
      // invalid path info
    }
    $this->browser_encoding = $this->_detect_browser_encoding();
  }

  /**
   * check PATH_INFO for file downloading
   *
   * @access public
   * @param string $file_name downloading file name on server environment
   * @return bool false if it will fail to get file name on client browser.
   */
  function check_pathinfo( $file_name ) {
    if ( strstr( $this->ua, 'KHTML' ) ) {
      // KHTML based browser require PATH_INFO for file downloading
      $file_name = $this->_encode_utf8( $file_name );
      if ( $this->pi != '/'.$file_name ) {
        // does not match file name.
        return false;
      }
      return true;
    }
    // other browsers
    return true;
  }

  /**
   * append PATH_INFO to url string
   *
   * @access public
   * @param string $url url string
   * @param string $file_name file name on server environment
   * @return string appended url
   */
  function append_pathinfo( $url, $file_name ) {
    $pathinfo = '/'.urlencode( $this->_encode_utf8( $file_name ) );
    if ( preg_match( '/^([^\\?]+)(\\?.*)$/', $url, $matches ) ) {
      $result = $matches[1].$pathinfo.$matches[2];
    } else {
      $result = $url.$pathinfo;
    }
    return $result;
  }

  /**
   * convert encoding to client environment
   *
   * @access public
   * @param string $text source text
   * @param string $fallback unmapped character encoding method
   *   'h' : encode to HTML numeric entities
   *   'u' : encode to UTF-8 based url string
   * @return string appended url
   */
  function convert_to_client( $text, $fallback ) {
    $result = $this->_convert_encoding( $text, $this->browser_encoding, $fallback );
    return $result;
  }

  /**
   * download file
   *
   * @access public
   * @param string $file_path downloading local file path
   * @param string $file_name file name on server environment
   * @param string $mime_type mime type of downloading file
   */
  function download_file( $file_path, $file_name, $mime_type ) {
    // check file exists
    if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
      die( 'Fatal Error : file not found' );
    }

    // get file inforamation
    $file_size = filesize( $file_path );

    // output header
    $this->output_header( $file_name, $mime_type, $file_size );

    // output content body
    // readfile( $file_path );
    $chunksize = 1024 * 1024;
    $fh = fopen( $file_path, 'rb' );
    while ( ! feof( $fh ) ) {
      echo fread( $fh, $chunksize );
      flush();
    }
    fclose( $fh );
  }

  /**
   * download data
   *
   * @access public
   * @param string $str downloading data
   * @param string $file_name file name on server environment
   * @param string $mime_type mime type
   */
  function download_data( $str, $file_name, $mime_type ) {
    // get file inforamation
    $file_size = strlen( $str );
    $this->output_header( $file_name, $mime_type, $file_size );
    // output content body
    echo $str;
  }

  /**
   * output header for file download
   *
   * @access public
   * @param string $file_name file name on server environment
   * @param string $mime_type mime type
   * @param int $file_size file size
   */
  function output_header( $file_name, $mime_type, $file_size = '' ) {

    $content_disposition = $this->_content_disposition_filename( $file_name );
    // remove ob fileters
    $handlers = ob_list_handlers();
    while ( ! empty( $handlers ) ) {
      ob_end_clean();
      $handlers = ob_list_handlers();
    }

    // unlimit time out
    set_time_limit( 0 );

    // output header
    header( 'Expires: Sat, 01 Jan 2000 00:00:00 GMT' );
    header( 'Last-Modified: '.gmdate( 'D, d M Y H:i:s' ).' GMT' );
    // Cache-Control: avoid IE bug - see http://support.microsoft/kb/436605/ja
    header( 'Cache-Control: none' );
    if ( $content_disposition ) {
      header( 'Content-Disposition: attachment; filename="'.$content_disposition.'"' );
    }
    if ( ! empty( $file_size ) ) {
      header( 'Content-Length: '.$file_size );
    }
    header( 'Content-Type: "'.$mime_type.'"' );
  }

  /**
   * detect browser encoding
   *
   * @access private
   * @return string detected encoding
   */
  function _detect_browser_encoding() {
    static $windows1252_map = array(
      // English
      'en',
    );
    $encoding = 'ASCII';
    if ( strstr( $this->ua, 'Mac OS X' ) ) {
      $encoding = 'UTF-8';
    } else if ( strstr( $this->ua, 'Windows' ) ) {
      if ( strstr( $this->ua, 'MSIE' ) || strstr( $this->ua, 'Gecko' ) ) {
        if ( strstr( $this->al, 'ja' ) ) {
          // for japanese
          $encoding = 'SJIS-win';
        } else {
          // for Western Europian : Windows-1252
          foreach ( $windows1252_map as $lang ) {
            if ( strstr( $this->al, $lang ) ) {
              $encoding = 'Windows-1252';
              break;
            }
          }
        }
      }
    }
    return $encoding;
  }

  /**
   * generate file name for 'Content-Disposition:' header
   *
   * @access private
   * @param string $filename file name on server environment
   * @return string generated file name
   */
  function _content_disposition_filename( $file_name ) {
    if ( strstr( $this->ua, 'MSIE' ) ) {
      // Microsoft Internet Explorer
      // - utf8 + x-www-form-url
      $client_filename = $this->_convert_encoding( $file_name, $this->browser_encoding, 'u' );
      $utf8_client_filename = $this->_encode_utf8( $client_filename, $this->browser_encoding );
      return urlencode( $utf8_client_filename );
    } else if ( strstr( $this->ua, 'KHTML' ) ) {
      // KHTML based browser (e.g. Safari)
      // - return empty string. this browser have to use PATH_INFO.
      return '';
    } else if ( strstr( $this->ua, 'Gecko' ) || strstr( $this->ua, 'Mac OS X' ) ) {
      // Gecko based browser (e.g. Mozilla FireFox)
      // - rfc2047 : mime header encode
      $client_file_name = $this->convert_to_client( $file_name, 'u' );
      // set mime encoding
      $mime_encoding = $this->browser_encoding;
      // save current internal encoding
      $internal_encoding_orig = mb_internal_encoding();
      // change internal encoding for mb_encode_mimeheader()
      if ( ! @mb_internal_encoding( $this->browser_encoding ) ) {
        if ( $this->browser_encoding == 'SJIS-win' ) {
          // use fallback encoding 'Shift_JIS'
          mb_internal_encoding( 'Shift_JIS' );
        } else {
          // use fallback encoding 'ASCII'
          $client_file_name = $this->_convert_encoding( $file_name, 'ASCII', 'u' );
          mb_internal_encoding( 'ASCII' );
          $mime_encoding = 'ASCII';
        }
      }
      // encode mime header
      $mimeheader = mb_encode_mimeheader( $client_file_name, $mime_encoding, 'B' );
      // restore internal encoding
      mb_internal_encoding( $internal_encoding_orig );
      // done
      return $mimeheader;
    }
    // unknown browsers
    return $this->_convert_encoding( $file_name, 'ASCII', 'u' );
  }

  /**
   * convert encoding to UTF-8
   * @access private
   * @param string $text input text
   * @param string $encoding text encoding
   * @return string 'UTF-8' encoded text string
   */
  function _encode_utf8( $text, $encoding = '' ) {
    $textutil =& xoonips_getutility( 'text' );
    if ( empty( $encoding ) ) {
      $encoding = mb_detect_encoding( $text );
    }
    $text = mb_convert_encoding( $text, 'UTF-8', $encoding );
    $text = $textutil->html_numeric_entities( $text );
    $text = mb_decode_numericentity( $text, array( 0, 0x10ffff, 0, 0x1fffff ), 'UTF-8' );
    return $text;
  }

  /**
   * convert encoding
   * @access private
   * @param string $text input text
   * @param string $encoding output text encoding
   * @param string $fallback unmapped character encoding method
   *   'h' : encode to HTML numeric entities
   *   'u' : encode to UTF-8 based url string
   * @return string encoding converted text string
   */
  function _convert_encoding( $text, $encoding, $fallback ) {
    $unicode =& xoonips_getutility( 'unicode' );
    $text = $this->_encode_utf8( $text );
    $text = $unicode->decode_utf8( $text, $encoding, $fallback );
    return $text;
    
  }
}

/*

// example1 : file download
$download = new XooNIpsDownload();
$filename = 'hogehoge.txt'; // downloding file name on server environment
if ( ! $download->check_pathinfo( $filename ) ) {
  $url = '....'; // create url with PATH_INFO
  $url = $download->append_pathinfo( $url, $filename );
  header( 'Location: '.$url );
  exit();
}
// uncomment below line if use client filename
// $client_filename = $download->convert_to_client( $filename, 'u' );
// ... do something
$local_filepath = '/var/tmp/hogehoget.txt'; // generated local file
// ... do something
$download->download_file( $local_filepath, $filename, 'text/plain' );
unlink( $local_filepath );
exit();

// example2 : data download
$download = new XooNIpsDownload();
$filename = 'hogehoge.txt'; // downloding file name on server environment
if ( ! $download->check_pathinfo( $filename ) ) {
  $url = '....'; // create url with PATH_INFO
  $url = $download->append_pathinfo( $url, $filename );
  header( 'Location: '.$url );
  exit();
}
// uncomment below line if use client filename
// $client_filename = $download->convert_to_client( $filename, 'u' );
// ... do something
$data = readfile( '/var/tmp/ddddd.txt' ); // generated local file
$mimetype = 'text/plain; charset="ASCII"';
// ... do something
$download->download_data( $data, $filename, $mimetype );

*/

?>
