diff --git a/Changelog.md b/Changelog.md
index 71176cc..a26a333 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,12 +1,18 @@
# Changelog
This file holds the changelog for Pepperminty Wiki. This is the master list of things that have changed (second only to the commit history!) - though the information for any particular release can also be found in the description of it's page for every release made on GitHub too.
+## v0.19
+
+_(No changes have been made since the last beta release.)_
+
+
## v0.19-beta2
### Changed
- Updated the theme of the new documentation
- Revised the writing modules section of the documentation
+
## v0.19-beta1
> The update that changed the world! Turn everything upside-down.
@@ -87,22 +93,26 @@ _(No changes have been made since the last beta release.)_
- Long lines in code blocks now wrap correctly.
- The `export` action now correctly includes uploaded files alongside their descriptions
+
## v0.17.1
### Fixed
- Corrected default passwords. If you were having issues, try updating to this release, deleting `peppermint.json` and trying again (thanks for spotting this, @tspivey!)
+
## v0.17
### Fixed
- Removed stray debugging output
- Tweaked css to make new search context generation look better
+
## v0.17-beta2
### Fixed
- Fixed the cost-climbing bug in the last beta release
+
## v0.17-beta1
### Added
@@ -152,9 +162,11 @@ _(No changes have been made since the last beta release.)_
- Restyled "matching tags" in the search results in the default stylesheet
- Added moar icons to the nav / more menus. Delete the appropriate entries in `peppermint.json` to get the updated ones!
+
## v0.16
_(No changes since v0.16-beta1)_
+
## v0.16-beta1
### Added
@@ -198,6 +210,7 @@ _(No changes since v0.16-beta1)_
### Removed
- [Module API] Removed `accept_contains_mime`, as it's both unstable and currently unnecessary. Contributions for a better version are welcome!
+
## v0.15.1
### Added
@@ -210,9 +223,11 @@ _(No changes since v0.16-beta1)_
- Fix saving edits to pages with an ampersand in their name (#99)
- [Security] Fixed an authenticated denial-of-service attack when uploading a malicious SVG (ref XXE billion laughs attack, #152)
+
## v0.15
_(No changes since v0.15-beta2)_
+
## v0.15-beta2
### Added
diff --git a/docs/ModuleApi/classes/PeppermintParsedown.html b/docs/ModuleApi/classes/PeppermintParsedown.html
index 9f8053d..536055c 100644
--- a/docs/ModuleApi/classes/PeppermintParsedown.html
+++ b/docs/ModuleApi/classes/PeppermintParsedown.html
@@ -106,12 +106,12 @@
" . page_renderer::render_username($comment->username ?? "Unknown") . " said:
"; $result .= "\t"; diff --git a/docs/ModuleApi/files/modules/feature-firstrun.php.txt b/docs/ModuleApi/files/modules/feature-firstrun.php.txt new file mode 100644 index 0000000..35bf1d9 --- /dev/null +++ b/docs/ModuleApi/files/modules/feature-firstrun.php.txt @@ -0,0 +1,199 @@ + "First run wizard", + "version" => "0.1", + "author" => "Starbeamrainbowlabs", + "description" => "Displays a special page to aid in setting up a new wiki for the first time.", + "id" => "feature-firstrun", + "code" => function() { + global $settings, $env; + + + // NOTE: We auto-detect pre-existing wikis in 01-settings.fragment.php + if(!$settings->firstrun_complete && preg_match("/^firstrun/", $env->action) !== 1) { + http_response_code(307); + header("location: ?action=firstrun"); + exit("Redirecting you to the first-run wizard...."); + } + + /** + * @api {get} ?action=firstrun Display the firstrun page + * @apiName FirstRun + * @apiGroup Settings + * @apiPermission Anonymous + * + */ + + /* + * ███████ ██ ██████ ███████ ████████ ██████ ██ ██ ███ ██ + * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ + * █████ ██ ██████ ███████ ██ ██████ ██ ██ ██ ██ ██ + * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ + * ██ ██ ██ ██ ███████ ██ ██ ██ ██████ ██ ████ + */ + add_action("firstrun", function() { + global $settings, $settingsFilename; + + if($settings->firstrun_complete) { + http_response_code(400); + exit(page_renderer::render_main("Setup complete - Error - $settings->sitename", "
Oops! Looks like $settings->sitename is already setup and ready to go! Go to the " . htmlentities($settings->defaultpage)." to get started!
")); + } + + if(!module_exists("page-login")) { + http_response_code(503); + exit(page_renderer::render_main("Build error - Pepperminty Wiki", "The
+page-login
wasn't included in this build of Pepperminty Wiki, so the first-run installation wizard will not work correctly.You can still complete the setup manually, however! Once done, set
")); + } + + if(!$settings->disable_peppermint_access_check && + php_sapi_name() !== "cli-server") { // The CLI server is single threaded, so it can't support loopback requests + $request_url = full_url(); + $request_url = preg_replace("/\/(index.php)?\?.*$/", "/peppermint.json", $request_url); + file_get_contents($request_url); + $response_code = intval(explode(" ", $http_response_header[0])[1]); + if($response_code >= 200 || $response_code < 300) { + file_put_contents("$settingsFilename.compromised", "compromised"); + http_response_code(307); + header("location: index.php"); + exit(); + } + } + else { + error_log("Warning: The public peppermint.json access check has been disabled (either manually or because you're using a local PHP development server with php -S ....). It's strongly recommended you ensure that access from outside is blocked to peppermint.json to avoid (many) security issues and other nastiness such as stealing of site secrets and password hashes."); + } + + // TODO: Check the environment here first + // - Make sure peppermint.json isn't accessible + // - Check for required modules? + + // TODO: Add a button to skip the firstrun wizard & do your own manual setup + + $result = "firstrun_complete
in peppermint.json totrue
.Welcome!
+Welcome to Pepperminty Wiki.
+Fill out the below form to get your wiki up and running!
+"; + + exit(page_renderer::render_main("Welcome! - Pepperminty Wiki", $result)); + }); + + + /** + * @api {post} ?action=firstrun-complete Complete the first-run wizard. + * @apiName FirstRunComplete + * @apiGroup Settings + * @apiPermission Anonymous + * + * @apiParam {string} username The username for the first admin account + * @apiParam {string} password The password for the first admin account + * @apiParam {string} password-again The password repeated for the first admin account + * @apiParam {string} email-address The email address for the first admin account + * @apiParam {string} wiki-name The name of the wiki. Saved to $settings->sitename + * @apiParam {string} data-dir The directory on the server to save the wiki data to. Saved to $settings->data_storage_dir. + */ + add_action("firstrun-complete", function() { + global $version, $commit, $settings; + + if($settings->firstrun_complete) { + http_response_code(400); + exit(page_renderer::render_main("Setup complete - Error - $settings->sitename", "Oops! Looks like $settings->sitename is already setup and ready to go! Go to the " . htmlentities($settings->defaultpage)." to get started!
")); + } + + if($_POST["secret"] !== $settings->secret) { + http_response_code(401); + exit(page_renderer::render_main("Incorrect secret - Pepperminty Wiki", "Oops! That secret was incorrect. Open
")); + } + + // $_POST: username, email-address, password, password-again, wiki-name, data-dir + + if(empty($_POST["username"])) { + http_response_code(400); + exit(page_renderer::render_main("Missing information - Error - Pepperminty Wiki", "peppermint.json
that is automatically written to the directory alongside theindex.php
that you uploaded to your web server and copy the value of thesecret
property into the wiki secret box on the previous page, taking care to avoid copying the quotation marks.Oops! Looks like you forgot to enter a username. Try going back in your browser and filling one in.
")); + } + if(empty($_POST["email-address"])) { + http_response_code(400); + exit(page_renderer::render_main("Missing information - Error - Pepperminty Wiki", "Oops! Looks like you forgot to enter an email address. Try going back in your browser and filling one in.
")); + } + if(filter_var($_POST["email-address"], FILTER_VALIDATE_EMAIL) === false) { + http_response_code(400); + exit(page_renderer::render_main("Invalid email address - Error - Pepperminty Wiki", "Oops! Looks like that email address isn't valid. Try going back in your browser and correcting it.
")); + } + if(empty($_POST["password"]) || empty($_POST["password-again"])) { + http_response_code(400); + exit(page_renderer::render_main("Missing information - Error - Pepperminty Wiki", "Oops! Looks like you forgot to enter a password. Try going back in your browser and filling one in.
")); + } + if($_POST["password"] !== $_POST["password-again"]) { + http_response_code(422); + exit(page_renderer::render_main("Password mismatch - Error - Pepperminty Wiki", "Oops! Looks like the passwords you entered aren't the same. Try going back in your browser and entering it again.
")); + } + if(empty($_POST["wiki-name"])) { + http_response_code(400); + exit(page_renderer::render_main("Missing information - Error - Pepperminty Wiki", "Oops! Looks like you forgot to enter a name for your wiki. Try going back in your browser and filling one in.
")); + } + if(empty($_POST["data-dir"])) { + http_response_code(400); + exit(page_renderer::render_main("Missing information - Error - Pepperminty Wiki", "Oops! Looks like you forgot to enter a directory on the server to store the wiki's data in. Try going back in your browser and filling one in. Relative paths are ok - the default is
")); + } + + // Generate the user data object & replace the pre-generated users + $user_data = new stdClass(); + $user_data->password = hash_password($_POST["password"]); + $user_data->emailAddress = $_POST["email-address"]; + $settings->users = new stdClass(); + $settings->users->{$_POST["username"]} = $user_data; + $settings->admins = [ $_POST["username"] ]; // Don't forget to mark them as a mod + + // Apply the settings + $settings->firstrun_complete = true; + $settings->sitename = $_POST["wiki-name"]; + $settings->data_storage_dir = $_POST["data-dir"]; + + if(!save_settings()) { + http_response_code(500); + exit(page_renderer::render_main("Server Error - Pepperminty Wiki", ".
(i.e. the current directory).Oops! Pepperminty Wiki was unable to save your settings back to disk. This can happen if Pepperminty Wiki does not have write permissions on it's own directory and the files contained within (except
+index.php
of course).Try contacting your server owner and ask them to correct it. If you are the server owner, you may need to run
")); + } + + http_response_code(201); + exit(page_renderer::render_main("Setup complete! - Pepperminty Wiki", "sudo chown -R WEBSERVER_USERNAME:WEBSERVER_USERNAME PATH/TO/WIKI/DIRECTORY
, replacing the bits in UPPERCASE.Congratulations! You've completed the Pepperminty Wiki setup.
+Click here to start using $settings->sitename, your new wiki!
")); + }); + } +]); + diff --git a/docs/ModuleApi/files/modules/feature-guiconfig.php.txt b/docs/ModuleApi/files/modules/feature-guiconfig.php.txt index 5767378..6165e5d 100644 --- a/docs/ModuleApi/files/modules/feature-guiconfig.php.txt +++ b/docs/ModuleApi/files/modules/feature-guiconfig.php.txt @@ -1,7 +1,7 @@ "Settings GUI", - "version" => "0.1.3", + "version" => "0.1.4", "author" => "Starbeamrainbowlabs", "description" => "The module everyone has been waiting for! Adds a web based gui that lets mods change the wiki settings.", "id" => "feature-guiconfig", @@ -36,6 +36,8 @@ register_module([ $content = "Master Control Panel
\n"; $content .= "This page lets you configure $settings->sitename's master settings. Please be careful - you can break things easily on this page if you're not careful!
\n"; + if(module_exists("feature-user-table")) + $content .= "Looking to manage $settings->sitename's users? Try the user table instead!
\n"; $content .= "You're currently running Pepperminty Wiki $version+" . substr($commit, 0, 7) . ".
\n"; $content .= "Actions
"; diff --git a/docs/ModuleApi/files/modules/feature-history.php.txt b/docs/ModuleApi/files/modules/feature-history.php.txt index 67c8f00..a62749c 100644 --- a/docs/ModuleApi/files/modules/feature-history.php.txt +++ b/docs/ModuleApi/files/modules/feature-history.php.txt @@ -1,7 +1,7 @@ "Page History", - "version" => "0.4.1", + "version" => "0.4.2", "author" => "Starbeamrainbowlabs", "description" => "Adds the ability to keep unlimited page history, limited only by your disk space. Note that this doesn't store file history (yet). Currently depends on feature-recent-changes for rendering of the history page.", "id" => "feature-history", @@ -213,11 +213,12 @@ register_module([ * records a new revision against a page name. Thus it is possible to have a * disparaty between the history revisions and the actual content displayed in * the current revision if you're not careful! - * @param object $pageinfo The pageindex object of the page to operate on. - * @param string $newsource The page content to save as the new revision. - * @param string $oldsource The old page content that is the current revision (before the update). - * @param boolean $save_pageindex Whether the page index should be saved to disk. - * @param string $change_type The type of change to record this as in the history revision log + * @package feature-history + * @param object $pageinfo The pageindex object of the page to operate on. + * @param string $newsource The page content to save as the new revision. + * @param string $oldsource The old page content that is the current revision (before the update). + * @param bool $save_pageindex Whether the page index should be saved to disk. + * @param string $change_type The type of change to record this as in the history revision log */ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pageindex = true, $change_type = "edit") { global $env, $paths, $settings, $pageindex; @@ -233,7 +234,7 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein // this point // TODO Store tag changes here - end($pageinfo->history); // Calculate the next revision id - we can't just count the reivisions here because we might have a revision limit + end($pageinfo->history); // Calculate the next revision id - we can't just count the revisions here because we might have a revision limit $nextRid = !empty($pageindex->history) ? $pageinfo->history[key($pageinfo->history)]->rid + 1 : 0; $ridFilename = "$pageinfo->filename.r$nextRid"; // Insert a new entry into the history @@ -261,7 +262,7 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein // Save the edited pageindex if($result !== false && $save_pageindex) - $result = file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT)); + $result = save_pageindex(); return $result; diff --git a/docs/ModuleApi/files/modules/feature-search.php.txt b/docs/ModuleApi/files/modules/feature-search.php.txt index fb080af..1408e88 100644 --- a/docs/ModuleApi/files/modules/feature-search.php.txt +++ b/docs/ModuleApi/files/modules/feature-search.php.txt @@ -1,7 +1,7 @@ "Search", - "version" => "0.7", + "version" => "0.7.1", "author" => "Starbeamrainbowlabs", "description" => "Adds proper search functionality to Pepperminty Wiki using an inverted index to provide a full text search engine. If pages don't show up, then you might have hit a stop word. If not, try requesting the `invindex-rebuild` action to rebuild the inverted index from scratch.", "id" => "feature-search", @@ -483,6 +483,7 @@ class search { /** * Words that we should exclude from the inverted index + * @var string[] */ public static $stop_words = [ "a", "about", "above", "above", "across", "after", "afterwards", "again", @@ -562,7 +563,7 @@ class search /** * Converts a source string into a series of raw tokens. * @param string $source The source string to process. - * @param boolean $capture_offsets Whether to capture & return the character offsets of the tokens detected. If true, then each token returned will be an array in the form [ token, char_offset ]. + * @param bool $capture_offsets Whether to capture & return the character offsets of the tokens detected. If true, then each token returned will be an array in the form [ token, char_offset ]. * @return array An array of raw tokens extracted from the specified source string. */ public static function tokenize($source, $capture_offsets = false) @@ -690,13 +691,17 @@ class search /** * Reads in and parses an inverted index, measuring the time it takes to do so. * @param string $invindex_filename The path to the file inverted index to parse. + * @return boolean Whether the measurement was actually able to take place. Usually this will be true, but it will return false if it can't find the specified index. */ public static function measure_invindex_load_time($invindex_filename) { global $env; - + if(!file_exists($invindex_filename)) + return false; $searchindex_decode_start = microtime(true); search::load_invindex($invindex_filename); $env->perfdata->searchindex_decode_time = round((microtime(true) - $searchindex_decode_start)*1000, 3); + + return true; } /** diff --git a/docs/ModuleApi/files/modules/feature-upload.php.txt b/docs/ModuleApi/files/modules/feature-upload.php.txt index 043b45a..278b3d2 100644 --- a/docs/ModuleApi/files/modules/feature-upload.php.txt +++ b/docs/ModuleApi/files/modules/feature-upload.php.txt @@ -1,7 +1,7 @@ "Uploader", - "version" => "0.5.14", + "version" => "0.6", "author" => "Starbeamrainbowlabs", "description" => "Adds the ability to upload files to Pepperminty Wiki. Uploaded files act as pages and have the special 'File/' prefix.", "id" => "feature-upload", @@ -108,7 +108,7 @@ register_module([ // Make sure uploads are enabled if(!$settings->upload_enabled) { - if(!empty($_FILES["file"])) + if(!empty($_FILES["file"]) && file_exists($_FILES["file"]["tmp_name"])) unlink($_FILES["file"]["tmp_name"]); http_response_code(412); exit(page_renderer::render("Upload failed - $settings->sitename", "Your upload couldn't be processed because uploads are currently disabled on $settings->sitename. Go back to the main page.
")); @@ -258,7 +258,7 @@ register_module([ } // Save the pageindex - file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT)); + save_pageindex(); if(module_exists("feature-recent-changes")) { @@ -471,16 +471,15 @@ register_module([ $dimensions = $mime_type !== "image/svg+xml" ? getimagesize($env->storage_prefix . $filepath) : getsvgsize($env->storage_prefix . $filepath); $fileTypeDisplay = substr($mime_type, 0, strpos($mime_type, "/")); $previewUrl = "?action=preview&size=$settings->default_preview_size&page=" . rawurlencode($env->page); + $originalUrl = $env->storage_prefix == "./" ? $filepath : "?action=preview&size=original&page=" . rawurlencode($env->page); + if($mime_type == "application/pdf") + $fileTypeDisplay = "pdf"; $preview_html = ""; switch($fileTypeDisplay) { case "application": case "image": - if($mime_type == "application/pdf") - $fileTypeDisplay = "file"; - - $originalUrl = $env->storage_prefix == "./" ? $filepath : "?action=preview&size=original&page=" . rawurlencode($env->page); $preview_sizes = [ 256, 512, 768, 1024, 1440, 1920 ]; $preview_html .= "\t\t\tNo preview is available, but you can download it instead:
+ Download"; + break; } $fileInfo = []; @@ -547,7 +556,7 @@ register_module([ // Register a section on the help page on uploading files add_help_section("28-uploading-files", "Uploading Files", "$settings->sitename supports the uploading of files, though it is up to " . $settings->admindetails_name . ", $settings->sitename's administrator as to whether it is enabled or not (uploads are currently " . (($settings->upload_enabled) ? "enabled" : "disabled") . ").
-Currently Pepperminty Wiki (the software that $settings->sitename uses) only supports the uploading of images, although more file types should be supported in the future (open an issue on GitHub if you are interested in support for more file types).
+Currently Pepperminty Wiki (the software that $settings->sitename uses) only supports the uploading of images, videos, and audio, although more file types should be supported in the future (open an issue on GitHub if you are interested in support for more file types).
Uploading a file is actually quite simple. Click the "Upload" option in the "More..." menu to go to the upload page. The upload page will tell you what types of file $settings->sitename allows, and the maximum supported filesize for files that you upload (this is usually set by the web server that the wiki is running on).
Use the file chooser to select the file that you want to upload, and then decide on a name for it. Note that the name that you choose should not include the file extension, as this will be determined automatically. Enter a description that will appear on the file's page, and then click upload.
"); } diff --git a/docs/ModuleApi/files/modules/feature-user-table.php.txt b/docs/ModuleApi/files/modules/feature-user-table.php.txt index 7aba5f1..c6e60e9 100644 --- a/docs/ModuleApi/files/modules/feature-user-table.php.txt +++ b/docs/ModuleApi/files/modules/feature-user-table.php.txt @@ -1,7 +1,7 @@ "User Organiser", - "version" => "0.1", + "version" => "0.1.1", "author" => "Starbeamrainbowlabs", "description" => "Adds a organiser page that lets moderators (or better) control the reegistered user accounts, and perform adminstrative actions such as password resets, and adding / removing accounts.", "id" => "feature-user-table", @@ -44,8 +44,8 @@ register_module([ foreach($settings->users as $username => $user_data) { $content .= "Error: You aren't logged in as a moderator, so you don't have permission to set a user's password.
")); } if(empty($_POST["user"])) { diff --git a/docs/ModuleApi/files/modules/page-delete.php.txt b/docs/ModuleApi/files/modules/page-delete.php.txt index e84379d..87b8e61 100644 --- a/docs/ModuleApi/files/modules/page-delete.php.txt +++ b/docs/ModuleApi/files/modules/page-delete.php.txt @@ -1,7 +1,7 @@ "Page deleter", - "version" => "0.10", + "version" => "0.10.1", "author" => "Starbeamrainbowlabs", "description" => "Adds an action to allow administrators to delete pages.", "id" => "page-delete", @@ -78,7 +78,7 @@ register_module([ unset($pageindex->$page); // Save the new page index - file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT)); + save_pageindex(); // Remove the page's name from the id index ids::deletepagename($env->page); diff --git a/docs/ModuleApi/files/modules/page-edit.php.txt b/docs/ModuleApi/files/modules/page-edit.php.txt index baecab9..864b948 100644 --- a/docs/ModuleApi/files/modules/page-edit.php.txt +++ b/docs/ModuleApi/files/modules/page-edit.php.txt @@ -1,19 +1,17 @@ "Page editor", - "version" => "0.17.3", + "version" => "0.17.4", "author" => "Starbeamrainbowlabs", "description" => "Allows you to edit pages by adding the edit and save actions. You should probably include this one.", "id" => "page-edit", + "extra_data" => [ + "diff.min.js" => "https://cdnjs.cloudflare.com/ajax/libs/jsdiff/2.2.2/diff.min.js" + ], "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 @@ -438,7 +436,7 @@ window.addEventListener("load", function(event) { }); DIFFSCRIPT; // diff.min.js is downloaded above - $content .= "\n + $content .= "\n \n"; header("x-failure-reason: edit-conflict"); @@ -506,8 +504,7 @@ DIFFSCRIPT; if($pagedata !== $pagedata_orig) file_put_contents("$env->storage_prefix$env->page.md", $pagedata); - - file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT)); + save_pageindex(); if(isset($_GET["newpage"])) http_response_code(201); diff --git a/docs/ModuleApi/files/modules/page-list.php.txt b/docs/ModuleApi/files/modules/page-list.php.txt index bd55d51..a7b26be 100644 --- a/docs/ModuleApi/files/modules/page-list.php.txt +++ b/docs/ModuleApi/files/modules/page-list.php.txt @@ -1,7 +1,7 @@ "Page list", - "version" => "0.11", + "version" => "0.11.1", "author" => "Starbeamrainbowlabs", "description" => "Adds a page that lists all the pages in the index along with their metadata.", "id" => "page-list", @@ -175,7 +175,7 @@ register_module([ $tag_counts[] = count($page_entry->tags ?? []); $result = new stdClass(); // value, state, completed - $result->value = round(array_sum($tag_counts) / count($tag_counts), 3); + $result->value = empty($tag_counts) ? -1 : round(array_sum($tag_counts) / count($tag_counts), 3); $result->completed = true; return $result; } diff --git a/docs/ModuleApi/files/modules/page-login.php.txt b/docs/ModuleApi/files/modules/page-login.php.txt index 369854a..2272462 100644 --- a/docs/ModuleApi/files/modules/page-login.php.txt +++ b/docs/ModuleApi/files/modules/page-login.php.txt @@ -1,7 +1,7 @@ "Login", - "version" => "0.9.2", + "version" => "0.9.4", "author" => "Starbeamrainbowlabs", "description" => "Adds a pair of actions (login and checklogin) that allow users to login. You need this one if you want your users to be able to login.", "id" => "page-login", @@ -114,6 +114,13 @@ register_module([ error_log("[Pepperminty Wiki] Updated password hash for $user."); } + // If the email address is still in the old field, migrate it + if(!empty($settings->users->{$user}->email)) { + $settings->users->{$user}->emailAddress = $settings->users->{$user}->email; + unset($settings->users->{$user}->email); + save_settings(); + } + $_SESSION["$settings->sessionprefix-user"] = $user; $_SESSION["$settings->sessionprefix-pass"] = $new_password_hash ?? hash_password($pass); $_SESSION["$settings->sessionprefix-expiretime"] = time() + 60*60*24*30; // 30 days from now @@ -232,8 +239,7 @@ function hash_password_properties() { * @package page-login * @param string $pass The password to hash. * - * @return string The hashed password. Uses sha3 if $settings->use_sha3 is - * enabled, or sha256 otherwise. + * @return string The hashed password. Uses password_hash() under-the-hood, but with some additional extras to avoid known issues. */ function hash_password($pass) { $props = hash_password_properties(); @@ -271,7 +277,8 @@ function hash_password_update($pass, $hash) { * automatically. * Starts at 10 and works upwards in increments of 1. Goes on until a value is * found that's greater than the target - or 10x the target time elapses. - * @return integer The automatically calculated password hashing cost. + * @param bool $verbose Whether to output verbose progress information to the client or not. + * @return int The automatically calculated password hashing cost. */ function hash_password_compute_cost($verbose = false) { global $settings; diff --git a/docs/ModuleApi/files/modules/page-move.php.txt b/docs/ModuleApi/files/modules/page-move.php.txt index 9b99be6..144f7fd 100644 --- a/docs/ModuleApi/files/modules/page-move.php.txt +++ b/docs/ModuleApi/files/modules/page-move.php.txt @@ -1,7 +1,7 @@ "Page mover", - "version" => "0.9.3", + "version" => "0.9.4", "author" => "Starbeamrainbowlabs", "description" => "Adds an action to allow administrators to move pages.", "id" => "page-move", @@ -111,7 +111,7 @@ register_module([ } // Save the updated pageindex - file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT)); + save_pageindex(); // Move the page on the disk rename("$env->storage_prefix$env->page.md", "$env->storage_prefix$new_name.md"); diff --git a/docs/ModuleApi/files/modules/parser-parsedown.php.txt b/docs/ModuleApi/files/modules/parser-parsedown.php.txt index bc1e11f..01d54a9 100644 --- a/docs/ModuleApi/files/modules/parser-parsedown.php.txt +++ b/docs/ModuleApi/files/modules/parser-parsedown.php.txt @@ -4,14 +4,23 @@ register_module([ "version" => "0.10", "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.", + "extra_data" => [ + /******** Parsedown versions ******** + * Parsedown Core: 1.8.0-beta-5 * + * Parsedown Extra: 0.8.0-beta-1 * + ************************************/ + "Parsedown.php" => "https://raw.githubusercontent.com/erusev/parsedown/819c68899d593503180ed79ef4be5a4dcd8c5f92/Parsedown.php", + "ParsedownExtra.php" => "https://raw.githubusercontent.com/erusev/parsedown-extra/f21b40a1973b6674903a6da9857ee215e8839f96/ParsedownExtra.php" + ], "id" => "parser-parsedown", "code" => function() { global $settings; $parser = new PeppermintParsedown(); $parser->setInternalLinkBase("?page=%s"); - add_parser("parsedown", function($source) use ($parser) { + add_parser("parsedown", function($source, $untrusted) use ($parser) { global $settings; + $parser->setsafeMode($untrusted || $settings->all_untrusted); $parser->setMarkupEscaped($settings->clean_raw_html); $result = $parser->text($source); @@ -207,23 +216,8 @@ register_module([ } ]); -/*** Parsedown versions *** - * Parsedown Core: 1.6.0 * - * Parsedown Extra: 0.7.0 * - **************************/ -$env->parsedown_paths = new stdClass(); -$env->parsedown_paths->parsedown = "https://cdn.rawgit.com/erusev/parsedown/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7/Parsedown.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 -// 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) - file_put_contents("./ParsedownExtra.php", fopen($env->parsedown_paths->parsedown_extra, "r")); - -require_once("./Parsedown.php"); -require_once("./ParsedownExtra.php"); +require_once("$paths->extra_data_directory/parser-parsedown/Parsedown.php"); +require_once("$paths->extra_data_directory/parser-parsedown/ParsedownExtra.php"); /** * Attempts to 'auto-correct' a page name by trying different capitalisation @@ -260,13 +254,26 @@ function parsedown_pagename_resolve($pagename) { * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ * ███████ ██ ██ ██ ███████ ██ ████ ███████ ██ ██████ ██ ████ ███████ */ +/** + * The Peppermint-flavoured Parsedown parser. + */ class PeppermintParsedown extends ParsedownExtra { + /** + * The base directory with which internal links will be resolved. + * @var string + */ private $internalLinkBase = "./%s"; - protected $maxParamDepth = 0; + /** + * The parameter stack. Used for recursive templating. + * @var array + */ protected $paramStack = []; + /** + * Creates a new Peppermint Parsedown instance. + */ function __construct() { // Prioritise our internal link parsing over the regular link parsing @@ -287,6 +294,10 @@ class PeppermintParsedown extends ParsedownExtra * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ * ██ ███████ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ████ ██████ */ + /** + * Parses templating definitions. + * @param string $fragment The fragment to parse it out from. + */ protected function inlineTemplate($fragment) { global $env, $pageindex; @@ -417,6 +428,11 @@ class PeppermintParsedown extends ParsedownExtra } } + /** + * Handles parsing out templates - recursively - and the parameter stack associated with it. + * @param string $source The source string to process. + * @return array The parsed result + */ protected function templateHandler($source) { global $pageindex, $env; @@ -433,7 +449,6 @@ class PeppermintParsedown extends ParsedownExtra return false; // Parse the parameters - $this->maxParamDepth++; $params = []; $i = 0; foreach($parts as $part) @@ -468,7 +483,7 @@ class PeppermintParsedown extends ParsedownExtra return [ "name" => "div", - "text" => $parsedTemplateSource, + "rawHtml" => $parsedTemplateSource, "attributes" => [ "class" => "template" ] @@ -488,6 +503,10 @@ class PeppermintParsedown extends ParsedownExtra * ██ ██ ██ ██ ██ ██ ██ ██ * ███████ ██ ██ ████ ██ ██ ███████ */ + /** + * Parses internal links + * @param string $fragment The fragment to parse. + */ protected function inlineInternalLink($fragment) { global $pageindex, $env; @@ -600,6 +619,10 @@ class PeppermintParsedown extends ParsedownExtra * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ * ██ ██ ██ ██ ██ ██████ ███████ ███████ */ + /** + * Parses the extended image syntax. + * @param string $fragment The source fragment to parse. + */ protected function inlineExtendedImage($fragment) { global $pageindex; @@ -773,6 +796,12 @@ class PeppermintParsedown extends ParsedownExtra # Static Methods # ~ + /** + * Extracts the page names from internal links in a given markdown source. + * Does not actually _parse_ the source - only extracts via a regex. + * @param string $page_text The source text to extract a list of page names from. + * @return array A list of page names that the given source text links to. + */ public static function extract_page_names($page_text) { global $pageindex; preg_match_all("/\[\[([^\]]+)\]\]/", $page_text, $linked_pages); @@ -808,12 +837,23 @@ class PeppermintParsedown extends ParsedownExtra # Utility Methods # ~ - private function isFloatValue($value) + /** + * Returns whether a string is a valid float: XXXXXX; value. + * Used in parsing the extended image syntax. + * @param string $value The value check. + * @return bool Whether it's valid or not. + */ + private function isFloatValue(string $value) { return in_array(strtolower($value), [ "left", "right" ]); } - private function parseSizeSpec($text) + /** + * Parses a size specifier into an array. + * @param string $text The source text to parse. e.g. "256x128" + * @return array|bool The parsed size specifier. Example: ["x" => 256, "y" => 128]. Returns false if parsing failed. + */ + private function parseSizeSpec(string $text) { if(strpos($text, "x") === false) return false; @@ -834,6 +874,11 @@ class PeppermintParsedown extends ParsedownExtra ]; } + /** + * Escapes the source text via htmlentities. + * @param string $text The text to escape. + * @return string The escaped string. + */ protected function escapeText($text) { return htmlentities($text, ENT_COMPAT | ENT_HTML5); diff --git a/docs/ModuleApi/files/pack.html b/docs/ModuleApi/files/pack.html index 85e7769..75f23dc 100644 --- a/docs/ModuleApi/files/pack.html +++ b/docs/ModuleApi/files/pack.html @@ -106,12 +106,12 @@Functions
+log_str()
+ +log_str(string $line)
+Logs a string to stdout, but only on the CLI.
+ + +Parameters
+The line to log.
Documentation is powered by phpDocumentor and authored - on February 24th, 2019 at 16:02. + on July 5th, 2019 at 19:50.
Documentation is powered by phpDocumentor and authored - on February 24th, 2019 at 16:02. + on July 5th, 2019 at 19:50.
Documentation is powered by phpDocumentor and authored - on February 24th, 2019 at 16:02. + on July 5th, 2019 at 19:50.