Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git
includes/git_functions.php
* Git-related functions for repository operations
*/
+function getRepoPath($repo) {
+ return REPOS_PATH . '/' . basename($repo);
+}
/**
* Executes a Git command and caches the output.
*/
function execGitCached($repo, $command) {
- $cache_key = md5($repo . '|' . $command);
- $cache_file = CACHE_DIR . '/' . $cache_key . '.cache';
+ $cache_key = md5($repo . '|' . $command);
+ $cache_file = CACHE_DIR . '/' . $cache_key . '.cache';
- if (file_exists($cache_file) && (time() - filemtime($cache_file) < CACHE_EXPIRY)) {
- return file_get_contents($cache_file);
- }
+ if (file_exists($cache_file) && (time() - filemtime($cache_file) < CACHE_EXPIRY)) {
+ return file_get_contents($cache_file);
+ }
- $repoPath = REPOS_PATH . '/' . basename($repo);
- $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
+ $repoPath = getRepoPath($repo);
+ $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
- if ($isBare) {
- $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " " . $command . " 2>&1";
+ // Note: $command should be built using escapeshellarg() by the caller
+ if ($isBare) {
+ $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " " . $command . " 2>&1";
+ } else {
+ if (!is_dir($repoPath . '/.git')) {
+ $output = '';
} else {
- if (!is_dir($repoPath . '/.git')) {
- $output = '';
- } else {
- $cmd = "cd " . escapeshellarg($repoPath) . " && git " . $command . " 2>&1";
- }
+ $cmd = "cd " . escapeshellarg($repoPath) . " && git " . $command . " 2>&1";
}
+ }
- $output = isset($cmd) ? shell_exec($cmd) : '';
+ $output = isset($cmd) ? shell_exec($cmd) : '';
- if (!empty($output)) {
- file_put_contents($cache_file, $output);
- }
+ if (!empty($output)) {
+ file_put_contents($cache_file, $output);
+ }
- return $output;
+ return $output;
}
/**
* Executes a raw Git command without caching.
*/
function execGitRaw($repo, $command) {
- $repoPath = REPOS_PATH . '/' . basename($repo);
- $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
+ $repoPath = getRepoPath($repo);
+ $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
- if ($isBare) {
- $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " " . $command . " 2>&1";
- } else {
- if (!is_dir($repoPath . '/.git')) {
- return '';
- }
- $cmd = "cd " . escapeshellarg($repoPath) . " && git " . $command . " 2>&1";
+ if ($isBare) {
+ $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " " . $command . " 2>&1";
+ } else {
+ if (!is_dir($repoPath . '/.git')) {
+ return '';
}
+ $cmd = "cd " . escapeshellarg($repoPath) . " && git " . $command . " 2>&1";
+ }
- return shell_exec($cmd);
+ return shell_exec($cmd);
}
-/**
- * Main Git execution function (routes to cached version).
- */
function execGit($repo, $command) {
- return execGitCached($repo, $command);
+ return execGitCached($repo, $command);
}
/**
* Gets blob content as binary data (with caching).
*/
function getBlobBinary($repo, $hash) {
- $cache_key = md5($repo . '|blob_binary|' . $hash);
- $cache_file = CACHE_DIR . '/' . $cache_key . '.cache';
+ $cache_key = md5($repo . '|blob_binary|' . $hash);
+ $cache_file = CACHE_DIR . '/' . $cache_key . '.cache';
- if (file_exists($cache_file) && (time() - filemtime($cache_file) < CACHE_EXPIRY)) {
- return file_get_contents($cache_file);
- }
+ if (file_exists($cache_file) && (time() - filemtime($cache_file) < CACHE_EXPIRY)) {
+ return file_get_contents($cache_file);
+ }
- $repoPath = REPOS_PATH . '/' . basename($repo);
- $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
+ $repoPath = getRepoPath($repo);
+ $isBare = is_file($repoPath . '/HEAD') && !is_dir($repoPath . '/.git');
- if ($isBare) {
- $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " cat-file blob " . escapeshellarg($hash);
- } else {
- $cmd = "cd " . escapeshellarg($repoPath) . " && git cat-file blob " . escapeshellarg($hash);
- }
+ // Strictly escape the hash
+ $safeHash = escapeshellarg($hash);
- $descriptors = [
- 0 => ['pipe', 'r'],
- 1 => ['pipe', 'w'],
- 2 => ['pipe', 'w']
- ];
+ if ($isBare) {
+ $cmd = "git --git-dir=" . escapeshellarg($repoPath) . " cat-file blob " . $safeHash;
+ } else {
+ $cmd = "cd " . escapeshellarg($repoPath) . " && git cat-file blob " . $safeHash;
+ }
- $process = proc_open($cmd, $descriptors, $pipes);
- if (is_resource($process)) {
- fclose($pipes[0]);
- $output = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
+ $descriptors = [
+ 1 => ['pipe', 'w'],
+ 2 => ['pipe', 'w']
+ ];
- if (!empty($output)) {
- file_put_contents($cache_file, $output);
- }
+ $process = proc_open($cmd, $descriptors, $pipes);
+ if (is_resource($process)) {
+ $output = stream_get_contents($pipes[1]);
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ proc_close($process);
- return $output;
+ if (!empty($output)) {
+ file_put_contents($cache_file, $output);
}
- return '';
+
+ return $output;
+ }
+ return '';
}

Adds security to git functions

Author Dave Jarvis <email>
Date 2026-02-04 22:59:55 GMT-0800
Commit c8f36974979f51d3b9cb6b8acbe5d509025a3db1
Parent 559c829
Delta 64 lines added, 62 lines removed, 2-line increase