--- a/open-user-map/inc/Base/BaseController.php
+++ b/open-user-map/inc/Base/BaseController.php
@@ -1185,6 +1185,18 @@
$this->safe_log( "No webhook URL configured for Post ID: {$post_id}" );
return;
}
+ // Get first image URL if available
+ $first_image_url = '';
+ $image_value = oum_get_location_value( 'image', $post_id, true );
+ if ( !empty( $image_value ) ) {
+ // Extract first image from pipe-separated string
+ $images = explode( '|', $image_value );
+ if ( !empty( $images[0] ) ) {
+ $first_image = trim( $images[0] );
+ // Convert relative path to absolute URL if needed
+ $first_image_url = ( strpos( $first_image, 'http' ) !== 0 ? site_url() . $first_image : $first_image );
+ }
+ }
// Prepare webhook payload
$webhook_data = array(
'post_id' => $post_id,
@@ -1197,6 +1209,7 @@
'fields' => 'names',
) ),
'meta_data' => $data_meta ?? get_post_meta( $post_id, '_oum_location_key', true ),
+ 'image_url' => $first_image_url,
'event' => $event_type,
'timestamp' => current_time( 'mysql' ),
);
--- a/open-user-map/inc/Base/TaxController.php
+++ b/open-user-map/inc/Base/TaxController.php
@@ -226,7 +226,8 @@
public static function set_custom_region_columns( $columns ) {
// preserve default columns
- $name = $columns['name'];
+ // Check if 'name' key exists before accessing to prevent undefined array key warning
+ $name = ( isset( $columns['name'] ) ? $columns['name'] : '' );
unset($columns['description'], $columns['slug'], $columns['posts']);
$columns['name'] = $name;
$columns['geocoordinates'] = __( 'Coordinates', 'open-user-map' );
--- a/open-user-map/inc/Pages/Settings.php
+++ b/open-user-map/inc/Pages/Settings.php
@@ -660,6 +660,10 @@
if ( isset( $_POST['action'] ) && $_POST['action'] == 'oum_csv_import' ) {
// Initialize error handling
$error = new WP_Error();
+ // Security: Check user capabilities - only administrators can import CSV
+ if ( !current_user_can( 'manage_options' ) ) {
+ $error->add( '003', 'Insufficient permissions. Only administrators can import CSV files.' );
+ }
// Dont save without nonce
if ( !isset( $_POST['oum_location_nonce'] ) ) {
$error->add( '002', 'Not allowed' );
@@ -673,22 +677,61 @@
if ( !isset( $_POST['url'] ) ) {
$error->add( '001', 'File upload failed.' );
}
- // TODO: Exit if no CSV filetype
if ( $error->has_errors() ) {
// Return errors
wp_send_json_error( $error );
} else {
- // IMPORT
- $path_1 = wp_get_upload_dir()['basedir'];
- $path_2 = explode( '/uploads/', $_POST['url'] )['1'];
+ // Security: Sanitize and validate the file path to prevent path traversal attacks
+ $upload_url = sanitize_text_field( $_POST['url'] );
+ // Get uploads directory information
+ $upload_dir = wp_get_upload_dir();
+ $upload_basedir = $upload_dir['basedir'];
+ $upload_baseurl = $upload_dir['baseurl'];
+ // Verify that the URL is within the uploads directory
+ if ( strpos( $upload_url, $upload_baseurl ) !== 0 ) {
+ $error->add( '004', 'Invalid file path. File must be within the uploads directory.' );
+ wp_send_json_error( $error );
+ return;
+ }
+ // Extract the relative path from the uploads directory
+ $relative_path = str_replace( $upload_baseurl, '', $upload_url );
+ // Remove leading slash if present
+ $relative_path = ltrim( $relative_path, '/' );
+ // Security: Prevent path traversal attacks by removing any '../' sequences
+ $relative_path = str_replace( '..', '', $relative_path );
// Handle paths for both single and multisite installations
if ( is_multisite() ) {
- // For multisite, remove the duplicate sites/[blog_id] from path_2
+ // For multisite, remove the duplicate sites/[blog_id] from path
// as it's already included in wp_get_upload_dir()['basedir']
$blog_id = get_current_blog_id();
- $path_2 = preg_replace( "#^sites/{$blog_id}/#", '', $path_2 );
+ $relative_path = preg_replace( "#^sites/{$blog_id}/#", '', $relative_path );
+ }
+ // Construct the full file path
+ $csv_file = $upload_basedir . '/' . $relative_path;
+ // Security: Resolve the real path and verify it's still within uploads directory
+ $real_csv_file = realpath( $csv_file );
+ $real_upload_basedir = realpath( $upload_basedir );
+ // Verify file exists and is readable
+ if ( $real_csv_file === false || !is_readable( $real_csv_file ) ) {
+ $error->add( '005', 'File not found or not readable.' );
+ wp_send_json_error( $error );
+ return;
+ }
+ // Security: Ensure the resolved path is within the uploads directory (prevents path traversal)
+ if ( $real_upload_basedir === false || strpos( $real_csv_file, $real_upload_basedir ) !== 0 ) {
+ $error->add( '006', 'Invalid file path. File must be within the uploads directory.' );
+ wp_send_json_error( $error );
+ return;
+ }
+ // Security: Verify file extension is .csv
+ $file_extension = strtolower( pathinfo( $real_csv_file, PATHINFO_EXTENSION ) );
+ if ( $file_extension !== 'csv' ) {
+ $error->add( '007', 'Invalid file type. Only CSV files are allowed.' );
+ wp_send_json_error( $error );
+ return;
}
- $csv_file = $path_1 . '/' . $path_2;
+ // Use the resolved real path for file operations
+ $csv_file = $real_csv_file;
$delimiter = $this->detectDelimiter( $csv_file );
// parse csv file to array
$file_to_read = fopen( $csv_file, 'r' );
--- a/open-user-map/open-user-map.php
+++ b/open-user-map/open-user-map.php
@@ -8,7 +8,7 @@
Plugin URI: https://wordpress.org/plugins/open-user-map/
Description: Engage your visitors with an interactive map – let them add markers instantly or create a custom map showcasing your favorite spots.
Author: 100plugins
-Version: 1.4.16
+Version: 1.4.17
Author URI: https://www.open-user-map.com/
License: GPLv3 or later
Text Domain: open-user-map
--- a/open-user-map/templates/page-backend-settings.php
+++ b/open-user-map/templates/page-backend-settings.php
@@ -844,7 +844,7 @@
<script type="text/javascript" data-category="functional" class="cmplz-native" id="oum-inline-js">
const lat = '<?php
- echo ( esc_attr( $start_lat ) ? esc_attr( $start_lat ) : '28' );
+ echo ( esc_attr( $start_lat ) ? esc_attr( $start_lat ) : '26' );
?>';
const lng = '<?php
echo ( esc_attr( $start_lng ) ? esc_attr( $start_lng ) : '0' );
--- a/open-user-map/templates/partial-map-init.php
+++ b/open-user-map/templates/partial-map-init.php
@@ -635,7 +635,7 @@
$start_lat = get_term_meta( $oum_start_region->term_id, 'oum_lat', true );
$start_lng = get_term_meta( $oum_start_region->term_id, 'oum_lng', true );
$start_zoom = get_term_meta( $oum_start_region->term_id, 'oum_zoom', true );
-} elseif ( get_option( 'oum_start_lat' ) && get_option( 'oum_start_lng' ) && get_option( 'oum_start_zoom' ) ) {
+} elseif ( get_option( 'oum_start_lat' ) !== false && get_option( 'oum_start_lat' ) !== '' && (get_option( 'oum_start_lng' ) !== false && get_option( 'oum_start_lng' ) !== '') && (get_option( 'oum_start_zoom' ) !== false && get_option( 'oum_start_zoom' ) !== '') ) {
//get from settings
$oum_use_settings_start_location = 'true';
$start_lat = get_option( 'oum_start_lat' );
@@ -645,10 +645,10 @@
//get from single location
$start_lat = $locations_list[0]['lat'];
$start_lng = $locations_list[0]['lng'];
- $start_zoom = '8';
+ $start_zoom = $locations_list[0]['zoom'];
} else {
//default worldview
- $start_lat = '28';
+ $start_lat = '26';
$start_lng = '0';
$start_zoom = '1';
}