Overview

Classes

  • Package
  • Service
  • Tlaloc_File
  • User
  • Overview
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * A File management object meant for OpenBSD
   4:  *
   5:  * this object should allow; listing, verifying, updating, removing and installing
   6:  * files of all sort under OpenBSD.
   7:  * Meant to virtualize the base command line tools so we can later port
   8:  * this object to other OSes like Linux, CentOS, etc..
   9:  *
  10:  */
  11: /**
  12:  * Tlaloc_File
  13:  *
  14:  * @package
  15:  * @author selt
  16:  * @copyright Copyright (c) 2014
  17:  * @version $Id$
  18:  * @access public
  19:  */
  20: class Tlaloc_File {
  21:     public $SUPPORTED_COMMANDS=array("exists"=>"Check to see if a file exists","reset"=>"Overwrite the file if it differs","write"=>"Write a file (ignoring previous one)","delete"=>"Delete a local file","install"=>"install");
  22:     public $Repos = array();
  23:     private $Repository_Type;
  24:     private $Agent_PrivKey;
  25:     private $RSync_Excludes = array();
  26:     private $RSYNC_Excludes_Str;
  27:     public $Digest=array();
  28: 
  29:     /**
  30:      * Tlaloc_File::__construct()
  31:      * Instantiate a File object, make sure to supply a Repository array listing, the SSH agent's private key and optionally RSYNC Exclude clauses
  32:      * @param mixed $array_Repositories
  33:      * @param mixed $Agent_PrivKey
  34:      * @param mixed $array_Rsync_Excludes
  35:      */
  36:     function __construct($array_Repositories=null,$Agent_PrivKey=null,$array_Rsync_Excludes=null){
  37:         global $LOGLEVEL;
  38: 
  39:         if (! is_null($Agent_PrivKey)) {
  40:             $this->Agent_PrivKey=$Agent_PrivKey;
  41:         }
  42:         if (! is_null($array_Rsync_Excludes)) {
  43:             $this->RSYNC_Excludes_Str=$this->Merge_RSYNC_Clauses($array_Rsync_Excludes);
  44:             if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "Tlaloc_File->__construct() : INFO : RSYNC Exclude clause : ".$this->RSYNC_Excludes_Str."\n";
  45:         }
  46:         if (is_null($array_Repositories)) {
  47:             // emit an error/warning ?
  48:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Tlaloc_File->__construct() : INFO : Repositories array not set\n";
  49:             $this->Repos[0]="not set!";
  50:         } else {
  51:             if (is_array($array_Repositories)) {
  52:                 // all fine
  53:                 if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Tlaloc_File->__construct() : INFO : Got an array for Repos\n";
  54: //print_r($array_Repositories);
  55:                 $this->Repos = $array_Repositories;
  56: //print "\nAnd stored it as:\n";
  57: //print_r($this->Repos);
  58:             } else {
  59:                 if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Got a string for Repos\n";
  60:                 $this->Repos[0] = $array_Repositories;
  61:             }
  62: 
  63:             foreach ($this->Repos as $x=>$folder ){
  64:                 if (
  65:                 ( substr(strtolower($folder),0,3) == "ftp" OR substr(strtolower($folder),0,3) == "git" OR substr(strtolower($folder),0,4) == "http" )
  66:                 AND ( substr($folder,-1)!=="/"  ) ) {
  67:                     $this->Repos[$x].="/";
  68:                 }
  69:             }
  70:         }
  71:     }
  72: 
  73:     /**
  74:      * Tlaloc_File::Run_Process()
  75:      * Execute a shell command/process. We encapsulate these calls so we don't
  76:      * clobber code with pipes, buffering and such...
  77:      * TODO: make async vs sync calls (flag_WaitForCompletion) by forking or not.
  78:      * @param mixed $cmd
  79:      * @param mixed $flag_WaitForCompletion
  80:      * @param mixed $flag_TextualResult
  81:      * @param mixed $array_ENV
  82:      * @param mixed $flag_ShowOutput
  83:      * @return boolean $result
  84:      */
  85:     public function Run_Process($cmd,$flag_WaitForCompletion=true,$flag_TextualResult=false,$array_ENV=null,$flag_ShowOutput=false){
  86:         global $LOGLEVEL;
  87: 
  88:         $descriptorspec = array(
  89:                    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
  90:                    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
  91:                    2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
  92:                 );
  93: 
  94:         $cwd = '/tmp';
  95:         //$env = array('some_option' => 'aeiou');
  96:         if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Tlaloc_File->Run_Process() : INFO : Opening a process; $cmd\n";
  97:         $process = proc_open($cmd, $descriptorspec, $pipes, null, $array_ENV);
  98: 
  99:         if (is_resource($process)) {
 100:             // $pipes now looks like this:
 101:             // 0 => writeable handle connected to child stdin
 102:             // 1 => readable handle connected to child stdout
 103:             // Any error output will be appended to /tmp/error-output.txt
 104: 
 105:             $output = stream_get_contents($pipes[1]);
 106:             fclose($pipes[0]);
 107:             fclose($pipes[1]);
 108: 
 109:             if ($flag_ShowOutput) {
 110:                 print "Command output : \n$output\n";
 111:             }
 112: 
 113:             // It is important that you close any pipes before calling
 114:             // proc_close in order to avoid a deadlock
 115:             $return_value = proc_close($process);
 116: 
 117:             if (isset($LOGLEVEL) AND $LOGLEVEL > 3) echo "Tlaloc_File->Run_Process() : INFO : command returned $return_value\n";
 118:             if ($return_value == "0") {
 119:                 return true;
 120:             } else {
 121:                 if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "Tlaloc_File->Run_Process($cmd) : ERROR : sub-process returned an error!\n(cmd: $cmd\nexit code $return_value)\n";
 122:                 if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "Output from command execution:\n$output\n";
 123:                 return false;
 124:             }
 125:             return $return_value;
 126:         } else {
 127:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Tlaloc_File->Run_Process($cmd) : ERROR : Unable to open process\n";
 128:             return false;
 129:         }
 130: 
 131:     }
 132:     /**
 133:      * Tlaloc_File::Merge_RSYNC_Clauses()
 134:      * Internal function used to merge rsync command line parameters
 135:      * @param mixed $array_Input
 136:      * @param string $rsync_clause
 137:      * @return
 138:      */
 139:     private function Merge_RSYNC_Clauses($array_Input,$rsync_clause="--exclude"){
 140:         $tmp_str="";
 141:         if (is_array($array_Input)) {
 142:             foreach ($array_Input as $dtl){
 143:                 $tmp_str.=" ".$rsync_clause."=$dtl";
 144:             }
 145:             return $tmp_str;
 146:         } else {
 147:             $tmp_str=$rsync_clause."=$array_Input";
 148:             return $tmp_str;
 149:         }
 150:     }
 151: 
 152:     /**
 153:      * Tlaloc_File::Pick_A_Repos()
 154:      * Obtain a random repository from the list.
 155:      * @return string $repository
 156:      */
 157:     private function Pick_A_Repos(){
 158:         global $LOGLEVEL;
 159:         //print_r($this->Repos);
 160:         $num_repos = count($this->Repos);
 161:         if ($num_repos > 1) {
 162:             // pick a random one
 163:             $x = array_rand($this->Repos,1);
 164:             //          $x=rand(1,$num_repos)-1;
 165:             $selected_Repo = $this->Repos[$x];
 166:         } else {
 167:             $selected_Repo = $this->Repos[0];
 168:         }
 169: 
 170:         /**
 171:          * Attempt to determine Repository type
 172:          * ie; ftp, http, https, ssh/scp, rsync...
 173:          * ftp : ftp://[username:password@]servername/path
 174:          * http: http://[username:password@]servername/path
 175:          * ssh : username@servername:path
 176:          * rsync: username@servername:path
 177:          * git: git://* ?
 178:          *
 179:          * ssh+rsync = /^[a-zA-Z0-9\.-]*@[a-zA-Z0-9\.-]:* /
 180:          * ftp+http = /[ftp|http]:* /
 181:          */
 182:         // for the time being; default to rsync, testing sumething...
 183:         if (isset($LOGLEVEL) AND $LOGLEVEL > 1)  "File->Pick_A_Repos() : INFO : Defaulting to rsync\n";
 184:         $this->Repository_Type="RSYNC";
 185:         return $selected_Repo;
 186: 
 187:         if (strpos(strtolower($selected_Repo),"ftp://")===0) {
 188:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Pick_A_Repos() : INFO : We have an ftp repository\n";
 189:             $this->Repository_Type="FTP";
 190:         }elseif (strpos(strtolower($selected_Repo),"http://")===0){
 191:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Pick_A_Repos() : INFO : We have an http repository\n";
 192:             $this->Repository_Type="HTTP";
 193:         } elseif (strpos(strtolower($selected_Repo),"git://")===0){
 194:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Pick_A_Repos() : INFO : We have a Git repository\n";
 195:             $this->Repository_Type="GIT";
 196:         } elseif (strpos(strtolower($selected_Repo),"s3://")===0){
 197:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Pick_A_Repos() : INFO : We have a AWS:S3 repository\n";
 198:             $this->Repository_Type="S3";
 199:         } else {
 200:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Pick_A_Repos() : INFO : Assuming an SSH/SCP repository\n";
 201:             $this->Repository_Type="SSH";
 202:             // we should make sure we got a PrivKey for it !
 203:             if (! isset($this->Agent_PrivKey)) {
 204:                 print "File->Pick_A_Repos() : WARNING : missing the automated agent's Private key file location for use with SSH or SCP\n";
 205:             }
 206:         }
 207: 
 208:         return $selected_Repo;
 209:     }
 210: 
 211:     /**
 212:      * Tlaloc_File::Look_For_Source()
 213:      * Look for the source file in the stacked repositories, from node to defaults
 214:      * TODO: Make this work with other mediums than SSH, and perhaps, cache the remote listings somehow
 215:      * or have an agent running on the repositories (which would rule out Amazon:S3,arg)
 216:      * @param mixed $Filename
 217:      * @return string $repository_url
 218:      */
 219:     private function Look_For_BestSource($Filename,$Module_Name=null,$flag_UseOsSuffix=true){
 220:         global $Node_Name,$Node_OS,$LOGLEVEL;
 221: 
 222:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print __CLASS__."->".__METHOD__." ($Filename, $Module_Name, $flag_UseOsSuffix) looking for valid sources\n";
 223:         //  compile a list of potential locations to search into for our file
 224:         // the order is VERY important, we want to drill from most-personal to more-general
 225:         if (substr($Filename,-1) == "/" OR ! $flag_UseOsSuffix) {
 226:             // we're looking for a Folder, not a File...
 227:             $possible_srcs[]="nodes/$Node_Name/$Filename";
 228:             if (! is_null($Module_Name)) {
 229:                 $possible_srcs[]="modules/$Module_Name/$Filename";
 230:             }
 231:             $possible_srcs[]="defaults/$Filename";
 232:         } else {
 233:             // looking for a file, append the Node_OS string to the filename's source
 234:             $possible_srcs[]="nodes/$Node_Name/$Filename.".($Node_OS);
 235:             if (! is_null($Module_Name)) {
 236:                 $possible_srcs[]="modules/$Module_Name/$Filename.".($Node_OS);
 237:             }
 238:             $possible_srcs[]="defaults/$Filename.".($Node_OS);
 239:         }
 240: 
 241:         // looping through each potential folder, in each repos (in that order, again,
 242:         // most important. This way, we prioritize personal folders accross repositories
 243:         // before looking into the general or module files.
 244:         foreach ($possible_srcs as $ReposSubs){
 245: 
 246:             if (is_array($this->Repos)) {
 247:                 foreach ($this->Repos as $foo=>$ReposLink){
 248:                     list($AccessToken,$folder_base)=explode(":",$ReposLink,2);
 249:                     if (substr($folder_base,-1)!=='/') {
 250:                         $folder_base.="/";
 251:                     }
 252:                     $cmd_user="ls $folder_base$ReposSubs";
 253:                     $cmd="ssh -o BatchMode=yes -i {$this->Agent_PrivKey} $AccessToken \"$cmd_user\"";
 254:                     if ($this->Run_Process($cmd,true)!==false) {
 255:                         if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print __CLASS__."->".__METHOD__." ($Filename, $Module_Name, $flag_UseOsSuffix) Found a source file : $ReposLink$ReposSubs\n";
 256: 
 257:                         return $ReposLink."$ReposSubs";
 258:                     }
 259:                 }
 260:             }
 261:         }
 262:         print __CLASS__."->".__METHOD__." ($Filename, $Module_Name, $flags_UseOsSuffix) : FILE NOT FOUND !\n";
 263:             // if all else fails; return the default, or an error ?
 264:         return false;
 265:     }
 266: 
 267:     /**
 268:      * Tlaloc_File::Exists()
 269:      * See if a file exists on the local system
 270:      * @param mixed $File_Name
 271:      * @return boolean $result
 272:      */
 273:     public function Exists($File_Name){
 274:         return file_exists($File_Name);
 275:     }
 276: 
 277:     /**
 278:      * Tlaloc_File::Reset()
 279:      * Compare a local file with the repository copy, and if they differ, reset it to the Repository's version.
 280:      * @param mixed $Src_File
 281:      * @param mixed $param_Destination_Filename
 282:      * @return
 283:      */
 284:     public function Reset($Src_File,$param_Destination_Filename=null){
 285:         if (is_null($param_Destination_Filename)) {
 286:             $Destination_Filename = $Src_File;
 287:         } else {
 288:             $Destination_Filename =$param_Destination_Filename;
 289:         }
 290: 
 291:         if ($this->Exists($Destination_Filename)) {
 292:             /**
 293:              * Compare the source and destination files.
 294:              * If different, overwrite with source file.
 295:              */
 296:             return true;
 297:         } else {
 298:             /**
 299:              * just write the file !
 300:              *
 301:              */
 302:             return $this->Write($Src_File,$param_Destination_Filename);
 303:         }
 304:     }
 305: 
 306:     /**
 307:      * Tlaloc_File::Source()
 308:      * Source or re-source a file from a repository
 309:      * @param mixed $Src_File
 310:      * @param mixed $Destination_Filename
 311:      * @param mixed $Repository
 312:      * @param mixed $Permissions
 313:      * @param mixed $Owner
 314:      * @param mixed $Group
 315:      * @param mixed $Module_Name
 316:      * @return boolean $result
 317:      */
 318:     public function Source($Src_File,$Destination_Filename=null,$Repository=null,
 319:                         $Permissions=null,$Owner=null,$Group=null,$Module_Name=null,$RSync_Options="" ){
 320:         global $LOGLEVEL;
 321: 
 322:         $foo_Src_File=basename($Src_File);
 323:         if (is_null($Repository)) {
 324:             //$Selected_Repos = $this->Pick_A_Repos();
 325:             if ( ($Selected_Repos=$this->Look_For_BestSource($Src_File,$Module_Name)) === false ) {
 326:                 print "Taloc_File->Source() : ERROR : $Src_File couldn't be found in the repositories\n";
 327:                 return false;
 328:             }
 329:         } else {
 330:             $Selected_Repos = $Repository;
 331:             // add a trailing slash, clearer later.
 332:             if (substr($Selected_Repos,-1) !== "/") {
 333:                 $Selected_Repos.="/";
 334:             }
 335:         }
 336:         $cd_dir="";
 337: 
 338:         if (is_null($Destination_Filename)) {
 339: //          print "File->Write: Destination_Filename MUST be specified and absolute!\n";
 340: //          return false;
 341:             if ($this->Repository_Type == "SSH") {
 342:                 $param_Destination_Filename=$Src_File;
 343:             } else {
 344:                 // we should lcd into the appropriate reception folder before executing the transfer.
 345:                 // but its null, stay where we are
 346:             }
 347:             $param_Destination_Filename=$Src_File;
 348:         } else {
 349:             $param_Destination_Filename = $Destination_Filename;
 350:             if (file_exists($param_Destination_Filename) AND is_dir($param_Destination_Filename) ) {
 351:                 // we have an existing local folder reference, all good.
 352:                 if ($this->Repository_Type == "FTP" OR $this->Repository_Type == "HTTP") {
 353:                     $cd_dir="cd $param_Destination_Filename; ";
 354:                 }
 355:             }
 356:         }
 357: 
 358:         if (substr($Src_File,-1)==="/") {
 359:             if ($this->Repository_Type == "FTP" OR $this->Repository_Type == "HTTP") {
 360:                 print "File->Write: Repository type ( ".$this->Repository_Type." ) doesn't allow recursive transfers\n";
 361:                 return false;
 362:             }
 363:             if ($this->Repository_Type == "RSYNC") {
 364:                 // fix for rsync recursiveness...
 365:                 $Src_File=substr($Src_File,0,-1);
 366:             }
 367:             // we have a source Folder to copy; therefore, recursive call
 368:             // for which we can't diff sub-items.
 369:             $recurs="-r";
 370:         } else {
 371:             $recurs="";
 372:         }
 373: 
 374:         /**
 375:          * copy the source file to its destination
 376:          * be mindful of recursive directory copies !!!
 377:          *
 378:          * also; the methodology depends on the Repository_Type ;)
 379:          * ouch; ftp+http don't get recursion.
 380:          */
 381: //return 1;
 382:         /**
 383:          * Use RSYNC ???
 384:          *
 385:          */
 386:         $cmd="rsync -e 'ssh -o BatchMode=yes -i {$this->Agent_PrivKey}' $recurs $RSync_Options {$this->RSYNC_Excludes_Str} $Selected_Repos $param_Destination_Filename";
 387:         if (isset($LOGLEVEL) AND $LOGLEVEL > 0) print "Defaulting to rsync; executing: $cmd\n";
 388: 
 389: //      $result = shell_exec($cmd);
 390:         $result = $this->Run_Process($cmd,true);
 391: 
 392:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "rsync result = $result\n";
 393:         if (! is_null($Owner)) {
 394:             // a chown will be attempted.
 395:             $chown_cmd="chown ";
 396:             if ($recurs=="-r") {
 397:                 $chown_cmd.="-R ";
 398:             }
 399:             $chown_cmd.=$Owner;
 400:             if (! is_null($Group)) {
 401:                 $chown_cmd.=".$Group";
 402:             }
 403:             $chown_cmd.=" $param_Destination_Filename";
 404:             $chown_result = $this->Run_Process($chown_cmd,true);
 405:             $this->Digest[]=__CLASS__."->".__METHOD__." : chown executed [$chown_cmd] [$chown_result]";
 406:         } else if ( ! is_null($Group)) {
 407:             // chgrp requested...
 408:             $chown_cmd="chgrp ";
 409:             if ($recurs=="-r") {
 410:                 $chown_cmd.="-R ";
 411:             }
 412:             $chown_cmd.="$Group";
 413:             $chown_cmd.=" $param_Destination_Filename";
 414:             $chown_result = $this->Run_Process($chown_cmd,true);
 415:             $this->Digest[]=__CLASS__."->".__METHOD__." : chgrp executed [$chown_cmd] [$chown_result]";
 416:         }
 417: 
 418:         return $result;
 419: 
 420:         if ( $this->Repository_Type == "FTP" OR $this->Repository_Type == "HTTP" ) {
 421:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Will execute : \n$cd_dir ftp ".$Selected_Repo.$SrcFile." \n";
 422:             $result=`$cd_dir ftp $Selected_Repo$SrcFile`;
 423:         }elseif( $this->Repository_Type == "SSH" ){
 424:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "Will execute : \nscp -qBp $recurs ".$Selected_Repos.$Src_File." ".$param_Destination_Filename."\n";
 425:             $result=`scp -qBp $recurs $RSync_Options $Selected_Repos.$Src_File $param_Destination_Filename`;
 426:         }
 427: 
 428: 
 429:         return $result;
 430: 
 431:     }
 432: 
 433:     /**
 434:      * Tlaloc_File::File_ChangeGroup()
 435:      * Change Group settings on a file, usually used internally, but available publicly
 436:      * @param mixed $Filename
 437:      * @param string $Group
 438:      * @param boolean $flag_Recursive
 439:      * @return
 440:      */
 441:     public function File_ChangeGroup($Filename,$Group="wheel",$flag_Recursive=false){
 442:         if ($flag_Recursive) {
 443:             $recurs="-R";
 444:         } else {
 445:             $recurs="";
 446:         }
 447:         return `chgrp $recurs $Group $Filename`;
 448: //      return chgrp($Filename,$Group);
 449:     }
 450:     /**
 451:      * Tlaloc_File::File_Chown()
 452:      * Chown a file resource, usually used internally, but available publicly
 453:      * @param mixed $Filename
 454:      * @param string $Owner
 455:      * @param boolean $flag_Recursive
 456:      * @return boolean $result
 457:      */
 458:     public function File_Chown($Filename,$Owner="root",$flag_Recursive=false){
 459:         if ($flag_Recursive) {
 460:             $recurs="-R";
 461:         } else {
 462:             $recurs="";
 463:         }
 464:         return `chown $recurs $Owner $Filename`;
 465: //      return chown($Filename,$Owner);
 466:     }
 467:     /**
 468:      * Tlaloc_File::File_SetPermissions()
 469:      * Set File/Folder permissions, usually used internally, but available publicly
 470:      * @param mixed $Filename
 471:      * @param string $Permissions
 472:      * @param boolean $flag_Recursive
 473:      * @return boolean $result
 474:      */
 475:     function File_SetPermissions($Filename,$Permissions="755",$flag_Recursive=false){
 476:         global $LOGLEVEL;
 477:         if ($flag_Recursive) {
 478:             $recurs="-R";
 479:         } else {
 480:             $recurs="";
 481:         }
 482:         $fooPermissions="0$Permissions";
 483:         $cmd="chmod $recurs $fooPermissions $Filename";
 484: //      chmod($Filename,$Permissions);
 485:         if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print __CLASS__."->".__METHOD__." ($Filename,$Permissions,$flag_Recursive) : INFO : Executing $cmd\n";
 486:         return shell_exec($cmd);
 487: //      return chmod($Filename,$Permissions);
 488:     }
 489: 
 490:     /**
 491:      * Tlaloc_File::SetAttributes()
 492:      * Apply a set of attribute to a File/Folder object (Permissions, Owner, Group)
 493:      * Usually used internally, but available publicly
 494:      * @param mixed $Filename
 495:      * @param mixed $Permissions
 496:      * @param mixed $Owner
 497:      * @param mixed $Group
 498:      * @param boolean $flag_Recursive   boolean, default false
 499:      * @return
 500:      */
 501:     public function SetAttributes($Filename,$Permissions=null,$Owner=null,$Group=null,$flag_Recursive=false){
 502:         if (! is_null($Owner)) {
 503:             $this->File_Chown($Filename,$Owner,$flag_Recursive);
 504:         }
 505:         if (! is_null($Permissions)) {
 506:             $this->File_SetPermissions($Filename,$Permissions,$flag_Recursive);
 507:         }
 508:         if (! is_null($Group)) {
 509:             $this->File_ChangeGroup($Filename,$Group,$flag_Recursive);
 510:         }
 511:     }
 512: 
 513:     /**
 514:      * File::Makedir()
 515:      * Create a directory on the local host with Permissions,Owner and Group to be set
 516:      * @param mixed $Dirname
 517:      * @param string $Permissions   default "0755"
 518:      * @param string $Owner default "root"
 519:      * @param string $Group default "wheel"
 520:      * @return boolean $result
 521:      */
 522:     public function Makedir($Dirname,$Permissions="0755",$Owner="root",$Group="wheel"){
 523:         if (strpbrk($Permissions,"ugoaUGOA-+=") !== false) {
 524:             print "File->Makedir($Dirname,$Permissions,$Owner,$Group) : invalid permission set, use a numeric set like 0755\n";
 525:             return false;
 526:         }
 527:         if (substr($Dirname,-1)=="/") {
 528:             $Dirname=substr($Dirname,0,-1);
 529:         }
 530:         if (! $this->Exists($Dirname)) {
 531:             $mainstatus=mkdir($Dirname,$Permissions,true);
 532:         } else {
 533:             $mainstatus=true;
 534:         }
 535:         if (! is_null($Owner)) {
 536:             $this->File_Chown($Dirname,$Owner);
 537:         }
 538:         if (! is_null($Permissions)) {
 539:             $this->File_SetPermissions($Dirname,$Permissions);
 540:         }
 541:         if (! is_null($Group)) {
 542:             $this->File_ChangeGroup($Dirname,$Group);
 543:         }
 544:         //chmod($Dirname,$Permissions);
 545:         return $mainstatus;
 546:     }
 547: 
 548: 
 549:     /**
 550:      * Tlaloc_File::AddLine()
 551:      * Add a text line to a text file (in append mode at the bottom of the file)
 552:      * @param mixed $Filename
 553:      * @param mixed $LineToAdd
 554:      * @return boolean $result
 555:      */
 556:     public function AddLine($Filename,$LineToAdd){
 557:         global $LOGLEVEL;
 558:         $buf_Line=str_replace('"','\"',trim($LineToAdd));
 559:         $cmd="grep \"^$buf_Line$\" $Filename | wc -l";
 560:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->AddLine() : INFO : will execute : $cmd\n";
 561:         $result=intval(trim(`$cmd`));
 562:         if ($result > 0) {
 563:             if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->AddLine() : INFO : line already exists in target file, returning true to maintain indempotency\n";
 564:             // line found, just return true to maintain indempotency
 565:             return true;
 566:         }
 567:         $fwrite=fopen($Filename,"a");
 568:         if (substr($LineToAdd,-1) !== "\n") {
 569:             $LineToAdd.="\n";
 570:         }
 571:         $result = fputs($fwrite,$LineToAdd);
 572:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->AddLine() : INFO : line written with $result bytes\n";
 573: 
 574:         fclose($fwrite);
 575:         return $result;
 576:     }
 577: 
 578:     /**
 579:      * Tlaloc_File::AddLine_IfNotFound()
 580:      * Append a line of text to a text file, given that the submitted Grep pattern is not found in the file.
 581:      * @param mixed $Filename
 582:      * @param mixed $LineToAdd
 583:      * @param mixed $NotFound_Pattern
 584:      * @return boolean $result
 585:      */
 586:     public function AddLine_IfNotFound($Filename,$LineToAdd,$NotFound_Pattern){
 587:         global $LOGLEVEL;
 588:         $buf_Line=str_replace('"','\"',trim($NotFound_Pattern));
 589:         $cmd="grep \"^$buf_Line\" $Filename | wc -l";
 590:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->AddLine_IfNotFound() : INFO : will execute : $cmd\n";
 591:         $result=intval(trim(`$cmd`));
 592:         if ($result > 0) {
 593:             // line found, just return true to maintain indempotency
 594:             if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->AddLine_IfNotFound() : INFO : pattern found in target file, returning true to maintain indempotency\n";
 595: 
 596:             return true;
 597:         }
 598:         if (substr($LineToAdd,-1) !== "\n") {
 599:             $LineToAdd.="\n";
 600:         }
 601:         $fwrite=fopen($Filename,"a");
 602:         $result = fputs($fwrite,$LineToAdd);
 603:         fclose($fwrite);
 604:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->AddLine_IfNotFound() : INFO : line written with $result bytes\n";
 605: 
 606:         return $result;
 607: 
 608:     }
 609:     /**
 610:      * Tlaloc_File::RemoveLine()
 611:      * Remove a line, using a grep pattern, from a file. Note that you can grep many lines ;)
 612:      * @param mixed $Filename
 613:      * @param mixed $Filename
 614:      * @param mixed $Preg_Pattern
 615:      * @return boolean $result
 616:      */
 617:     public function RemoveLine($Filename,$Grep_Pattern){
 618:         global $LOGLEVEL;
 619: 
 620:         $buf_Pattern=str_replace('"','\"',trim($Grep_Pattern));
 621:         $cmd="grep \"^$buf_Pattern\" $Filename | wc -l";
 622:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->RemoveLine() : INFO : will execute : $cmd\n";
 623: 
 624:         $result=intval(trim(`$cmd`));
 625:         if ($result == 0) {
 626:             // line not found, just return true to maintain indempotency
 627:             print "File->RemoveLine() : INFO : ($Filename,$Grep_Pattern) : pattern not found\n";
 628:             return true;
 629:         }
 630:         /**
 631:          * TODO : Duh ! could just use grep -v "Pattern" sourcefile | outputfile... hello ?
 632:          *
 633:          */
 634: 
 635:         $Line_Content_ToRemove=`grep -n "^$buf_Pattern" $Filename`;
 636:         $arr_Lines=split("/\n/",$Line_Content_ToRemove);
 637:         foreach ($arr_Lines as $foo=>$grep_result){
 638:             list($linenumber,$linecontent)=preg_split("/:/",$grep_result,2);
 639:             $arr_Removals[$linenumber]=trim($linecontent);
 640:         }
 641:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) {
 642:             print "File->RemoveLine() : INFO : matching lines for removal\n";
 643:             print_r($arr_Removals);
 644:         }
 645:         if ( ($fsource=fopen($Filename,"r")) !== false ) {
 646:             $flag_error=false;
 647:             $num_lines_read=0;
 648:             $num_lines_removed=0;
 649:             $num_lines_written=0;
 650: 
 651:             if ( ($fdest=fopen($Filename.".tmp","w")) !== false) {
 652:                 while (($buffer = fgets($fsource, 4096)) !== false) {
 653:                     $num_lines_read++;
 654:                     if (isset($arr_Removals[$num_lines_read])) {
 655:                         // a line to remove normally... according to our pre-parser
 656:                         $num_lines_removed++;
 657:                         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->RemoveLine() : INFO : A line to be removed, line $num_lines_read\n";
 658:                     } else {
 659:                         if (! fputs($fdest,$buffer) ) {
 660:                             echo "File->RemoveLine() : Error: error during file writing";
 661:                             print "Aborting new file and leaving old file as-is ($Filename)\n";
 662:                             $flag_error=true;
 663:                         } else {
 664:                             $num_lines_written++;
 665:                         }
 666:                     }
 667:                     /*
 668:                     * We favored the previous method because starting to mix
 669:                        grep and preg can get fucking confusing...
 670:                     if (preg_match("/^$Preg_Pattern/",$buffer)!== false) {
 671:                         $num_lines_removed++;
 672:                         //if (trim(buffer)==$LineToRemove) {
 673:                         // skip this line ! hourray !
 674:                     } else {
 675:                         if (! fputs($fdest,$buffer) ) {
 676:                             echo "File->RemoveLine() : Error: error during file writing";
 677:                             print "Aborting new file and leaving old file as-is ($Filename)\n";
 678:                             $flag_error=true;
 679:                         } else {
 680:                             $num_lines_written++;
 681:                         }
 682:                     }
 683:                     */
 684:                 }
 685:                 if (!feof($fsource)) {
 686:                     echo "File->RemoveLine() : Error: unexpected fgets() failure\n";
 687:                     print "Aborting new file and leaving old file as-is ($Filename)\n";
 688:                     $flag_error=true;
 689:                 }
 690:                 fclose($fsource);
 691:                 fclose($fdest);
 692:                 if (! $flag_error ) {
 693:                     // file generation was successful, replace real file with tmp one
 694:                     //return 1;
 695:                     if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->RemoveLine() : INFO : $num_lines_removed lines were removed\n";
 696:                     return rename($Filename.".tmp",$Filename);
 697:                 }
 698:             } else {
 699:                 fclose($fsource);
 700:                 return false;
 701:             }
 702: 
 703:         }
 704:         return false;
 705:     }
 706: 
 707:     /**
 708:      * Tlaloc_File::WriteFile()
 709:      * Create and write a file with the provided content. set flag_Overwrite to true to force an overwrite.
 710:      * @param mixed $Filename
 711:      * @param mixed $Content
 712:      * @param mixed $flag_OverwriteIfExists
 713:      * @return int $bytes_written or boolean FALSE
 714:      */
 715:     public function WriteFile($Filename,$Content,$flag_OverwriteIfExists=false){
 716:         global $LOGLEVEL;
 717: 
 718:         if ($this->Exists($Filename)) {
 719:             if (! $flag_OverwriteIfExists ) {
 720:                 print "File->WriteFile() : ACTION NOT ALLOWED : File already exists and the Overwrite flag is set to false\n";
 721:                 return false;
 722:             } else {
 723:                 $flags="w";
 724:             }
 725:         }
 726:         $fhandle=fopen($Filename,"w");
 727:         //$status=fputs($fwrite,$Content);
 728:         for ($written = 0; $written < strlen($Content); $written += $fwrite) {
 729:             $fwrite = fwrite($fhandle, substr($Content, $written));
 730:             if ($fwrite === false) {
 731:                 fclose($fhandle);
 732:                 return $written;
 733:             }
 734:         }
 735:         fclose($fhandle);
 736:         return $written;
 737:     }
 738: 
 739:     /**
 740:      * Tlaloc_File::Append_To_Var()
 741:      * Append to a var content within a config text file.
 742:      * @param mixed $Filename
 743:      * @param mixed $Varname
 744:      * @param mixed $Value_To_Add
 745:      * @param mixed $Var_Style (SSH|RC)
 746:      * @return boolean $result
 747:      */
 748:     public function Append_To_Var($Filename,$Varname,$Value_To_Add,$Var_Style="RC"){
 749:         if (! $this->Exists($Filename) ) {
 750:             print "File->Append_To_Var() : ERROR : File [$Filename] does not exists\nFunction returning false\n";
 751:             return false;
 752:         }
 753:         if ($Var_Style=="RC") {
 754:             $result=intval(trim(`grep "^$Varname=" $Filename | wc -l`));
 755:         } else {
 756:             $result=intval(trim(`grep "^$Varname" $Filename | wc -l`));
 757:         }
 758:         if ($result < 1) {
 759:             // variable not found, ah ! we should just add it, duh !
 760:             if ($Var_Style=="RC") {
 761:                 return $this->AddLine($Filename,"$Varname=\"$Value_To_Add\"");
 762:             } else {
 763:                 return $this->AddLine($Filename,"$Varname   $Value_To_Add");
 764:             }
 765: 
 766: 
 767:             //print "File->Append_To_Var() : ERROR : Variable [$Varname] not found within file [$Filename]\nFunction returning false\n";
 768:             return false;
 769:         } elseif ($result > 1){
 770:             print "File->Append_To_Var() : ERROR : Ambigous variable, it was found more than once in file [$Filename]\nFunction returning false\n";
 771:             return false;
 772:         } else {
 773: 
 774:             // make sure the value is not already in there !!!
 775:             $result2=intval(trim(`grep "^$Varname" $Filename | grep "$Value_To_Add" | wc -l`));
 776:             if ($result2 > 0) {
 777:                 // the value seems to already exist in the variable line.
 778:                 if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Append_To_Var() : INFO : Value already exists within file [$Filename] var [$Varname]\nFunction returning true for idempotency\n";
 779:                 return true;
 780:             }
 781: 
 782:             if ($Var_Style=="RC") {
 783:                 $varline=trim(`grep "^$Varname=" $Filename`);
 784:                 if (substr($varline,-1)=='"') {
 785:                     // quoted var value, nice...
 786:                     $newline=substr($varline,0,-1)." ".$Value_To_Add.'"';
 787:                 } else {
 788:                     $newline=$varline." ".$Value_To_Add;
 789:                 }
 790:                 $result1=$this->Replace_Line($Filename,"^$Varname=",$newline);
 791: //              $result1=$this->RemoveLine($Filename,"$Varname=");
 792:             } else {
 793:                 $varline=trim(`grep "^$Varname" $Filename`);
 794:                 if (substr($varline,-1)=='"') {
 795:                     // quoted var value, nice...
 796:                     $newline=substr($varline,0,-1)." ".$Value_To_Add.'"';
 797:                 } else {
 798:                     $newline=$varline." ".$Value_To_Add;
 799:                 }
 800: //              $result1=$this->RemoveLine($Filename,"$Varname");
 801:                 $result1=$this->Replace_Line($Filename,"^$Varname",$newline);
 802:             }
 803: 
 804: //          $result2=$this->AddLine($Filename,$newline);
 805: 
 806:             return $result2;
 807: 
 808:         }
 809:     }
 810: 
 811:     /**
 812:      * Tlaloc_File::Replace_Line()
 813:      * Internal function used in swapping old and new text lines in config files.
 814:      * @param mixed $Filename
 815:      * @param mixed $Old_Line
 816:      * @param mixed $New_Line
 817:      * @return boolean $result
 818:      */
 819:     private function Replace_Line($Filename,$Old_Line,$New_Line){
 820:         global $LOGLEVEL;
 821: 
 822:         $buf_Old_Line=str_replace('"','\"',trim($Old_Line));
 823:         $buf_New_Line=str_replace('"','\"',trim($New_Line));
 824: 
 825:         $cmd="grep \"$buf_Old_Line\" $Filename | wc -l";
 826:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "FileReplace_LineRemoveLine() : INFO : will execute to see if the old line is in there : $cmd\n";
 827:         $result=intval(trim(`$cmd`));
 828: 
 829:         if ($result == 0) {
 830:             // line not found, just return true to maintain idempotency
 831:             print "File->Replace_Line() : INFO : ($Filename,$Old_Line) : old pattern not found\n";
 832:             // see if the new pattern is in there already
 833:             $cmd="grep \"$buf_New_Line\" $Filename | wc -l";
 834:             if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->Replace_Line() : INFO : will execute to see if the new line already exists : $cmd\n";
 835:             $result_newline=intval(trim(`$cmd`));
 836:             if ($result_newline>0) {
 837:                 // new line is already set; return true to remain idempotent.
 838:                 return true;
 839:             } else {
 840:                 // neither old or new lines could be found, this *should* be an error
 841:                 print "File->Replace_Line() : ERROR : Neither old or new line could be found within the file, returning false\n";
 842:                 print "File->Replace_Line() : DUMP : Filename: $Filename\n";
 843:                 print "File->Replace_Line() : DUMP : Old line: $Old_Line\n";
 844:                 print "File->Replace_Line() : DUMP : New line: $New_Line\n";
 845: 
 846:             }   // else, just keep going...
 847:         }
 848:         /**
 849:          * TODO : Duh ! could just use grep -v "Pattern" sourcefile | outputfile... hello ?
 850:          *
 851:          */
 852: 
 853:         $Line_Content_ToRemove=`grep -n "$buf_Old_Line" $Filename`;
 854:         $arr_Lines=explode("\n",$Line_Content_ToRemove);
 855:         foreach ($arr_Lines as $foo=>$grep_result){
 856:             list($linenumber,$linecontent)=explode(":",$grep_result,2);
 857:             $arr_Removals[$linenumber]=trim($linecontent);
 858:         }
 859:         if (isset($LOGLEVEL) AND $LOGLEVEL > 3) {
 860:             print "File->Replace_Line() : INFO : matching lines for removal\n";
 861:             print_r($arr_Removals);
 862:         }
 863:         if ( ($fsource=fopen($Filename,"r")) !== false ) {
 864:             $flag_error=false;
 865:             $num_lines_read=0;
 866:             $num_lines_removed=0;
 867:             $num_lines_written=0;
 868:             $num_lines_inserted=0;
 869:             $flag_reinsertion_done=false;
 870: 
 871:             if ( ($fdest=fopen($Filename.".tmp","w")) !== false) {
 872:                 while (($buffer = fgets($fsource, 4096)) !== false AND ! $flag_error) {
 873:                     $num_lines_read++;
 874:                     if (isset($arr_Removals[$num_lines_read])) {
 875:                         // a line to replace normally... according to our pre-parser
 876:                         if ( ! $flag_reinsertion_done ) {
 877:                             if (substr($New_Line,-1)!=="\n") {
 878:                                 $New_Line.="\n";
 879:                             }
 880:                             if (! fputs($fdest,$New_Line) ) {
 881:                                 echo "File->Replace_Line() : Error: error during file writing";
 882:                                 print "Aborting new file and leaving old file as-is ($Filename)\n";
 883:                                 $flag_error=true;
 884:                             } else {
 885:                                 $num_lines_written++;
 886:                                 $flag_reinsertion_done=true;
 887:                                 $num_lines_inserted++;
 888:                                 $num_lines_removed++;
 889:                             }
 890:                         } else {
 891:                             if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->Replace_Line() : INFO : Removing an additional line, matching our Old pattern input. But not re-inserting the replacement content as that was already done.\n";
 892:                             $num_lines_removed++;
 893:                         }
 894: 
 895: 
 896:                     } else {
 897:                         if (! fputs($fdest,$buffer) ) {
 898:                             echo "File->Replace_Line() : Error: error during file writing";
 899:                             print "Aborting new file and leaving old file as-is ($Filename)\n";
 900:                             $flag_error=true;
 901:                         } else {
 902:                             $num_lines_written++;
 903:                         }
 904:                     }
 905:                 }
 906:                 if (!feof($fsource)) {
 907:                     echo "File->Replace_Line() : Error: unexpected fgets() failure\n";
 908:                     print "Aborting new file and leaving old file as-is ($Filename)\n";
 909:                     $flag_error=true;
 910:                 }
 911:                 fclose($fsource);
 912:                 fclose($fdest);
 913:                 if (! $flag_error ) {
 914:                     // file generation was successful, replace real file with tmp one
 915:                     //return 1;
 916:                     if (isset($LOGLEVEL) AND $LOGLEVEL > 3) print "File->Replace_Line() : INFO : lines (removed,inserted,written) ($num_lines_removed,$num_lines_inserted,$num_lines_written)\n";
 917:                     return rename($Filename.".tmp",$Filename);
 918:                 } else {
 919:                     if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Replace_Line() : INFO : An error was detected during file transformation, operation aborted, the old file is maintained.\n";
 920:                     return false;
 921:                 }
 922:             } else {
 923:                 fclose($fsource);
 924:                 return false;
 925:             }
 926: 
 927:         }
 928:         return false;
 929:     }
 930: 
 931:     /**
 932:      * Tlaloc_File::Remove_From_Var()
 933:      * Remove a value from a var within a specified text/config file
 934:      * @param mixed $Filename
 935:      * @param mixed $Varname
 936:      * @param mixed $Value_To_Remove
 937:      * @param string $Var_Style
 938:      * @return boolean $result
 939:      */
 940:     public function Remove_From_Var($Filename,$Varname,$Value_To_Remove,$Var_Style="RC"){
 941:         global $LOGLEVEL;
 942: 
 943:         $buf_Value_To_Remove=str_replace('"','\"',trim($Value_To_Remove));
 944: 
 945:         if (! $this->Exists($Filename) ) {
 946:             print "File->Remove_From_Var() : ERROR : File [$Filename] does not exists\nFunction returning false\n";
 947:             return false;
 948:         }
 949:         if ($Var_Style=="RC") {
 950:             $result=intval(trim(`grep "^$Varname=" $Filename | wc -l`));
 951:         } else {
 952:             $result=intval(trim(`grep "^$Varname " $Filename | wc -l`));
 953:         }
 954:         if ($result < 1) {
 955:             // variable not found, emit a warning beep and return true to maintain indempotency
 956:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Remove_From_Var() : ERROR : Variable [$Varname] not found within file [$Filename]\nFunction returning false\n";
 957:             return false;
 958:         } elseif ($result > 1){
 959:             print "File->Remove_From_Var() : ERROR : Ambigous variable, it was found more than once in file [$Filename]\nFunction returning false\n";
 960:             return false;
 961:         } else {
 962: 
 963:             /**
 964:              * do the remove + addline trick as above...
 965:              *
 966:              */
 967: 
 968: 
 969:             if ($Var_Style=="RC") {
 970:                 /**
 971:                  * make sure the value is there
 972:                  *
 973:                  */
 974:                 $result2=intval(trim(`grep "^$Varname=" $Filename | grep "$buf_Value_To_Remove" | wc -l`));
 975:                 if ($result2 == 0) {
 976:                     // value already removed, to maintain idempotency, return true.
 977:                     if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Remove_From_Var() : INFO : Value already removed within file [$Filename] var [$Varname]\nFunction returning true for idempotency\n";
 978:                     return true;
 979:                 }
 980:                 $varline=trim(`grep "^$Varname=" $Filename`);
 981:                 $newline=preg_replace("/\b$Value_To_Remove\b[\s]*/","",$varline);
 982: //              $newline=str_replace($buf_Value_To_Remove,"",$varline);
 983:                 /**
 984:                  * todo, convert the following 2 calls into a ReplaceLine()
 985:                  *
 986:                  */
 987:                 $result2 = $this->Replace_Line($Filename,$varline,$newline);
 988:                 //$this->RemoveLine($Filename,"$Varname=");
 989:                 //$result2=$this->AddLine($Filename,$newline);
 990:             } else {
 991:                 /**
 992:                  * make sure the value is there
 993:                  *
 994:                  */
 995:                 $result2=intval(trim(`grep "^$Varname " $Filename | grep "$buf_Value_To_Remove" | wc -l`));
 996:                 if ($result2 == 0) {
 997:                     // value already removed, to maintain idempotency, return true.
 998:                     if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Remove_From_Var() : INFO : Value already removed within file [$Filename] var [$Varname]\nFunction returning true for idempotency\n";
 999:                     return true;
1000:                 }
1001:                 $varline=trim(`grep "^$Varname " $Filename`);
1002:                 //$newline=str_replace($buf_Value_To_Remove,"",$varline);
1003:                 $newline=preg_replace("/\b$Value_To_Remove\b[\s]*/","",$varline);
1004:                 /**
1005:                  * todo, convert the following 2 calls into a ReplaceLine()
1006:                  *
1007:                  */
1008:                 $result2 = $this->Replace_Line($Filename,$varline,$newline);
1009:                 //$this->RemoveLine($Filename,"$Varname ");
1010:                 //$result2=$this->AddLine($Filename,$newline);
1011:             }
1012:             if (isset($LOGLEVEL) AND $LOGLEVEL > 2) print "File->Remove_From_Var() : INFO : removing line [$varline] and inserting line [$newline]\n";
1013: 
1014:             if (isset($LOGLEVEL) AND $LOGLEVEL > 1) print "File->Remove_From_Var() : INFO : Value removed from within file [$Filename] var [$Varname]\nFunction returning [$result2]\n";
1015:             return $result2;
1016: 
1017:         }
1018:     }
1019: 
1020: 
1021: 
1022:     /**
1023:      * Tlaloc_File::ldd_check()
1024:      * Execute the ldd utility on a file and return its dependency list or null if none, or false on error
1025:      * @param mixed $Src_File
1026:      * @return array $dependency_list
1027:      */
1028:     protected function ldd_check($Src_File){
1029:         $this->Digest[]="running ldd on $Src_File";
1030:         $output=array();
1031:         $return_value=null;
1032:         $result=exec("file $Src_File | grep -q \"statically linked\"",$output,$return_value);
1033:         if ($return_value == 0) {
1034:             // statically linked, easy as pie!
1035:             return null;
1036:         } else {
1037:             $output=array();
1038:             $return_value=null;
1039:             $result=exec("file $Src_File | grep -q \"dynamically linked\"",$output,$return_value);
1040:             if ($return_value == 0) {
1041:                 // dynamically linked, it has dependencies!
1042:                 $dependencies_arr=array();
1043:                 $fooresult=exec("ldd $Src_File | awk '{print ($7)}'",$dependencies_arr,$return_value);
1044:                 if (count($dependencies_arr)>= 3) {
1045:                     for( $x=2; $x < count($dependencies_arr); $x++ ){
1046:                         $return_list[]=$dependencies_arr[$x];
1047:                     }
1048:                     return $return_list;
1049:                 } else {
1050:                     return false;
1051:                 }
1052:             } else {
1053:                 // erm... not statically or dynamically linked ?
1054:                 // we would assume a simple text file ?
1055:                 return null;
1056:             }
1057:         }
1058:     }
1059:     /**
1060:      * Tlaloc_File::Jail()
1061:      * Jail a program file or a config file within a particular Destination_Root, making sure to transfer
1062:      * any dependencies as reported by the ldd unix utility, and creating the necessary sub-folders in the destination.
1063:      * @param mixed $Src_File
1064:      * @param mixed $Destination_Root
1065:      * @param boolean $flag_Strip_Source_Path
1066:      * @return boolean $result
1067:      */
1068:     public function Jail($Src_File,$Destination_Root,$flag_Strip_Source_Path=false,$flag_Executable=true){
1069:         global $LOGLEVEL;
1070: 
1071:         if (isset($LOGLEVEL) AND $LOGLEVEL > 0) print __CLASS__."->".__METHOD__." : will jail $Src_File\n";
1072: 
1073:         $ldd_result = $this->ldd_check($Src_File);
1074:         if ($ldd_result===false) {
1075:             // an error occurred
1076:             print __CLASS__."->".__METHOD__. " : CRITICAL ERROR : ldd returned an error\n";
1077:             return false;
1078:         } elseif (is_null($ldd_result)){
1079:             // simple static executable or regular file
1080:             $tmp_dst=$Destination_Root.dirname($Src_File);
1081:             $tmp_Filename=basename($Src_File);
1082:             if ( ! file_exists($tmp_dst) ) {
1083:                 $this->Makedir($tmp_dst, "755", "root", "wheel");
1084:             }
1085:             if (! copy($Src_File,$tmp_dst."/".$tmp_Filename) ) {
1086:                 // an error occurred
1087:                 print __CLASS__."->".__METHOD__.":Error: unable to copy a dependency; from $Src_File to $tmp_dst/$tmp_Filename\n";
1088:                 return false;
1089:             } else {
1090:                 if ($flag_Executable) {
1091:                     $this->File_SetPermissions($tmp_dst."/".$tmp_Filename,"755");
1092:                 } else {
1093:                     $this->File_SetPermissions($tmp_dst."/".$tmp_Filename,"644");
1094:                 }
1095:                 if (isset($LOGLEVEL) AND $LOGLEVEL > 0) print "Jailed a static file : $tmp_dst/$tmp_Filename\n";
1096:                 return true;
1097:             }
1098:         } elseif (is_array($ldd_result)){
1099:             // dynamic executable with dependencies
1100:             // rememeber; we are chrooting executables; they should be locked-down against group/other modifications. (and perhaps even root's, but that
1101:             // would suck ass when re-writing stuff over.
1102:             $return_status=true;
1103:             $num_files=0;
1104:             foreach ($ldd_result as $foo=>$foo_src_file) {
1105:                 $tmp_dst=$Destination_Root.dirname($foo_src_file);
1106:                 $tmp_Filename=basename($foo_src_file);
1107:                 if ( ! file_exists($tmp_dst) ) {
1108:                     $this->Makedir($tmp_dst, "755", "root", "wheel");
1109:                 }
1110:                 $num_files++;
1111: 
1112:                 if ( file_exists($tmp_dst."/".$tmp_Filename)) {
1113:                     // dynamically-linked file already in the jail... do nothing
1114:                     if (isset($LOGLEVEL) AND $LOGLEVEL > 0) print "dynamically-linked file already jailed : $tmp_dst/$tmp_Filename\n";
1115:                     if ($num_files==1) {
1116:                         // assuming this first file *could* be an executable.
1117:                         if ($flag_Executable) {
1118:                             $this->File_SetPermissions($tmp_dst."/".$tmp_Filename,"755");
1119:                         }
1120:                     }
1121:                 } else {
1122: 
1123:                     if (! copy($foo_src_file,$tmp_dst."/".$tmp_Filename)) {
1124:                         $return_status=false;
1125:                         print __CLASS__."->".__METHOD__.":Error: unable to copy a dependency; from $foo_src_file to $tmp_dst/$tmp_Filename\n";
1126:                     } else {
1127:                         if ($num_files==1) {
1128:                             // assuming this first file *could* be an executable.
1129:                             if ($flag_Executable) {
1130:                                 $this->File_SetPermissions($tmp_dst."/".$tmp_Filename,"755");
1131:                             } else {
1132:                                 $this->File_SetPermissions($tmp_dst."/".$tmp_Filename,"644");
1133:                             }
1134:                         }
1135:                         if (isset($LOGLEVEL) AND $LOGLEVEL > 0) print "Jailed a dynamically-linked file : $tmp_dst/$tmp_Filename\n";
1136:                     }
1137:                 }
1138: 
1139:             }
1140:             return $return_status;
1141:         }
1142:     }
1143: }
1144: 
1145: 
1146: ?>
1147: 
API documentation generated by ApiGen 2.6.0