<?php
/**
  @licence GPL 2005-2010  The osCSS developers - osCSS Open Source E-commerce
  @portion code Copyright (c) 2002 osCommerce
  @package osCSS-2 <www http://www.oscss.org>
  @version 2.1.0
  @date  18/12/10, 22:46
  @author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
  @encode UTF-8
  Original:
	  Made: by Vlad Savitsky http://forums.oscommerce.com/index.php?showuser=20490
	  Support: http://forums.oscommerce.com/index.php?showtopic=156667
*/
error_reporting(-1);
Interface PackageTags {
  /// gerenal
  public function get_data_from_xml_parser($xml_data='');
//   public function write_to_xml();
  /// actions
  /**-----------------------------permissions--------------------------- */
  public function permissions_check_for_install();
  public function permissions_check_for_remove();
  /**-----------------------------conflicts--------------------------- */
  public function conflicts_check_for_install() ;
  public function conflicts_check_for_remove();
  /**-----------------------------EXE--------------------------- */
  public function do_install();
  public function do_remove();
  /**-----------------------------Backup--------------------------- */


}


Abstract class ContribInstallerBaseTag
/*  extends CIP */{
  var $contrib; //contrib name
  var $tag_name; //name of the tag used in xml-file
  var $data;//contain a value and used to store to database
  var $params;//array with attributes
      /**
	* number of this type tag in xml
	*/
  var $id;
  /**
    @param bool true if error
  */
//   public static $error;
  /**
    * priority in which this tag will be processed
    */
  var $priority = 0;
  /**
    * dependencie path for this tag
    */
  var $depend;
  /**
    * parent cip for this tag
    */
  var $cip;



// Class Constructor
  function ContribInstallerBaseTag($cip='', $id='', $xml_data='', $dep='') {
      $this->cip = $cip;
      $this->contrib=CIP::$cip_name;
      $this->id=$id+1;//For human understanding we add one.
//       $this->table=DB_PREFIX."cip_".$this->tag_name;
      $this->depend = $dep;

      if ($xml_data) $this->read_from_xml($xml_data);

      $this->add_log();

//       $this->write_to_database();

//       $this->read_from_database();
  }



  //Data
  //=======================================================================
  function get_contrib() {return $this->contrib;}
  function get_tag_name() {return $this->tag_name;}
  function get_id() {return $this->id;}
  function get_cip_id() {
    $DB=Database::getInstance();
    $query="select cip_id from ".TABLE_CIP." where cip_folder_name='".$this->contrib."' ";
    $result=$DB->query($query);
    if ($result===false)CIP::$ArrayError[]=(sql_error($query));
    else {
	$installed=$result->fetchAssoc();
	return $installed['cip_id'];
    }
  }

  //=======================================================================
  function get_filename() {return $this->data['filename'];}

  function get_find() {return $this->data['find'];}
  function get_add() {return $this->data['add'];}
  function get_add_type() {return $this->data['add_type'];}
  function get_type() {
      if(!isset($this->data['type']) || $this->data['type']=='') return 'php';
      return $this->data['type'];
  }
  function get_start() {return $this->data['start'];}
  function get_end() {return $this->data['end'];}
  //findreplace
  function get_replace() {return $this->data['replace'];}
  function get_replace_type() {return $this->data['replace_type'];}
  //description
  function get_contrib_ref() {return $this->data['contrib_ref'];}
  function get_forum_ref() {return $this->data['forum_ref'];}
  function get_contrib_type() {return $this->data['contrib_type'];}
  function get_status() {return $this->data['status'];}
  function get_last_update() {return $this->data['last_update'];}
  function get_comments() {return $this->data['comments'];}
  function get_credits() {return $this->data['credits'];}
  //make_dir
  function get_parent_dir() {return $this->data['parent_dir'];}
  function get_dir() {return $this->data['dir'];}
  //sql
  function get_query() {return $this->data['query'];}
  function get_remove_query() {return $this->data['remove_query'];}
  //php
  function get_remove() {return $this->data['remove'];}
  function get_install() {return $this->data['install'];}

  //=======================================================================
  //extra data:
  //=======================================================================
  function fs_filename($id=0) {
      if(is_array($this->data['filename'])){
	      return $this->get_fs_filename($this->data['filename'][$id]);
      }
      return $this->get_fs_filename($this->data['filename']);
  }

  function get_fs_filename($fname) {
    if($this->isJoscom()){
      $fname = str_replace(DIR_WS_CATALOG,"",$fname);
      $fname = str_replace(DIR_WS_ADMIN,"admin/",$fname);

      if (strpos($fname, "admin/") === false) {
	$filepath = DIR_FS_CATALOG;
      } else {
	$filepath = DIR_FS_ADMIN;
	$fname = substr($fname, 6);
      }

      return $filepath.$fname;
    }else{
      if ($fname)return DIR_FS_CATALOG.$fname;
    }
  }
  function isJoscom(){return ((defined("JOSCOM_VERSION")) ? true : false);}

  /**
    @fn add_str($add_string='',$add_type='php')
    @brief check string for add in file.
    @date 19-12-2010
    @param $add_type string type file
    @param $add_string string content for add in file
  */
  function add_str($add_string='',$add_type='php') {
    if(!empty($add_string)){
      return  $this->linebreak_fixing($this->comment_string($add_string, $add_type));
    }
    elseif (isset($this->data['add']) && isset($this->data['add_type'])){
      $type=(isset($this->data['add_type'])) ?$this->data['add_type'] : 'php' ;
      return  $this->linebreak_fixing($this->comment_string($this->data['add'], $type));
    }
  }


  function rep_str() {
//         if ($this->data['replace'])
	  return $this->linebreak_fixing($this->comment_string($this->data['replace'], $this->data['replace_type']));
  }
  function multi_search() {return (($this->data['type']=='continued') ? true : false);}
  //=======================================================================
  //error
  //=======================================================================
//   function get_error() {return CIP::$error;}



  //=======================================================================
  //Database functions:
  //=======================================================================
//   function create_database_table() {
//       $query="CREATE TABLE IF NOT EXISTS  `".$this->table."` (
// 			  `cip_id` int(11) NOT NULL PRIMARY KEY,
// 			  `tag_id` int NOT NULL, ";
//       foreach ($this->params as $columns=>$info)     $query.= '`'.$columns.'` '.$info['sql_type'].' NOT NULL, ';
//       $query=substr($query, 0, -2) . ");";
//       tep_db_query($query);
//   }
//
//
//   function delete_database_table() {cip_db_query("DROP TABLE IF EXISTS `".$this->table."`");}
//
//   function is_database_table_exists() {
//     $check_query=tep_db_query("SHOW TABLE STATUS");
//     while ($table=tep_db_fetch_array($check_query))
//       if ($table['Name']==$this->table)return true;
//     return false;
//   }
//
//
//   function write_to_database() {
//     if (!$this->is_database_table_exists())    $this->create_database_table();
//     $data=$this->data;
//     $data['cip_id']=$this->get_cip_id();
//     $data['tag_id']=$this->get_id();
//
//
//     tep_db_perform($this->table, $data);
//   }
//
//
//   function read_from_database() {
//     if (!$this->is_database_table_exists())    return;
//     $query="SELECT ";
// //     while (list($columns, ) = each($data)) {$query .= 'tag.'.$columns.', ';}
// $query .= 'tag.*  ' ;
//     $query = substr($query, 0, -2) . " FROM ".$this->table." tag, ".TABLE_CIP." cip WHERE tag_id='".$this->id."' AND cip.cip_id=tag.cip_id AND cip.cip_folder_name='".$this->contrib."'";
//     $data=tep_db_output(tep_db_fetch_array(tep_db_query($query)));
//     return true;
//   }

//======================================================================= //XML: //=======================================================================

  function get_data_from_xml_parser($xml_data='') {
    $this->data=$xml_data->ChildNodes;
  }

  function read_from_xml($xml_data) {
    if (is_object($xml_data) and isset($xml_data->childNodes) )   $this->get_data_from_xml_parser($xml_data);
    else {
//       die(__CLASS__.'->'.__FUNCTION__.'::'.__LINE__);
      CIP::InProcess('No data from XML-file', __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'error');
    }
  }

//   function xml_check() {
//     foreach ($this->params as $tag=>$tag_data) {
//       if (!isset($tag_data['xml_error']))     continue; //'addcode' and 'find'
//       if ($tag=='start' or $tag=='end' or $tag=='type') {
// 	if (
// 	    ($this->data['start'] && $this->data['end'] && !$this->data['type'])
// 	    or
// 	    (!$this->data['start'] && !$this->data['end'] && $this->data['type'])
// 	) {}
// 	else
// 	  CIP::InProcess($tag_data['xml_error'], __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'info');
//       }
//       else if (!isset($this->data[$tag]) && isset($tag)) {
// 	CIP::InProcess($tag_data['xml_error'], __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'info');
//       }
//       else if(is_array($this->data[$tag])){
// 	$pocet = count(array_values($this->data[$tag]));
// 	for($i=0;$i <$pocet; $i++){
// 	  if(!isset($this->data[$tag][$i])) CIP::InProcess($tag_data['xml_error']." on ".$i. ". subtag", __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'info');
// 	}
//       }
//     }
//   }

//   function data_range_check() {
//     //For addcode and findreplace start<=end!!!!
//     //Check if we have <find> between lines with numbers "start" and "end".
//
//
//     //Range check:
//     while (list($tag_name, ) = each($this->params)) {
//       $value=$this->data[$tag_name];
//       if($value) {
// 	$pieces=strtolower(explode(" ", $this->params[$tag_name]['sql_type']));//get a first word
// 	$pos=strpos($pieces[0], '(');
// 	if ($pos) {
// 	    $type=substr($pieces[0], 0, $pos-1);
// 	    $type_value=substr($pieces[0], $pos - strlen($pieces[0]), 1); //without '(' and ')'
// 	} else    $type=$pieces[0];
//
// 	switch ($type[0]) {
// 	  case 'varchar':
// 	    if (strlen($value)>$type_value) CIP::InProcess(__("value lenth must be less then  ").$type_value, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
//
// 	  break;
// 	  case 'text':
// 	    if (strlen($value)>65535)CIP::InProcess(__("value lenth must be less then 65535"), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
// 	  break;
// 	  case 'enum':
// 	    $values=strtolower(explode(",",str_replace("'", "",$this->params[$tag_name]['sql_type']) ));
// 	    if (!in_array($value, $values))CIP::InProcess(__("value must be ").implode (" or ", $values), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
// 	  break;
// 	  case 'int':
// 	  case 'integer'://unsigned
// 	    if ($value>4294967295)CIP::InProcess(__("value must be integer and less then 4294967295."), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
// 	  break;
// 	  case 'tinyint'://unsigned
// 	    if ($value>255) CIP::InProcess(__("value must be integer and less then 4294967295.").$type_value, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
// 	  break;
// 	  case 'smallint'://unsigned
// 	    if ($value>65535)CIP::InProcess(__("value must be integer and less then 65535.").$type_value, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
// 	  break;
//
// 	}
//       }
//     }
//   }




///======================================================================= //Backup //=======================================================================
//   public function backup_file($filename=''){
//     $filename=((isset($filename))
// 		    ? (is_array($filename)
// 			? $filename
// 			: array($filename)
// 		      )
// 		    : ((isset($this->data['filename']))
// 			? $this->data['filename']
// 			: ''
// 		      )
// 		    );
//
//     if(is_array($filename)) $filenames= $filename;
//     else $filenames[0] = $filename;
//
//     foreach($filenames as $filename){
//       $full_path=$this->get_fs_filename($filename);
//       if(!is_file($full_path) or is_link($full_path))return false;
//
// //       CIP::$ArrayError[]=
//       if(!$res=fileUtility::_mkdir(dirname(CIP::PATH_BACKUP.$this->contrib.'/'.$filename).'/'))CIP::InProcess(__('_medir error'). implode(',',$res). " to ".CIP::PATH_BACKUP.$this->contrib.'/'.$filename, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
//
//       if(in_array(false,CIP::$ArrayError)) return false ;
//
//       if(!fileUtility::_copy($full_path, CIP::PATH_BACKUP.$this->contrib.'/'.$filename)){
// 	CIP::InProcess(__('couldnt copy to text'). $full_path. " to ".CIP::PATH_BACKUP.$this->contrib.'/'.$filename, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
// 	return false;
//       }
//       elseif (file_exists(CIP::PATH_BACKUP.$this->contrib.'/'.$filename))
// 	fileUtility::_chmod(CIP::PATH_BACKUP.$this->contrib.'/'.$filename, 0777);
//
//     }
//     return true;
//   }

//   public function restore_file($filename=''){
//     $filename=((isset($filename)) ? $filename : ((isset($this->data['filename'])) ? $this->data['filename'] : ''));
//     if (!isset($filename)) return false;
//     if(is_array($filename))  $filenames= $filename;
//     else   $filenames[0] = $filename;
//
//     foreach($filenames as $filename){
//       $backup_file=CIP::PATH_BACKUP.$this->contrib.'/'.$filename;
//       $current_file=$this->get_fs_filename($filename);
//       if(is_link($current_file)) return false;
//       //Remove current_file
//       fileUtility::_rmdir($current_file);
//       if (!is_file($backup_file)) return false;
//       //Restore
//       if (!fileUtility::_copy($backup_file, $current_file)) {
// 	CIP::InProcess(__("Couldn't restore file ").' '. $filename. __("from").' '.$backup_file, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
// 	return false;
//       }
//       else{
// 	if(!ci_remove($backup_file)) return false;
//       }
//     }
//     return true;
//   }

  //=======================================================================
  //Helpfull functions:
  //=======================================================================
  function write_to_file($path, $content) {
    if (!is_file($path) or !$content)     return;
    if (!is_writable($path))      return;
    $file=fopen($path, 'w');
    fwrite($file, $content);
    fclose($file);
  }
  function linebreak_view($line) {return preg_replace( "/[[:space:]]*\n/", "[r][n]\r\n",  preg_replace("/[[:space:]]*\r/", "", $line));}

  function linebreak_fixing($line) {
    $line = str_replace("\r\n","\r",$line);
    $line = str_replace("\r","\n",$line);
    $line = str_replace("\n","\r\n",$line);
    return preg_replace( "/(?<=\S)[ \t]+\r\n/","\r\n",$line);
  }

  function remove_fl_linebreaks($line){
    $line =  preg_replace( "/^\r\n/","",$line);
    return preg_replace( "/\r\n$/","",$line);
  }

  function comment_string($str, $type="php") {
    switch ($type) {
      case 'html':
	$start_com="\n<!-- ";
	$end_com=" //-->";
	break;
      default:
	$start_com="\n/* ";
	$end_com=" */";
	break;
    }
    $back_part=$this->contrib." - installed by ".CONTRIB_INSTALLER_NAME.$end_com."\n";
    return  $start_com. "Begin ".$back_part. $this->remove_fl_linebreaks($str). $start_com."End ".$back_part ;
  }


  /**
    Copy repertoire recursif
    @author oscim <mail oscim@oscss.org> <www http://www.oscim.fr>
  */
  public static function recurse_copy($src,$dst){
    fileUtility::CfgComport(true);
    if( ($res= fileUtility::_copy($src,$dst)) && $res ==false) {
      foreach(fileUtility::GetError() as $error)
	CIP::InProcess($error['text'].dirname($path), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
    }
    return $res;
  }


  function recursive_mkdir($path) {
    fileUtility::CfgComport(true);
    if( ($res= fileUtility::_mkdir($path)) && $res ==false) {
      foreach(fileUtility::GetError() as $error)
	CIP::InProcess($error['text'].dirname($path), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
    }
    return $res;
  }

  function recursive_rmdir($path) {
    fileUtility::CfgComport(true);
    if( ($res= fileUtility::_rmdir($path)) && $res ==false) {
      foreach(fileUtility::GetError() as $error)
	CIP::InProcess($error['text'].dirname($path), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
    }
    return $res;
  }

  function add_file_end($fname, $fpart) {
//     global $messageStack;
    $enter = false;
    $fs_fname = $this->get_fs_filename($fname);
    if (is_file($fs_fname)) {
      $old_file = file_get_contents($fs_fname);
      $position = strpos($old_file, $fpart);

      if ($position === false) {
	if($this->get_type() == 'php'){
	  $count = preg_match_all("(\?>\s*$\s*)",$old_file,$matches,PREG_OFFSET_CAPTURE);
	  if ($count == 0) { // if file no ends with \?\>
	    $new_file = rtrim($old_file). "\n<?php " . $fpart . " ?>";
	  }else{
	    $new_file = substr_replace($old_file, $fpart, $matches[0][0][1], 0); //inserts string into another string
	  }
	}
	else
	  $new_file = $old_file.$fpart;

	$this->write_to_file($fs_fname, $new_file);
	return true;
      }
      else {
	CIP::InProcess(__("found string, no add script"), __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'noblock');
      }
    }
    else return false;

    return true;
  //$messageStack->add(FILE_NOT_EXISTS_TEXT . ": " . $fs_fname);
  }

  function remove_file_part($fname, $fpart) {
    global $messageStack;
    $output='';
    $fs_fname = $this->get_fs_filename($fname);
    if (is_file($fs_fname)) {
      $old_file = file_get_contents($fs_fname);
      $position = strpos($old_file, "<?php " . $fpart . " ?>");

      if ($position === false)   $position = strpos($old_file, $fpart);
      else $fpart = "<?php " . $fpart . " ?>";

      if ($position === false) {
	CIP::InProcess(__("couldnt find text") . ": " . nl2br(htmlentities($fpart)) .
	"</p>" . ('in the file text') . $fs_fname, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
	return false;
// 	$output .= "<p class=\"error\">" . COULDNT_FIND_TEXT . ": " . nl2br(htmlentities($fpart)) .
	"</p>" . IN_THE_FILE_TEXT . $fs_fname . '</div>';
      } else {
	$length = strlen($fpart);
	$new_file = substr_replace($old_file, '', $position, $length);
	$this->write_to_file($fs_fname, $new_file);
	return true;
      }
    }
    else return false;
//       $messageStack->add(FILE_NOT_EXISTS_TEXT . ": " . $fs_fname);
  }

  function replace_dbprefix($txt){
    return trim(str_replace("%DB_PREFIX%", DB_PREFIX,$txt));
  }

  function error($text='') {
    global $messageStack, $cip;
    if ($text) {
      if (CIP::was_unpacked() && CIP::is_unpacked())ci_remove(DIR_FS_CIP.'/'.$this->contrib);
      else {
	CIP::InProcess($text."<br>&#060;<i>".$this->get_tag_name()."&#062; #".$this->get_id(). " ".$this->depend, __CLASS__.'->'.__FUNCTION__.'::'.__LINE__,'block');
	return false;
      }
//       return CIP::$error=$messageStack->add($text.
// 	  "<br>&#060;<i>".$this->get_tag_name()."&#062; #".$this->get_id(). " ".$this->depend. "</i>" , 'error');
    }
// else ret
//     return false;
  }

  function get_lang_file_encoding($fname) {
    $encoding = CHARSET;
    $fs_fname = $this->get_fs_filename($fname);
    if (file_exists($fs_fname)) {
      $old_file = file_get_contents($fs_fname);
      $rx = "((?m)^[ ]*define\(.*CHARSET.*[\"'](.*?)[\"'].*\)[ ]*;)";
      if (preg_match($rx, $old_file, $m))  $encoding = strtoupper($m[1]);
    }
    return $encoding;
  }

  /**
    Checksum 2 files
    @return bool
  */
  function equal_files($file1, $file2) {
    return fileUtility::equal_files($file1, $file2);
  }


  function getITagAttr($tag, $tagpos,$attrname, $defval=NULL){
    if(is_object($tag->item($tagpos))){
	    $rrer=$tag->item($tagpos);
	      return $rrer->getAttribute($attrname);
    }
    return $defval;
  }

  function getTagAttr($xml_data,$tagname, $tagpos,$attrname,$defval=NULL){
    if(is_object($xml_data)){
      $obj = $xml_data->getElementsByTagName($tagname);
      if(is_object($obj))
	if(is_object($obj->item($tagpos))){
	  $rret = $obj->item($tagpos);
	  return $rret->getAttribute($attrname);
	}
    }
    return $defval;
  }

  function getITagText($tag, $tagpos, $defval=NULL){
    if(is_object($tag->item($tagpos))){
	    $rret = $tag->item($tagpos);
	  return trim($rret->nodeValue);
    }
    return $defval;
  }

  function getTagText($xml_data,$tagname, $tagpos, $defval=NULL){
    if(is_object($xml_data)){
      $obj = $xml_data->getElementsByTagName($tagname);
      if(is_object($obj))
	if(is_object($obj->item($tagpos))){
	  $rret = $obj->item($tagpos);
// 	  return $rret->getText();
	  return trim($rret->nodeValue);
	}
    }
    return $defval;
  }

  function isTagName($name){
    return($this->tag_name == $name);
  }


  /**
    Creer un fichier par package
    Rep /tmp
  */
  function add_log(){
//     global $messageStack;
//     if(!_cst_bool('USE_LOG_SYSTEM')) return;
    $tag_data='';
    $file_log=DIR_FS_ADMIN.'includes/tmp/cip_'.$this->contrib.'.log';
    if($this->data==null) return false;
    foreach($this->data as $key=>$value) {
      if(is_array($value)) {
	  $tag_data.="\r\n".$key." (Array):";
	  foreach($value as $ky=>$val)    $tag_data.= "\r\n".$ky."=>".$this->linebreak_view($val)."\r\n";
      } elseif ($value) {
	  if($this->linebreak_view($value)==$value) {
	      $tag_data.= "\r\n".$key.": ".$this->linebreak_view($value);
	  } else $tag_data.= "\r\n".$key.":\r\n".$this->linebreak_view($value);
      }
    }
    $deb=(file_exists($file_log) )?file_get_contents($file_log) : '';
    $deb .="\n\n=======================================================\n\n";
    $fp=fopen($file_log,'w+');
    fwrite($fp,$deb.$this->get_contrib()."\r\n".$this->get_tag_name()."#".$this->get_id()."\r\n". $tag_data);
    fclose($fp);
//     $messageStack->add_log($this->get_contrib()."\r\n".$this->get_tag_name()."#".$this->get_id()."\r\n". $tag_data);
  }


  function cnv_to_regex($text){
    $lines = explode("\n",$text);
    $tt = "((?m)";
    $i=0;
    foreach ($lines as $line){
      $line = trim($line);
      if($i==0){
	$pos = strpos($line,'/* Begin');
	if($pos !== false)
	  $tt .= '\/\* Begin [^-]* - installed by Contrib_Installer[^\*]* \*\/[\s]*';
	else
	  $tt .= preg_quote($line).'[\s]*';
      }else{
	$tt .= preg_quote($line).'[\s]*';
      }
      if(strlen($line)>0)$i++;
    }
    $tt = substr($tt,0,-5).")";
    return $tt;
  }

  function get_num_lines($text){
	  return preg_match_all('((?m)(^.*$))',$text,$m);
  }

}
?>