Add remote file system

This commit is contained in:
Starbeamrainbowlabs 2017-11-13 23:12:13 +00:00
parent 7bbd2f3328
commit 09a26653c9
6 changed files with 91 additions and 12 deletions

View File

@ -7,12 +7,13 @@ This file holds the changelog for Pepperminty Wiki. This is the master list of t
- Statistics! (#97) - Statistics! (#97)
- Added a new statistics engine, which you can add your own statistic calculators to with `statistic_add` - Added a new statistics engine, which you can add your own statistic calculators to with `statistic_add`
- Added action `stats` to view the calculated statisics - Added action `stats` to view the calculated statisics
- Statistics are automagically recalculated every day - this can be controlled with `stats_update_interval` and `stats_update_processingtime` - Statistics are automagically recalculated every day - this can be controlled with the `stats_update_interval` and `stats_update_processingtime` settings
- Added new "« Parent Page" to subpages so that you can easily visit their parent pages - Added new "« Parent Page" to subpages so that you can easily visit their parent pages
- Added new `get_page_parent($pagename)` API method. - The `history` action now supports `format=json` and `format=csv`
- The `history` action no supports `format=json` and `format=csv`
- Added tags next to the names of pages in the search results - Added tags next to the names of pages in the search results
- Added new `random_page_exclude` setting that allows you to exclude pages from the random action with a (PHP) regular expression - Added new `random_page_exclude` setting that allows you to exclude pages from the random action with a (PHP) regular expression
- [module api] Added new `get_page_parent($pagename)` method.
- [module api] Added new remote file system to download additional required files. Use it with `register_remote_file`
### Fixed ### Fixed
- Fixed invalid opensearch description. - Fixed invalid opensearch description.

View File

@ -26,7 +26,7 @@ $guiConfig = <<<'GUICONFIG'
"defaultpage": {"type": "text", "description": "The name of the page that will act as the home page for the wiki. This page will be served if you don't specify a page.", "default": "Main Page"}, "defaultpage": {"type": "text", "description": "The name of the page that will act as the home page for the wiki. This page will be served if you don't specify a page.", "default": "Main Page"},
"admindetails_name": {"type": "text", "description": "Your name as the wiki administrator.", "default": "Administrator"}, "admindetails_name": {"type": "text", "description": "Your name as the wiki administrator.", "default": "Administrator"},
"admindetails_email": {"type": "email", "description": "Your email address as the wiki administrator. Will be displayed as a support contact address.", "default": "admin@localhost"}, "admindetails_email": {"type": "email", "description": "Your email address as the wiki administrator. Will be displayed as a support contact address.", "default": "admin@localhost"},
"favicon": {"type": "url", "description": "A url that points to the favicon you want to use for your wiki. This image By default this is set to a data: url of a Peppermint (Credit: by bluefrog23, source: https://openclipart.org/detail/19571/peppermint-candy-by-bluefrog23)", "default": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB3VBMVEXhERHbKCjeVVXjb2/kR0fhKirdHBziDg6qAADaHh7qLy/pdXXUNzfMAADYPj7ZPDzUNzfbHx/fERHpamrqMTHgExPdHx/bLCzhLS3fVFTjT0/ibm7kRkbiLi7aKirdISHeFBTqNDTpeHjgERHYJCTVODjYQkLaPj6/AADVOTnpbW3cIyPdFRXcJCThMjLiTU3ibW3fVVXaKyvcERH4ODj+8fH/////fHz+Fxf4KSn0UFD/CAj/AAD/Xl7/wMD/EhL//v70xMT/+Pj/iYn/HBz/g4P/IyP/Kyv/7Oz0QUH/9PT/+vr/ior/Dg7/vr7/aGj/QED/bGz/AQH/ERH/Jib/R0f/goL/0dH/qan/YWH/7e3/Cwv4R0f/MTH/enr/vLz/u7v/cHD/oKD/n5//aWn+9/f/k5P/0tL/trb/QUH/cXH/dHT/wsL/DQ3/p6f/DAz/1dX/XV3/kpL/i4v/Vlb/2Nj/9/f/pKT+7Oz/V1f/iIj/jIz/r6//Zmb/lZX/j4//T0//Dw/4MzP/GBj/+fn/o6P/TEz/xMT/b2//Tk7/OTn/HR3/hIT/ODj/Y2P/CQn/ZGT/6Oj0UlL/Gxv//f3/Bwf/YmL/6+v0w8P/Cgr/tbX0QkL+9fX4Pz/qNzd0dFHLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfeCxINNSdmw510AAAA5ElEQVQYGQXBzSuDAQCA8eexKXOwmSZepa1JiPJxsJOrCwcnuchBjg4O/gr7D9zk4uAgJzvuMgcTpYxaUZvSm5mUj7TX7ycAqvoLIJBwStVbP0Hom1Z/ejoxrbaR1Jz6nWinbKWttGRgMSSjanPktRY6mB9WtRNTn7Ilh7LxnNpKq2/x5LnBitfz+hx0qxUaxhZ6vwqq9bx6f2XXvuUl9SVQS38NR7cvln3v15tZ9bQpuWDtZN3Lgh5DWJex3Y+z1KrVhw21+CiM74WZo83DiXq0dVBDYNJkFEU7WrwDAZhRtQrwDzwKQbT6GboLAAAAAElFTkSuQmCC"}, "favicon": {"type": "url", "description": "A url that points to the favicon you want to use for your wiki. By default this is set to a data: url of a Peppermint (Credit: by bluefrog23, source: https://openclipart.org/detail/19571/peppermint-candy-by-bluefrog23)", "default": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB3VBMVEXhERHbKCjeVVXjb2/kR0fhKirdHBziDg6qAADaHh7qLy/pdXXUNzfMAADYPj7ZPDzUNzfbHx/fERHpamrqMTHgExPdHx/bLCzhLS3fVFTjT0/ibm7kRkbiLi7aKirdISHeFBTqNDTpeHjgERHYJCTVODjYQkLaPj6/AADVOTnpbW3cIyPdFRXcJCThMjLiTU3ibW3fVVXaKyvcERH4ODj+8fH/////fHz+Fxf4KSn0UFD/CAj/AAD/Xl7/wMD/EhL//v70xMT/+Pj/iYn/HBz/g4P/IyP/Kyv/7Oz0QUH/9PT/+vr/ior/Dg7/vr7/aGj/QED/bGz/AQH/ERH/Jib/R0f/goL/0dH/qan/YWH/7e3/Cwv4R0f/MTH/enr/vLz/u7v/cHD/oKD/n5//aWn+9/f/k5P/0tL/trb/QUH/cXH/dHT/wsL/DQ3/p6f/DAz/1dX/XV3/kpL/i4v/Vlb/2Nj/9/f/pKT+7Oz/V1f/iIj/jIz/r6//Zmb/lZX/j4//T0//Dw/4MzP/GBj/+fn/o6P/TEz/xMT/b2//Tk7/OTn/HR3/hIT/ODj/Y2P/CQn/ZGT/6Oj0UlL/Gxv//f3/Bwf/YmL/6+v0w8P/Cgr/tbX0QkL+9fX4Pz/qNzd0dFHLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfeCxINNSdmw510AAAA5ElEQVQYGQXBzSuDAQCA8eexKXOwmSZepa1JiPJxsJOrCwcnuchBjg4O/gr7D9zk4uAgJzvuMgcTpYxaUZvSm5mUj7TX7ycAqvoLIJBwStVbP0Hom1Z/ejoxrbaR1Jz6nWinbKWttGRgMSSjanPktRY6mB9WtRNTn7Ilh7LxnNpKq2/x5LnBitfz+hx0qxUaxhZ6vwqq9bx6f2XXvuUl9SVQS38NR7cvln3v15tZ9bQpuWDtZN3Lgh5DWJex3Y+z1KrVhw21+CiM74WZo83DiXq0dVBDYNJkFEU7WrwDAZhRtQrwDzwKQbT6GboLAAAAAElFTkSuQmCC"},
"logo_url": {"type": "url", "description": "A url that points to the site's logo. Leave blank to disable. When enabled the logo will be inserted next to the site name on every page.", "default": "//starbeamrainbowlabs.com/images/logos/peppermint.png"}, "logo_url": {"type": "url", "description": "A url that points to the site's logo. Leave blank to disable. When enabled the logo will be inserted next to the site name on every page.", "default": "//starbeamrainbowlabs.com/images/logos/peppermint.png"},
"logo_position": {"type": "text", "description": "The side of the site name at which the logo should be placed.", "default": "left"}, "logo_position": {"type": "text", "description": "The side of the site name at which the logo should be placed.", "default": "left"},
"show_subpages": {"type": "text", "description": "Whether to show a list of subpages at the bottom of the page.", "default": true}, "show_subpages": {"type": "text", "description": "Whether to show a list of subpages at the bottom of the page.", "default": true},
@ -186,6 +186,12 @@ GUICONFIG;
$settingsFilename = "peppermint.json"; $settingsFilename = "peppermint.json";
if(file_exists("$settingsFilename.compromised")) {
http_response_code(500);
header("content-type: text/plain");
exit("Error: $settingsFilename.compromised exists on disk, so it's likely you need to block access to 'peppermint.json' from the internet. If you've done this already, please delete $settingsFilename.compromised and reload this page.");
}
$guiConfig = json_decode($guiConfig); $guiConfig = json_decode($guiConfig);
$settings = new stdClass(); $settings = new stdClass();
if(!file_exists($settingsFilename)) if(!file_exists($settingsFilename))
@ -1952,6 +1958,25 @@ if($settings->require_login_view === true && // If this site requires a login in
////////////////////////////////////// //////////////////////////////////////
////////////////////////////////////// //////////////////////////////////////
$remote_files = [];
/**
* Registers a request for a remote file to be downloaded before execution. Will block until all files are downloaded.
* Example definition:
* [ "local_filename" => "file.ext", "remote_url": "https://example.com" ]
* @param array $remote_file_def The remote file definition to register.
* @throws Exception Exception Throws an exception if a definition for the requested local file already exists.
*/
function register_remote_file($remote_file_def) {
global $remote_files;
foreach($remote_files as $ex_remote_file_def) {
if($ex_remote_file_def["local_filename"] == $remote_file_def["local_filename"])
throw new Exception("Error: A remote file with the local filename '{$remote_file_def["local_filename"]}' is already registered.");
}
$remote_files[] = $remote_file_def;
}
////////////////////////// //////////////////////////
/// Module functions /// /// Module functions ///
////////////////////////// //////////////////////////
@ -1960,7 +1985,7 @@ if($settings->require_login_view === true && // If this site requires a login in
// register themselves // // register themselves //
// or new pages. // // or new pages. //
////////////////////////// //////////////////////////
/** A list of all the currentlyloaded modules. Not guaranteed to be populated until an action is executed. */ /** A list of all the currently loaded modules. Not guaranteed to be populated until an action is executed. */
$modules = []; $modules = [];
/** /**
* Registers a module. * Registers a module.
@ -5910,6 +5935,12 @@ register_module([
"code" => function() { "code" => function() {
global $settings, $env; global $settings, $env;
// Download diff.min.js - which we use when displaying edit conflicts
register_remote_file([
"local_filename" => "diff.min.js",
"remote_url" => "https://cdnjs.cloudflare.com/ajax/libs/jsdiff/2.2.2/diff.min.js"
]);
/** /**
* @api {get} ?action=edit&page={pageName}[&newpage=yes] Get an editing page * @api {get} ?action=edit&page={pageName}[&newpage=yes] Get an editing page
@ -6260,8 +6291,8 @@ window.addEventListener("load", function(event) {
destination.innerHTML = output; destination.innerHTML = output;
}); });
DIFFSCRIPT; DIFFSCRIPT;
// diff.min.js is downloaded above
$content .= "\n<script src='https://cdnjs.cloudflare.com/ajax/libs/jsdiff/2.2.2/diff.min.js'></script> $content .= "\n<script src='diff.min.js'></script>
<script>$diffScript</script>\n"; <script>$diffScript</script>\n";
exit(page_renderer::render_main("Edit Conflict - $env->page - $settings->sitename", $content)); exit(page_renderer::render_main("Edit Conflict - $env->page - $settings->sitename", $content));
@ -7664,6 +7695,7 @@ $env->parsedown_paths->parsedown = "https://cdn.rawgit.com/erusev/parsedown/3ebb
$env->parsedown_paths->parsedown_extra = "https://cdn.rawgit.com/erusev/parsedown-extra/11a44e076d02ffcc4021713398a60cd73f78b6f5/ParsedownExtra.php"; $env->parsedown_paths->parsedown_extra = "https://cdn.rawgit.com/erusev/parsedown-extra/11a44e076d02ffcc4021713398a60cd73f78b6f5/ParsedownExtra.php";
// Download parsedown and parsedown extra if they don't already exist // Download parsedown and parsedown extra if they don't already exist
// These must still use this old method, as the parser may be asked to render some HTML before Pepperminty Wiki has had a chance to run the downloads
if(!file_exists("./Parsedown.php") || filesize("./Parsedown.php") === 0) if(!file_exists("./Parsedown.php") || filesize("./Parsedown.php") === 0)
file_put_contents("./Parsedown.php", fopen($env->parsedown_paths->parsedown, "r")); file_put_contents("./Parsedown.php", fopen($env->parsedown_paths->parsedown, "r"));
if(!file_exists("./ParsedownExtra.php") || filesize("./ParsedownExtra.php") === 0) if(!file_exists("./ParsedownExtra.php") || filesize("./ParsedownExtra.php") === 0)
@ -8223,6 +8255,16 @@ if(!isset($actions->credits))
exit(page_renderer::render_main("Error - $settings->$sitename", "<p>No credits page detected. The credits page is a required module!</p>")); exit(page_renderer::render_main("Error - $settings->$sitename", "<p>No credits page detected. The credits page is a required module!</p>"));
} }
// Download all the requested remote files
ini_set("user_agent", "$settings->sitename (Pepperminty-Wiki-Downloader; PHP/" . phpversion() . "; +https://github.com/sbrl/Pepperminty-Wiki/) Pepperminty-Wiki/$version");
foreach($remote_files as $remote_file_def) {
if(file_exists($remote_file_def["local_filename"]) && filesize($remote_file_def["local_filename"]) > 0)
continue;
error_log("[Pepperminty-Wiki/$settings->sitename] Downloading {$remote_file_def["local_filename"]} from {$remote_file_def["remote_url"]}");
file_put_contents($remote_file_def["local_filename"], fopen($remote_file_def["remote_url"], "rb"));
}
// Perform the appropriate action // Perform the appropriate action
$action_name = $env->action; $action_name = $env->action;
if(isset($actions->$action_name)) if(isset($actions->$action_name))

View File

@ -1583,6 +1583,25 @@ if($settings->require_login_view === true && // If this site requires a login in
////////////////////////////////////// //////////////////////////////////////
////////////////////////////////////// //////////////////////////////////////
$remote_files = [];
/**
* Registers a request for a remote file to be downloaded before execution. Will block until all files are downloaded.
* Example definition:
* [ "local_filename" => "file.ext", "remote_url": "https://example.com" ]
* @param array $remote_file_def The remote file definition to register.
* @throws Exception Exception Throws an exception if a definition for the requested local file already exists.
*/
function register_remote_file($remote_file_def) {
global $remote_files;
foreach($remote_files as $ex_remote_file_def) {
if($ex_remote_file_def["local_filename"] == $remote_file_def["local_filename"])
throw new Exception("Error: A remote file with the local filename '{$remote_file_def["local_filename"]}' is already registered.");
}
$remote_files[] = $remote_file_def;
}
////////////////////////// //////////////////////////
/// Module functions /// /// Module functions ///
////////////////////////// //////////////////////////
@ -1591,7 +1610,7 @@ if($settings->require_login_view === true && // If this site requires a login in
// register themselves // // register themselves //
// or new pages. // // or new pages. //
////////////////////////// //////////////////////////
/** A list of all the currentlyloaded modules. Not guaranteed to be populated until an action is executed. */ /** A list of all the currently loaded modules. Not guaranteed to be populated until an action is executed. */
$modules = []; $modules = [];
/** /**
* Registers a module. * Registers a module.
@ -1763,6 +1782,16 @@ if(!isset($actions->credits))
exit(page_renderer::render_main("Error - $settings->$sitename", "<p>No credits page detected. The credits page is a required module!</p>")); exit(page_renderer::render_main("Error - $settings->$sitename", "<p>No credits page detected. The credits page is a required module!</p>"));
} }
// Download all the requested remote files
ini_set("user_agent", "$settings->sitename (Pepperminty-Wiki-Downloader; PHP/" . phpversion() . "; +https://github.com/sbrl/Pepperminty-Wiki/) Pepperminty-Wiki/$version");
foreach($remote_files as $remote_file_def) {
if(file_exists($remote_file_def["local_filename"]) && filesize($remote_file_def["local_filename"]) > 0)
continue;
error_log("[ Pepperminty-Wiki/$settings->sitename ] Downloading {$remote_file_def["local_filename"]} from {$remote_file_def["remote_url"]}");
file_put_contents($remote_file_def["local_filename"], fopen($remote_file_def["remote_url"], "rb"));
}
// Perform the appropriate action // Perform the appropriate action
$action_name = $env->action; $action_name = $env->action;
if(isset($actions->$action_name)) if(isset($actions->$action_name))

View File

@ -167,7 +167,7 @@
"author": "Starbeamrainbowlabs", "author": "Starbeamrainbowlabs",
"description": "Allows you to edit pages by adding the edit and save actions. You should probably include this one.", "description": "Allows you to edit pages by adding the edit and save actions. You should probably include this one.",
"id": "page-edit", "id": "page-edit",
"lastupdate": 1501321761, "lastupdate": 1510613807,
"optional": false "optional": false
}, },
{ {
@ -266,7 +266,7 @@
"author": "Emanuil Rusev & Starbeamrainbowlabs", "author": "Emanuil Rusev & Starbeamrainbowlabs",
"description": "An upgraded (now default!) parser based on Emanuil Rusev's Parsedown Extra PHP library (https:\/\/github.com\/erusev\/parsedown-extra), which is licensed MIT. Please be careful, as this module adds some weight to your installation, and also *requires* write access to the disk on first load.", "description": "An upgraded (now default!) parser based on Emanuil Rusev's Parsedown Extra PHP library (https:\/\/github.com\/erusev\/parsedown-extra), which is licensed MIT. Please be careful, as this module adds some weight to your installation, and also *requires* write access to the disk on first load.",
"id": "parser-parsedown", "id": "parser-parsedown",
"lastupdate": 1505563677, "lastupdate": 1510610037,
"optional": false "optional": false
} }
] ]

View File

@ -8,6 +8,12 @@ register_module([
"code" => function() { "code" => function() {
global $settings, $env; global $settings, $env;
// Download diff.min.js - which we use when displaying edit conflicts
register_remote_file([
"local_filename" => "diff.min.js",
"remote_url" => "https://cdnjs.cloudflare.com/ajax/libs/jsdiff/2.2.2/diff.min.js"
]);
/** /**
* @api {get} ?action=edit&page={pageName}[&newpage=yes] Get an editing page * @api {get} ?action=edit&page={pageName}[&newpage=yes] Get an editing page
@ -358,8 +364,8 @@ window.addEventListener("load", function(event) {
destination.innerHTML = output; destination.innerHTML = output;
}); });
DIFFSCRIPT; DIFFSCRIPT;
// diff.min.js is downloaded above
$content .= "\n<script src='https://cdnjs.cloudflare.com/ajax/libs/jsdiff/2.2.2/diff.min.js'></script> $content .= "\n<script src='diff.min.js'></script>
<script>$diffScript</script>\n"; <script>$diffScript</script>\n";
exit(page_renderer::render_main("Edit Conflict - $env->page - $settings->sitename", $content)); exit(page_renderer::render_main("Edit Conflict - $env->page - $settings->sitename", $content));

View File

@ -124,6 +124,7 @@ $env->parsedown_paths->parsedown = "https://cdn.rawgit.com/erusev/parsedown/3ebb
$env->parsedown_paths->parsedown_extra = "https://cdn.rawgit.com/erusev/parsedown-extra/11a44e076d02ffcc4021713398a60cd73f78b6f5/ParsedownExtra.php"; $env->parsedown_paths->parsedown_extra = "https://cdn.rawgit.com/erusev/parsedown-extra/11a44e076d02ffcc4021713398a60cd73f78b6f5/ParsedownExtra.php";
// Download parsedown and parsedown extra if they don't already exist // Download parsedown and parsedown extra if they don't already exist
// These must still use this old method, as the parser may be asked to render some HTML before Pepperminty Wiki has had a chance to run the downloads
if(!file_exists("./Parsedown.php") || filesize("./Parsedown.php") === 0) if(!file_exists("./Parsedown.php") || filesize("./Parsedown.php") === 0)
file_put_contents("./Parsedown.php", fopen($env->parsedown_paths->parsedown, "r")); file_put_contents("./Parsedown.php", fopen($env->parsedown_paths->parsedown, "r"));
if(!file_exists("./ParsedownExtra.php") || filesize("./ParsedownExtra.php") === 0) if(!file_exists("./ParsedownExtra.php") || filesize("./ParsedownExtra.php") === 0)