= 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();
}