**/ function gitweb_check_repository ($obj, $repo, $dir, $base_url) /* {{{ */ { $output = array (); $retval = 0; $cmd = 'git --git-dir=' . escapeshellarg ($dir) . ' rev-parse --verify ' . escapeshellarg ($obj) . ' 2>/dev/null'; $obj_name = trim (shell_exec ($cmd)); if (!$obj_name) return (false); if (!preg_match ('/^[0-9a-fA-F]{40}$/', $obj_name)) { error_log ("git-rev-parse(1) returned unexpected object name: $obj_name"); return (false); } $cmd = 'git --git-dir=' . escapeshellarg ($dir) . ' cat-file -t ' . escapeshellarg ($obj_name) . ' 2>/dev/null'; $obj_type = trim (shell_exec ($cmd)); if (!$obj_type) { error_log ("gitweb_check_repository: git-cat-file(1) failed."); return (false); } if ($obj_type == 'commit') { $to_url = "$base_url?p=" . urlencode ($repo) . ';a=commitdiff;h=' . urlencode ($obj_name); yourls_redirect ($to_url, /* status = */ 301); return (true); } elseif ($obj_type == 'tag') { $to_url = "$base_url?p=" . urlencode ($repo) . ';a=tag;h=' . urlencode ($obj_name); yourls_redirect ($to_url, /* status = */ 301); return (true); } elseif ($obj_type == 'tree') { $to_url = "$base_url?p=" . urlencode ($repo) . ";a=tree;h=" . urlencode ($obj_name); yourls_redirect ($to_url, /* status = */ 301); return (true); } elseif ($obj_type == 'blob') { $to_url = "$base_url?p=" . urlencode ($repo) . ";a=blob;h=" . urlencode ($obj_name); yourls_redirect ($to_url, /* status = */ 301); return (true); } else { error_log ("Gitweb plugin: Object \"$obj_name\" in repository \"$repo\" has unknown type \"$obj_type\"."); return (false); } } /* }}} function gitweb_check_repository */ /* This callback function is called when the given keyword was not found in the * database. I'll see if this looks like an object identifier in a Git * repository and, if so, try to locate the object using the local * repositories. */ function gitweb_redirect_keyword_not_found ($args) /* {{{ */ { $keyword = $args[0]; if (!preg_match ('/^[0-9a-fA-F]{6,40}$/', $keyword)) return; $base_directory = yourls_get_option ('gitweb_base_directory'); if (!$base_directory) return; $base_url = yourls_get_option ('gitweb_base_url'); if (!$base_url) return; $dh = opendir ($base_directory); if (!$dh) return; while (($subdir = readdir ($dh)) !== false) { /* Ignore all files and directories starting with a dot, including the * special directories "." and "..". */ if (substr ($subdir, 0, 1) == '.') continue; $absdir = "$base_directory/$subdir"; if (!is_dir ($absdir)) continue; /* Ignore repositories which are private (i.e. not exported by the * git-daemon(1). We might leak information if we don't. */ if (!file_exists ("$absdir/git-daemon-export-ok")) continue; if (gitweb_check_repository ($keyword, $subdir, $absdir, $base_url)) break; } closedir ($dh); } /* }}} function gitweb_redirect_keyword_not_found */ function gitweb_set_base_directory ($dir) /* {{{ */ { /* Remove trailing slashes. */ $dir = preg_replace ('/\/+$/', '', $dir); if (!preg_match ('/^\//', $dir)) { print ("

Not an absolute path: " . htmlspecialchars ($dir) . "

\n"); return (false); } if (!is_dir ($dir)) { print ("

Not a directory: " . htmlspecialchars ($dir) . "

\n"); return (false); } /* Open the directory only to check its permissions. */ $dh = opendir ($dir); if (!$dh) { print ("

Unable to open directory.

\n"); return (false); } closedir ($dh); yourls_update_option ('gitweb_base_directory', $dir); return (true); } /* }}} function gitweb_set_base_directory */ function gitweb_set_base_url ($url) /* {{{ */ { if (!preg_match ('/https?:\/\//i', $url)) { print ("

This does not look like a valid URL: " . htmlspecialchars ($url) . "

\n"); return (false); } $url = preg_replace ('/\?.*/', '', $url); yourls_update_option ('gitweb_base_url', $url); return (true); } /* }}} function gitweb_set_base_directory */ function gitweb_show_plugin_page () /* {{{ */ { echo <<Gitweb Plugin Administration Page

This plugin redirects to a Gitweb installation if a keyword wasn't found in the database, looks like a Git object ID and is found in a local Git repository.

HTML; if (isset ($_POST['base_directory'])) gitweb_set_base_directory ($_POST['base_directory']); if (isset ($_POST['base_url'])) gitweb_set_base_url ($_POST['base_url']); $base_directory = yourls_get_option ('gitweb_base_directory'); if ($base_directory) $base_directory = htmlspecialchars ($base_directory); $base_url = yourls_get_option ('gitweb_base_url'); if ($base_url) $base_url = htmlspecialchars ($base_url); echo <<
HTML; } /* }}} function gitweb_show_plugin_page */ function gitweb_register_plugin_page () /* {{{ */ { yourls_register_plugin_page ('gitweb_page', 'Gitweb', 'gitweb_show_plugin_page'); } /* }}} function gitweb_register_plugin_page */ yourls_add_action ('plugins_loaded', 'gitweb_register_plugin_page'); yourls_add_action ('redirect_keyword_not_found', 'gitweb_redirect_keyword_not_found'); /* vim: set sw=2 sts=2 et fdm=marker : */ ?>