Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/mappress-google-maps-for-wordpress/languages/texts.php
+++ b/mappress-google-maps-for-wordpress/languages/texts.php
@@ -29,9 +29,6 @@
__("Dark");
__("Satellite");
__("Satellite Streets");
-__("Liberty");
-__("Bright");
-__("Positron");
__("Roadmap");
__("Terrain");
__("Hybrid");
@@ -70,15 +67,13 @@
__("Address");
__("Distance");
__("URL");
-__("Custom field");
-__("POI data field");
+__("Custom Field");
__("Email");
__("Display Name");
-__("Custom Field");
-__("Address or lat/lng was missing in ACF field");
__("Post type");
__("Role");
__("Text search");
+__("Address or lat/lng was missing in ACF field");
__("Invalid geocoder: %s");
__("API Key is missing - see MapPress Settings");
__("Invalid status: %s, %s");
@@ -104,7 +99,6 @@
__("Automatic");
__("No address or lat/lng specified");
__("Communication error, please try again later");
-__("Your server's IP has been blocked by Siteground's antibot system. Please contact Siteground and your hosting service to resolve.");
__("JSON error");
__("Error when checking license");
__("Widget title");
@@ -124,14 +118,14 @@
__("In");
__(" Tagged ");
__("My location");
-__("Swap start and end");
__("Get Directions");
+__("All");
__("Filter");
__("%d Results");
__("%d Result");
-__("Clear");
+__("Reset");
__("Done");
-__("All");
+__("Unable to get your location");
__("Toggle fullscreen view");
__("Your Location");
__("MapPress FAQ");
@@ -141,22 +135,21 @@
__("Google Maps API not loaded");
__("A theme or plugin is preventing Google Maps from loading.");
__("Google Maps API key required");
+__("Google Maps API loaded multiple times");
+__("A theme or plugin has loaded Google Maps twice");
__("Map Error");
__("Map error: please see the developer console (F12 in most browsers) for details.");
-__("Browser does not support geolocation");
-__("Unable to get your location");
__("Add to map");
__("Search");
__("List");
__("Map");
-__("Center map");
__("Traffic");
__("Bicycling");
__("Transit");
+__("Center map");
__("Help");
__("%d of %d");
-__("Enter an address, place, KML URL, or lat,lng");
-__("Enter an address, place or lat,lng");
+__("Enter an address, place, KML file URL, or lat,lng");
__("Error reading KML file.");
__("This may be a CORS error. See the MapPress FAQ for help.");
__("No posts found");
@@ -195,10 +188,8 @@
__("KML");
__("Description");
__("Data");
-__("Detach");
-__("Attach to post");
-__("Delete");
__("Save");
+__("Delete");
__("Create new icon");
__("Upload icons");
__("Shape");
@@ -214,7 +205,6 @@
__("File -> Share -> Publish to web");
__("Select 'Entire Document' and 'Comma-Separated Values (.csv)");
__("Copy the URL and paste it here");
-__("Looks like the import timed out or there was a server error. Temporarily deactivate all other plugins and check your PHP max_execution_time");
__("Source");
__("File");
__("Google Sheets");
@@ -251,34 +241,18 @@
__("Geocode users");
__("For bulk geocoding (>100 items) online geocoding services are faster and less expensive.");
__("Geocoding errors");
-__("Directions");
-__("Inline");
-__("Directions link");
-__("Show in popup");
-__("Show in list");
__("Demo Map");
__("Maps for WordPress");
__("Basic Settings");
-__("MapPress license key");
-__("Enter license to enable automatic updates");
-__("Get license");
-__("Check now");
-__("Your account");
-__("Active");
-__("License is invalid or expired");
-__("Beta versions");
-__("Enable updates for beta versions");
__("Mapping API");
__("Leaflet is free and requires no API key. Google requires an API key.");
__("Get an Access Token");
__("Mapbox access token");
__("Enter token to use Mapbox");
__("Mapbox makes Leaflet maps look great and provides an excellent geocoder.");
-__("Enter a Mapbox access token");
-__("Tile Service");
__("Nominatim is free but inaccurate. Consider using Mapbox or Google instead.");
-__("Enter a Location IQ access token");
-__("Enter a Google API key");
+__("The Mapbox geocoder requires a Mapbox access token");
+__("The Google geocoder requires a Google API key");
__("Geocoder");
__("LocationIQ access token");
__("Enter token to use LocationIQ");
@@ -286,6 +260,15 @@
__("Google API key");
__("Enter API key to use Google maps");
__("Enter API key to use Google geocoder");
+__("MapPress license key");
+__("Enter license to enable automatic updates");
+__("Get license");
+__("Check now");
+__("Your account");
+__("Active");
+__("License is invalid or expired");
+__("Beta versions");
+__("Enable updates for beta versions");
__("Prevents conflicts with other plugins");
__("Required because %s is active");
__("Compatibility mode");
@@ -301,12 +284,12 @@
__("Center");
__("Left");
__("Right");
+__("Directions");
+__("Inline");
__("Mini width");
__("Width (px) to use map/list toggle buttons");
__("Scroll wheel zoom");
__("Enable map zoom with mouse scroll wheel");
-__("Map controls");
-__("Map menu");
__("POIs");
__("Open first POI");
__("Open first POI when a map is displayed");
@@ -317,7 +300,7 @@
__("Circle");
__("Scale");
__("Hover");
-__("Open popup on hover");
+__("Open POIs on hover");
__("Travel lines");
__("Connect POIs with lines");
__("Arrow");
@@ -340,8 +323,6 @@
__("POIs per page");
__("Sort");
__("Distance to last search");
-__("Include KML POIs in list");
-__("Directions text");
__("POI Data");
__("Data fields");
__("New field");
@@ -352,10 +333,12 @@
__("Name");
__("Label");
__("Format");
+__("Show in popups");
__("Value");
__("Values");
__("Styled Maps");
__("Default style");
+__("Replace the default "roadmap" or "streets" style");
__("Icons");
__("Default icon");
__("Icon directory");
@@ -386,14 +369,13 @@
__("POI images");
__("KMLs");
__("Include KML POIs in mashups");
-__("Display search");
+__("Enable search for mashups");
__("Search radius");
__("Minimum search radius (km)");
-__("Custom search placeholder");
-__("Leave blank for default");
+__("Search placeholder");
__("Search country");
__("Country code for searches");
-__("Search URL parameter");
+__("URL parameter");
__("Bounding box");
__("Restrict searches to a bounding box (optional)");
__("Geolocate");
@@ -402,7 +384,6 @@
__("User location");
__("Show user location as a blue circle on the map");
__("Filters");
-__("Display filters");
__("Filters position");
__("Top");
__("POI list");
@@ -412,19 +393,23 @@
__("New filter");
__("Slug");
__("Placeholder");
-__("Include slugs");
-__("Exclude slugs");
-__("Show separately");
-__("Search title");
-__("Search title + body");
+__("Include term slugs");
+__("Exclude term slugs");
__("Templates");
__("Custom templates");
+__("Directions link");
+__("Show in popup");
+__("Show in list");
__("Popups");
__("Popup thumbnail size");
__("or");
__("Localization");
__("Language");
__("Language for searches and Google map controls");
+__("Directions server");
+__("Distance units");
+__("Metric (km)");
+__("Imperial (mi)");
__("Generate Maps from Custom Fields");
__("Posts");
__("Users");
@@ -437,8 +422,8 @@
__("Server API key for geocoding. Only required if client key is restricted by referrer.");
__("Frontend Forms");
__("Advanced Custom Fields");
-__("Use this setting if your posts have an ACF location field. Only posts with this field will be displayed on mashups.");
-__("ACF location field");
+__("To generate MapPress maps from ACF fields, leave this blank and use the Geocoding section instead");
+__("ACF map field to include in mashups");
__("Miscellaneous");
__("Map sizes");
__("Width");
@@ -449,6 +434,8 @@
__("Copy maps when overwriting a translation");
__("Google API");
__("Prevent other plugins from loading the Google Maps API twice");
+__("Web Component (beta)");
+__("Render maps as a web component");
__("Index");
__("Reset Defaults");
__("Upgrade to MapPress Pro");
@@ -473,6 +460,8 @@
__("Shortcode");
__("Shortcode copied");
__("Insert into post");
+__("Detach");
+__("Attach to post");
__("Copy");
__("Map %d copied");
__("Trash");
@@ -481,31 +470,33 @@
__("Map ID, post title, or map title...");
__("Add New");
__("Map %d saved");
-__("On");
-__("Off");
__("Map settings");
__("Style");
__("Custom");
__("Size");
__("px, %, vw");
__("px, %, vh");
-__("Set");
__("Center/Zoom");
-__("Viewport set");
__("Viewport automatic");
+__("Viewport set");
+__("Set");
+__("Enable search");
+__("Enable filters");
__("Enter style name");
__("JSON");
-__("URL returned %s");
-__("URL returned invalid JSON");
-__("URL is unreachable, check if blocked by CORS policy");
+__("Style already exists, overwrite?");
+__("Please enter a Mapbox access token in the MapPress settings screen to use styled maps.");
__("Edit");
-__("Enter a Mapbox access token to use styled maps.");
+__("Add style");
+__("Enter style from Mapbox Studio");
+__("MapBox Share URL");
+__("Style name");
+__("Custom styles");
__("Select a style");
__("New style");
__("Download style");
-__("Edit Style");
-__("Style name");
-__("Style Type");
+__("Standard styles");
+__("Download");
__("MapPress Support");
__("Build amazing maps with the easiest and most powerful mapping plugin available");
__("Open Setup Wizard");
@@ -523,7 +514,7 @@
__("Contact");
__("Please Choose a Mapping API");
__("MapPress supports both Leaflet and Google mapping APIs.");
-__("No API key required");
+__("No API key");
__("No credit card");
__("Unlimited free usage");
__("Good functionality");
@@ -539,7 +530,7 @@
__("Enter your API key here");
__("Sign up with Mapbox");
__("(optional - credit card required)");
-__("Mapbox makes Leaflet even better, with great-looking map tiles, styled maps, and a powerful geocoder.");
+__("Mapbox makes Leaflet better, with great-looking map tiles, styled maps, and a powerful geocoder.");
__("A generous monthly usage credit means it's free for most sites.");
__("Get Mapbox Access Token");
__("Enter your access token here");
@@ -559,6 +550,5 @@
__("User list item");
__("New");
__("Reset template to default");
-__("Reset");
__("Editor");
?>
No newline at end of file
--- a/mappress-google-maps-for-wordpress/mappress.php
+++ b/mappress-google-maps-for-wordpress/mappress.php
@@ -5,7 +5,7 @@
Author URI: https://www.mappresspro.com
Pro Update URI: https://www.mappresspro.com
Description: MapPress makes it easy to add Google Maps and Leaflet Maps to WordPress
-Version: 2.96.6
+Version: 2.97.1
Author: Chris Richardson
Text Domain: mappress-google-maps-for-wordpress
Thanks to all the translators and to Scott DeJonge for his wonderful icons
@@ -41,7 +41,7 @@
}
class Mappress {
- const VERSION = '2.96.6';
+ const VERSION = '2.97.1';
static
$api,
@@ -124,7 +124,7 @@
add_action('admin_init', array(__CLASS__, 'admin_init'), 10, 2);
// Iframes
- if (isset($_GET['mappress']) && $_GET['mappress'] = 'embed')
+ if (isset($_GET['mappress']))
add_action('template_redirect', array(__CLASS__, 'template_redirect'));
// Temporary fix for https://core.trac.wordpress.org/ticket/56969
@@ -181,7 +181,7 @@
self::styles_enqueue('backend');
if (isset($pages['main']) && $hook == $pages['main']) {
self::scripts_enqueue('settings');
- } else if (in_array($hook, $pages) || in_array($hook, $admin_pages)) {
+ } else if ( (in_array($hook, $pages) || in_array($hook, $admin_pages)) && current_user_can(Mappress::cap()) ) {
self::scripts_enqueue('backend');
}
}
@@ -193,7 +193,7 @@
self::$pages['main'] = add_menu_page('MapPress', 'MapPress', 'manage_options', 'mappress', array('Mappress_Settings', 'options_page'), 'dashicons-location');
self::$pages['settings'] = add_submenu_page($parent, __('Settings', 'mappress-google-maps-for-wordpress'), __('Settings', 'mappress-google-maps-for-wordpress'), 'manage_options', 'mappress', array('Mappress_Settings', 'options_page'));
- self::$pages['maps'] = add_submenu_page($parent, __('Maps', 'mappress-google-maps-for-wordpress'), __('Maps', 'mappress-google-maps-for-wordpress'), 'edit_posts', 'mappress_maps', array(__CLASS__, 'map_library'));
+ self::$pages['maps'] = add_submenu_page($parent, __('Maps', 'mappress-google-maps-for-wordpress'), __('Maps', 'mappress-google-maps-for-wordpress'), Mappress::cap(), 'mappress_maps', array(__CLASS__, 'map_library'));
if (self::$pro)
self::$pages['import'] = add_submenu_page($parent, __('Import', 'mappress-google-maps-for-wordpress'), __('Import', 'mappress-google-maps-for-wordpress'), 'manage_options', 'mappress_import', array('Mappress_Import', 'import_page'));
self::$pages['support'] = add_submenu_page($parent, __('Support', 'mappress-google-maps-for-wordpress'), __('Support', 'mappress-google-maps-for-wordpress'), 'manage_options', 'mappress_support', array('Mappress_Settings', 'support_page'));
@@ -208,7 +208,7 @@
$error = "<div class='notice notice-error'><p>%s</p></div>";
$maps_table = $wpdb->prefix . "mapp_maps";
- $exists = $wpdb->get_var("show tables like '$maps_table'");
+ $exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $maps_table));
// Non-dismissible notices
if (!$exists) {
@@ -239,7 +239,7 @@
echo Mappress::script("jQuery('[data-mapp-dismiss]').on('click', '.notice-dismiss, .mapp-dismiss', function(e) {
var key = jQuery(this).closest('.notice').attr('data-mapp-dismiss');
jQuery(this).closest('[data-mapp-dismiss]').remove();
- jQuery.post(ajaxurl, { action : 'mapp_dismiss', key : key });
+ jQuery.post(ajaxurl, { action : 'mapp_dismiss', key : key, nonce : '" . wp_create_nonce('mappress') . "' });
});");
}
}
@@ -264,11 +264,13 @@
update_user_meta( get_current_user_id(), 'mappress_dismissed', implode( ',', $dismissed ));
}
- static function ajax_dismiss() {
+ static function ajax_dismiss() {
+ check_ajax_referer('mappress', 'nonce');
+
// Still sent via jQuery
- $key = (isset($_POST['key'])) ? $_POST['key'] : null;
- if (!$key || sanitize_key( $key) != $key)
- wp_die( 0 );
+ $key = isset($_POST['key']) ? sanitize_key(wp_unslash($_POST['key'])) : null;
+ if (!$key) wp_die(0);
+
self::admin_notices_dismiss($key, true);
self::ajax_response('OK');
}
@@ -301,10 +303,19 @@
)
);
}
+
+ static function cap($action = null) {
+ if ($action == 'empty_trash')
+ return 'manage_options';
+ else if ($action == 'delete_map')
+ return 'delete_others_posts';
+ else
+ return 'edit_others_posts';
+ }
static function deactivate() {
- $reason = (isset($_REQUEST['mapp_reason'])) ? $_REQUEST['mapp_reason'] : null;
- $reason_text = (isset($_REQUEST['mapp_reason_text'])) ? $_REQUEST['mapp_reason_text'] : null;
+ $reason = isset($_REQUEST['mapp_reason']) ? sanitize_key($_REQUEST['mapp_reason']) : null;
+ $reason_text = isset($_REQUEST['mapp_reason_text']) ? sanitize_textarea_field(wp_unslash($_REQUEST['mapp_reason_text'])) : null;
if (!$reason || $reason == 'private' || $reason == 'temporary')
return;
@@ -328,22 +339,6 @@
static function debugging() {
global $wpdb;
- if (isset($_GET['mp_info'])) {
- echo "<b>Plugin</b> " . self::$version;
- $maps_table = $wpdb->prefix . 'mapp_maps';
- $results = $wpdb->get_results("SELECT otype, oid, mapid FROM $maps_table");
- echo "<br/>otype/oid => mapid<br/>";
- foreach($results as $i => $result) {
- if ($i > 50)
- break;
- echo "<br/>$result->otype / $result->oid => $result->mapid";
- }
- $options = Mappress_Options::get();
- unset($options->mapbox, $options->license, $options->apiKey, $options->apiKeyServer);
- echo str_replace(array("r", "n"), array('<br/>', '<br/>'), print_r($options, true));
- die();
- }
-
// Can be used to force otype when upgrading from ancient versions
//if (isset($_REQUEST['mp_upgrade']) && is_admin()) {
// $maps_table = $wpdb->prefix . 'mapp_maps';
@@ -355,9 +350,7 @@
// }
//}
- if (isset($_REQUEST['mp_debug']))
- self::$debug = max(1, (int) $_REQUEST['mp_debug']);
- else if (defined('MAPPRESS_DEBUG') && MAPPRESS_DEBUG)
+ if (defined('MAPPRESS_DEBUG') && MAPPRESS_DEBUG)
self::$debug = true;
if (self::$debug) {
@@ -446,7 +439,7 @@
$mashup->query = Mappress_Query::parse_query($atts);
// If parameter test="true", output the query result (or global query) without using a map
- if (isset($_GET['mp_test']) || (isset($atts['test']) && $atts['test'])) {
+ if ( (isset($_GET['mp_test']) && current_user_can('manage_options')) || (isset($atts['test']) && $atts['test']) ) {
$wpq = ($mashup->query) ? new WP_Query($mashup->query) : $wp_query;
return "<pre>" . print_r($wpq, true) . "</pre>";
}
@@ -458,6 +451,24 @@
}
return $mashup->display();
}
+
+ static function get_sample_oids($limit = 2) {
+ $cache_key = 'mappress_sample_oids';
+ $cached = get_transient($cache_key);
+ if ($cached !== false)
+ return $cached;
+
+ global $wpdb;
+ $maps_table = $wpdb->prefix . 'mapp_maps';
+ $oids = $wpdb->get_col($wpdb->prepare(
+ "SELECT DISTINCT m.oid FROM $maps_table m JOIN $wpdb->posts p ON p.ID = m.oid
+ WHERE m.otype = 'post' AND m.status != 'trashed' AND p.post_status = 'publish' AND m.oid > 0
+ ORDER BY m.mapid ASC LIMIT %d", $limit
+ ));
+ $oids = $oids ? array_map('intval', $oids) : array();
+ set_transient($cache_key, $oids, 300);
+ return $oids;
+ }
static function get_tile_service() {
if (self::$options->engine != 'leaflet')
@@ -481,6 +492,12 @@
*
*/
static function init() {
+ // Check minimum version - mappress_db now requires 6.2
+ if (version_compare(get_bloginfo('version'), '6.2', '<')) {
+ self::$notices['min_wp'] = array('error', __('MapPress requires WordPress 6.2 or later. Please update WordPress.', 'mappress-google-maps-for-wordpress'));
+ return;
+ }
+
Mappress_Compliance::register();
Mappress_Db::register();
Mappress_Map::register();
@@ -560,9 +577,6 @@
if (self::$pro && empty(self::$options->license) && (!is_multisite() || (is_super_admin() && is_main_site())))
self::$notices['nolicense'] = array('warning', __('Please enter your MapPress license key to enable plugin updates', 'mappress-google-maps-for-wordpress'));
- if (self::VERSION >= '2.55' && version_compare(get_bloginfo('version'),'5.3', '<') )
- self::$notices['255_min_version'] = array('error', __('MapPress Gutenberg blocks require WordPress 5.3 or the latest Gutenberg Plugin. Please update if using the block editor.', 'mappress-google-maps-for-wordpress'));
-
if ($current_version && $current_version < '2.55' && self::VERSION >= '2.55')
self::$notices['255_whats_new'] = array('info', sprintf(__('MapPress has many new features! %s.', 'mappress-google-maps-for-wordpress'), '<a target="_blank" href="https://mappresspro.com/whats-new">' . __("Learn more", 'mappress-google-maps-for-wordpress') . '</a>'));
@@ -668,14 +682,14 @@
}
static function is_dev() {
- if (defined('MAPPRESS_DEV') && MAPPRESS_DEV)
- return MAPPRESS_DEV;
- else if (isset($_REQUEST['mp_dev']))
- return ($_REQUEST['mp_dev']) ? $_REQUEST['mp_dev'] : 'dev';
- else
- return false;
+ if (isset($_REQUEST['mp_dev']) && current_user_can('manage_options')) {
+ $val = $_REQUEST['mp_dev'];
+ if (in_array($val, array('dev', 'dev2'), true))
+ return $val;
+ }
+ return false;
}
-
+
static function is_footer() {
if (defined('DOING_AJAX') && DOING_AJAX)
return false;
@@ -927,10 +941,12 @@
$register = array(
array("mappress-leaflet", $lib . '/leaflet/leaflet.js', null, null, $footer),
array("mappress-leaflet-togeojson", $lib . '/leaflet/togeojson.min.js', null, null, $footer),
- array('mappress-markerclusterer', 'https://unpkg.com/@googlemaps/markerclusterer@2.6.2/dist/index.min.js', null, null, $footer),
+
+ array('mappress-markerclusterer', $lib . '/markerclusterer/index.min.js', null, '2.6.2', $footer),
array('mappress-leaflet-markercluster', $lib . '/leaflet/leaflet.markercluster.js', null, null, $footer),
- array("mappress-maplibre", "https://unpkg.com/maplibre-gl@5.18.0/dist/maplibre-gl.js", null, null, $footer),
- array("mappress-leaflet-maplibre", "https://unpkg.com/@maplibre/maplibre-gl-leaflet/leaflet-maplibre-gl.js", null, null, $footer),
+ array("mappress-maplibre", $lib . '/maplibre/maplibre-gl.js', null, '5.18.0', $footer),
+ array("mappress-leaflet-maplibre", $lib . '/maplibre/leaflet-maplibre-gl.js', null, '0.0.22', $footer),
+
array('mappress', $js . "/index_mappress.js", $deps, self::$version, $footer),
array('mappress_admin', $js . "/index_mappress_admin.js", $admin_deps, self::$version, $footer)
);
@@ -1096,7 +1112,7 @@
// Openfreemap / maplibre
$tile_service = self::get_tile_service();
if ($tile_service == 'ofm') {
- $styles->add('mappress-maplibre', 'https://unpkg.com/maplibre-gl@5.18.0/dist/maplibre-gl.css', null, null);
+ $styles->add('mappress-maplibre', self::$baseurl . '/lib/maplibre/maplibre-gl.css', null, '5.18.0');
$deps[] = 'mappress-maplibre';
}
@@ -1115,10 +1131,10 @@
$styles->add('mappress-admin', self::$baseurl . '/css/mappress_admin.css', array('mappress', 'wp-edit-blocks'), self::$version);
// Mappress CSS from theme directory
- if ( @file_exists( get_stylesheet_directory() . '/mappress.css' ) )
+ if ( is_readable( get_stylesheet_directory() . '/mappress.css' ) )
$file = get_stylesheet_directory_uri() . '/mappress.css';
- elseif ( @file_exists( get_template_directory() . '/mappress.css' ) )
- $file = get_template_directory_uri() . '/mappress.css';
+ elseif ( is_readable( get_template_directory() . '/mappress.css' ) )
+ $file = get_template_directory_uri() . '/mappress.css';
if (isset($file)) {
$styles->add('mappress-custom', $file, array('mappress'), self::$version);
}
@@ -1247,7 +1263,7 @@
}
static function wp_head() {
- echo "rn<!-- MapPress Easy Google Maps " . __('Version', 'mappress-google-maps-for-wordpress') . ':' . self::$version . " (https://www.mappresspro.com) -->rn";
+ echo "rn<!-- MapPress Easy Google Maps " . esc_html__('Version', 'mappress-google-maps-for-wordpress') . ':' . esc_html(self::$version) . " (https://www.mappresspro.com) -->rn";
}
}
--- a/mappress-google-maps-for-wordpress/mappress_api.php
+++ b/mappress-google-maps-for-wordpress/mappress_api.php
@@ -22,10 +22,11 @@
}
public function create_map($request) {
+ ob_start();
$mapdata = $request->get_json_params();
if (!$mapdata)
- return new WP_Error('create_map', 'Map save data missing');
+ return new WP_Error('create_map', 'Map save data missing', array('status' => 400));
$map = new Mappress_Map($mapdata);
$result = $map->save();
@@ -38,11 +39,17 @@
public function delete_map($request) {
ob_start();
- $mapid = $request->get_param('mapid');
+ $url_params = $request->get_url_params();
+ $mapid = isset($url_params['mapid']) ? $url_params['mapid'] : null;
+
+ if (!Mappress_Map::get($mapid))
+ return new WP_Error('delete_item', 'Map not found', array('status' => 404));
+
$result = Mappress_Map::delete($mapid);
if (!$result)
- return new WP_Error('delete_item', "Internal error when deleting map ID '$mapid'!");
+ return new WP_Error('delete_item', "Internal error when deleting map ID '$mapid'!", array('status' => 500));
+
return $this->rest_response($mapid);
}
@@ -76,7 +83,8 @@
ob_start();
$result = Mappress_Map::empty_trash();
if (!$result)
- return new WP_Error('empty_trash', 'Internal error when emptying trash, your data was not saved!');
+ return new WP_Error('empty_trash', 'Internal error when emptying trash, your data was not saved!', array('status' => 500));
+
return $this->rest_response('OK');
}
@@ -93,8 +101,18 @@
$map = ($mapid) ? Mappress_Map::get($mapid) : null;
if (!$map)
- return new WP_Error('get_map', 'Map not found');
+ return new WP_Error('get_map', 'Map not found', array('status' => 404));
+ // Anonymous read follows parent post visibility. Editors see everything.
+ if (!current_user_can(Mappress::cap())) {
+ if ($map->status === 'trashed')
+ return new WP_Error('get_map', 'Map not found', array('status' => 404));
+ if ($map->otype === 'post' && (int) $map->oid > 0) {
+ $post_status = get_post_status((int) $map->oid);
+ if ($post_status !== 'publish' && $post_status !== 'inherit')
+ return new WP_Error('get_map', 'Map not found', array('status' => 404));
+ }
+ }
return $this->rest_response($map);
}
@@ -203,7 +221,7 @@
$fields = "SELECT $maps_table.mapid, $maps_table.otype, $maps_table.oid, $maps_table.status, $maps_table.title, $wpdb->users.nicename as otitle ";
$from = " FROM $maps_table ";
$join = " LEFT OUTER JOIN $wpdb->users ON ($wpdb->users.ID = $maps_table.oid) ";
- $where .= " AND $maps_table.otype = 'post' ";
+ $where .= " AND $maps_table.otype = 'user' ";
}
$where .= ($filter == 'trashed') ? " AND $maps_table.status = 'trashed' " : " AND $maps_table.status != 'trashed' ";
@@ -218,15 +236,13 @@
$orderby = '';
- // Note that sort_by should be ;already sanitized by wpdb->prepare
- if ($sort_by == 'mapid') {
- $orderby = $wpdb->prepare(" ORDER BY %1s ", $sort_by) . ( ($sort_asc == 'true') ? "ASC" : "DESC" );
- if ($sort_by != 'mapid')
- $orderby .= ", mapid";
- }
-
- if ($page_size > 0)
- $limit = $wpdb->prepare(" LIMIT %d, %d", ($page-1) * $page_size, $page_size);
+ // Only "mapid" is supported; if more sort columns are added, whitelist them explicitly.
+ if ($sort_by == 'mapid')
+ $orderby = " ORDER BY mapid " . (($sort_asc == 'true') ? "ASC" : "DESC");
+
+ $page = max(1, (int)$page);
+ $page_size = max(1, (int)$page_size);
+ $limit = $wpdb->prepare(" LIMIT %d, %d", ($page-1) * $page_size, $page_size);
// Run query, then check if more results exist
$results = $wpdb->get_results($fields . $from . $join . $where . $orderby . $limit);
@@ -252,11 +268,15 @@
public function mutate_map($request) {
ob_start();
- $mapid = $request->get_param('mapid');
- $mapdata = $request->get_param('changes');
+ $url_params = $request->get_url_params();
+ $mapid = isset($url_params['mapid']) ? $url_params['mapid'] : null;
+ $mapdata = $request->get_param('changes');
if (!$mapid || !$mapdata)
- return new WP_Error('mutate_map', 'Missing parameter while mutating');
+ return new WP_Error('mutate_map', 'Missing parameter while mutating', array('status' => 400));
+
+ if (!Mappress_Map::get($mapid))
+ return new WP_Error('mutate_map', 'Map not found', array('status' => 404));
$result = Mappress_Map::mutate($mapid, $mapdata);
if (!$result)
@@ -266,13 +286,15 @@
}
public function update_map($request) {
- $mapid = $request->get_param('mapid');
+ ob_start();
+ $url_params = $request->get_url_params();
+ $mapid = isset($url_params['mapid']) ? $url_params['mapid'] : null;
$mapdata = (object) $request->get_json_params();
if (!$mapdata)
- return new WP_Error('update_map', 'Map save data missing');
- if (!$mapid || $mapid != $mapdata->mapid)
- return new WP_Error('update_map', 'Map ID missing');
+ return new WP_Error('update_map', 'Map save data missing', array('status' => 400));
+ if (!$mapid || !isset($mapdata->mapid) || $mapid != $mapdata->mapid)
+ return new WP_Error('update_map', 'Map ID missing', array('status' => 400));
$map = new Mappress_Map($mapdata);
$result = $map->save();
@@ -281,19 +303,17 @@
return new WP_Error('update_map', 'Internal error, your data has not been saved!');
return $this->rest_response($map->mapid);
- }
-
+ }
+
public function rest_api_init() {
register_rest_route(
$this->namespace,
'/maps',
array(
- array(
+ array(
'methods' => 'GET',
'callback' => array($this, 'get_maps'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap()); },
'args' => array(
'filter' => array('sanitize_callback' => 'sanitize_title', 'default' => 'all'),
'oid' => array('sanitize_callback' => 'sanitize_title', 'default' => null),
@@ -309,9 +329,7 @@
array(
'methods' => 'POST',
'callback' => array($this, 'create_map'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap()); },
),
'schema' => array($this, 'get_map_schema')
)
@@ -325,31 +343,25 @@
array(
'methods' => 'GET',
'callback' => array($this, 'get_map'),
- 'permission_callback' => '__return_true',
- ),
-
+ 'permission_callback' => '__return_true',
+ ),
+
array(
'methods' => 'DELETE',
'callback' => array($this, 'delete_map'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap('delete_map')); },
),
array(
'methods' => 'POST',
'callback' => array($this, 'update_map'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap()); },
),
array(
'methods' => 'PATCH',
'callback' => array($this, 'mutate_map'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap()); },
),
'schema' => array($this, 'get_map_schema'),
)
@@ -362,9 +374,7 @@
array (
'methods' => 'POST',
'callback' => array($this, 'duplicate_map'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap()); },
'schema' => array($this, 'get_map_schema'),
)
);
@@ -376,9 +386,7 @@
array(
'methods' => 'GET',
'callback' => array($this, 'get_counts'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- },
+ 'permission_callback' => function() { return current_user_can(Mappress::cap()); },
'args' => array(
'otype' => array('sanitize_callback' => 'sanitize_title'),
'oid' => array('sanitize_callback' => 'absint'),
@@ -394,9 +402,7 @@
array(
'methods' => 'POST',
'callback' => array($this, 'empty_trash'),
- 'permission_callback' => function() {
- return current_user_can('edit_posts');
- }
+ 'permission_callback' => function() { return current_user_can(Mappress::cap('empty_trash')); },
)
);
--- a/mappress-google-maps-for-wordpress/mappress_compliance.php
+++ b/mappress-google-maps-for-wordpress/mappress_compliance.php
@@ -20,23 +20,34 @@
}
static function clear_complianz_cache() {
- delete_transient('cmplz_blocked_scripts');
- }
-
+ // Refresh MapPress options so we have the latest
+ Mappress::$options = Mappress_Options::get();
+
+ // Complianz uses its own cache, not standard WP transients
+ if ( function_exists( 'cmplz_delete_transient' ) ) {
+ cmplz_delete_transient( 'cmplz_blocked_scripts' );
+ }
+ }
+
static function cmplz_script( $tags ) {
+ // OpenFreeMap + Leaflet: OFM does not track users and sets no cookies, so no consent required
+ if (Mappress::$options->engine == 'leaflet' && Mappress::get_tile_service() == 'ofm') {
+ return $tags;
+ }
+
+ // Iframe with google or mapbox
if (Mappress::$options->iframes) {
- // Iframes
$tags[] = array(
- 'name' => 'mappress iframes',
- 'urls' => array(
- 'mappress=embed',
- ),
- 'category' => 'marketing',
- 'iframe' => 1,
+ 'name' => 'mappress',
+ //'placeholder' => 'google-maps', // causes disconcerting flash before iframe loads
+ 'urls' => array('mappress=embed'),
+ 'category' => 'marketing',
+ 'iframe' => 1,
);
+ return $tags;
}
-
- else if (Mappress::$options->engine == 'google') {
+
+ if (Mappress::$options->engine == 'google') {
// Google Maps — requires consent (tracks users)
// maps.googleapis.com is loaded dynamically by index_mappress.js (not a WP-enqueued script),
// so we only block index_mappress.js. No placeholder — Complianz fires it automatically on consent.
@@ -47,23 +58,17 @@
'build/index_mappress',
),
);
- }
-
- else if (Mappress::$options->engine == 'leaflet' && Mappress::get_tile_service() == 'ofm') {
- // OpenFreeMap + Leaflet: OFM does not track users and sets no cookies.
- // No consent is required — do not register with Complianz so scripts load freely.
return $tags;
- }
+ }
else {
// Leaflet with Mapbox tiles (or other non-OFM tile service) — Mapbox may track
$dependency = array();
-
- if (Mappress::$options->clustering) {
- $dependency = [
- 'leaflet.js' => 'leaflet.markercluster.js',
+ if (Mappress::$options->clustering) {
+ $dependency = [
+ 'leaflet.js' => 'leaflet.markercluster.js',
'leaflet.markercluster.js' => 'index_mappress.js',
- ];
+ ];
}
// Without clustering, still ensure leaflet loads before index_mappress
@@ -83,7 +88,8 @@
'enable_dependency' => true,
'dependency' => $dependency,
);
- }
+ return $tags;
+ }
return $tags;
}
--- a/mappress-google-maps-for-wordpress/mappress_db.php
+++ b/mappress-google-maps-for-wordpress/mappress_db.php
@@ -11,12 +11,14 @@
global $wpdb;
$maps_table = $wpdb->prefix . 'mapp_maps';
- $exists = $wpdb->get_var("show tables like '$maps_table'");
+ $exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $maps_table));
if ($exists)
return;
$wpdb->show_errors(true);
- $result = $wpdb->query("CREATE TABLE IF NOT EXISTS $maps_table (
+
+ $result = $wpdb->query($wpdb->prepare(
+ "CREATE TABLE IF NOT EXISTS %i (
mapid INT NOT NULL AUTO_INCREMENT,
otype VARCHAR(32),
oid INT,
@@ -26,8 +28,9 @@
INDEX title_idx (title(191)),
PRIMARY KEY (mapid),
UNIQUE KEY object_idx (otype, oid, mapid)
- ) CHARACTER SET utf8;"
- );
+ ) CHARACTER SET utf8;",
+ $maps_table
+ ));
$wpdb->show_errors(false);
return $result;
}
@@ -87,20 +90,25 @@
$posts_table = $wpdb->prefix . 'mappress_posts';
// Create new maps table
- $wpdb->query("DROP TABLE IF EXISTS $new_maps");
+ $wpdb->query($wpdb->prepare("DROP TABLE IF EXISTS %i", $new_maps));
$result = self::create_db();
if ($result === false)
return $wpdb->last_error();
// Populate
- $sql = "SELECT $posts_table.mapid, $posts_table.postid, $old_maps.obj "
- . " FROM $old_maps "
- . " INNER JOIN $posts_table ON ($posts_table.mapid = $old_maps.mapid)";
- $rows = $wpdb->get_results($sql);
-
+ $sql = $wpdb->prepare(
+ "SELECT %i.mapid, %i.postid, %i.obj
+ FROM %i
+ INNER JOIN %i ON (%i.mapid = %i.mapid)",
+ $posts_table, $posts_table, $old_maps,
+ $old_maps,
+ $posts_table, $posts_table, $old_maps
+ );
+ $rows = $wpdb->get_results($sql);
+
// Modify rows, can be rerun because most data is read from legacy posts table
foreach($rows as $row) {
- $mapdata = unserialize($row->obj);
+ $mapdata = unserialize($row->obj, array('allowed_classes' => array('Mappress_Map', 'Mappress_Poi'))); // Note only these classes expected
$mapdata->mapid = $row->mapid;
$mapdata->oid = $row->postid;
$mapdata->otype = 'post';
--- a/mappress-google-maps-for-wordpress/mappress_map.php
+++ b/mappress-google-maps-for-wordpress/mappress_map.php
@@ -114,7 +114,8 @@
add_action('deleted_post', array(__CLASS__, 'deleted_post'));
add_action('trashed_post', array(__CLASS__, 'trashed_post'));
- add_action('media_buttons', array(__CLASS__, 'media_buttons'));
+ if (current_user_can(Mappress::cap()))
+ add_action('media_buttons', array(__CLASS__, 'media_buttons'));
add_action('show_user_profile', array(__CLASS__, 'display_user_map'));
add_action('edit_user_profile', array(__CLASS__, 'display_user_map'));
@@ -160,9 +161,8 @@
static function ajax_get_post() {
global $post;
- check_ajax_referer('mappress', 'nonce');
ob_start();
- $oid = (isset($_GET['oid'])) ? $_GET['oid'] : null;
+ $oid = isset($_GET['oid']) ? absint($_GET['oid']) : 0;
$post = get_post( $oid );
@@ -486,9 +486,15 @@
}
static function media_buttons($editor_id) {
- $button = sprintf("<button type='button' class='button wp-media-buttons-icon mapp-classic-button'><span class='dashicons dashicons-location'></span>%s</button>", __('MapPress', 'mappress-google-maps-for-wordpress'));
- echo "<div class='mapp-classic'>$button</div>";
- }
+ ?>
+ <div class='mapp-classic'>
+ <button type='button' class='button mapp-classic-button'>
+ <span class='dashicons dashicons-location'></span>
+ <?php echo esc_html(__('MapPress', 'mappress-google-maps-for-wordpress')); ?>
+ </button>
+ </div>
+ <?php
+ }
static function mutate($mapid, $mapdata) {
if (!$mapid || !$mapdata)
@@ -571,7 +577,7 @@
if (!$this->mapid) {
$sql = "INSERT INTO $maps_table (otype, oid, status, title, obj) VALUES(%s, %d, %s, %s, %s)";
$result = $wpdb->query($wpdb->prepare($sql, $this->otype, $this->oid, $this->status, $this->title, $obj));
- $this->mapid = $wpdb->get_var("SELECT LAST_INSERT_ID()");
+ $this->mapid = $wpdb->insert_id;
} else {
$sql = "INSERT INTO $maps_table (mapid, otype, oid, status, title, obj) VALUES(%d, %s, %d, %s, %s, %s) "
. " ON DUPLICATE KEY UPDATE mapid=%d, otype=%s, oid=%d, status=%s, title=%s, obj=%s ";
--- a/mappress-google-maps-for-wordpress/mappress_settings.php
+++ b/mappress-google-maps-for-wordpress/mappress_settings.php
@@ -104,9 +104,6 @@
if (Mappress_Settings::iframes_required())
$options['iframes'] = true;
- if (isset($_REQUEST['mp_iframes']))
- $options['iframes'] = ($_REQUEST['mp_iframes']) ? true : false;
-
return new Mappress_Options($options);
}
@@ -141,7 +138,9 @@
if (!current_user_can('manage_options'))
Mappress::ajax_response('Not authorized');
- $args = json_decode(wp_unslash($_POST['data']));
+ $args = isset($_POST['data']) ? json_decode(wp_unslash($_POST['data'])) : null;
+ if (!$args) Mappress::ajax_response('Missing data');
+
$batch_size = $args->batch_size;
$otype = $args->otype;
$start = $args->start;
@@ -156,16 +155,19 @@
Mappress::ajax_response('OK', array('logs' => array(), 'errors' => array()));
// Get all meta keys for otype, as a quoted, comma-separated list to be used in sql
- $string_keys = array_map(function($key) { return "'$key'"; }, $keys);
- $string_keys = join(',', $string_keys);
- $meta_table = ($otype == 'post') ? $wpdb->postmeta : $wpdb->usermeta;
+ $keys = array_map(function($k) { return "'" . esc_sql($k) . "'"; }, $keys);
+ $string_keys = join(',', $keys);
+ $meta_table = ($otype == 'post') ? $wpdb->postmeta : $wpdb->usermeta;
+
// Read all objects with at least ONE of the mapped keys
$where = " WHERE meta_key IN ($string_keys)";
$limit = sprintf(" LIMIT %d, %d", $start, $batch_size);
if ($otype == 'post') {
- $where .= " AND $wpdb->posts.post_type IN ('" . implode("', '", Mappress::$options->postTypes) . "')";
+ $post_types = Mappress::$options->postTypes;
+ $placeholders = implode(',', array_fill(0, count($post_types), '%s'));
+ $where .= $wpdb->prepare(" AND $wpdb->posts.post_type IN ($placeholders) ", $post_types);
$sql = "SELECT DISTINCT post_id AS oid, post_title AS title FROM $wpdb->postmeta INNER JOIN $wpdb->posts ON $wpdb->postmeta.post_id = $wpdb->posts.ID $where $limit";
} else {
$sql = "SELECT DISTINCT user_id AS oid, user_nicename AS title FROM $wpdb->usermeta INNER JOIN $wpdb->users ON $wpdb->usermeta.user_id = $wpdb->users.ID $where $limit";
@@ -183,10 +185,11 @@
// Get errors only when finished
$errors = (count($logs) < $batch_size) ? self::get_geocoding_errors($otype) : array();
- // For testing, mp_geocode=10 will stop after 10 rows processed
- if (isset($_REQUEST['mp_geocode']) && $start > $_REQUEST['mp_geocode'])
- Mappress::ajax_response('OK', array('logs' => array(), 'errors' => $errors));
-
+ // For testing - mp_geocode=10 will stop after 10 rows processed
+ $mp_geocode_limit = isset($_REQUEST['mp_geocode']) ? absint($_REQUEST['mp_geocode']) : 0;
+ if ($mp_geocode_limit && $start > $mp_geocode_limit)
+ Mappress::ajax_response('OK', array('logs' => array(), 'errors' => $errors));
+
Mappress::ajax_response('OK', array('logs' => $logs, 'errors' => $errors));
}
@@ -195,14 +198,13 @@
if (!current_user_can('manage_options'))
Mappress::ajax_response('Not authorized');
-
- $args = json_decode(wp_unslash($_POST['data']));
- $license = $args->license;
- if (!$license)
- Mappress::ajax_response('Internal error, missing license!');
-
+
+ $args = isset($_POST['data']) ? json_decode(wp_unslash($_POST['data'])) : null;
+ if (!$args || !isset($args->license))
+ Mappress::ajax_response('Missing data');
+
ob_start();
- $status = Mappress::$updater->check($license);
+ $status = Mappress::$updater->check($args->license);
Mappress::ajax_response('OK', $status);
}
@@ -211,8 +213,8 @@
if (!current_user_can('manage_options'))
Mappress::ajax_response('Not authorized');
- $args = json_decode(wp_unslash($_POST['data']));
- if (!$args->id)
+ $args = isset($_POST['data']) ? json_decode(wp_unslash($_POST['data'])) : null;
+ if (!$args || !isset($args->id))
Mappress::ajax_response('Missing style ID');
$options = Mappress_Options::get();
@@ -233,13 +235,14 @@
$args = json_decode(wp_unslash($_POST['data']));
$style = $args->style;
- if (!$style)
- Mappress::ajax_response('Missing style');
+ if (!$style || !is_object($style))
+ Mappress::ajax_response('Missing style');
+
$options = Mappress_Options::get();
$setting = ($options->engine == 'google') ? 'stylesGoogle' : 'stylesMapbox';
// Update if style has an ID, otherwise treat it as new. New Snazzy styles have an ID, otherwise assign uniqid
- $id = ($style->id) ? $style->id : null;
+ $id = (isset($style->id) && $style->id) ? $style->id : null;
$i = ($id) ? array_search($id, array_column($options->$setting, 'id')) : false;
if ($i === false) {
@@ -258,14 +261,16 @@
if (!current_user_can('manage_options'))
Mappress::ajax_response('Not authorized');
- $args = json_decode(wp_unslash($_POST['data']));
- $settings = $args->settings;
+ $args = isset($_POST['data']) ? json_decode(wp_unslash($_POST['data'])) : null;
+ if (!$args || !isset($args->settings) || !is_object($args->settings))
+ Mappress::ajax_response('Missing settings');
+
$options = Mappress_Options::get();
- foreach($settings as $setting => $value)
+ foreach($args->settings as $setting => $value)
$options->$setting = $value;
$options->save();
Mappress::ajax_response('OK');
- }
+ }
// Save all the options
static function ajax_options_save() {
@@ -275,21 +280,26 @@
ob_start();
- // Receive arrays, not objects
- $args = json_decode(wp_unslash($_POST['data']), true);
+ // Receive arrays, not objects
+ $args = isset($_POST['data']) ? json_decode(wp_unslash($_POST['data']), true) : null;
+ if (!$args)
+ Mappress::ajax_response('Internal error, missing data!');
+
$settings = (object) $args['settings'];
-
if (!$settings)
Mappress::ajax_response('Internal error, missing settings!');
// Convert JS object arrays to PHP associative arrays
- self::assoc($settings->autoicons['values'], true);
- self::assoc($settings->metaKeys['post'], true);
- self::assoc($settings->metaKeys['user'], true);
+ if (isset($settings->autoicons['values']))
+ self::assoc($settings->autoicons['values'], true);
+ if (isset($settings->metaKeys['post']))
+ self::assoc($settings->metaKeys['post'], true);
+ if (isset($settings->metaKeys['user']))
+ self::assoc($settings->metaKeys['user'], true);
// If license changed, clear cache so it re-checks on next load
- if ($settings->license && $settings->license != Mappress::$options->license)
- Mappress::$updater->clear_cache();
+ if (isset($settings->license) && $settings->license && $settings->license != Mappress::$options->license)
+ Mappress::$updater->clear_cache();
// Update() converts strings to booleans, but it's not recursive, so explicitly convert nested booleans inside arrays
if (isset($settings->clusteringOptions['spiderfyOnMaxZoom']))
@@ -318,7 +328,8 @@
$options->update($settings);
// Default icon may be null, in which case update will have skipped it
- $options->defaultIcon = $settings->defaultIcon;
+ if (isset($settings->defaultIcon))
+ $options->defaultIcon = $settings->defaultIcon;
$options->save();
Mappress::ajax_response('OK');
@@ -334,11 +345,15 @@
if (!$user_id)
Mappress::ajax_response('No user ID');
- $data = json_decode(wp_unslash($_POST['data']));
+ $args = isset($_POST['data']) ? json_decode(wp_unslash($_POST['data'])) : null;
+ if (!$args || !isset($args->preferences))
+ Mappress::ajax_response('Missing data');
+
$user_prefs = get_user_meta($user_id, 'mappress_preferences', true);
$user_prefs = ($user_prefs) ? $user_prefs : (object) array();
- foreach($data->preferences as $pref => $value)
+ foreach($args->preferences as $pref => $value)
$user_prefs->$pref = $value;
+
update_user_meta($user_id, 'mappress_preferences', $user_prefs);
Mappress::ajax_response('OK');
}
@@ -579,8 +594,6 @@
return 'Jetpack infinite scroll';
if (Mappress::is_plugin_active('amp'))
return 'Google AMP';
- if (isset($_REQUEST['mp_iframes']))
- return 'Debugging';
}
static function options_page() {
@@ -620,7 +633,7 @@
$initial_state = array(
'apiKey' => $options->apiKey,
'engine' => $options->engine,
- 'isOpen' => (isset($_REQUEST['wizard']) && $_REQUEST['wizard']) ? true : false,
+ 'isOpen' => (current_user_can('manage_options') && !empty($_REQUEST['wizard'])) ? true : false,
'mapbox' => $options->mapbox,
);
?>
--- a/mappress-google-maps-for-wordpress/mappress_template.php
+++ b/mappress-google-maps-for-wordpress/mappress_template.php
@@ -55,40 +55,49 @@
static function ajax_delete() {
check_ajax_referer('mappress', 'nonce');
-
- if (!current_user_can('manage_options'))
- Mappress::ajax_response('Not authorized');
+ if (!current_user_can('manage_options')) Mappress::ajax_response('Not authorized');
$args = json_decode(wp_unslash($_POST['data']));
- $name = isset($args->name) ? sanitize_text_field($args->name) : '';
+ $name = isset($args->name) ? $args->name : '';
+ $filepath = self::get_ajax_filepath($name);
+
+ $result = @unlink($filepath);
+ if ($result === false) Mappress::ajax_response('Unable to delete');
+ Mappress::ajax_response('OK');
+ }
+
+ static function get_ajax_filepath($name) {
+ $name = sanitize_text_field((string) $name);
if ($name === '')
Mappress::ajax_response('Missing template name');
- $filepath = get_stylesheet_directory() . '/' . $name . '.php';
-
- $result = @unlink($filepath);
- if ($result === false)
- Mappress::ajax_response('Unable to delete');
+ if ($name !== basename($name))
+ Mappress::ajax_response('Invalid template name');
- Mappress::ajax_response('OK');
- }
+ $stylesheet_dir = realpath(get_stylesheet_directory());
+ $filepath = $stylesheet_dir . '/' . $name . '.php';
+ $resolved = realpath($filepath);
+
+ // If the file already exists, confirm it's still inside the stylesheet dir
+ if ($resolved !== false && strpos($resolved, $stylesheet_dir) !== 0)
+ Mappress::ajax_response('Path traversal blocked');
+
+ return $filepath;
+ }
static function ajax_get() {
check_ajax_referer('mappress', 'nonce');
if (!current_user_can('manage_options'))
- Mappress::ajax_response('Not authorized');
-
- // Get user template
- $name = isset($_GET['name']) ? sanitize_text_field(wp_unslash($_GET['name'])) : '';
- if ($name === '')
- Mappress::ajax_response('Missing template name');
+ Mappress::ajax_response('Not authorized');
- $filename = $name . '.php';
- $filepath = get_stylesheet_directory() . '/' . $filename;
+ $name = isset($_GET['name']) ? wp_unslash($_GET['name']) : '';
+ $filepath = self::get_ajax_filepath($name);
+ $name = sanitize_text_field($name); // for use below
+ $filename = $name . '.php';
- $html = (is_string($filepath) && $filepath !== '' && file_exists($filepath)) ? @file_get_contents($filepath) : null;
+ $html = (file_exists($filepath)) ? file_get_contents($filepath) : null;
// Get standard template
$basedir = realpath(Mappress::$basedir);
@@ -97,7 +106,7 @@
if (!$basedir || !$standard_file || strpos($standard_file, $basedir) !== 0)
Mappress::ajax_response('Invalid standard template path');
- $standard_html = @file_get_contents($standard_file);
+ $standard_html = file_get_contents($standard_file);
if (!$standard_html)
Mappress::ajax_response('Invalid standard template');
@@ -126,14 +135,10 @@
Mappress::ajax_response('Not authorized: DISALLOW_UNFILTERED_HTML is set in wp-config.php');
$args = json_decode(wp_unslash($_POST['data']));
- $name = isset($args->name) ? sanitize_text_field($args->name) : '';
+ $name = isset($args->name) ? $args->name : '';
$content = isset($args->content) ? $args->content : '';
- if ($name === '')
- Mappress::ajax_response('Missing template name');
-
- $filename = $name . '.php';
- $filepath = get_stylesheet_directory() . '/' . $filename;
+ $filepath = self::get_ajax_filepath($name);
$result = @file_put_contents($filepath, $content);
if ($result === false)
@@ -155,7 +160,7 @@
// If user template exists, check it's not empty (or all whitespace)
$html = null;
if ($template_file && file_exists($template_file)) {
- $html = @file_get_contents($template_file);
+ $html = file_get_contents($template_file);
if ($html !== false) {
$html = trim(str_replace(array("rn", "t"), array(), $html));
$html = ($html === '') ? null : $html;
@@ -193,7 +198,7 @@
$props[$token] = get_metadata($otype, $oid, $token, true);
return apply_filters('mappress_poi_props', $props, $oid, $poi, $otype);
}
-
+
static function get_custom_tokens($otype) {
$tokens = array();
$templates = ($otype == 'user') ? array('user-mashup-popup', 'user-mashup-item') : array('map-popup', 'map-item', 'mashup-item', 'mashup-popup');
@@ -236,7 +241,8 @@
$template = self::get_template($template_name);
if ($template) {
$template = str_replace('</script', '</script', $template); // Remove any script tags in the template itself
- echo "<script type='text/html' class='mapp-tmpl' id='mapp-tmpl-$template_name'>$template</script>";
+ $template_id = esc_attr("mapp-tmpl-$template_name");
+ echo "<script type='text/html' class='mapp-tmpl' id='$template_id'>$template</script>";
}
}