<?php rg_log("FILE: /inc/user/repo-page"); $_repo_page = ""; if (rg_user_ok($user) !== TRUE) { $_repo_page .= rg_warning("Invalid user!"); return; } $rg['page_ui'] = rg_user_info($db, 0, $user, ""); if ($rg['page_ui']['ok'] != 1) { $_repo_page .= rg_warning("Internal error!"); return; } if ($rg['page_ui']['exists'] != 1) { $_repo_page .= rg_template("user/invalid.html", $rg, TRUE /*xss*/); return; } if (rg_repo_ok($repo) !== TRUE) { $_repo_page .= rg_template('repo/err/invalid.html', $rg, TRUE /*xss*/); return; } $rg['ri'] = rg_repo_info($db, 0, $rg['page_ui']['uid'], $repo); if ($rg['ri']['ok'] != 1) { $_repo_page .= rg_warning("Internal error!"); return; } $allow = FALSE; while (1) { if ($rg['ri']['exists'] != 1) break; if ($rg['ri']['deleted'] > 0) break; $x = array(); $x['obj_id'] = $rg['ri']['repo_id']; $x['type'] = 'repo'; $x['owner'] = $rg['ri']['uid']; $x['uid'] = $rg['login_ui']['uid']; $x['username'] = $rg['login_ui']['username']; $x['needed_rights'] = 'A'; $x['ip'] = $rg['ip']; $x['misc'] = ""; if (rg_rights_allow($db, $x) !== TRUE) break; $allow = TRUE; break; } if ($allow !== TRUE) { $_repo_page .= rg_template("user/repo/deny.html", $rg, TRUE /*xss*/); return; } if (!isset($rg['ri']['git_dir_done'])) $rg['ri']['git_dir_done'] = 0; $x['needed_rights'] = 'E'; $can_admin = rg_rights_allow($db, $x) === TRUE ? 1 : 0; $rg['url_user'] = rg_re_userpage($rg['page_ui']); $rg['url_repo'] = rg_re_repopage($rg['page_ui'], $repo); $rg['can_admin'] = $can_admin; $rg['HTML:hints'] = ''; $rg['mr'] = array('id' => ''); $rg['repo_path'] = rg_repo_path_by_id($rg['ri']['uid'], $rg['ri']['repo_id']); rg_log('repo_path=' . $rg['repo_path']); putenv('GIT_DIR=' . $rg['repo_path']); // TODO: this will be removed after all functios will got a path para $rg['HTML:menu_repo_level2'] = ''; $rg['HTML:branches_and_tags'] = ''; $_repo_body = ""; // build urls list $urls = array(); $urls[]['HTML:clone_url'] = '<a href="' . $rg['ri']['clone_url_http'] . '">' . $rg['ri']['clone_url_http'] . '</a>'; if ($rg_ssh_port != 0) $urls[]['HTML:clone_url'] = '<a href="' . $rg['ri']['clone_url_ssh'] . '">' . $rg['ri']['clone_url_ssh'] . '</a>'; if ($rg_git_port != 0) $urls[]['HTML:clone_url'] = '<a href="' . $rg['ri']['clone_url_git'] . '">' . $rg['ri']['clone_url_git'] . '</a>'; $rg['HTML:urls'] = rg_template_table('repo/urls', $urls, $rg); function rg_add_clone_hints($db, &$rg, $ref) { global $rg_ssh_port; global $rg_git_port; $hints = array(); $hints[]['HTML:hint'] = rg_template("hints/repo/git_setup.html", $rg, TRUE /*xss*/); if ($rg['ri']['uid'] == $rg['login_ui']['uid']) { $hints[]['HTML:hint'] = rg_template("hints/repo/clone_owner.html", $rg, TRUE /*xss*/); } else { $hints[]['HTML:hint'] = rg_template("hints/repo/clone_http.html", $rg, TRUE /*xss*/); if ($rg_ssh_port != 0) $hints[]['HTML:hint'] = rg_template("hints/repo/clone_ssh.html", $rg, TRUE /*xss*/); if ($rg_git_port != 0) $hints[]['HTML:hint'] = rg_template("hints/repo/clone_git.html", $rg, TRUE /*xss*/); $x = array(); $x['obj_id'] = $rg['ri']['repo_id']; $x['type'] = 'repo_refs'; $x['owner'] = $rg['ri']['uid']; $x['uid'] = $rg['login_ui']['uid']; $x['username'] = $rg['login_ui']['username']; $x['needed_rights'] = 'H'; /* anon push */ $x['ip'] = $rg['ip']; $x['misc'] = $ref; if (rg_rights_allow($db, $x) === TRUE) $hints[]['HTML:hint'] = rg_template("hints/repo/anon_push.html", $rg, TRUE /*xss*/); } $rg['HTML:hints'] = rg_template_table("hints/list", $hints, $rg); } /* * Helper for repo_page_blob */ function repo_page_cb_input($index, &$a, $stream) { switch ($stream) { case 1: // stdout echo $a['in_buf']; $a['in_buf'] = ''; break; case 2: // stderr rg_log('DEBUG: ' . $a['err_buf']); $a['err_buf'] = ''; break; } } function repo_page_blob(&$_repo_body, $type, &$rg, &$paras, $ref) { $_path = implode("/", $paras); $_tree = rg_git_ls_tree($rg['repo_path'], $ref, $_path); if ($_tree === FALSE) { $_repo_body .= rg_warning('Error: ' . rg_git_error()); return; } $blob = $_tree[0]; $_hash = trim($_tree[0]['ref']); $size = trim($_tree[0]['size']); if (strcmp($type, 'blob_download') == 0) { $format = rg_var_get('format'); $fn = addcslashes(basename($_path), '"\\'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . $fn . '"'); header('Content-Length: ' . $size); $cmd = array( 'cmds' => array( 'cmd1' => array( 'cmd' => RG_GIT_CMD . ' show ' . escapeshellarg($_hash), 'cb_input' => 'repo_page_cb_input', 'my_format' => $format ) ) ); $e = rg_exec2($cmd); if (!isset($e['code'])) exit(1); if ($e['ok'] != 1) { $err = 'error executing command: ' . $e['errmsg']; rg_internal_error($err); exit(1); } exit(0); } if (strcmp($type, "blob") == 0) { $rg['path'] = "/" . $_path; if ($size > 400000) { $_repo_body .= rg_template('repo/err/file_too_big.html', $rg, FALSE /*xss*/); return; } $c = rg_git_content($_hash); // TODO: error code check $_content = array( "hash" => $_hash, "HTML:content" => rg_xss_safe($c) ); $blob = array_merge($blob, $_content); $blob = array_merge($blob, $rg); $_repo_body .= rg_template('repo/blob.html', $blob, TRUE /*xss*/); return; } $_repo_body .= rg_template('invalid_link.html', $rg, TRUE /*xss*/); } function rg_repo_page_source($db, &$rg, &$paras) { $ret = ''; while (1) { // possible URLs: // log/commit/b9...43 // log/tag/v1.1 // tree/tag/v1.1/blob/path // tree/branch/name/blob/path $_subsubop = empty($paras) ? 'log' : array_shift($paras); $rg['source_menu'][$_subsubop] = 1; if ($rg['ri']['git_dir_done'] == 0) { $ret .= rg_template('repo/err/no_git_dir.html', $rg, TRUE /*xss*/); break; } $r = rg_git_repo_is_empty($rg['repo_path']); if ($r == -1) { $ret .= rg_template('internal_err.html', $rg, TRUE /*xss*/); break; } if ($r == 1) { $ret .= rg_template('repo/err/not_init.html', $rg, TRUE /*xss*/); break; } $existing_refs = rg_git_refs($rg['repo_path']); rg_log_ml('DEBUG: existing_refs: ' . print_r($existing_refs, TRUE)); $paras2 = array(array_shift($paras), array_shift($paras)); rg_log('DEBUG: paras: [' . rg_array2string($paras) . ']'); $list = array( $paras2, array('branch', $rg['ri']['main_branch']), array('branch', 'main'), array('branch', 'master') ); // Add first existing branch if (!empty($existing_refs['branch'])) $list[] = array('branch', $existing_refs['branch'][0]); $ok = FALSE; foreach ($list as $a) { rg_log('DEBUG: a=[' . rg_array2string($a) . ']'); $type_ref = rg_git_parse_ref($a); if (rg_git_ref_valid($existing_refs, $type_ref['ref_type'], $type_ref['ref_val']) === TRUE) { $ref = $type_ref['ref_path']; $ok = TRUE; break; } } rg_log('DEBUG: paras XXX: ' . rg_array2string($paras)); if ($ok) { rg_log('DEBUG: ref=[' . $ref . ']'); $rg = array_merge($rg, $type_ref); $bt = rg_git_branches_and_tags($existing_refs, $rg['ri']['url_repo'], $type_ref['ref_url']); $rg = array_merge($rg, $bt); rg_add_clone_hints($db, $rg, $ref); $ret .= rg_template('repo/source.html', $rg, TRUE /*xss*/); } rg_log('DEBUG: _subsubop=[' . $_subsubop . ']'); if (strcmp($_subsubop, 'tree') == 0) { $type = array_shift($paras); rg_log('DEBUG: tree: type=' . $type); if (strncmp($type, 'blob', 4) == 0) { repo_page_blob($ret, $type, $rg, $paras, $ref); } else if (strcmp($type, 'tree') == 0) { // find treeish of dir $_path = implode('/', $paras); $rg['path'] = '/' . rawurlencode($_path); $_tree = rg_git_ls_tree($rg['repo_path'], $ref, $_path); if ($_tree === FALSE) { $ret .= rg_warning('Error: ' . rg_git_error()); break; } $_hash = $_tree[0]['ref']; $_tree = rg_git_ls_tree($rg['repo_path'], $_hash, ''); if ($_tree === FALSE) { $ret .= rg_warning('Error: ' . rg_git_error()); break; } $ret .= rg_template_table('repo/tree', $_tree, $rg); break; } // default is to show root tree $rg['path'] = ''; $_tree = rg_git_ls_tree($rg['repo_path'], $ref, ''); if ($_tree === FALSE) { $ret .= rg_warning('Error: ' . rg_git_error()); break; } $ret .= rg_template_table('repo/tree', $_tree, $rg); break; } // show the log $log = rg_git_log($rg['repo_path'], 10, '', $ref, FALSE, 0); if ($log === FALSE) { $ret .= rg_template('internal_err.html', $rg, TRUE /*xss*/); break; } //rg_log_ml('DEBUG: log: ' . print_r($log, TRUE)); $ret .= rg_git_log_template($log, 'repo/log', $rg); $type = array_shift($paras); //rg_log('DEBUG: log: type=' . $type); if ((strcmp($type, 'commit') == 0)) { if (empty($paras)) $commit = FALSE; else $commit = rg_git_reference($paras[0]); if ($commit === FALSE) { rg_log('Invalid commit; make it empty.'); // TODO: give an error on the page?! $commit = ''; } rg_log('Show diff for commit [' . $commit . ']'); if (strstr($commit, '..')) { $t = explode('..', $commit); $first = $t[0]; $second = $t[1]; } else { $first = ''; $second = $commit; } $rg['HTML:commit_labels'] = rg_repo_commit_labels_html( $db, $rg['ri']['repo_id'], $commit); $patch_limit = rg_git_patch_limit($db); $log = rg_git_log($rg['repo_path'], 1, $first, $second, TRUE /*also_patch*/, $patch_limit); $ret .= rg_git_log2listing($log, $rg, FALSE); } break; } return $ret; } // default tab $_subop = empty($paras) ? "history" : array_shift($paras); if (strcmp($_subop, "history") == 0) { rg_add_clone_hints($db, $rg, ''); $hist = rg_repo_history_load($db, $rg['ri']['repo_id'], 0, 20, 0); if ($hist === FALSE) $_repo_body .= rg_warning("Cannot load history. Try again later."); else $_repo_body .= rg_template_table("repo/history", $hist, $rg); } else if (strcmp($_subop, "admin") == 0) { $_repo_body .= rg_repo_admin($db, $rg, $paras); } else if (strcmp($_subop, "source") == 0) { $_repo_body .= rg_repo_page_source($db, $rg, $paras); } else if (strcmp($_subop, "bug") == 0) { include($INC . "/user/repo/bug/main.php"); $_repo_body .= $bug_body; } else if (strcmp($_subop, 'artifacts') == 0) { include($INC . "/user/repo/artifacts/main.php"); $_repo_body .= $artifacts_body; } else if (strcmp($_subop, "stats") == 0) { $_repo_body .= rg_repo_stats($rg); } else if (strcmp($_subop, "mr") == 0) { $_repo_body .= rg_mr_high_level($db, $rg, $paras); } rg_watch_hl_process($db, $rg, 'repo', $rg['ri']['repo_id'], 0 /*obj_id2*/, $rg['current_url']); $rg['per_repo_menu'][$_subop] = 1; $rg['HTML:repo_body'] = $_repo_body; $_repo_page = rg_template("repo/main.html", $rg, TRUE /*xss*/);