= 10) { return false; } // Validate with API $response = wp_remote_post('https://aboutbuzz.com/wp-json/aboutbuzz/v1/validate-code/', [ 'timeout' => 8, 'headers' => [ 'Content-Type' => 'application/json', 'User-Agent' => 'AboutBuzz-WordPress-Plugin/1.7.5', 'Accept' => 'application/json', 'Cache-Control' => 'no-cache' ], 'body' =>wp_json_encode([ 'code' => sanitize_text_field($saved_code), 'site_url' => home_url(), 'plugin_version' => '1.7.5' ]), 'sslverify' => true, 'redirection' => 0, // Prevent redirects 'httpversion' => '1.1' ]); // Update rate limiting counter $new_count = $rate_limit_count ? $rate_limit_count + 1 : 1; set_transient($rate_limit_key, $new_count, 3600); // 1 hour window if (is_wp_error($response)) { // Cache negative result for shorter time set_transient($cache_key, 'invalid', 300); // 5 minutes return false; } $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); // Enhanced response validation if ($response_code !== 200) { set_transient($cache_key, 'invalid', 300); return false; } // Validate JSON response $data = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { set_transient($cache_key, 'invalid', 300); return false; } $valid = !empty($data['success']); // Cache result with different times $cache_value = $valid ? 'valid' : 'invalid'; $cache_time = $valid ? 3600 : 300; // 1 hour for valid, 5 minutes for invalid set_transient($cache_key, $cache_value, $cache_time); return $valid; } // === Admin Menu === function aboutbuzz_activation_menu() { add_options_page( 'AboutBuzz Activation', 'AboutBuzz Activation', 'manage_options', 'aboutbuzz-activation', 'aboutbuzz_activation_page' ); } add_action('admin_menu', 'aboutbuzz_activation_menu'); function aboutbuzz_activation_page() { if (!current_user_can('manage_options')) { wp_die('Unauthorized user'); } if (isset($_POST['aboutbuzz_secret_code']) && isset($_POST['aboutbuzz_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['aboutbuzz_nonce'])), 'aboutbuzz_save_code')) { $code = sanitize_text_field(wp_unslash($_POST['aboutbuzz_secret_code'])); if (strlen($code) > 0 && strlen($code) <= 255) { update_option('aboutbuzz_secret_code', $code); echo '

' . esc_html__('Secret code saved.', 'aboutbuzz-stories-embed') . '

'; } else { echo '

' . esc_html__('Invalid secret code length.', 'aboutbuzz-stories-embed') . '

'; } } $current_code = get_option('aboutbuzz_secret_code', ''); ?>

AboutBuzz Activation


