"Theme Gallery", "version" => "0.4.1", "author" => "Starbeamrainbowlabs", "description" => "Adds a theme gallery page and optional automatic theme updates. Contacts a remote server, where IP addresses are stored in automatic server logs for security and attack mitigation purposes.", "id" => "feature-theme-gallery", "code" => function() { global $settings, $env; /** * @api {get} ?action=theme-gallery Display the theme gallery * @apiName ThemeGallery * @apiGroup Utility * @apiPermission Moderator */ add_action("theme-gallery", function() { global $settings, $env; if(!$env->is_admin) { $errorMessage = "

You don't have permission to change $settings->sitename's theme.

\n"; if(!$env->is_logged_in) $errorMessage .= "

You could try logging in.

"; else $errorMessage .= "

You could try logging out and then logging in again with a different account that has the appropriate privileges..

"; exit(page_renderer::render_main("Error - $settings->sitename", $errorMessage)); } $gallery_urls = explode(" ", $settings->css_theme_gallery_index_url); if(!isset($_GET["load"]) || $_GET["load"] !== "yes") { $result = "

Theme Gallery

Load the theme gallery? A HTTP request will be made to the following endpoints:

...with the following user agent string: ".htmlentities (ini_get("user_agent"))."

No external HTTP requests will be made without your consent.

Ok, load the gallery.

Actually, take me back.

"; exit(page_renderer::render_main("Theme Gallery - $settings->sitename", $result)); } $themes_available = []; foreach($gallery_urls as $url) { if(empty($url)) continue; $next_obj = json_decode(@file_get_contents($url)); if(empty($next_obj)) { http_response_code(503); exit(page_renderer::render_main("Error - Theme Gallery - $settings->sitename", "

Error: Failed to download theme index file from " . htmlentities($url) . ".")); } foreach($next_obj as $theme) { $theme->index_url = $url; $theme->root = dirname($url) . "/{$theme->id}"; $theme->url = "{$theme->root}/theme.css"; $theme->preview_large = "{$theme->root}/preview_large.png"; $theme->preview_small = "{$theme->root}/preview_small.png"; $themes_available[] = $theme; } } $sorter = new Collator(""); usort($themes_available, function($a, $b) use ($sorter) : int { return $sorter->compare($a->name, $b->name); }); $content = "

Theme Gallery

$settings->sitename is currently using ".(strlen($settings->css_theme_autoupdate_url) > 0 ? "an external" : "the internal")." theme".(strlen($settings->css_theme_autoupdate_url) > 0 ? " (reset to the internal default theme)" : "").".

\n"; foreach($themes_available as $theme) { $selected = $theme->id == $settings->css_theme_gallery_selected_id ? " selected" : ""; $content .= "

" . str_replace("\n", "

\n

", htmlentities($theme->description)) . "

By " . htmlentities($theme->author) . " (View CSS, View Index)

"; } $content .= "

Warning: If you've altered $settings->sitename's CSS by changing the value of the css setting, then your changes will be overwritten by clicking the button below! If necessary, move your changes to the css_custom setting first before continuing here.

"; exit(page_renderer::render_main("Theme Gallery - $settings->sitename", "$content")); }); /** * @api {get} ?action=theme-gallery-select&theme-selector=theme-id Set the site theme * @apiName ThemeGallerySelect * @apiGroup Utility * @apiPermission Moderator * * @apiParam {string} theme-selector The id of the theme to switch into, or 'default-internal' to switch back to the internal theme. */ add_action("theme-gallery-select", function() { global $env, $settings, $guiConfig; if(!$env->is_admin) { $errorMessage = "

You don't have permission to change $settings->sitename's theme.

\n"; if(!$env->is_logged_in) $errorMessage .= "

You could try logging in.

"; else $errorMessage .= "

You could try logging out and then logging in again with a different account that has the appropriate privileges..

"; exit(page_renderer::render_main("Error - $settings->sitename", $errorMessage)); } if(!isset($_GET["theme-selector"])) { http_response_code(400); exit(page_renderer::render_main("No theme selected - Error - $settings->sitename", "

Oops! Looks like you didn't select a theme. Try going back and selecting one.

")); } if($_GET["theme-selector"] === "default-internal") { $settings->css_theme_gallery_selected_id = $guiConfig->css_theme_gallery_selected_id->default; $settings->css_theme_autoupdate_url = $guiConfig->css_theme_autoupdate_url->default; $settings->css = $guiConfig->css->default; if(!save_settings()) { http_response_code(503); exit(page_renderer::render_main("Server error - $settings->sitename", "

Oops! $settings->sitename wasn't able to save the peppermint.json settings file back to disk. If you're the administrator, try checking the permissions on disk. If not, try contacting $settings->sitename's administrator, who's contact details can be found at the bottom of every page.

")); } exit(page_renderer::render_main("Theme reset - Theme Gallery - $settings->sitename", "

$settings->sitename's theme has been reset to the internal theme.

Go to the homepage.

")); } // Set the new theme's id $settings->css_theme_gallery_selected_id = $_GET["theme-selector"]; $gallery_urls = explode(" ", $settings->css_theme_gallery_index_url); // Find the URL of the selected theme // FUTURE: Figure out a way to pass this information through the UI interface instead to avoid a re-download? $theme_autoupdate_url = null; foreach($gallery_urls as $url) { $next_index = json_decode(@file_get_contents($url)); if(empty($next_index)) { error_log("[PeppermintyWiki/$settings->sitename/theme_gallery] Error: Failed to download theme index file from '$url' when setting the wiki theme."); continue; } foreach($next_index as $next_theme) { if($next_theme->id == $settings->css_theme_gallery_selected_id) { $theme_autoupdate_url = dirname($url) . "/{$next_theme->id}/theme.css"; break; } } if($theme_autoupdate_url !== null) break; } if($theme_autoupdate_url === null) { http_response_code(503); exit(page_renderer::render_main("[PeppermintyWiki/$settings->sitename/theme_gallery] Failed to set theme - Error - $settings->sitename)", "

Oops! $settings->sitename couldn't find the theme you selected. Perhaps it has been changed or deleted, or perhaps there was an error during the download process.

Try heading back to the theme gallery and trying again.

")); } $settings->css_theme_autoupdate_url = $theme_autoupdate_url; if(!theme_update(true)) { http_response_code(503); exit(page_renderer::render_main("Failed to download theme - $settings->sitename", "

Oops! $settings->sitename wasn't able to download the theme you selected. If you're the administrator, try checking the PHP server logs. If not, try contacting $settings->sitename's administrator, who's contact details can be found at the bottom of every page.

")); } // TODO: Add option to disable theme updates if(!save_settings()) { http_response_code(503); exit(page_renderer::render_main("Server error - $settings->sitename", "

Oops! $settings->sitename wasn't able to save the peppermint.json settings file back to disk. If you're the administrator, try checking the permissions on disk. If not, try contacting $settings->sitename's administrator, who's contact details can be found at the bottom of every page.

")); } http_response_code(200); exit(page_renderer::render_main("Theme Changed - $settings->sitename", "

$settings->sitename's theme was changed successfully to ".htmlentities($settings->css_theme_gallery_selected_id).".

Go to the homepage.

")); }); if($env->is_admin) add_help_section("945-theme-gallery", "Changing the theme", "

$settings->sitename allows you to change the theme by selecting a theme from the public theme gallery. You can visit the theme gallery to take a look. The theme gallery does make a remote HTTP request, but a warning is displayed before this is performed. Once a theme is downloaded, occasional (but infrequent) HTTP requests are made to make sure it is up to date.

Note that when using a theme from the theme gallery, the internal theme is disabled. There is a button to disable any loaded theme gallery theme though.

The default theme has support for the prefers-color-scheme CSS media query, enabling it to be dark or light depending on your operating system preference.

"); } ]); /** * Updates the currently selected theme by fetching it from a remote url. * @param bool $force_update Whether to force an update - even if we've already updated recently. * @return bool Whether the update was sucessful. It might fail because of network issues, or the theme update requires a newer version of Pepperminty Wiki than is currently installed. */ function theme_update($force_update = false) : bool { global $version, $settings; // If there's no url to update from or updates are disabled, then we're done here if(empty($settings->css_theme_autoupdate_url) || $settings->css_theme_autoupdate_interval < 0) return true; // If it's not time for an update, then end here // ...unless we're supposed to force an update if(time() - $settings->css_theme_autoupdate_lastcheck < $settings->css_theme_autoupdate_interval || !$force_update) return true; // Fetch the new css $new_css = @file_get_contents($settings->css_theme_autoupdate_url); // Make sure it's valid if(empty($new_css)) { error_log("[PeppermintyWiki/$settings->sitename/theme_gallery] Error: Failed to update theme: Got an error while trying to download theme update from $settings->css_theme_autoupdate_url"); return false; } // TODO: Check the hash against themeindex.json? $min_version_loc = strpos($new_css, "@minversion") + strlen("@minversion"); $min_version = substr($new_css, $min_version_loc, strpos($new_css, "\n", $min_version_loc)); if(version_compare($version, $min_version) == -1) { error_log("[PeppermintyWiki/$settings->sitename/theme_gallery] Error: Failed to update theme: $settings->css_theme_gallery_selected_id requires Pepperminty Wiki $min_version, but $version is installed."); return false; } // If the css is identical to the string we've got stored already, then no point in updating if($new_css == $settings->css) return true; $settings->css = $new_css; return save_settings(); } ?>