Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : July 26, 2026

CVE-2026-56064: Tourfic – AI Powered Travel Booking, Hotel Booking & Car Rental WordPress Plugin <= 2.22.5 Authenticated (Subscriber+) SQL Injection PoC, Patch Analysis & Rule

Plugin tourfic
Severity Medium (CVSS 6.5)
CWE 89
Vulnerable Version 2.22.5
Patched Version 2.22.6
Disclosed June 24, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-56064:

The Tourfic plugin versions 2.22.5 and earlier contain a SQL injection vulnerability in the REST API order retrieval endpoint. This flaw affects the TF_Booking_Rest_API.php file, where the tf_get_orders function directly interpolates user-provided parameters into SQL queries without proper sanitization or parameterization. Authenticated attackers with subscriber-level access can exploit this to execute arbitrary SQL commands and extract sensitive database information.

Root Cause:
The vulnerability stems from insufficient input validation and lack of prepared statements in the tf_get_orders and tf_get_enquiries functions within TF_Booking_Rest_API.php and TF_Enquiry_Rest_API.php. The diff shows the vulnerable code (before patch) in TF_Booking_Rest_API.php at lines 25-82, where parameters like ‘checkinout’, ‘post_id’, ‘order_status’, and ‘post_type’ are retrieved directly from the request and concatenated into the SQL query string without escaping. Specifically, lines such as `$tf_filter_query .= ” AND checkinout = ‘$checkinout'”;` and `$tf_filter_query .= ” AND post_id = ‘$post_id'”;` directly embed the raw parameter values. The final query is passed to Helper::tourfic_order_table_data(), which executes `$wpdb->prepare( “SELECT $query_select FROM {$wpdb->prefix}tf_order_data WHERE post_type = %s $query_where”, $query_type )`, but the `$query_where` is appended after the placeholder, meaning the injected SQL is not part of the prepared statement and remains executable.

Exploitation:
An authenticated attacker with subscriber-level access can send a GET request to the WordPress REST API endpoint `/wp-json/tf/v1/orders`. The request includes parameters like `post_type`, `checkinout`, `post_id`, or `order_status`. The attacker injects SQL in one of these parameters, for example: `checkinout=in’ UNION SELECT user_login,user_pass FROM wp_users– -`. Since the plugin does not validate the input against an allowlist (the diff adds such validation), the injected SQL string is concatenated directly into the query, allowing the attacker to retrieve user credentials or other sensitive data from the database. The attack requires authentication, but subscriber-level access is sufficient.

Patch Analysis:
The patch introduces strict validation for all parameters in the REST API endpoint. In TF_API_Routes.php, new ‘args’ arrays are added to the route registration for both `/orders` and `/enquiries`. Each parameter now has a ‘sanitize_callback’ (e.g., sanitize_key, absint) and a ‘validate_callback’ that checks the value against an allowlist of allowed strings (e.g., specific post types, checkinout statuses, order statuses). Additionally, in TF_Booking_Rest_API.php, the tf_get_orders function no longer uses string concatenation for building the WHERE clause. Instead, it constructs a structured $filters array and passes it as a ‘where’ key to Helper::tourfic_order_table_data(). The Helper class now includes a new method `tf_order_table_structured_sql()` that safely builds the WHERE clause by checking each column against an allowed list and using placeholders (`%d`, `%s`) for values. The user_id parameter has been removed, preventing privilege escalation via arbitrary user ID selection. The permission callback has been updated to `tf_order_permission_callback`, which likely enforces stricter role checks.

Impact:
Successful exploitation allows an authenticated attacker with subscriber-level access to execute arbitrary SQL commands against the WordPress database. This can lead to the extraction of sensitive data including user credentials (hashed passwords), email addresses, session tokens, and potentially any data stored in the database, such as private booking details, payment information, and admin-level data. In some cases, further exploitation could lead to privilege escalation if the attacker extracts admin credentials or manipulates user roles.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/tourfic/inc/Admin/TF_API_Documentation.php
+++ b/tourfic/inc/Admin/TF_API_Documentation.php
@@ -997,9 +997,8 @@
 				'url'         => '/orders',
 				'description' => __( 'Get booking orders list with optional filtering and calendar event data.', 'tourfic' ),
 				'parameters'  => array(
-					array( 'name' => 'user_id', 'type' => 'integer', 'required' => false, 'description' => __( 'Target user ID. Defaults to current user.', 'tourfic' ) ),
 					array( 'name' => 'checkinout', 'type' => 'string', 'required' => false, 'description' => __( 'Check-in status filter (in, out, not).', 'tourfic' ) ),
-					array( 'name' => 'post_type', 'type' => 'string', 'required' => false, 'description' => __( 'Booking type filter (tf_hotel, tf_tours, tf_apartment, tf_carrental).', 'tourfic' ) ),
+					array( 'name' => 'post_type', 'type' => 'string', 'required' => true, 'description' => __( 'Booking type filter (hotel, tour, apartment, car). CPT aliases are also accepted: tf_hotel, tf_tours, tf_apartment, tf_carrental.', 'tourfic' ) ),
 					array( 'name' => 'post_id', 'type' => 'integer', 'required' => false, 'description' => __( 'Filter bookings for a specific post ID.', 'tourfic' ) ),
 					array( 'name' => 'order_status', 'type' => 'string', 'required' => false, 'description' => __( 'Order status filter.', 'tourfic' ) ),
 				),
@@ -1048,8 +1047,7 @@
 				'url'         => '/enquiries',
 				'description' => __( 'Get enquiry list by user role context with optional filters.', 'tourfic' ),
 				'parameters'  => array(
-					array( 'name' => 'user_id', 'type' => 'integer', 'required' => false, 'description' => __( 'Target user ID. Defaults to current user.', 'tourfic' ) ),
-					array( 'name' => 'post_type', 'type' => 'string', 'required' => true, 'description' => __( 'Post type for enquiries (tf_hotel, tf_tours, tf_apartment, tf_carrental).', 'tourfic' ) ),
+					array( 'name' => 'post_type', 'type' => 'string', 'required' => true, 'description' => __( 'Post type for enquiries (tf_hotel, tf_tours, tf_apartment).', 'tourfic' ) ),
 					array( 'name' => 'post_id', 'type' => 'integer', 'required' => false, 'description' => __( 'Filter by specific post ID.', 'tourfic' ) ),
 					array( 'name' => 'filters', 'type' => 'string', 'required' => false, 'description' => __( 'Status filter (for example: replied, responded, not-replied, not-responded).', 'tourfic' ) ),
 				),
@@ -1279,4 +1277,4 @@
 		);
 	}

-}
 No newline at end of file
+}
--- a/tourfic/inc/App/Without_Payment/Hotel_Offline_Booking.php
+++ b/tourfic/inc/App/Without_Payment/Hotel_Offline_Booking.php
@@ -50,7 +50,18 @@
 		$check_out       = isset( $_POST['check_out_date'] ) ? sanitize_text_field( $_POST['check_out_date'] ) : '';
 		$deposit         = isset( $_POST['deposit'] ) ? sanitize_text_field( $_POST['deposit'] ) : false;
 		$airport_service = isset( $_POST['airport_service'] ) ? sanitize_text_field( $_POST['airport_service'] ) : '';
-		$extras = isset( $_POST['extras'] ) ? $_POST['extras'] : [];
+		$extras = isset( $_POST['extras'] ) ? wp_unslash( $_POST['extras'] ) : [];
+		$hotel_extra_quantities = isset( $_POST['hotel_extra_quantity'] ) ? Helper::tf_sanitize_extra_quantities( wp_unslash( $_POST['hotel_extra_quantity'] ) ) : [];
+
+		if ( is_string( $extras ) ) {
+			$extras = explode( ',', sanitize_text_field( $extras ) );
+		}
+
+		if ( is_array( $extras ) ) {
+			$extras = array_map( 'sanitize_text_field', $extras );
+		} else {
+			$extras = [];
+		}

 		$total_people    = $adult + $child;

@@ -98,6 +109,10 @@
 		if ( $avail_by_date ) {
 			$avail_date = ! empty( $room_meta['avail_date'] ) ? json_decode( $room_meta['avail_date'], true ) : [];
 		}
+		$use_explicit_availability_pricing = false;
+		if ( $avail_by_date && function_exists( 'is_tf_pro' ) && is_tf_pro() ) {
+			$use_explicit_availability_pricing = Availability::has_explicit_available_rules( $avail_date );
+		}
 		$room_name       = get_the_title( $room_id );
 		$pricing_by      = $room_meta['pricing-by'];
 		$price_multi_day = ! empty( $room_meta['price_multi_day'] ) ? $room_meta['price_multi_day'] : false;
