Changeset 3480942
- Timestamp:
- 03/12/2026 08:42:24 AM (3 weeks ago)
- Location:
- hostel/trunk
- Files:
-
- 13 edited
-
controllers/bookings.php (modified) (8 diffs)
-
controllers/help.php (modified) (1 diff)
-
controllers/rooms.php (modified) (1 diff)
-
controllers/shortcodes.php (modified) (2 diffs)
-
controllers/sync.php (modified) (2 diffs)
-
hostel.php (modified) (1 diff)
-
models/booking.php (modified) (2 diffs)
-
models/room.php (modified) (1 diff)
-
views/booking-form.html.php (modified) (1 diff)
-
views/booking.html.php (modified) (1 diff)
-
views/bookings.html.php (modified) (1 diff)
-
views/email-log.html.php (modified) (1 diff)
-
views/options.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
hostel/trunk/controllers/bookings.php
r3478265 r3480942 7 7 switch($_GET['do'] ?? null) { 8 8 case 'add': 9 if(!empty($_POST['ok']) ) {9 if(!empty($_POST['ok']) and check_admin_referer('wphostel_booking')) { 10 10 $_POST['from_date'] = $_POST['fromyear'].'-'.$_POST['frommonth'].'-'.$_POST['fromday']; 11 11 $_POST['to_date'] = $_POST['toyear'].'-'.$_POST['tomonth'].'-'.$_POST['today']; … … 61 61 // @codingStandardsIgnoreLine WordPress.DB.DirectDatabaseQuery.NoCaching 62 62 $booking = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".WPHOSTEL_BOOKINGS." WHERE id=%d", (int)$_GET['id'])); 63 // @codingStandardsIgnoreLine WordPress.DB.DirectDatabaseQuery.DirectQuery 64 // @codingStandardsIgnoreLine WordPress.DB.DirectDatabaseQuery.NoCaching 65 $room = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".WPHOSTEL_ROOMS." WHERE id=%d", $booking['room_id'])); 63 64 if (empty($booking)) { 65 wp_die('Booking not found'); 66 } 67 68 // @codingStandardsIgnoreLine WordPress.DB.DirectDatabaseQuery.DirectQuery 69 // @codingStandardsIgnoreLine WordPress.DB.DirectDatabaseQuery.NoCaching 70 $room = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".WPHOSTEL_ROOMS." WHERE id=%d", (int)$booking->room_id)); 66 71 67 72 if(@file_exists(get_stylesheet_directory().'/wphostel/view-booking.html.php')) include get_stylesheet_directory().'/wphostel/view-booking.html.php'; … … 75 80 $type = empty($_GET['type']) ? 'upcoming' : sanitize_text_field($_GET['type']); 76 81 $offset = empty($_GET['offset']) ? 0 : intval($_GET['offset']); 77 $dir = empty($_GET['dir']) ? 'ASC' : $_GET['dir'];78 if($dir != 'ASC' and$dir != 'DESC') $dir = 'ASC';82 $dir = empty($_GET['dir']) ? 'ASC' : strtoupper(sanitize_text_field($_GET['dir'])); 83 if($dir != 'ASC' && $dir != 'DESC') $dir = 'ASC'; 79 84 $odir = ($dir == 'ASC') ? 'DESC' : 'ASC'; 80 85 81 86 // mark booking as fully paid 82 87 if(!empty($_GET['mark_paid'])) { 88 if (!isset($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], 'mark_paid')) { 89 wp_die('Security check failed'); 90 } 83 91 $_booking->mark_paid($_GET['id']); 84 92 … … 90 98 } 91 99 92 // define $where_sql and orderby depending on the $type 93 $curdate = date("Y-m-d", current_time('timestamp')); 100 // define $where_sql and orderby depending on the $type 101 $curdate = date("Y-m-d", current_time('timestamp')); 94 102 if($type == 'upcoming') { 95 103 $where_sql = "AND from_date >= '$curdate' "; 96 104 $orderby = "ORDER BY from_date"; 97 105 98 106 } 99 107 else { … … 101 109 $orderby = "ORDER BY from_date DESC"; 102 110 } 103 111 104 112 // define limit (as it's paginated) 105 113 $page_limit = 20; … … 107 115 108 116 // search filter 117 $filters = array(); 109 118 if(!empty($_GET['contact_email'])) { 110 $_GET['contact_email'] = sanitize_text_field($_GET['contact_email']); 111 $where_sql .= " AND contact_email LIKE '%".$_GET['contact_email']."%' "; 119 $contact_email = sanitize_text_field($_GET['contact_email']); 120 $where_sql .= $wpdb->prepare(" AND contact_email LIKE %s ", '%' . $wpdb->esc_like($contact_email) . '%'); 121 $filters[] = 'contact_email=' . urlencode($contact_email); 112 122 } 113 123 if(!empty($_GET['contact_name'])) { 114 $_GET['contact_name'] = sanitize_text_field($_GET['contact_name']); 115 $where_sql .= " AND contact_name LIKE '%".$_GET['contact_name']."%' "; 124 $contact_name = sanitize_text_field($_GET['contact_name']); 125 $where_sql .= $wpdb->prepare(" AND contact_name LIKE %s ", '%' . $wpdb->esc_like($contact_name) . '%'); 126 $filters[] = 'contact_name=' . urlencode($contact_name); 116 127 } 117 128 if(!empty($_GET['room_id'])) { 118 129 $_GET['room_id'] = intval($_GET['room_id']); 119 130 $where_sql .= $wpdb->prepare(" AND room_id = %d ", $_GET['room_id']); 131 $filters[] = 'room_id=' . $_GET['room_id']; 120 132 } 121 133 if(!empty($_GET['status'])) { 122 134 $_GET['status'] = sanitize_text_field($_GET['status']); 123 135 $where_sql .= $wpdb->prepare(" AND status = %s ", $_GET['status']); 124 } 136 $filters[] = 'status=' . urlencode($_GET['status']); 137 } 125 138 if(!empty($_GET['booking_id'])) { 126 139 $_GET['booking_id'] = intval($_GET['booking_id']); 127 140 $where_sql .= $wpdb->prepare(" AND tB.id = %d ", $_GET['booking_id']); 128 } 129 if(!empty($_GET['contact_email']) or !empty($_GET['contact_name']) 130 or !empty($_GET['room_id']) or !empty($_GET['status']) or !empty($_GET['booking_id'])) $filters_apply = true; 131 141 $filters[] = 'booking_id=' . $_GET['booking_id']; 142 } 143 if(!empty($_GET['contact_email']) or !empty($_GET['contact_name']) 144 or !empty($_GET['room_id']) or !empty($_GET['status']) or !empty($_GET['booking_id'])) $filters_apply = true; 145 132 146 if(!empty($_GET['ob'])) { 133 147 $ob = sanitize_text_field($_GET['ob']); … … 136 150 } 137 151 $orderby = "ORDER BY $ob $dir"; 138 } 152 $filters[] = 'ob=' . urlencode($ob); 153 } 154 155 // Build filters string for pagination links 156 $filters_str = !empty($filters) ? '&' . implode('&', $filters) : ''; 139 157 140 158 // select bookings - direct query necessary for custom plugin table … … 267 285 static function book() { 268 286 global $wpdb, $post; 287 288 // Verify nonce for CSRF protection 289 if (!isset($_POST['wphostel_nonce']) || !wp_verify_nonce($_POST['wphostel_nonce'], 'wphostel_booking')) { 290 return '<!--BOOKERROR-->' . __('Security check failed. Please refresh the page and try again.', 'wphostel'); 291 } 269 292 270 293 // insert booking details -
hostel/trunk/controllers/help.php
r3478265 r3480942 8 8 static function email_log() { 9 9 global $wpdb; 10 $date = empty($_POST['date']) ? date('Y-m-d') : $_POST['date'];11 if(!empty($_POST['cleanup']) ) update_option('hostelpro_cleanup_email_log', $_POST['cleanup_days']);10 $date = empty($_POST['date']) ? date('Y-m-d') : sanitize_text_field($_POST['date']); 11 if(!empty($_POST['cleanup']) and check_admin_referer('wphostel_email_log')) update_option('hostelpro_cleanup_email_log', intval($_POST['cleanup_days'])); 12 12 13 13 // select emails from log - direct query necessary for custom plugin table -
hostel/trunk/controllers/rooms.php
r3478265 r3480942 88 88 if(empty($booking_start)) $booking_start = 'tomorrow'; 89 89 $book_to_date = ($booking_start == 'tomorrow') ? '+2 days' : 'tomorrow'; 90 $show_titles = empty($atts['show_titles']) ? 0 : $atts['show_titles'];90 $show_titles = empty($atts['show_titles']) ? 0 : intval($atts['show_titles']); 91 91 92 92 // the dropdown defaults to "from tomorrow to 1 day after" -
hostel/trunk/controllers/shortcodes.php
r3478265 r3480942 53 53 $booking_start = get_option('wphostel_booking_start'); 54 54 $min_date = ($booking_start == 'tomorrow') ? 1 : 0; 55 $show_titles = empty($atts['show_titles']) ? 0 : $atts['show_titles'];56 $show_table = isset($atts['show_table']) ? $atts['show_table']: 1;57 55 $show_titles = empty($atts['show_titles']) ? 0 : intval($atts['show_titles']); 56 $show_table = isset($atts['show_table']) ? intval($atts['show_table']) : 1; 57 58 58 // the dropdown defaults to "from tomorrow to 1 day after" 59 $datefrom = empty($_POST['wphostel_from']) ? date("Y-m-d", strtotime($booking_start)) : $_POST['wphostel_from'];60 $dateto = empty($_POST['wphostel_to']) ? date("Y-m-d", strtotime($default_dateto_diff)) : $_POST['wphostel_to'];59 $datefrom = empty($_POST['wphostel_from']) ? date("Y-m-d", strtotime($booking_start)) : sanitize_text_field($_POST['wphostel_from']); 60 $dateto = empty($_POST['wphostel_to']) ? date("Y-m-d", strtotime($default_dateto_diff)) : sanitize_text_field($_POST['wphostel_to']); 61 61 62 62 wphostel_enqueue_datepicker(); … … 69 69 70 70 // displays a Book! button 71 static function book($atts) { 71 static function book($atts) { 72 72 global $post; 73 73 $room_id = intval($atts[0]); 74 74 $shortcode_id = self :: get_id(); 75 76 // this if will be removed when bookiing by ajax is done 77 if(!empty($_GET['in_booking_mode']) and $_GET['room_id']==$room_id) {75 76 // this if will be removed when bookiing by ajax is done 77 if(!empty($_GET['in_booking_mode']) and intval($_GET['room_id'])==$room_id) { 78 78 return self :: booking(); 79 79 } 80 80 81 $text = empty($atts[1]) ? __('Book', 'wphostel') : $atts[1];82 81 $text = empty($atts[1]) ? __('Book', 'wphostel') : esc_attr($atts[1]); 82 83 83 wphostel_enqueue_datepicker(); 84 84 85 85 return '<div id="wphostelBookForm'.$shortcode_id.'"> 86 86 <form method="post"> 87 87 <input type="hidden" name="from_date" value="'.date("Y-m-d", strtotime('tomorrow')).'"> 88 88 <input type="hidden" name="to_date" value="'.date("Y-m-d", strtotime('+2 days')).'"> 89 <input type="hidden" name="room_id" value="'. $room_id.'">89 <input type="hidden" name="room_id" value="'.esc_attr($room_id).'"> 90 90 <input type="hidden" name="action" value="wphostel_ajax"> 91 91 <input type="hidden" name="type" value="load_booking_form"> 92 <input type="hidden" name="in_booking_mode" value="1"> 93 <input type="button" onclick="WPHostelLoadBooking(this.form, '."'wphostelBookForm". $shortcode_id."'".');" value="'.$text.'">92 <input type="hidden" name="in_booking_mode" value="1"> 93 <input type="button" onclick="WPHostelLoadBooking(this.form, '."'wphostelBookForm".esc_attr($shortcode_id)."'".');" value="'.esc_attr($text).'"> 94 94 </form></div>'; 95 95 } -
hostel/trunk/controllers/sync.php
r3478265 r3480942 12 12 // @codingStandardsIgnoreLine WordPress.DB.DirectDatabaseQuery.NoCaching 13 13 $bookings = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WPHOSTEL_BOOKINGS." 14 WHERE room_id=%d AND to_date >= ".date('Y-m-d', current_time('timestamp'))." ORDER BY id", intval($_GET['room_id'])));14 WHERE room_id=%d AND to_date >= %s ORDER BY id", intval($_GET['room_id']), date('Y-m-d', current_time('timestamp')))); 15 15 16 16 if(!empty($_GET['download'])) { … … 98 98 static function icsToArray($paramUrl) { 99 99 $paramUrl = trim($paramUrl); 100 ob_start(); 101 $icsFile = file_get_contents($paramUrl); 102 103 $error = ob_get_clean(); 104 if(!empty($error)) { 105 // log error 106 $msg = "Importing iCal events failed at ".date(get_option('date_format'), current_time('timestamp'))." with message: $error"; 107 update_option('wphostel_ical_import_error', $msg); 108 } 109 if(empty($icsFile)) { 110 // try curl 100 101 // Validate URL - must be http or https only to prevent SSRF 102 if (!preg_match('#^https?://#i', $paramUrl)) { 103 return false; 104 } 105 106 // Parse URL and block private/local IP addresses to prevent SSRF 107 $parsed_url = parse_url($paramUrl); 108 if (isset($parsed_url['host'])) { 109 $host = $parsed_url['host']; 110 // Check if host resolves to a private IP 111 $ip = gethostbyname($host); 112 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) { 113 return false; 114 } 115 } 116 117 // Use wp_remote_get instead of file_get_contents for better security and WordPress standards 118 $response = wp_remote_get($paramUrl, array( 119 'timeout' => 15, 120 'sslverify' => true, 121 'user-agent' => 'Mozilla/5.0 (compatible; Hostel Plugin/' . WPHOSTEL_VERSION . ')' 122 )); 123 124 if (is_wp_error($response)) { 125 $msg = "Importing iCal events failed at ".date(get_option('date_format'), current_time('timestamp'))." with message: " . $response->get_error_message(); 126 update_option('wphostel_ical_import_error', $msg); 127 return false; 128 } 129 130 $icsFile = wp_remote_retrieve_body($response); 131 132 if (empty($icsFile)) { 133 // try curl as fallback 111 134 $curl = curl_init(); 112 135 curl_setopt($curl, CURLOPT_URL, $paramUrl); 113 136 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 114 curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); 115 //curl_setopt($curl, CURLOPT_HEADER, false); 116 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 137 curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; Hostel Plugin/" . WPHOSTEL_VERSION . ")"); 138 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, TRUE); 117 139 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); 118 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);140 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); // Disable follow location for security 119 141 $icsFile = curl_exec($curl); 120 142 curl_close($curl); 121 //echo $icsFile; 122 } 143 } 123 144 124 145 if(empty($icsFile)) return false; -
hostel/trunk/hostel.php
r3478265 r3480942 5 5 Description: Hostel / BnB management plugin 6 6 Author: Kiboko Labs 7 Version: 1.1. 77 Version: 1.1.8 8 8 Author URI: http://kibokolabs.com 9 9 License: GPLv2 or later -
hostel/trunk/models/booking.php
r3478265 r3480942 160 160 $wpdb->query($wpdb->prepare("INSERT INTO ".WPHOSTEL_EMAILLOG." SET 161 161 sender=%s, receiver=%s, subject=%s, date=CURDATE(), status=%s", 162 $ admin_email, $email_options['admin_email'], $subject, $status));162 $email_options['admin_email'], $email_options['admin_email'], $subject, $status)); 163 163 } // end do email admin 164 164 … … 191 191 $wpdb->query($wpdb->prepare("INSERT INTO ".WPHOSTEL_EMAILLOG." SET 192 192 sender=%s, receiver=%s, subject=%s, date=CURDATE(), status=%s", 193 $ admin_email, $booking->contact_email, $subject, $status));193 $email_options['admin_email'], $booking->contact_email, $subject, $status)); 194 194 } // end do email user 195 195 } // end email -
hostel/trunk/models/room.php
r3478265 r3480942 63 63 } 64 64 65 // list all rooms, paginated. 65 // list all rooms, paginated. 66 66 // allow filters 67 67 function find($filters = null) { 68 68 global $wpdb; 69 69 70 70 $ob = "id"; 71 71 $dir = "DESC"; 72 $offset = empty($_GET['offset']) ? 0 : $_GET['offset'];72 $offset = empty($_GET['offset']) ? 0 : intval($_GET['offset']); 73 73 $limit = 20; 74 74 75 // ORDER BY cannot be parameterized with $wpdb->prepare(), use whitelist validation 76 $allowed_orderby = array('id', 'title', 'price', 'rtype', 'beds'); 77 if (!empty($_GET['ob']) && in_array($_GET['ob'], $allowed_orderby)) { 78 $ob = $_GET['ob']; 79 } 80 $ob = esc_sql($ob); 81 82 // ORDER direction whitelist 83 if (!empty($_GET['dir']) && strtoupper($_GET['dir']) === 'ASC') { 84 $dir = 'ASC'; 85 } 86 $dir = esc_sql($dir); 87 75 88 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 76 $rooms = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WPHOSTEL_ROOMS." ORDER BY %s %s LIMIT %d, %d", 77 $ob, $dir, $offset, $limit)); 78 79 return $rooms; 89 $rooms = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WPHOSTEL_ROOMS." ORDER BY $ob $dir LIMIT %d, %d", $offset, $limit)); 90 91 return $rooms; 80 92 } 81 93 -
hostel/trunk/views/booking-form.html.php
r3478265 r3480942 35 35 <input type="hidden" name="type" value="book"> 36 36 <input type="hidden" name="shortcode_id" value="<?php echo esc_attr($shortcode_id);?>"> 37 <?php wp_nonce_field('wphostel_booking', 'wphostel_nonce'); ?> 37 38 </form> 38 39 </div> -
hostel/trunk/views/booking.html.php
r3478265 r3480942 36 36 <input type="button" value="<?php esc_attr_e('Delete booking', 'wphostel');?>" onclick="wpHostelConfirmDelete(this.form);" class="button"> 37 37 <?php endif;?> 38 <input type="button" value="<?php esc_attr_e('Go Back', 'wphostel');?>" onclick="window.location='admin.php?page=wphostel_bookings&type=<?php echo esc_ attr($_GET['type']);?>&offset=<?php echo (int)$_GET['offset'];?>';" class="button">38 <input type="button" value="<?php esc_attr_e('Go Back', 'wphostel');?>" onclick="window.location='admin.php?page=wphostel_bookings&type=<?php echo esc_js($_GET['type'] ?? '');?>&offset=<?php echo (int)($_GET['offset'] ?? 0);?>';" class="button"> 39 39 </div> 40 40 <input type="hidden" name="ok" value="1"> -
hostel/trunk/views/bookings.html.php
r3478265 r3480942 71 71 notice_str = "&send_emails=1"; 72 72 } 73 window.location = 'admin.php?page=wphostel_bookings&type=<?php echo esc_js($type);?>&offset=<?php echo (int)$offset;?>&mark_paid=1&id='+id + notice_str; 73 var nonce = '<?php echo esc_js(wp_create_nonce('mark_paid'));?>'; 74 window.location = 'admin.php?page=wphostel_bookings&type=<?php echo esc_js($type);?>&offset=<?php echo (int)$offset;?>&mark_paid=1&id='+id + notice_str + '&nonce=' + nonce; 74 75 } 75 76 } -
hostel/trunk/views/email-log.html.php
r3478265 r3480942 7 7 <div class="postbox wp-admin" style="padding:20px;"> 8 8 <form method="post"> 9 <?php wp_nonce_field('wphostel_email_log');?> 9 10 <p><label><?php esc_html_e('Log date:', 'wphostel');?></label> <input type="text" name="date" class="wphostelDatePicker" value="<?php echo esc_attr($date);?>"> 10 11 <input type="submit" value="<?php esc_attr_e('Show log', 'wphostel');?>" class="button button-primary"> -
hostel/trunk/views/options.php
r3478265 r3480942 31 31 <?php if(!empty($payment_errors)):?> 32 32 <p><a href="#" onclick="jQuery('#hostelErrorlog').toggle();return false;"><?php esc_html_e('View payments errorlog', 'wphostel');?></a></p> 33 <div id="hostelErrorlog" style="display:none;"><?php echo esc_html(nl2br($payment_errors));?></div>33 <div id="hostelErrorlog" style="display:none;"><?php echo nl2br(esc_html($payment_errors));?></div> 34 34 <?php endif;?> 35 35
Note: See TracChangeset
for help on using the changeset viewer.