From 09a26653c992550f78681026f060ec8f877a9fa1 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Mon, 13 Nov 2017 23:12:13 +0000 Subject: [PATCH] Add remote file system --- Changelog.md | 7 ++--- build/index.php | 50 +++++++++++++++++++++++++++++++++--- core.php | 31 +++++++++++++++++++++- module_index.json | 4 +-- modules/page-edit.php | 10 ++++++-- modules/parser-parsedown.php | 1 + 6 files changed, 91 insertions(+), 12 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9542b5b..d464cbe 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,12 +7,13 @@ This file holds the changelog for Pepperminty Wiki. This is the master list of t - Statistics! (#97) - 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 - - 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 `get_page_parent($pagename)` API method. - - The `history` action no supports `format=json` and `format=csv` + - The `history` action now supports `format=json` and `format=csv` - 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 + - [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 invalid opensearch description. diff --git a/build/index.php b/build/index.php index 7cf7ead..0931e83 100644 --- a/build/index.php +++ b/build/index.php @@ -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"}, "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"}, - "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_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}, @@ -186,6 +186,12 @@ GUICONFIG; $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); $settings = new stdClass(); 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 /// ////////////////////////// @@ -1960,7 +1985,7 @@ if($settings->require_login_view === true && // If this site requires a login in // register themselves // // 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 = []; /** * Registers a module. @@ -5910,6 +5935,12 @@ register_module([ "code" => function() { 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 @@ -6260,8 +6291,8 @@ window.addEventListener("load", function(event) { destination.innerHTML = output; }); DIFFSCRIPT; - - $content .= "\n + // diff.min.js is downloaded above + $content .= "\n \n"; 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"; // 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) file_put_contents("./Parsedown.php", fopen($env->parsedown_paths->parsedown, "r")); 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", "

No credits page detected. The credits page is a required module!

")); } +// 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 $action_name = $env->action; if(isset($actions->$action_name)) diff --git a/core.php b/core.php index 9a7adf5..e6684a5 100644 --- a/core.php +++ b/core.php @@ -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 /// ////////////////////////// @@ -1591,7 +1610,7 @@ if($settings->require_login_view === true && // If this site requires a login in // register themselves // // 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 = []; /** * Registers a module. @@ -1763,6 +1782,16 @@ if(!isset($actions->credits)) exit(page_renderer::render_main("Error - $settings->$sitename", "

No credits page detected. The credits page is a required module!

")); } +// 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 $action_name = $env->action; if(isset($actions->$action_name)) diff --git a/module_index.json b/module_index.json index 535a17d..182461e 100755 --- a/module_index.json +++ b/module_index.json @@ -167,7 +167,7 @@ "author": "Starbeamrainbowlabs", "description": "Allows you to edit pages by adding the edit and save actions. You should probably include this one.", "id": "page-edit", - "lastupdate": 1501321761, + "lastupdate": 1510613807, "optional": false }, { @@ -266,7 +266,7 @@ "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.", "id": "parser-parsedown", - "lastupdate": 1505563677, + "lastupdate": 1510610037, "optional": false } ] \ No newline at end of file diff --git a/modules/page-edit.php b/modules/page-edit.php index b60b695..2707b83 100644 --- a/modules/page-edit.php +++ b/modules/page-edit.php @@ -8,6 +8,12 @@ register_module([ "code" => function() { 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 @@ -358,8 +364,8 @@ window.addEventListener("load", function(event) { destination.innerHTML = output; }); DIFFSCRIPT; - - $content .= "\n + // diff.min.js is downloaded above + $content .= "\n \n"; exit(page_renderer::render_main("Edit Conflict - $env->page - $settings->sitename", $content)); diff --git a/modules/parser-parsedown.php b/modules/parser-parsedown.php index 25afe4d..43a7aa8 100644 --- a/modules/parser-parsedown.php +++ b/modules/parser-parsedown.php @@ -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"; // 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) file_put_contents("./Parsedown.php", fopen($env->parsedown_paths->parsedown, "r")); if(!file_exists("./ParsedownExtra.php") || filesize("./ParsedownExtra.php") === 0)