@@ -125,8 +140,13 @@
 		if(function_exists( 'is_tf_pro' ) && is_tf_pro() && !empty($hotel_extra_option)){
 			$hotel_extras     = ! empty( $meta['hotel-extra'] ) ? Helper::tf_data_types($meta['hotel-extra']) : [];
 			foreach ( $extras as $key => $extra ) {
-				$extra_service = Helper::tf_hotel_extras_title_price( $post_id, $adult, $child, $extra );
-				$total_extras_title[] = $hotel_extras[$extra]['title'];
+				if ( empty( $hotel_extras[ $extra ] ) ) {
+					continue;
+				}
+				$extra_quantity = ! empty( $hotel_extra_quantities[ $key ] ) ? $hotel_extra_quantities[ $key ] : 1;
+				$extra_service = Helper::tf_hotel_extras_title_price( $post_id, $adult, $child, $extra, $extra_quantity );
+				$extra_price_type = ! empty( $hotel_extras[ $extra ]['price_type'] ) ? $hotel_extras[ $extra ]['price_type'] : 'fixed';
+				$total_extras_title[] = 'quantity' === $extra_price_type && ! empty( $extra_service['title'] ) ? $hotel_extras[$extra]['title'] . ' (' . wp_strip_all_tags( $extra_service['title'] ) . ')' : $hotel_extras[$extra]['title'];
 				$total_extras_price += $extra_service['price'];
 			}
 		}
@@ -315,7 +335,7 @@
 			/**
 			 * Calculate Pricing
 			 */