Loading...' ); } function aboutbuzz_is_mobile() { return wp_is_mobile() || (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i', sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])))); } // Helper function to get user identifier for both logged-in and anonymous users function aboutbuzz_get_user_identifier() { $user_id = get_current_user_id(); if ($user_id) { return 'user_' . $user_id; } // For anonymous users, use IP address as identifier $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown'; // Hash the IP for privacy return 'anon_' . md5($ip . NONCE_SALT); } // Add this function after aboutbuzz_is_mobile() function aboutbuzz_get_detailed_error($response_code, $response_body) { switch ($response_code) { case 401: return 'Invalid secret code. Please check your activation settings.'; case 403: return 'Access forbidden. Your secret code may be expired.'; case 404: return 'Brand ID not found. Please check your brand ID.'; case 429: return 'Too many requests. Please wait a moment and try again.'; case 500: return 'Server error. Please try again later.'; default: $data = json_decode($response_body, true); if (isset($data['message'])) { return 'API Error: ' . $data['message']; } return 'Unknown API error (Code: ' . $response_code . ')'; } } // === Enhanced Shortcode with Security Improvements === function aboutbuzz_smart_brand_stories_shortcode($atts) { // Public shortcode - no authentication required for viewing stories if (!aboutbuzz_is_activated()) { return '
Plugin not activated. Please enter a valid secret code in the AboutBuzz Activation settings.
'; } $atts = shortcode_atts(['brand_id' => ''], $atts); if (empty($atts['brand_id'])) { return '
Brand ID is required.
'; } // Enhanced brand_id validation with security checks $brand_id_input = sanitize_text_field($atts['brand_id']); if (strlen($brand_id_input) > 100) { // Prevent extremely long inputs return '
Brand ID too long.
'; } $brand_ids_array = array_filter( array_map('intval', explode(',', $brand_id_input)), function($id) { return $id > 0 && $id <= 999999; } ); // Limit to max 10 brand IDs if (count($brand_ids_array) > 10) { return '
Too many brand IDs. Maximum 10 allowed.
'; } if (empty($brand_ids_array)) { return '
Invalid brand ID(s).
'; } $brand_ids = implode(',', $brand_ids_array); $secret_code = get_option('aboutbuzz_secret_code'); // Ensure secret code exists before making API call if (empty($secret_code)) { return '
Plugin not properly configured.
'; } // Build URL with brand_id in the path $url = "https://aboutbuzz.com/wp-json/aboutbuzz/v1/stories/brand/" . $brand_ids; // Enhanced caching with user-specific cache $cache_key = 'aboutbuzz_stories_' . md5($brand_ids . $secret_code . aboutbuzz_get_user_identifier()); $cached_stories = get_transient($cache_key); if ($cached_stories !== false) { $data = $cached_stories; } else { // Add rate limiting for API calls $api_rate_limit_key = 'aboutbuzz_api_rate_' . aboutbuzz_get_user_identifier(); $api_rate_count = get_transient($api_rate_limit_key); if ($api_rate_count && $api_rate_count >= 20) { return '
Too many requests. Please wait a moment.
'; } $response = wp_remote_post($url, [ 'timeout' => 10, // Increased timeout for better reliability 'headers' => [ 'Content-Type' => 'application/json', 'User-Agent' => 'AboutBuzz-WordPress-Plugin/1.7.5', 'Accept' => 'application/json', 'Cache-Control' => 'max-age=300', 'Referer' => home_url() ], 'body' => wp_json_encode([ 'code' => sanitize_text_field($secret_code) ]), 'sslverify' => true, 'redirection' => 0, // Prevent redirects 'httpversion' => '1.1' ]); // Update API rate limiting $new_api_count = $api_rate_count ? $api_rate_count + 1 : 1; set_transient($api_rate_limit_key, $new_api_count, 3600); // 1 hour window if (is_wp_error($response)) { return '
Error fetching stories. Please try again later.
'; } $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); // Enhanced response validation if ($response_code !== 200) { $error_message = aboutbuzz_get_detailed_error($response_code, $response_body); return '
' . esc_html($error_message) . '
'; } // Validate response size (prevent memory issues) if (strlen($response_body) > 5000000) { // 5MB limit return '
Response too large. Please contact support.
'; } $data = json_decode($response_body, true); // Validate JSON and structure if (json_last_error() !== JSON_ERROR_NONE) { return '
Invalid response format.
'; } // Cache successful responses for 5 minutes if (!empty($data['success'])) { set_transient($cache_key, $data, 300); } } if (empty($data['success']) || empty($data['posts'])) { return '
Ni video ocen
'; } // Sanitize and validate posts data $posts = array_slice($data['posts'], 0, 50); // Limit to 50 posts max $sanitized_posts = []; foreach ($posts as $post) { if (!is_array($post) || empty($post['ID'])) { continue; // Skip invalid posts } // Check if the post is approved - look in both meta and acf for approval $is_approved = false; // Check in meta field first (new structure) if (isset($post['meta']) && is_array($post['meta'])) { $approval_meta = $post['meta']['approval'] ?? null; if (is_array($approval_meta)) { $is_approved = in_array('1', $approval_meta) || in_array(1, $approval_meta) || in_array(true, $approval_meta); } else { $is_approved = $approval_meta == '1' || $approval_meta == 1 || $approval_meta === true; } } // Fallback to acf field (old structure) if (!$is_approved && isset($post['acf']) && is_array($post['acf'])) { $approval_acf = $post['acf']['approval'] ?? null; $is_approved = $approval_acf == '1' || $approval_acf == 1 || $approval_acf === true; } // Skip non-approved posts if (!$is_approved) { continue; } $sanitized_post = [ 'ID' => intval($post['ID']), 'post_title' => sanitize_text_field($post['post_title'] ?? $post['title'] ?? ''), 'acf' => [], 'meta' => [] ]; // Handle meta fields (new structure) if (isset($post['meta']) && is_array($post['meta'])) { $meta = $post['meta']; $sanitized_post['meta'] = [ 'story' => isset($meta['story'][0]) ? esc_url_raw($meta['story'][0]) : '', 'rating' => isset($meta['rating'][0]) ? max(0, min(5, intval($meta['rating'][0]))) : 0, 'vote_count' => isset($meta['vote_count'][0]) ? max(0, intval($meta['vote_count'][0])) : 0, 'watermark_video' => isset($meta['watermark_video'][0]) ? esc_url_raw($meta['watermark_video'][0]) : '' ]; } // Handle ACF fields (old structure) - fallback if (isset($post['acf']) && is_array($post['acf'])) { $acf = $post['acf']; $sanitized_post['acf'] = [ 'watermark_video' => isset($acf['watermark_video']) ? esc_url_raw($acf['watermark_video']) : '', 'story' => isset($acf['story']) ? esc_url_raw($acf['story']) : '', 'rating' => isset($acf['rating']) ? max(0, min(5, intval($acf['rating']))) : 0, 'vote_count' => isset($acf['vote_count']) ? max(0, intval($acf['vote_count'])) : 0 ]; } $sanitized_posts[] = $sanitized_post; } // Calculate average rating from sanitized data $total_rating = 0; $rating_count = 0; foreach ($sanitized_posts as $post) { // Try meta first, then fallback to acf $rating = $post['meta']['rating'] ?? $post['acf']['rating'] ?? 0; if ($rating > 0) { $total_rating += $rating; $rating_count++; } } $average_rating = $rating_count > 0 ? round($total_rating / $rating_count, 2) : 0; // Generate unique nonce for this widget instance $widget_nonce = wp_create_nonce('aboutbuzz_widget_' . md5($brand_ids)); ob_start(); ?>
✓ Preverjeno ★ /5 uporabno
400)); } $nonce = sanitize_text_field(wp_unslash($_POST['nonce'])); $post_id = intval(wp_unslash($_POST['post_id'])); // Verify nonce format if (!wp_verify_nonce($nonce, 'aboutbuzz_widget_' . md5(strval($post_id)))) { wp_die('Security check failed'); } // Get user identifier $user_id = aboutbuzz_get_user_identifier(); // Check if user already liked this post $like_key = 'aboutbuzz_liked_' . $post_id . '_' . $user_id; if (get_transient($like_key)) { wp_send_json_error(['message' => 'Already liked']); return; } // Rate limiting $rate_limit_key = 'aboutbuzz_like_rate_' . $user_id; $rate_count = get_transient($rate_limit_key); if ($rate_count && $rate_count >= 5) { wp_send_json_error(['message' => 'Too many likes']); return; } // Update rate limiting $new_rate_count = $rate_count ? $rate_count + 1 : 1; set_transient($rate_limit_key, $new_rate_count, 3600); // 1 hour // Call API to increment like count $secret_code = get_option('aboutbuzz_secret_code'); if (!$secret_code) { wp_send_json_error(['message' => 'Plugin not configured']); return; } $response = wp_remote_post('https://aboutbuzz.com/wp-json/aboutbuzz/v1/like-post/', [ 'timeout' => 8, 'headers' => [ 'Content-Type' => 'application/json', 'User-Agent' => 'AboutBuzz-WordPress-Plugin/1.7.6' ], 'body' => wp_json_encode([ 'code' => sanitize_text_field($secret_code), 'post_id' => $post_id ]) ]); if (is_wp_error($response)) { wp_send_json_error(['message' => 'API error']); return; } $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); if ($response_code !== 200) { wp_send_json_error(['message' => 'API error']); return; } $data = json_decode($response_body, true); if (!$data || !isset($data['success']) || !$data['success']) { wp_send_json_error(['message' => 'API error']); return; } // Mark as liked set_transient($like_key, true, 86400); // 24 hours wp_send_json_success([ 'vote_count' => intval($data['vote_count'] ?? 0) ]); } add_action('wp_ajax_aboutbuzz_like_post', 'aboutbuzz_like_post'); add_action('wp_ajax_nopriv_aboutbuzz_like_post', 'aboutbuzz_like_post'); // === Uninstall Hook === register_uninstall_hook(__FILE__, 'aboutbuzz_uninstall'); function aboutbuzz_uninstall() { try { // Remove all plugin options delete_option('aboutbuzz_secret_code'); // Clean up all transients using WordPress functions $transient_keys = [ 'aboutbuzz_validation_', 'aboutbuzz_rate_limit_', 'aboutbuzz_cache_' ]; foreach ($transient_keys as $key) { // Use WordPress function to clean transients wp_cache_delete($key, 'transient'); } // Clear caches wp_cache_flush(); } catch (Exception $e) { // Silent fail for WordPress.org compliance } } // === Plugin Activation Hook === register_activation_hook(__FILE__, 'aboutbuzz_activate'); function aboutbuzz_activate() { // Check minimum requirements if (version_compare(PHP_VERSION, '7.4', '<')) { deactivate_plugins(plugin_basename(__FILE__)); wp_die('This plugin requires PHP 7.4 or higher.'); } // Set default options add_option('aboutbuzz_secret_code', ''); // Clear any existing caches wp_cache_flush(); } // === Plugin Deactivation Hook === register_deactivation_hook(__FILE__, 'aboutbuzz_deactivate'); function aboutbuzz_deactivate() { // Clean up transients using WordPress functions $transient_keys = [ 'aboutbuzz_validation_', 'aboutbuzz_rate_limit_', 'aboutbuzz_cache_' ]; foreach ($transient_keys as $key) { wp_cache_delete($key, 'transient'); } // Clear caches wp_cache_flush(); }