Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ services:
- "9000"
links:
- svn:svn
environment:
REPOS_DOWNLOAD_RULE: "|^/svn/[^/]+/downloadableDirs/.+|"
volumes:
- .:/opt/rweb
3 changes: 3 additions & 0 deletions repos-web/conf/Presentation.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@ function showError($error_msg, $headline='An error occurred') {
* @param String $headline the contents of the <h1> tag
*/
function showErrorNoRedirect($error_msg, $headline='An error occurred') {
if (preg_match('/^[1-5][0-9][0-9] /', $headline)) {
header("HTTP/1.1 $headline");
}
$template = $this->getLocaleFile(dirname(__FILE__) . '/Error');
$this->assign('headline', $headline);
$this->assign('error', $error_msg);
Expand Down
13 changes: 12 additions & 1 deletion repos-web/open/SvnOpenFile.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,18 @@ function isReadableInHead() {
$this->_head();
return ($this->headStatus == 200);
}


function isDownloadAllowed() {
$rule = isset($_SERVER['REPOS_DOWNLOAD_RULE']) ? $_SERVER['REPOS_DOWNLOAD_RULE'] : '';
if ($rule) {
$urlFull = $this->getUrlNoquery();
$pathFromRoot = substr($urlFull, strpos($urlFull, '/', 8));
if (preg_match($rule, $pathFromRoot)) return true;
}
// backwards compatibility with no env
return $this->isFile();
}

/**
* Checks for write access.
* Authenticates if prompted by server upon DAV request.
Expand Down
15 changes: 14 additions & 1 deletion repos-web/open/SvnOpenFile.test.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class TestSvnOpenFile extends UnitTestCase {

function setUp() {
_svnOpenFile_setInstance(null);
$_SERVER['SERVER_NAME'] = 'localhost';
}

function testGetUrl() {
Expand Down Expand Up @@ -435,6 +434,20 @@ function testIsFolderNameLooksLikeFile() {
$file = new SvnOpenFile('/test/a.folder', HEAD, false);
}

function testIsDownloadAllowed() {
$orgRule = isset($_SERVER['REPOS_DOWNLOAD_RULE']) && $_SERVER['REPOS_DOWNLOAD_RULE'];

$file = new SvnOpenFile('/testfolder/file.txt', HEAD, false);
$this->assertEqual('http://svn/svn', $file->getRepository(), 'This tests assumes the docker-compose setup or equivalent. %s');
$_SERVER['REPOS_DOWNLOAD_RULE'] = '|^/svn/test.*|';
$this->assertTrue($file->isDownloadAllowed(), 'Matching REPOS_DOWNLOAD_RULE so should be downloadable. %s');

$_SERVER['REPOS_DOWNLOAD_RULE'] = $orgRule;
return; // the test below requires a response, mock or real
$file = new SvnOpenFile('/test/a.txt', HEAD, false);
$this->assertTrue($file->isDownloadAllowed(), 'Files can always be downloadable, as they are streamed. %s');
}

}

testrun(new TestSvnOpenFile());
Expand Down
18 changes: 14 additions & 4 deletions repos-web/open/download/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,21 @@
// if revision is set it is peg
$file = new SvnOpenFile(getTarget(), $revisionRule->getValue());
if ($file->getStatus() != 200) {
// TODO have some kind of forwarding to the error pages for matching status code
require("../../conf/Presentation.class.php");
trigger_error('Failed to read '.$file->getPath().' from repository (status '.$file->getStatus().
'). Maybe it exists in a version other than '.$revisionRule->getValue().'.', E_USER_ERROR);
$p = Presentation::getInstance();
$p->showErrorNoRedirect('Failed to read '.$file->getPath().' from repository (status '.$file->getStatus().
'). Maybe it exists in '.($revisionRule->getValue() ? 'a revision other than '.$revisionRule->getValue().'.' : 'a historical revision.'),
'404 Not Found');
exit;
}

if (!$file->isDownloadAllowed()) {
require("../../conf/Presentation.class.php");
$p = Presentation::getInstance();
$p->showErrorNoRedirect('Download has been disabled at '.$file->getPath().
'. Folder downloads can grow very big, which is why the feature is blocked by default.',
'405 Method Not Allowed');
exit;
}

// Revision number should be "last changed" so we don't get different downloads for identical file
Expand All @@ -33,7 +44,6 @@
}

if ($file->isFolder()) {
echo 'This service has been disabled.'; exit;
require dirname(__FILE__).'/zipfolder.php';
$zip = reposExportZip($file);
if ($zip === false) {
Expand Down
4 changes: 2 additions & 2 deletions repos-web/open/index_en.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ <h3 class="view"><a id="open" href="open/?target={=$target}{=$file,revParam}">Vi
<h3 class="view"><a id="open" href="list/?target={=$target}{=$file,revParam}">List contents</a></h3>
<p>Shows a defailed view of the folder's contents at the current revision.</p>
{=/if}
{=if $file,isFile}<h3 class="view"><a id="download" href="download/?target={=$target}{=$file,revParam}">Download</a></h3>
<p>Download this
{=if $file,isDownloadAllowed}<h3 class="view"><a id="download" href="download/?target={=$target}{=$file,revParam}">Download</a></h3>
<p>Download this
{=if $file,isFile} file {=else} folder as zip archive {=/if}
to your hard drive. The revision number {=$file,revision}
will be appended to the filename, so you will know which version it is.</p>
Expand Down
12 changes: 11 additions & 1 deletion repos-web/open/json/listjson.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@ function getListXml($url, $rev=false) {
$list->addArgUrl($url);
}

if ($list->exec()) trigger_error('Could not read entry for URL '.$url, E_USER_ERROR);
if ($list->exec()) {
$err = implode(array_slice($list->getOutput(), -1));
if (strBegins($err,'svn: E200009')) {
header('HTTP/1.1 404 Not Found', true, 404);
} else {
header('HTTP/1.1 500 Internal Server Error', true, 500);
}
echo '{"end": "'.preg_replace('/"/', '\\"', $err);
echo '"}'."\n";
exit;
}
// TODO detect access denied

return implode($list->getOutput(),"\n");
Expand Down