-			if ( $avail_by_date && function_exists( 'is_tf_pro' ) && is_tf_pro() ) {
+			if ( $use_explicit_availability_pricing ) {

 				// Check availability by date option
 				$period = new DatePeriod(
--- a/tourfic/inc/Classes/Enqueue.php
+++ b/tourfic/inc/Classes/Enqueue.php
@@ -269,9 +269,23 @@
 		/**
 		 * Google Map
 		 */
-		if ( 'googlemap' === $tf_openstreet_map ) {
+		$tf_should_enqueue_google_map = 'googlemap' === $tf_openstreet_map;
+		if ( is_singular( array( 'tf_hotel', 'tf_tours', 'tf_apartment', 'tf_carrental' ) ) ) {
+			$tf_should_enqueue_google_map = false;
+		}
+
+		if ( $tf_should_enqueue_google_map ) {
 			$tf_map_api_key = ! empty( Helper::tfopt( 'tf-googlemapapi' ) ) ? Helper::tfopt( 'tf-googlemapapi' ) : '';
-			wp_enqueue_script( 'googleapis', '//maps.googleapis.com/maps/api/js?key=' . $tf_map_api_key . '&sensor=false&libraries=places', array(), TOURFIC, true );
+			$tf_google_map_url = add_query_arg(
+				array(
+					'key'       => $tf_map_api_key,
+					'libraries' => 'places',
+					'loading'   => 'async',
+				),
+				'https://maps.googleapis.com/maps/api/js'
+			);
+
+			wp_enqueue_script( 'googleapis', $tf_google_map_url, array(), TOURFIC, true );
 			wp_enqueue_script( 'markerclusterer', TF_ASSETS_URL . 'app/libs/markerclusterer.min.js', array(), TOURFIC, true );
 			wp_enqueue_script('map-marker-label', TF_ASSETS_URL . 'app/libs/markerwithlabel.js', array(), TOURFIC, true);
 		}
@@ -357,6 +371,7 @@
 			$tf_tour_global_template    = ! empty( Helper::tf_data_types( Helper::tfopt( 'tf-template' ) )['single-tour'] ) ? Helper::tf_data_types( Helper::tfopt( 'tf-template' ) )['single-tour'] : 'design-1';
 			$tf_tour_selected_template  = ! empty( $tf_tour_single_template ) ? $tf_tour_single_template : $tf_tour_global_template;
 			$tour_type                  = ! empty( $meta['type'] ) ? $meta['type'] : '';
+			$pricing_rule               = ! empty( $meta['pricing'] ) ? $meta['pricing'] : '';
 			$tour_date_format_for_users = ! empty( Helper::tfopt( "tf-date-format-for-users" ) ) ? Helper::tfopt( "tf-date-format-for-users" ) : "Y/m/d";

 			$raw_tour_availability = $meta['tour_availability'] ?? '';
@@ -376,6 +391,7 @@

 			$single_tour_form_data['tf_tour_selected_template'] = $tf_tour_selected_template;
 			$single_tour_form_data['tour_type']                 = $tour_type;
+			$single_tour_form_data['pricing_rule']              = $pricing_rule;
 			$single_tour_form_data['first_day_of_week'] = !empty(Helper::tfopt("tf-week-day-flatpickr")) ? Helper::tfopt("tf-week-day-flatpickr") : 0;
 			$single_tour_form_data['select_time_text'] = esc_html__( "Select Time", "tourfic" );
 			$single_tour_form_data['date_format']      = esc_html( $tour_date_format_for_users );
@@ -485,6 +501,18 @@
 				'car_mobile_button_hide' => esc_html__( 'Hide', 'tourfic' ),
 				'car_mobile_button_book_now' => esc_html__( 'Book Now', 'tourfic' ),
 				'car_location_required_msg' => esc_html__( 'Select Pickup & Dropoff Location', 'tourfic' ),
+				'car_location_invalid_msg' => esc_html__(
+					'Please select supported Pick-up and Drop-off locations from the suggestions.',
+					'tourfic'
+				),
+				'car_pickup_location_invalid_msg' => esc_html__(
+					'Please select a supported Pick-up location from the suggestions.',
+					'tourfic'
+				),
+				'car_dropoff_location_invalid_msg' => esc_html__(
+					'Please select a supported Drop-off location from the suggestions.',
+					'tourfic'
+				),
 				'car_date_required_msg' => esc_html__( 'Select Pickup & Dropoff Date', 'tourfic' ),
 				'open_street_map_text' => esc_html__( 'OpenStreetMap', 'tourfic' ),
 				'required' => esc_html__( 'This field is required.', 'tourfic'),
--- a/tourfic/inc/Classes/Helper.php
+++ b/tourfic/inc/Classes/Helper.php
@@ -469,27 +469,40 @@
 	}


-    static function tf_hotel_extras_title_price( $post_id, $adult, $child, $key ) {
+	static function tf_hotel_extras_title_price( $post_id, $adult, $child, $key, $quantity = 1 ) {
 		$meta = get_post_meta( $post_id, 'tf_hotels_opt', true );
 		$hotel_extras     = ! empty( $meta['hotel-extra'] ) ? $meta['hotel-extra'] : '';

 		if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && ! empty( $hotel_extras[$key] ) ) {
 			if ( !empty($hotel_extras[$key]['price']) ) {
+				$extra_price = $hotel_extras[$key]['price'];
+				$extra_quantity = 0 < intval( $quantity ) ? intval( $quantity ) : 1;
+				$extra_price_type = ! empty( $hotel_extras[$key]['price_type'] ) ? $hotel_extras[$key]['price_type'] : 'fixed';

-				if ( "fixed" == $hotel_extras[$key]['price_type'] ) {
+				if ( "fixed" == $extra_price_type ) {
 					$airport_service_arr = array(
 						'title' => __( 'Fixed Price', 'tourfic' ),
-						'price' => $hotel_extras[$key]['price']
+						'price' => $extra_price
 					);
 				}
-				if ( "person" == $hotel_extras[$key]['price_type'] ) {
+				if ( "person" == $extra_price_type ) {
 					$airport_service_arr = array(
                         /* translators: %1$s: number of adult and %2$s: extra price */
 						'title' => sprintf( __( 'Adult ( %1$s × %2$s )', 'tourfic' ),
 							$adult,
-							wp_strip_all_tags( wc_price( $hotel_extras[$key]['price'] ) )
+							wp_strip_all_tags( wc_price( $extra_price ) )
 						),
-						'price' => $hotel_extras[$key]['price'] * (int) $adult
+						'price' => $extra_price * (int) $adult
+					);
+				}
+				if ( "quantity" == $extra_price_type ) {
+					$airport_service_arr = array(
+						/* translators: %1$s: extra quantity and %2$s: extra price */
+						'title' => sprintf( __( 'Quantity ( %1$s × %2$s )', 'tourfic' ),
+							$extra_quantity,
+							wp_strip_all_tags( wc_price( $extra_price ) )
+						),
+						'price' => $extra_price * $extra_quantity
 					);
 				}
 			}
@@ -497,6 +510,23 @@

 		return !empty( $airport_service_arr ) ? $airport_service_arr : array( 'title' => '', 'price' => 0 );
 	}
+
+	static function tf_sanitize_extra_quantities( $quantities ) {
+		if ( is_string( $quantities ) ) {
+			$quantities = explode( ',', sanitize_text_field( $quantities ) );
+		}
+
+		if ( ! is_array( $quantities ) ) {
+			return [];
+		}
+
+		return array_map(
+			function( $quantity ) {
+				return 0 < intval( $quantity ) ? intval( $quantity ) : 1;
+			},
+			$quantities
+		);
+	}

     /**
 	 * Template 3 Compatible to others Themes
@@ -1038,6 +1068,82 @@
 		return $template;
 	}

+	private static function tf_order_table_select_sql( $select ) {
+		$select          = '*' === trim( $select ) ? '*' : $select;
+		$allowed_columns = array(
+			'id',
+			'order_id',
+			'post_id',
+			'post_type',
+			'room_number',
+			'room_id',
+			'check_in',
+			'check_out',
+			'billing_details',
+			'shipping_details',
+			'order_details',
+			'customer_id',
+			'payment_method',
+			'ostatus',
+			'order_date',
+			'checkinout',
+			'checkinout_by',
+		);
+
+		if ( '*' === $select ) {
+			return '*';
+		}
+
+		$columns = array_map( 'trim', explode( ',', $select ) );
+		$columns = array_values( array_intersect( $columns, $allowed_columns ) );
+
+		return ! empty( $columns ) ? implode( ', ', $columns ) : '*';
+	}
+
+	private static function tf_order_table_structured_sql( $query, &$values ) {
+		$sql             = '';
+		$allowed_columns = array(
+			'order_id'    => '%d',
+			'post_id'     => '%d',
+			'customer_id' => '%d',
+			'room_id'     => '%s',
+			'ostatus'     => '%s',
+			'checkinout'  => '%s',
+		);
+
+		if ( ! empty( $query['where'] ) && is_array( $query['where'] ) ) {
+			foreach ( $query['where'] as $column => $value ) {
+				if ( ! isset( $allowed_columns[ $column ] ) || '' === $value || null === $value ) {
+					continue;
+				}
+
+				$sql     .= " AND {$column} = {$allowed_columns[ $column ]}";
+				$values[] = '%d' === $allowed_columns[ $column ] ? absint( $value ) : sanitize_text_field( $value );
+			}
+		}
+
+		if ( ! empty( $query['orderby'] ) ) {
+			$allowed_orderby = array( 'id', 'order_id', 'order_date', 'check_in', 'check_out' );
+			$orderby         = sanitize_key( $query['orderby'] );
+			if ( in_array( $orderby, $allowed_orderby, true ) ) {
+				$order = ! empty( $query['order'] ) && 'ASC' === strtoupper( $query['order'] ) ? 'ASC' : 'DESC';
+				$sql  .= " ORDER BY {$orderby} {$order}";
+			}
+		}
+
+		if ( ! empty( $query['limit'] ) && is_array( $query['limit'] ) ) {
+			$offset   = ! empty( $query['limit']['offset'] ) ? absint( $query['limit']['offset'] ) : 0;
+			$per_page = ! empty( $query['limit']['per_page'] ) ? absint( $query['limit']['per_page'] ) : 0;
+			if ( ! empty( $per_page ) ) {
+				$sql     .= ' LIMIT %d, %d';
+				$values[] = $offset;
+				$values[] = $per_page;
+			}
+		}
+
+		return $sql;
+	}
+
 	/*
      * Retrive Orders Data
      *
@@ -1048,10 +1154,14 @@
      */
 	static function tourfic_order_table_data( $query ) {
 		global $wpdb;
-		$query_type          = $query['post_type'];
-		$query_select        = $query['select'];
-		$query_where         = $query['query'];
-		$tf_tour_book_orders = $wpdb->get_results( $wpdb->prepare( "SELECT $query_select FROM {$wpdb->prefix}tf_order_data WHERE post_type = %s $query_where", $query_type ), ARRAY_A );
+		$query_type   = sanitize_key( $query['post_type'] );
+		$query_select = self::tf_order_table_select_sql( $query['select'] );
+		$values       = array( $query_type );
+		$query_where  = isset( $query['where'] ) && is_array( $query['where'] )
+			? self::tf_order_table_structured_sql( $query, $values )
+			: $query['query'];
+
+		$tf_tour_book_orders = $wpdb->get_results( $wpdb->prepare( "SELECT $query_select FROM {$wpdb->prefix}tf_order_data WHERE post_type = %s $query_where", $values ), ARRAY_A );

 		return $tf_tour_book_orders;
 	}
@@ -3877,7 +3987,7 @@
 		$has_deposit = ! empty( $room['allow_deposit'] ) && $room['allow_deposit'] == true;
 		if ( $has_deposit == true ) {
 			if ( $room['deposit_type'] == 'percent' ) {
-				$deposit_amount = $price * ( intval( $room['deposit_amount'] ) / 100 );
+				$deposit_amount = $price * ( floatval( $room['deposit_amount'] ) / 100 );
 			} else {
 				$deposit_amount = $room['deposit_amount'];
 			}
--- a/tourfic/inc/Classes/Hotel/Hotel.php
+++ b/tourfic/inc/Classes/Hotel/Hotel.php
@@ -392,7 +392,8 @@
         <tbody>
         <?php
         echo wp_kses_post( ob_get_clean() );
-        $error    = $rows = null;
+        $error    = esc_html__( 'No rooms available for the selected date.', 'tourfic' );
+        $rows     = null;
         $has_room = false;

         // generate table rows
@@ -2656,7 +2657,13 @@
 		// room
 		$room_selected = ! empty( $_GET['room'] ) ? absint( wp_unslash( $_GET['room'] ) ) : 1;
 		// Check-in & out date
-		$check_in_out = ! empty( $_GET['check-in-out-date'] ) ? sanitize_text_field( $_GET['check-in-out-date'] ) : '';
+		$check_in_out = ! empty( $_GET['check-in-out-date'] ) ? sanitize_text_field( wp_unslash( $_GET['check-in-out-date'] ) ) : '';
+		if ( empty( $check_in_out ) ) {
+			$hotel_current_timestamp = current_time( 'timestamp' );
+			$hotel_default_check_in  = wp_date( 'Y/m/d', $hotel_current_timestamp );
+			$hotel_default_check_out = wp_date( 'Y/m/d', strtotime( '+1 day', $hotel_current_timestamp ) );
+			$check_in_out            = $hotel_default_check_in . ' - ' . $hotel_default_check_out;
+		}
 		//get features
 		$features = ! empty( $_GET['features'] ) ? sanitize_text_field( $_GET['features'] ) : '';

@@ -3371,11 +3378,13 @@
 							<div class="tf-booking-content-service">
 								<?php foreach ( $hotel_extras as $key => $extra ) {
 									$extra_service = Helper::tf_hotel_extras_title_price( $post_id, $adult, $child, $key );
+									$hotel_extra_pricetype = ! empty( $extra['price_type'] ) ? $extra['price_type'] : 'fixed';
 									?>
 									<div class="tf-single-hotel-service tour-extra-single">
 										<label for="service-<?php echo esc_attr( $key ) . '_' . esc_attr($room_id); ?>">
 											<div class="tf-service-radio">
 												<input type="checkbox" value="<?php echo esc_attr( $key ); ?>" id="service-<?php echo esc_attr( $key) . '_' . esc_attr($room_id); ?>" name="extra_service">
+												<span class="tf-checkmark"></span>
 											</div>
 											<div class="tf-service-content">
 												<h5>
@@ -3384,6 +3393,20 @@
 												<p><?php echo esc_html($extra_service['title']); ?> = <?php echo wp_kses_post(wc_price( $extra_service['price'] )); ?></p>
 											</div>
 										</label>
+										<?php if ( "quantity" == $hotel_extra_pricetype ) : ?>
+											<div class="tf-field-group tf-mt-16 tf_quantity-acrselection">
+												<div class="tf-field quanity-acr-fields">
+													<div class="quanity-acr-label">
+														<?php echo esc_html__( "Select Quantity", "tourfic" ); ?>
+													</div>
+													<div class="quanity-acr-select tf-flex">
+														<div class="quanity-acr-dec">-</div>
+														<input type="number" name="extra-quantity" min="1" value="1">
+														<div class="quanity-acr-inc">+</div>
+													</div>
+												</div>
+											</div>
+										<?php endif; ?>
 									</div>
 								<?php } ?>
                             </div>
@@ -4160,7 +4183,7 @@
                             <div class="tf-section-title-and-location">
 								<!-- Title -->
 								<?php if( $show_title == 'yes' ): ?>
-                                <h2 class="tf-section-title"><a href="<?php echo esc_url( get_the_permalink() ); ?>"><?php echo esc_html( Helper::tourfic_character_limit_callback( get_the_title(), $title_length ) ); ?></a></h2>
+                                <h2 class="tf-section-title"><a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( Helper::tourfic_character_limit_callback( get_the_title(), $title_length ) ); ?></a></h2>
 								<?php endif; ?>

 								<!-- Location -->
--- a/tourfic/inc/Classes/REST_API/TF_API_Routes.php
+++ b/tourfic/inc/Classes/REST_API/TF_API_Routes.php
@@ -147,13 +147,40 @@
 		register_rest_route( 'tf/v1', '/orders', array(
 			'methods'             => 'GET',
 			'callback'            => array( $api, 'tf_get_orders' ),
-			'permission_callback' => array( $api, 'tf_permission_callback' ),
+			'permission_callback' => array( $api, 'tf_order_permission_callback' ),
+			'args'                => array(
+				'post_type'    => array(
+					'required'          => true,
+					'sanitize_callback' => 'sanitize_key',
+					'validate_callback' => function( $value ) {
+						return in_array( $value, array( 'hotel', 'tf_hotel', 'tour', 'tf_tours', 'apartment', 'tf_apartment', 'car', 'tf_carrental' ), true );
+					},
+				),
+				'post_id'      => array(
+					'sanitize_callback' => 'absint',
+					'validate_callback' => function( $value ) {
+						return '' === $value || null === $value || ( is_numeric( $value ) && absint( $value ) > 0 );
+					},
+				),
+				'checkinout'   => array(
+					'sanitize_callback' => 'sanitize_key',
+					'validate_callback' => function( $value ) {
+						return '' === $value || null === $value || in_array( $value, array( 'in', 'out', 'not' ), true );
+					},
+				),
+				'order_status' => array(
+					'sanitize_callback' => 'sanitize_key',
+					'validate_callback' => function( $value ) {
+						return '' === $value || null === $value || in_array( $value, array( 'pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed', 'trash' ), true );
+					},
+				),
+			),
 		) );

 		register_rest_route( 'tf/v1', '/order/(?P<id>\d+)', array(
 			'methods'             => 'GET',
 			'callback'            => array( $api, 'tf_get_order_details' ),
-			'permission_callback' => array( $api, 'tf_permission_callback' ),
+			'permission_callback' => array( $api, 'tf_order_permission_callback' ),
 		) );
 	}

@@ -163,13 +190,34 @@
 		register_rest_route( 'tf/v1', '/enquiries', array(
 			'methods'             => 'GET',
 			'callback'            => array( $api, 'tf_get_enquiries' ),
-			'permission_callback' => array( $api, 'tf_permission_callback' ),
+			'permission_callback' => array( $api, 'tf_enquiry_permission_callback' ),
+			'args'                => array(
+				'post_type' => array(
+					'required'          => true,
+					'sanitize_callback' => 'sanitize_key',
+					'validate_callback' => function( $value ) {
+						return in_array( $value, array( 'tf_hotel', 'tf_tours', 'tf_apartment' ), true );
+					},
+				),
+				'post_id'   => array(
+					'sanitize_callback' => 'absint',
+					'validate_callback' => function( $value ) {
+						return '' === $value || null === $value || ( is_numeric( $value ) && absint( $value ) > 0 );
+					},
+				),
+				'filters'   => array(
+					'sanitize_callback' => 'sanitize_key',
+					'validate_callback' => function( $value ) {
+						return '' === $value || null === $value || in_array( $value, array( 'read', 'unread', 'replied', 'responded', 'not-replied', 'not-responded' ), true );
+					},
+				),
+			),
 		) );

 		register_rest_route( 'tf/v1', '/enquiries/(?P<id>\d+)', array(
 			'methods'             => 'GET',
 			'callback'            => array( $api, 'tf_get_enquiry_details' ),
-			'permission_callback' => array( $api, 'tf_permission_callback' ),
+			'permission_callback' => array( $api, 'tf_enquiry_permission_callback' ),
 		) );
 	}

@@ -185,7 +233,7 @@
 		register_rest_route( 'tf/v1', '/user/(?P<id>\d+)', array(
 			'methods'             => 'GET',
 			'callback'            => array( $api, 'tf_get_user' ),
-			'permission_callback' => array( $api, 'tf_permission_callback' ),
+			'permission_callback' => array( $api, 'tf_user_permission_callback' ),
 		) );

 		register_rest_route( 'tf/v1', '/user-bookings', array(
--- a/tourfic/inc/Classes/REST_API/TF_Booking_Rest_API.php
+++ b/tourfic/inc/Classes/REST_API/TF_Booking_Rest_API.php
@@ -25,43 +25,57 @@
 		 * @author Foysal
 		 */
 		public function tf_get_orders( $request ) {
-			$current_user_id = $request->get_param( 'user_id' ) ? $request->get_param( 'user_id' ) : get_current_user_id();
-			$checkinout = $request->get_param( 'checkinout' ) ? $request->get_param( 'checkinout' ) : '';
-			$post_type = $request->get_param( 'post_type' ) ? $request->get_param( 'post_type' ) : '';
-			$post_id = $request->get_param( 'post_id' ) ? $request->get_param( 'post_id' ) : '';
-			$order_status = $request->get_param( 'order_status' ) ? $request->get_param( 'order_status' ) : '';
-
-            $tf_filter_query = "";
-            if ( $checkinout ) {
-                $tf_filter_query .= " AND checkinout = '$checkinout'";
-            }
-            if ( $post_id ) {
-                $tf_filter_query .= " AND post_id = '$post_id'";
-            }
-            if ( $order_status ) {
-                $tf_filter_query .= " AND ostatus = '$order_status'";
-            }
-			if ( $this->user_has_role( $current_user_id, 'administrator' ) || $this->user_has_role( $current_user_id, 'tf_manager' ) ) {
+			$current_user_id = get_current_user_id();
+			$post_type       = $this->tf_validate_allowed_param( $request, 'post_type', $this->tf_order_post_types(), true );
+			$post_id         = $this->tf_get_rest_absint_param( $request, 'post_id' );
+			$checkinout      = $this->tf_validate_allowed_param( $request, 'checkinout', $this->tf_checkinout_statuses() );
+			$order_status    = $this->tf_validate_allowed_param( $request, 'order_status', $this->tf_order_statuses() );
+
+			foreach ( array( $post_type, $post_id, $checkinout, $order_status ) as $validation_error ) {
+				if ( is_wp_error( $validation_error ) ) {
+					return $validation_error;
+				}
+			}
+			$post_type = $this->tf_normalize_order_post_type( $post_type );
+
+			$filters = array();
+			if ( ! empty( $checkinout ) ) {
+				$filters['checkinout'] = $checkinout;
+			}
+			if ( ! empty( $post_id ) ) {
+				$filters['post_id'] = $post_id;
+			}
+			if ( ! empty( $order_status ) ) {
+				$filters['ostatus'] = $order_status;
+			}
+
+			$orders_result = array();
+			if ( $this->tf_current_user_can_manage_records() ) {

 				$tf_orders_select = array(
 					'select'    => "*",
 					'post_type' => $post_type,
-					'query'     => " $tf_filter_query ORDER BY order_date DESC"
+					'where'     => $filters,
+					'orderby'   => 'order_date',
+					'order'     => 'DESC'
 				);

 				$orders_result = Helper::tourfic_order_table_data( $tf_orders_select );
-			}
-			if ( $this->user_has_role( $current_user_id, 'tf_vendor' ) ) {
+			} elseif ( $this->user_has_role( $current_user_id, 'tf_vendor' ) ) {

 				$tf_orders_select = array(
 					'select'    => "*",
 					'post_type' => $post_type,
 					'author'    => $current_user_id,
-                    'query'     => " $tf_filter_query ORDER BY order_date DESC",
+					'where'     => $filters,
+					'orderby'   => 'order_date',
+					'order'     => 'DESC',
 					'limit'     => ""
 				);

 				$orders_result = tourfic_vendor_order_table_data( $tf_orders_select );
+			} else {
+				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this endpoint.', 'tourfic' ), array( 'status' => 403 ) );
 			}
             $events = array();
 			$orders_data = array();
@@ -150,8 +164,15 @@
 		 */
 		public function tf_get_order_details( $request ) {
 			global $wpdb;
-			$id    = $request->get_param( 'id' );
+			$id    = absint( $request->get_param( 'id' ) );
 			$order = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_order_data WHERE id = %d", $id ), ARRAY_A );
+			if ( empty( $order ) ) {
+				return new WP_Error( 'tf_order_not_found', esc_html__( 'Order not found.', 'tourfic' ), array( 'status' => 404 ) );
+			}
+			if ( ! $this->tf_current_user_can_access_order( $order ) ) {
+				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this order.', 'tourfic' ), array( 'status' => 403 ) );
+			}
+
 			$order_details = json_decode( $order['order_details'] );

             //post title
@@ -162,11 +183,11 @@
             //order date
             if ( ! empty( $order['order_date'] ) ) {
 				$order['order_detail']['order_date'] = esc_html(gmdate('F d, Y',strtotime($order['order_date'])));
-			}
+            }

             //booked by
-            $tf_booking_by = get_user_by('id', $order->customer_id);
-            if("offline"==$order->payment_method && empty($tf_booking_by)){
+            $tf_booking_by = get_user_by('id', $order['customer_id']);
+            if("offline"==$order['payment_method'] && empty($tf_booking_by)){
                 $order['order_detail']['booked_by'] = "Administrator";
             }else{
                 $order['order_detail']['booked_by'] = !empty($tf_booking_by->roles[0]) ? esc_html($tf_booking_by->roles[0]) : 'Administrator';
@@ -260,6 +281,9 @@

             //total person
             $total_person = 0;
+			$adult_count  = array();
+			$child_count  = array();
+			$infant_count = array();
             if(!empty($order_details->adult)){
                 $adult_count = explode( " × ", $order_details->adult );
                 $total_person += $adult_count[0] ? $adult_count[0] : 0;
@@ -272,9 +296,9 @@
                 $infant_count = explode( " × ", $order_details->infants );
                 $total_person += $infant_count[0] ? $infant_count[0] : 0;
             }
-            $order['adult_count'] = $adult_count[0] ? $adult_count[0] : '';
-            $order['child_count'] = $child_count[0] ? $child_count[0] : '';
-            $order['infant_count'] = $infant_count[0] ? $infant_count[0] : '';
+            $order['adult_count'] = ! empty( $adult_count[0] ) ? $adult_count[0] : '';
+            $order['child_count'] = ! empty( $child_count[0] ) ? $child_count[0] : '';
+            $order['infant_count'] = ! empty( $infant_count[0] ) ? $infant_count[0] : '';
             $order['total_person'] = $total_person;

 			return $order;
@@ -282,4 +306,4 @@
 	}
 }

-TF_Booking_Rest_API::get_instance();
 No newline at end of file
+TF_Booking_Rest_API::get_instance();
--- a/tourfic/inc/Classes/REST_API/TF_Enquiry_Rest_API.php
+++ b/tourfic/inc/Classes/REST_API/TF_Enquiry_Rest_API.php
@@ -25,30 +25,47 @@
 		 * @author Foysal
 		 */
 		public function tf_get_enquiries( $request ) {
-			$current_user_id = $request->get_param( 'user_id' ) ? $request->get_param( 'user_id' ) : get_current_user_id();
-			$post_type = $request->get_param( 'post_type' ) ? $request->get_param( 'post_type' ) : '';
-			$post_id = $request->get_param( 'post_id' ) ? $request->get_param( 'post_id' ) : '';
-			$filters = $request->get_param( 'filters' ) ? $request->get_param( 'filters' ) : '';
-
-            $tf_filter_query = "";
-            if ( $post_id ) {
-                $tf_filter_query .= " AND post_id = '$post_id'";
-            }
-			if( !empty($filters) ) {
-				if( $filters == 'not-replied') {
-					$tf_filter_query .= sprintf(' AND enquiry_status != "%s"', 'replied' );
-				} elseif( $filters == 'not-responded') {
-					$tf_filter_query .= sprintf(' AND enquiry_status != "%s"', 'responded' );
-				} else {
-					$tf_filter_query .= sprintf(' AND enquiry_status = "%s"', $filters );
+			$current_user_id = get_current_user_id();
+			$post_type       = $this->tf_validate_allowed_param( $request, 'post_type', $this->tf_enquiry_post_types(), true );
+			$post_id         = $this->tf_get_rest_absint_param( $request, 'post_id' );
+			$filters         = $this->tf_validate_allowed_param( $request, 'filters', $this->tf_enquiry_status_filters() );
+
+			foreach ( array( $post_type, $post_id, $filters ) as $validation_error ) {
+				if ( is_wp_error( $validation_error ) ) {
+					return $validation_error;
 				}
 			}

 			global $wpdb;
-			if ( $this->user_has_role( $current_user_id, 'administrator' ) || $this->user_has_role( $current_user_id, 'tf_manager' ) ) {
-				$hotel_enquiry_result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE post_type = %s {$tf_filter_query} ORDER BY id DESC", $post_type ), ARRAY_A );
+			$where  = array( 'post_type = %s' );
+			$values = array( $post_type );
+
+			if ( ! empty( $post_id ) ) {
+				$where[]  = 'post_id = %d';
+				$values[] = $post_id;
+			}
+
+			if ( ! empty( $filters ) ) {
+				if ( 'not-replied' === $filters ) {
+					$where[]  = 'enquiry_status != %s';
+					$values[] = 'replied';
+				} elseif ( 'not-responded' === $filters ) {
+					$where[]  = 'enquiry_status != %s';
+					$values[] = 'responded';
+				} else {
+					$where[]  = 'enquiry_status = %s';
+					$values[] = $filters;
+				}
+			}
+
+			if ( $this->tf_current_user_can_manage_records() ) {
+				$hotel_enquiry_result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE " . implode( ' AND ', $where ) . " ORDER BY id DESC", $values ), ARRAY_A );
 			} elseif ( $this->user_has_role( $current_user_id, 'tf_vendor' ) ) {
-				$hotel_enquiry_result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE post_type = %s {$tf_filter_query} AND author_id = %d ORDER BY id DESC", $post_type, $current_user_id ), ARRAY_A );
+				$where[]  = 'author_id = %d';
+				$values[] = $current_user_id;
+				$hotel_enquiry_result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE " . implode( ' AND ', $where ) . " ORDER BY id DESC", $values ), ARRAY_A );
+			} else {
+				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this endpoint.', 'tourfic' ), array( 'status' => 403 ) );
 			}

 			$enquirys_data = array();
@@ -68,8 +85,15 @@
          */
         public function tf_get_enquiry_details( $request ){
             global $wpdb;
-			$id    = $request->get_param( 'id' );
+			$id    = absint( $request->get_param( 'id' ) );
 			$enquiry = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE id = %d", $id ), ARRAY_A );
+			if ( empty( $enquiry ) ) {
+				return new WP_Error( 'tf_enquiry_not_found', esc_html__( 'Enquiry not found.', 'tourfic' ), array( 'status' => 404 ) );
+			}
+			if ( ! $this->tf_current_user_can_access_enquiry( $enquiry ) ) {
+				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this enquiry.', 'tourfic' ), array( 'status' => 403 ) );
+			}
+
 			$reply_data = !empty( $enquiry["reply_data"] ) ? json_decode($enquiry["reply_data"], true) : array();

 			if(class_exists('TourficCoreEnquiry')){
@@ -102,4 +126,4 @@
 	}
 }

-TF_Enquiry_Rest_API::get_instance();
 No newline at end of file
+TF_Enquiry_Rest_API::get_instance();
--- a/tourfic/inc/Classes/REST_API/TF_Rest_API.php
+++ b/tourfic/inc/Classes/REST_API/TF_Rest_API.php
@@ -59,6 +59,9 @@
 				return false;
 			}
 			$user_meta  = get_userdata( $user_id );
+			if ( empty( $user_meta ) || empty( $user_meta->roles ) ) {
+				return false;
+			}
 			$user_roles = $user_meta->roles;

 			return in_array( $role_name, $user_roles );
@@ -110,13 +113,208 @@
 		 */
 		public function tf_admin_permission_callback( WP_REST_Request $request ) {
 			$current_user_id = get_current_user_id();
-			if ( is_user_logged_in() && $this->user_has_role( $current_user_id, 'administrator' ) || $this->user_has_role( $current_user_id, 'tf_manager' ) ) {
+			if ( is_user_logged_in() && ( $this->user_has_role( $current_user_id, 'administrator' ) || $this->user_has_role( $current_user_id, 'tf_manager' ) ) ) {
 				return true;
 			} else {
 				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this endpoint.' ), array( 'status' => 403 ) );
 			}
 		}

+		public function tf_user_permission_callback( WP_REST_Request $request ) {
+			if ( ! is_user_logged_in() ) {
+				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this endpoint.', 'tourfic' ), array( 'status' => 403 ) );
+			}
+
+			if ( $this->tf_current_user_can_access_user( $request->get_param( 'id' ) ) ) {
+				return true;
+			}
+
+			return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this user.', 'tourfic' ), array( 'status' => 403 ) );
+		}
+
+		public function tf_order_permission_callback( WP_REST_Request $request ) {
+			return $this->tf_admin_vendor_permission_callback();
+		}
+
+		public function tf_enquiry_permission_callback( WP_REST_Request $request ) {
+			return $this->tf_admin_vendor_permission_callback();
+		}
+
+		protected function tf_admin_vendor_permission_callback() {
+			$current_user_id = get_current_user_id();
+
+			if (
+				is_user_logged_in()
+				&& (
+					$this->user_has_role( $current_user_id, 'administrator' )
+					|| $this->user_has_role( $current_user_id, 'tf_manager' )
+					|| $this->user_has_role( $current_user_id, 'tf_vendor' )
+				)
+			) {
+				return true;
+			}
+
+			return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this endpoint.', 'tourfic' ), array( 'status' => 403 ) );
+		}
+
+		protected function tf_current_user_can_manage_records() {
+			$current_user_id = get_current_user_id();
+
+			return $this->user_has_role( $current_user_id, 'administrator' ) || $this->user_has_role( $current_user_id, 'tf_manager' );
+		}
+
+		protected function tf_current_user_can_access_user( $user_id ) {
+			$user_id         = absint( $user_id );
+			$current_user_id = get_current_user_id();
+
+			if ( empty( $user_id ) || empty( $current_user_id ) ) {
+				return false;
+			}
+
+			if ( $user_id === $current_user_id ) {
+				return true;
+			}
+
+			return $this->tf_current_user_can_manage_records()
+				|| current_user_can( 'list_users' )
+				|| current_user_can( 'edit_user', $user_id );
+		}
+
+		protected function tf_current_user_can_manage_vendor_record( $post_id = 0, $author_id = 0 ) {
+			$current_user_id = get_current_user_id();
+
+			if ( ! $this->user_has_role( $current_user_id, 'tf_vendor' ) ) {
+				return false;
+			}
+
+			if ( ! empty( $author_id ) && absint( $author_id ) === $current_user_id ) {
+				return true;
+			}
+
+			return ! empty( $post_id ) && absint( get_post_field( 'post_author', absint( $post_id ) ) ) === $current_user_id;
+		}
+
+		protected function tf_current_user_can_access_order( $order ) {
+			if ( $this->tf_current_user_can_manage_records() ) {
+				return true;
+			}
+
+			return ! empty( $order['post_id'] ) && $this->tf_current_user_can_manage_vendor_record( $order['post_id'] );
+		}
+
+		protected function tf_current_user_can_access_enquiry( $enquiry ) {
+			if ( $this->tf_current_user_can_manage_records() ) {
+				return true;
+			}
+
+			$post_id   = ! empty( $enquiry['post_id'] ) ? $enquiry['post_id'] : 0;
+			$author_id = ! empty( $enquiry['author_id'] ) ? $enquiry['author_id'] : 0;
+
+			return $this->tf_current_user_can_manage_vendor_record( $post_id, $author_id );
+		}
+
+		protected function tf_order_post_types() {
+			return array_keys( $this->tf_order_post_type_map() );
+		}
+
+		protected function tf_order_post_type_map() {
+			return array(
+				'hotel'        => 'hotel',
+				'tf_hotel'     => 'hotel',
+				'tour'         => 'tour',
+				'tf_tours'     => 'tour',
+				'apartment'    => 'apartment',
+				'tf_apartment' => 'apartment',
+				'car'          => 'car',
+				'tf_carrental' => 'car',
+			);
+		}
+
+		protected function tf_normalize_order_post_type( $post_type ) {
+			$post_type = sanitize_key( $post_type );
+			$post_map  = $this->tf_order_post_type_map();
+
+			return ! empty( $post_map[ $post_type ] ) ? $post_map[ $post_type ] : $post_type;
+		}
+
+		protected function tf_enquiry_post_types() {
+			return array( 'tf_hotel', 'tf_tours', 'tf_apartment' );
+		}
+
+		protected function tf_checkinout_statuses() {
+			return array( 'in', 'out', 'not' );
+		}
+
+		protected function tf_order_statuses() {
+			return array( 'pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed', 'trash' );
+		}
+
+		protected function tf_enquiry_status_filters() {
+			return array( 'read', 'unread', 'replied', 'responded', 'not-replied', 'not-responded' );
+		}
+
+		protected function tf_validate_allowed_param( WP_REST_Request $request, $param, $allowed, $required = false ) {
+			$value = $request->get_param( $param );
+
+			if ( '' === $value || null === $value ) {
+				if ( $required ) {
+					return new WP_Error(
+						'tf_rest_invalid_param',
+						sprintf( esc_html__( '%s is required.', 'tourfic' ), esc_html( $param ) ),
+						array( 'status' => 400 )
+					);
+				}
+
+				return '';
+			}
+
+			if ( ! is_scalar( $value ) ) {
+				return new WP_Error(
+					'tf_rest_invalid_param',
+					sprintf( esc_html__( 'Invalid %s value.', 'tourfic' ), esc_html( $param ) ),
+					array( 'status' => 400 )
+				);
+			}
+
+			$value = sanitize_key( $value );
+			if ( ! in_array( $value, $allowed, true ) ) {
+				return new WP_Error(
+					'tf_rest_invalid_param',
+					sprintf( esc_html__( 'Invalid %s value.', 'tourfic' ), esc_html( $param ) ),
+					array( 'status' => 400 )
+				);
+			}
+
+			return $value;
+		}
+
+		protected function tf_get_rest_absint_param( WP_REST_Request $request, $param ) {
+			$value = $request->get_param( $param );
+
+			if ( '' === $value || null === $value ) {
+				return 0;
+			}
+
+			if ( ! is_scalar( $value ) || ! is_numeric( $value ) ) {
+				return new WP_Error(
+					'tf_rest_invalid_param',
+					sprintf( esc_html__( 'Invalid %s value.', 'tourfic' ), esc_html( $param ) ),
+					array( 'status' => 400 )
+				);
+			}
+
+			$value = absint( $value );
+			if ( empty( $value ) ) {
+				return new WP_Error(
+					'tf_rest_invalid_param',
+					sprintf( esc_html__( 'Invalid %s value.', 'tourfic' ), esc_html( $param ) ),
+					array( 'status' => 400 )
+				);
+			}
+
+			return $value;
+		}
+

 		static function convert_to_wp_timezone($date_string, $format = 'Y-m-d H:i:s') {
 			$timezone = wp_timezone();
@@ -168,4 +366,4 @@
 	}
 }

-TF_Rest_API::get_instance();
 No newline at end of file
+TF_Rest_API::get_instance();
--- a/tourfic/inc/Classes/REST_API/TF_User_Rest_API.php
+++ b/tourfic/inc/Classes/REST_API/TF_User_Rest_API.php
@@ -93,6 +93,10 @@
 				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this endpoint.' ), array( 'status' => 403 ) );
 			}

+			if ( ! $this->tf_current_user_can_access_user( $user->ID ) ) {
+				return new WP_Error( 'rest_forbidden', esc_html__( 'You are not authorized to access this user.', 'tourfic' ), array( 'status' => 403 ) );
+			}
+
 			$user_data = array(
 				'id'                 => $user->ID,
 				'username'           => $user->user_login,
@@ -173,9 +177,14 @@
 		 * @auther Foysal
 		 */
 		public function tf_user_bookings( $request ) {
-			$current_user_id = $request->get_param( 'user_id' ) ? $request->get_param( 'user_id' ) : get_current_user_id();
-			$booking_type    = $request->get_param( 'booking_type' ) ? $request->get_param( 'booking_type' ) : 'all';
+			$current_user_id = get_current_user_id();
+			$booking_type    = $request->get_param( 'booking_type' ) ? sanitize_key( $request->get_param( 'booking_type' ) ) : 'all';
 			$disable_services = ! empty( Helper::tfopt( 'disable-services' ) ) ? Helper::tfopt( 'disable-services' ) : [];
+			$user_hotel_orders_result = array();
+
+			if ( ! in_array( $booking_type, array( 'all', 'hotel', 'tour', 'apartment', 'car' ), true ) ) {
+				return new WP_Error( 'tf_rest_invalid_param', esc_html__( 'Invalid booking_type value.', 'tourfic' ), array( 'status' => 400 ) );
+			}

 			if ( $this->user_has_role( $current_user_id, 'customer' ) ) {

@@ -239,7 +248,7 @@
 		 * @auther Foysal
 		 */
 		public function tf_user_wishlist( $request ) {
-			$current_user_id = $request->get_param( 'user_id' ) ? $request->get_param( 'user_id' ) : get_current_user_id();
+			$current_user_id = get_current_user_id();
 			$remove          = $request->get_param( 'remove' ) ? $request->get_param( 'remove' ) : false;
 			$postId          = $request->get_param( 'post_id' ) ? $request->get_param( 'post_id' ) : '';
 			$wishlist_data = array();
--- a/tourfic/inc/Classes/Tour/Tour.php
+++ b/tourfic/inc/Classes/Tour/Tour.php
@@ -1059,7 +1059,7 @@
                         <input type='text' name='check-in-out-date' id='check-in-out-date' class='tf-field tours-check-in-out' onkeypress="return false;" placeholder='<?php esc_html_e( "Select Date", "tourfic" ); ?>'
                                value='' required/>
                     </div>
-					<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' ) { ?>
+					<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && 'package' !== $pricing_rule ) { ?>
                         <div class="tf-field-group check-in-time-div tf-mt-8" id="" style="display: none;">
                             <i class="fa-regular fa-clock"></i>
                             <select class="tf-field" name="check-in-time" id="" style="min-width: 100px;"></select>
@@ -1225,7 +1225,7 @@
                                 <input type="text" class="tf-field tours-check-in-out" placeholder="<?php esc_html_e( "Select Date", "tourfic" ); ?>" value="" required/>
                             </div>

-							<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' ) { ?>
+							<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && 'package' !== $pricing_rule ) { ?>
                                 <div class="tf-bottom-booking-field check-in-time-div" id="" style="display: none;">
                                     <div class="tf-bottom-booking-field-icon">
                                         <i class="ri-time-line"></i>
@@ -1266,7 +1266,7 @@
                         <input type='text' name='check-in-out-date' id='check-in-out-date' class='tf-field tours-check-in-out' onkeypress="return false;" placeholder='<?php esc_html_e( "Select Date", "tourfic" ); ?>'
                                value='' required/>
                     </div>
-					<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed') { ?>
+					<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && 'package' !== $pricing_rule ) { ?>
                         <div class="tf-field-group check-in-time-div tf-mt-8 tf-field-calander" id="" style="display: none;">
                             <i class="fa-regular fa-clock"></i>
                             <select class="tf-field" name="check-in-time" id="" style="min-width: 100px;"></select>
@@ -1454,7 +1454,7 @@
                                 <input type="text" class="tf-field tours-check-in-out" placeholder="<?php esc_html_e( "Select Date", "tourfic" ); ?>" value="" required/>

                             </div>
-							<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && !empty($allowed_times)) { ?>
+							<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && 'package' !== $pricing_rule && !empty($allowed_times)) { ?>
                                 <div class="tf-bottom-booking-field check-in-time-div" id="" style="display: none;">
                                     <select class="tf-field" name="check-in-time" id=""></select>
                                 </div>
@@ -1623,7 +1623,7 @@
                                 <input type="text" class="tf-field tours-check-in-out" placeholder="<?php esc_html_e( "Select Date", "tourfic" ); ?>" value="" required/>

                             </div>
-							<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && !empty($allowed_times)) { ?>
+							<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && 'package' !== $pricing_rule && !empty($allowed_times)) { ?>
                                 <div class="tf-bottom-booking-field check-in-time-div" id="" style="display: none;">
                                     <select class="tf-field" name="check-in-time" id=""></select>
                                 </div>
@@ -1850,7 +1850,7 @@
                             </label>
                         </div>

-						<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' ) { ?>
+						<?php if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && $tour_type != 'fixed' && 'package' !== $pricing_rule ) { ?>
                             <div class='tf_form-row check-in-time-div' id="" style="display: none;">
                                 <label class='tf_label-row'>
                                     <div class='tf_form-inner'>
@@ -1998,12 +1998,14 @@
 								$tour_extras          = unserialize( $tour_extras_unserial );

 							}
-							$traveller_info_coll_global = function_exists( 'is_tf_pro' ) && is_tf_pro() && ! empty( Helper::tfopt( 'disable_traveller_info' ) ) ? Helper::tfopt( 'disable_traveller_info' ) : '';
-
-							$traveller_info_coll = function_exists( 'is_tf_pro' ) && is_tf_pro() && ! empty( $meta['tour-traveler-info'] ) ? $meta['tour-traveler-info'] : $traveller_info_coll_global;
+							$traveller_info_coll = function_exists( 'tf_tour_is_traveler_info_enabled' ) ? tf_tour_is_traveler_info_enabled( $meta ) : false;
 							$tf_booking_by = ! empty( $meta['booking-by'] ) ? $meta['booking-by'] : 1;
 							$pricing_type = function_exists( 'is_tf_pro' ) && is_tf_pro() && ! empty( $meta['pricing'] ) ? $meta['pricing'] : '';
 							$package_pricing = function_exists( 'is_tf_pro' ) && is_tf_pro() && ! empty( $meta['package_pricing'] ) ? $meta['package_pricing'] : '';
+							$booking_info_step = ! empty( $traveller_info_coll ) ? 4 : 3;
+							if ( empty( $traveller_info_coll ) && $pricing_type == 'package' && $package_pricing && empty( $tour_extras ) ) {
+								$booking_info_step = 2;
+							}
 							$active_steps = [];
 							if( ($pricing_type!='package' || empty($package_pricing)) && empty( $tour_extras ) && empty( $traveller_info_coll ) && 3 != $tf_booking_by ){ ?>
 								<li class="tf-booking-step tf-booking-step-1 active">
@@ -2033,9 +2035,9 @@
 							<?php }
 							$tf_booking_by = ! empty( $meta['booking-by'] ) ? $meta['booking-by'] : 1;
 							if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && 3 == $tf_booking_by ) {
-								$active_steps[4] = 4;
+								$active_steps[ $booking_info_step ] = $booking_info_step;
 								?>
-                                <li class="tf-booking-step tf-booking-step-<?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( "3" ) : esc_attr( "4" ); ?> <?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( 'active' ) : ''; ?>">
+                                <li class="tf-booking-step tf-booking-step-<?php echo esc_attr( $booking_info_step ); ?> <?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( 'active' ) : ''; ?>">
                                     <i class="ri-calendar-check-line"></i> <?php echo esc_html__( "Booking info", "tourfic" ); ?>
                                 </li>
 							<?php } ?>
@@ -2241,7 +2243,7 @@
 						?>

                         <!-- Popup Booking Confirmation -->
-                        <div class="tf-booking-content tf-booking-content-<?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( "3" ) : esc_attr( "4" ); ?> <?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( 'show' ) : ''; ?>">
+                        <div class="tf-booking-content tf-booking-content-<?php echo esc_attr( $booking_info_step ); ?> <?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( 'show' ) : ''; ?>">
                             <p><?php echo esc_html( $traveler_details_text ); ?></p>
                             <div class="tf-booking-content-traveller">
                                 <div class="tf-single-tour-traveller">
@@ -2453,10 +2455,10 @@
 					if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && 3 == $tf_booking_by ) {
 						?>
                         <!-- Popup Booking Confirmation -->
-                        <div class="tf-control-pagination tf-pagination-content-<?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( "3" ) : esc_attr( "4" ); ?> <?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( 'show' ) : ''; ?>">
+                        <div class="tf-control-pagination tf-pagination-content-<?php echo esc_attr( $booking_info_step ); ?> <?php echo ($pricing_type!='package' || empty( $package_pricing )) && empty( $tour_extras ) && empty( $traveller_info_coll ) ? esc_attr( 'show' ) : ''; ?>">
 							<?php
-							if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && ( $tour_extras || $traveller_info_coll ) ) { ?>
-                                <a href="#" class="tf-back-control tf-step-back" data-step="4"><i class="fa fa-angle-left"></i><?php echo esc_html__( "Back", "tourfic" ); ?></a>
+							if ( function_exists( 'is_tf_pro' ) && is_tf_pro() && ( $tour_extras || $traveller_info_coll || ( $pricing_type == 'package' && $package_pricing ) ) ) { ?>
+                                <a href="#" class="tf-back-control tf-step-back" data-step="<?php echo esc_attr( $booking_info_step ); ?>"><i class="fa fa-angle-left"></i><?php echo esc_html__( "Back", "tourfic" ); ?></a>
 							<?php } ?>
                             <button type="submit" class="tf-book-confirm-error tf_btn"><?php echo esc_html__( "Continue", "tourfic" ); ?></button>
                         </div>
@@ -4127,7 +4129,7 @@
 		// Tour date
 		$tour_date = ! empty( $_POST['check_in_date'] ) ? sanitize_text_field( $_POST['check_in_date'] ) : '';
 		$tour_time = isset( $_POST['check_in_time'] ) ? sanitize_text_field( $_POST['check_in_time'] ) : null;
-		$selectedPackage = ! empty( $_POST['selectedPackage'] ) ? sanitize_text_field( wp_unslash( $_POST['selectedPackage'] ) ) : '';
+		$selectedPackage = isset( $_POST['selectedPackage'] ) ? sanitize_text_field( wp_unslash( $_POST['selectedPackage'] ) ) : '';
 		// var_dump($tour_time);

 		$post_id              = isset( $_POST['post_id'] ) ? intval( sanitize_text_field( $_POST['post_id'] ) ) : '';
@@ -4138,6 +4140,8 @@
 		$disable_child_price  = ! empty( $meta['disable_child_price'] ) ? $meta['disable_child_price'] : false;
 		$disable_infant_price = ! empty( $meta['disable_infant_price'] ) ? $meta['disable_infant_price'] : false;
 		$tf_package_pricing = ! empty( $meta['package_pricing'] ) ? $meta['package_pricing'] : '';
+		$default_min_people  = ! empty( $meta['min_person'] ) ? absint( $meta['min_person'] ) : 0;
+		$default_max_people  = ! empty( $meta['max_person'] ) ? absint( $meta['max_person'] ) : 0;

 		/**
 		 * If fixed is selected but pro is not activated
@@ -4210,8 +4214,8 @@

 			$start_date            = ! empty( $matched_availability['check_in'] ) ? $matched_availability['check_in'] : '';
 			$end_date              = ! empty( $matched_availability['check_out'] ) ? $matched_availability['check_out'] : '';
-			$min_people            = ! empty( $matched_availability['min_person'] ) ? $matched_availability['min_person'] : '';
-			$max_people            = ! empty( $matched_availability['max_person'] ) ? $matched_availability['max_person'] : '';
+			$min_people            = ! empty( $matched_availability['min_person'] ) ? $matched_availability['min_person'] : $default_min_people;
+			$max_people            = ! empty( $matched_availability['max_person'] ) ? $matched_availability['max_person'] : $default_max_people;
 			$tf_tour_booking_limit = ! empty( $matched_availability['max_capacity'] ) ? $matched_availability['max_capacity'] : 0;
 			// Fixed tour maximum capacity limit

@@ -4267,8 +4271,8 @@

 			// $pricing_rule = ! empty( $matched_availability['pricing_type'] ) ? $matched_availability['pricing_type'] : '';

-			$min_people = ! empty( $matched_availability['min_person'] ) ? $matched_availability['min_person'] : '';
-			$max_people = ! empty( $matched_availability['max_person'] ) ? $matched_availability['max_person'] : '';
+			$min_people = ! empty( $matched_availability['min_person'] ) ? $matched_availability['min_person'] : $default_min_people;
+			$max_people = ! empty( $matched_availability['max_person'] ) ? $matched_availability['max_person'] : $default_max_people;
 			$allowed_times_field = ! empty( $matched_availability['allowed_time'] ) ? $matched_availability['allowed_time'] : [''];


@@ -4422,8 +4426,8 @@
 			// frontend selected date value
 			$front_date = strtotime( str_replace( '/', '-', $tour_date ) );
 			// Backend continuous min/max people values
-			$min_people = ! empty( $matched_availability['min_person'] ) ? $matched_availability['min_person'] : '';
-			$max_people = ! empty( $matched_availability['max_person'] ) ? $matched_availability['max_person'] : '';
+			$min_people = ! empty( $matched_availability['min_person'] ) ? $matched_availability['min_person'] : $default_min_people;
+			$max_people = ! empty( $matched_availability['max_person'] ) ? $matched_availability['max_person'] : $default_max_people;
 			/* translators: %s: minimum number of people */
 			$min_text = sprintf( _n( '%s person', '%s people', $min_people, 'tourfic' ), $min_people );
 			/* translators: %s: maximum number of people */
@@ -4794,7 +4798,8 @@

 			}

-			$traveller_info_fields = ! empty( Helper::tfopt( 'without-payment-field' ) ) ? Helper::tf_data_types( Helper::tfopt( 'without-payment-field' ) ) : '';
+			$traveller_info_coll   = function_exists( 'tf_tour_is_traveler_info_enabled' ) ? tf_tour_is_traveler_info_enabled( $meta ) : false;
+			$traveller_info_fields = ! empty( $traveller_info_coll ) && ! empty( Helper::tfopt( 'without-payment-field' ) ) ? Helper::tf_data_types( Helper::tfopt( 'without-payment-field' ) ) : '';

 			$response['traveller_info']    = '';
 			$response['traveller_summery'] = '';
@@ -4928,10 +4933,10 @@

 			$passenger_type_map = function_exists( 'tf_tour_get_passenger_type_map' ) ? tf_tour_get_passenger_type_map( $adults, $children, $infant ) : array();

-			if ( 'single' === $traveler_info_collection_mode ) {
+			if ( ! empty( $traveller_info_coll ) && 'single' === $traveler_info_collection_mode ) {
 				$single_passenger_type = ! empty( $passenger_type_map[1] ) ? $passenger_type_map[1] : 'adult';
 				$response['traveller_info'] .= $render_traveller_block( 1, esc_html__( 'Traveler Information', 'tourfic' ), $single_passenger_type, esc_html__( 'Traveler', 'tourfic' ) );
-			} else {
+			} elseif ( ! empty( $traveller_info_coll ) ) {
 				$traveller_groups   = array(
 					'adult'  => array(
 						'title' => esc_html__( 'Adults', 'tourfic' ),
--- a/tourfic/inc/Core/Enquiry.php
+++ b/tourfic/inc/Core/Enquiry.php
@@ -717,25 +717,35 @@
 		 global $wpdb;
 		 $enquiry_data = array();

-		$tf_filter_query = "";
+		$where  = array( 'post_type = %s' );
+		$values = array( sanitize_key( $post_type ) );
+
 		if ( $post_id ) {
-			$tf_filter_query .= " AND post_id = '$post_id'";
+			$where[]  = 'post_id = %d';
+			$values[] = absint( $post_id );
 		}
 		if( !empty($status) ) {
+			$status = sanitize_key( $status );
 			if( $status == 'not-replied') {
-				$tf_filter_query .= sprintf(' AND enquiry_status != "%s"', 'replied' );
+				$where[]  = 'enquiry_status != %s';
+				$values[] = 'replied';
 			} elseif( $status == 'not-responded') {
-				$tf_filter_query .= sprintf(' AND enquiry_status != "%s"', 'responded' );
+				$where[]  = 'enquiry_status != %s';
+				$values[] = 'responded';
 			} else {
-				$tf_filter_query .= sprintf(' AND enquiry_status = "%s"', $status );
+				$where[]  = 'enquiry_status = %s';
+				$values[] = $status;
 			}
 		}

+		$query_limit = '';
 		if( !empty( $offset ) && !empty( $per_page ) ) {
-			$tf_filter_query .= sprintf(' LIMIT %d, %d', $offset, $per_page);
+			$query_limit = ' LIMIT %d, %d';
+			$values[]    = absint( $offset );
+			$values[]    = absint( $per_page );
 		}

-		$results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE post_type = %s {$tf_filter_query} ORDER BY id DESC", $post_type ), ARRAY_A );
+		$results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tf_enquiry_data WHERE " . implode( ' AND ', $where ) . " ORDER BY id DESC{$query_limit}", $values ), ARRAY_A );

 		if( !empty($results) ) {
 			foreach( $results as $result ) {
@@ -1270,4 +1280,4 @@
         }
     }

-}
 No newline at end of file
+}
--- a/tourfic/

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.