Skip to content
Closed
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
5 changes: 3 additions & 2 deletions conf.php.sample
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,10 @@ define('2FA_ENABLED', true);
//define('SERVICE_DOCS_TO_EXPAND_DIRS', 'Templates/To_Expand');

// To make certain document folders visible within the members interface,
// add their paths here.
// add their paths here. Paths, if relative, are relative to DOCUMENTS_ROOT_PATH
// Separate multiple entries with pipe (|).
// define('MEMBER_FILES_DIRS', 'Member_Files');
// Note: generally this should be left unset. Use the 'Member Visible Folders' config setting instead.
// define('MEMBER_FILES_DIRS', '/path/to/member/files/');

// How to contact the system administrator (probably the person editing this file)
// either mailto:[email protected] or http://somedomain.com/info-page
Expand Down
24 changes: 24 additions & 0 deletions include/documents_manager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@ public static function getRootPath()
}
}

/**
* Get directories that Members should be able to access, and that exist. Paths are either absolute or relative to DOCUMENTS_ROOT_PATH.
*/
public static function getMemberFilesDirs(): array
{
$dirs = array();
if (defined('MEMBER_VISIBLE_FOLDERS')) {
foreach (explode('|', MEMBER_VISIBLE_FOLDERS) as $dir) {
// Enforce relativeness and existence
if ($reldir = safe_subdirectory(DOCUMENTS_ROOT_PATH, $dir)) {
$dirs[] = $reldir;
}
}
}
// For backwards-compatibility. Note we don't check for existence, again for backwards-compatibility.
if (defined('MEMBER_FILES_DIRS')) {
foreach (array_remove_empties(explode('|', MEMBER_FILES_DIRS)) as $dir) {
$dirs[] = $dir;
}
}
return array_unique($dirs);
}


// If $filename is an acceptable filename (extension not prohibited, no leading dot, no slashes)
// returns it intact; else triggers an error and returns blank string
public static function validateFileName($filename) {
Expand Down
30 changes: 30 additions & 0 deletions include/general.php
Original file line number Diff line number Diff line change
Expand Up @@ -1076,3 +1076,33 @@ function error_response(int $code, string $message): void {
echo ents($message);
exit;
}

/** Return $path if it is an existing subdirectory of $base, or false otherwise.
* @param $base Directory we want to be relative to. May not contain '..'.
* @param $path Path to check. E.g. 'foo' returns 'foo', '/foo' returns 'foo'. '' return false. '../' returns false.
* @return false|string
*/
function safe_subdirectory($base, $path) {
$base = rtrim(realpath($base), DIRECTORY_SEPARATOR);
if ($base === false) return false;
if ($path === '') return false;

// Build full path
$full = ($path[0] === DIRECTORY_SEPARATOR)
? $base . $path
: $base . DIRECTORY_SEPARATOR . $path;

$realpath = realpath($full);
if ($realpath === false) return false;

// Ensure result is inside base
if (strncmp($realpath, $base . DIRECTORY_SEPARATOR, strlen($base) + 1) !== 0 &&
$realpath !== $base) {
return false;
}

// Return relative portion (false if same directory)
return $realpath === $base
? false
: substr($realpath, strlen($base) + 1);
}
5 changes: 2 additions & 3 deletions members/views/view_4_documents.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class View_Documents extends View
public static function getMenuRequiredFeature()
{
// Only make it visible if the config is set
return strlen(ifdef('MEMBER_FILES_DIRS', '')) ? 'DOCUMENTS' : '-1';
return (Documents_Manager::getMemberFilesDirs() ? 'DOCUMENTS' : '-1');
}

function processView()
Expand All @@ -18,7 +18,7 @@ function getTitle()

function printView()
{
$dirs = array_remove_empties(explode('|', MEMBER_FILES_DIRS));
$dirs = Documents_Manager::getMemberFilesDirs();
if (empty($dirs)) { // prevent issue #1334
echo 'No files to show';
return;
Expand Down Expand Up @@ -56,5 +56,4 @@ private function _printDir($dir)
}
}
}

}
9 changes: 9 additions & 0 deletions upgrades/2025-upgrade-to-2.37.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,12 @@ ALTER TABLE roster_role_assignment MODIFY COLUMN assignedon TIMESTAMP NOT NULL D
-- #1227 - fix CCLI song links
update setting set value='https://songselect.ccli.com/songs/__NUMBER__' where value='https://au.songselect.com/songs/__NUMBER__' and symbol='CCLI_DETAIL_URL';
update setting set value='https://songselect.ccli.com/search/results?search=__TITLE__' where value='http://us.search.ccli.com/search/results?SearchText=__TITLE__' and symbol='CCLI_SEARCH_URL';
-- #1224 - configurable member-visible folders
INSERT INTO setting
(`rank`, symbol, type, value, note)
SELECT `rank`+1, 'MEMBER_VISIBLE_FOLDERS', 'text', 'Member_Files', 'Folders in Documents which, if they exist, are visible to Members and can be used to share documents with them. Separate multiple directories with a pipe (''|'') character'
FROM setting
WHERE symbol = 'MEMBERS_SEE_AGE_BRACKET'
AND NOT EXISTS (
select 1 from setting s2 where s2.symbol='MEMBER_VISIBLE_FOLDERS'
);