Changeset 3424024
- Timestamp:
- 12/20/2025 01:30:07 AM (3 months ago)
- Location:
- pretty-google-calendar/trunk
- Files:
-
- 7 edited
-
admin/admin.php (modified) (6 diffs)
-
init/init.php (modified) (1 diff)
-
init/shortcode.php (modified) (3 diffs)
-
pretty-google-calendar.php (modified) (2 diffs)
-
public/js/pgcal.js (modified) (2 diffs)
-
readme.txt (modified) (3 diffs)
-
util/utils.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
pretty-google-calendar/trunk/admin/admin.php
r3015663 r3424024 62 62 ?> 63 63 </form> 64 </div>65 64 <?php 66 65 } … … 79 78 'pgcal-main-settings', 80 79 esc_attr__('Usage', 'pretty-google-calendar'), 81 array($this, 'pgcal_prin g_main_info'), // Callback80 array($this, 'pgcal_print_main_info'), // Callback 82 81 'pgcal-setting-admin' // Page 83 82 ); … … 90 89 'pgcal-main-settings' // Section 91 90 ); 92 93 // add_settings_field(94 // 'use_tooltip',95 // esc_attr__('Use Tooltip (Migrating to shortcode attribute use_tooltip)', 'pretty-google-calendar'),96 // array($this, 'pgcal_tooltip_callback'),97 // 'pgcal-setting-admin',98 // 'pgcal-main-settings'99 // );100 101 // add_settings_field(102 // 'no_link',103 // esc_attr__('Disable Event Link (Migrating to shortcode attribute no_link)', 'pretty-google-calendar'),104 // array($this, 'pgcal_no_link_callback'),105 // 'pgcal-setting-admin',106 // 'pgcal-main-settings'107 // );108 91 } 109 92 … … 117 100 if (isset($input['google_api'])) 118 101 // TODO test api? 119 $sanitized_input['google_api'] = $input['google_api']; 120 121 // if (isset($input['use_tooltip'])) 122 // $sanitized_input['use_tooltip'] = sanitize_text_field($input['use_tooltip']); 123 124 // if (isset($input['no_link'])) 125 // $sanitized_input['no_link'] = sanitize_text_field($input['no_link']); 126 102 $sanitized_input['google_api'] = sanitize_text_field($input['google_api']); 127 103 return $sanitized_input; 128 104 } … … 131 107 * Print the Section text 132 108 */ 133 public function pgcal_prin g_main_info() {109 public function pgcal_print_main_info() { 134 110 printf( 135 111 '<p>%s [pretty_google_calendar gcal="address@group.calendar.google.com"] </p> … … 153 129 ); 154 130 } 155 156 // public function pgcal_tooltip_callback() {157 // printf(158 // '<input title="%s" type="checkbox" id="use_tooltip" name="pgcal_settings[use_tooltip]" value="yes" %s />',159 // esc_html__("Use the popper/tooltip plugin to display event information.", "pretty-google-calendar"),160 // isset($this->options['use_tooltip']) ? 'checked' : ''161 // );162 // }163 164 // public function pgcal_no_link_callback() {165 // printf(166 // '<input title="%s" type="checkbox" id="no_link" name="pgcal_settings[no_link]" value="yes" %s />',167 // esc_html__("Disable the link to the calendar.google.com event.", "pretty-google-calendar"),168 // isset($this->options['no_link']) ? 'checked' : ''169 // );170 // }171 131 } -
pretty-google-calendar/trunk/init/init.php
r3422453 r3424024 68 68 */ 69 69 function pgcal_register_admin_css() { 70 wp_register_style('pgcal-admin-css', PGCAL_URL . 'public/css/pgcal-admin.css' );70 wp_register_style('pgcal-admin-css', PGCAL_URL . 'public/css/pgcal-admin.css', array(), PGCAL_VER); 71 71 wp_enqueue_style('pgcal-admin-css'); 72 72 } -
pretty-google-calendar/trunk/init/shortcode.php
r3422486 r3424024 18 18 'show_today_button' => "true", 19 19 'show_title' => "true", 20 'id_hash' => bin2hex(random_bytes(5)),20 'id_hash' => pgc_generate_unique_id_hash(), 21 21 'use_tooltip' => isset($globalSettings['use_tooltip']) ? "true" : "false", 22 22 'no_link' => isset($globalSettings['no_link']) ? "true" : "false", … … 30 30 $pgcalSettings["id_hash"] = preg_replace('/[\W]/', '', $pgcalSettings["id_hash"]); 31 31 32 // Auto-resolve views based on user-provided attributes 33 $pgcalSettings['views'] = pgc_resolve_views($atts, $args); 34 35 // Auto-resolve initial_view based on views (validate it's in the list, or pick smartly) 36 $pgcalSettings['initial_view'] = pgc_resolve_initial_view($pgcalSettings['views'], $pgcalSettings['initial_view']); 37 32 38 // Include public-facing global settings needed by the frontend. 33 39 // The Google API key is intended for client-side use to render public 34 40 // calendars; embed it directly in the inline settings so anonymous 35 41 // visitors don't rely on an AJAX endpoint to retrieve it. 36 if ( isset($globalSettings['google_api'])) {42 if (isset($globalSettings['google_api'])) { 37 43 $pgcalSettings['google_api'] = $globalSettings['google_api']; 38 44 } … … 79 85 80 86 $shortcode_output = " 81 <div id='pgcalendar-" . $pgcalSettings["id_hash"]. "' class='pgcal-container'>" . esc_html__("loading...", "pretty-google-calendar") . "</div>87 <div id='pgcalendar-" . esc_attr($pgcalSettings["id_hash"]) . "' class='pgcal-container'>" . esc_html__("loading...", "pretty-google-calendar") . "</div> 82 88 <div class='pgcal-branding'>" . esc_html__("Powered by", "pretty-google-calendar") . " <a href='https://wordpress.org/plugins/pretty-google-calendar/'>Pretty Google Calendar</a></div> 83 89 "; -
pretty-google-calendar/trunk/pretty-google-calendar.php
r3422486 r3424024 4 4 Plugin URI: https://github.com/lbell/pretty-google-calendar 5 5 Description: Google Calendars that aren't ugly. 6 Version: 2. 0.26 Version: 2.1.0 7 7 Author: LBell 8 8 Author URI: http://lorenbell.com … … 27 27 28 28 29 define('PGCAL_VER', "2. 0.2");29 define('PGCAL_VER', "2.1.0"); 30 30 define('PGCAL_DIR', plugin_dir_path(__FILE__)); // Trailing slash 31 define('PGCAL_TEMPLATE_DIR', PGCAL_DIR . 'templates/');31 // define('PGCAL_TEMPLATE_DIR', PGCAL_DIR . 'templates/'); 32 32 define('PGCAL_URL', plugin_dir_url(__FILE__)); 33 33 34 34 load_plugin_textdomain('pretty-google-calendar', false, PGCAL_DIR . 'languages'); 35 35 36 require(PGCAL_DIR . 'util/utils.php'); 37 require(PGCAL_DIR . 'admin/admin.php'); 38 require(PGCAL_DIR . 'init/shortcode.php'); 39 require(PGCAL_DIR . 'init/init.php'); 36 37 require_once PGCAL_DIR . 'util/utils.php'; 38 require_once PGCAL_DIR . 'admin/admin.php'; 39 require_once PGCAL_DIR . 'init/shortcode.php'; 40 require_once PGCAL_DIR . 'init/init.php'; 40 41 41 42 // require(PGCAL_DIR . 'dev/console-log.php'); // DEBUG -
pretty-google-calendar/trunk/public/js/pgcal.js
r3422486 r3424024 35 35 // attempt to fetch globals via AJAX (admin-only usage). 36 36 let globalSettings = {}; 37 if (pgcalSettings && pgcalSettings[ 'google_api']) {38 globalSettings = { 'google_api': pgcalSettings['google_api'] };37 if (pgcalSettings && pgcalSettings["google_api"]) { 38 globalSettings = { google_api: pgcalSettings["google_api"] }; 39 39 } else { 40 40 globalSettings = await pgcalFetchGlobals(ajaxurl, ajaxNonce); … … 79 79 meridiem: "short", 80 80 }, 81 }, 82 // Standard List Views 83 listDay: { 84 type: "list", 85 duration: { days: 1 }, 86 buttonText: pgcalSettings["custom_list_button"], 87 }, 88 listWeek: { 89 type: "list", 90 duration: { days: 7 }, 91 buttonText: pgcalSettings["custom_list_button"], 92 }, 93 listMonth: { 94 type: "list", 95 duration: { months: 1 }, 96 buttonText: pgcalSettings["custom_list_button"], 97 }, 98 listYear: { 99 type: "list", 100 duration: { years: 1 }, 101 buttonText: pgcalSettings["custom_list_button"], 81 102 }, 82 103 // Custom List View -
pretty-google-calendar/trunk/readme.txt
r3422486 r3424024 6 6 Requires at least: 3.0 7 7 Tested up to: 6.9 8 Stable tag: 2. 0.28 Stable tag: 2.1.0 9 9 License: GPLv2 or later 10 10 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 67 67 68 68 `initial_view="dayGridMonth"` 69 Sets the default view to be displayed when opening the page. Defaults to "dayGridMonth". 69 Sets the default view to be displayed when opening the page. Defaults to "dayGridMonth". Note: If only one view is specified in "views", "initial_view" will automatically be set to that view and does not need to be specified. 70 70 71 71 `enforce_listview_on_mobile="true"` … … 151 151 152 152 == Changelog == 153 = 2.1.0 = 154 155 - Fixed: Better list args parsing (Fixes #57) 156 - Fixed: Removed hardcoded timezone argument for correct local time display. Override with `fc_args='{"timeZone":"###"}'` if needed. 157 - Fixed: Admin CSS versioning 158 - Fixed: Sanitization of Google API key in admin 159 - Improved: id_hash generation 160 - Improved: Automatic initial_view resolution when only one view is specified (Fixes #51) 161 153 162 = 2.0.2 = 154 163 155 - Fixed: Prevent unauthorized disclosure of the Google API (CVE-2025-12898)164 - Fixed: Security fix (no known exploit) 156 165 157 166 = 2.0.1 = -
pretty-google-calendar/trunk/util/utils.php
r2613868 r3424024 1 1 <?php 2 // Shhhh 2 3 /** 4 * Generate a guaranteed unique ID hash for calendar instances on a page. 5 * 6 * Uses a static counter combined with a timestamp to guarantee uniqueness 7 * across multiple calendar shortcodes on the same page load. This ensures 8 * that even 200+ calendars on one page will never have ID collisions. 9 * 10 * @return string Unique hex ID hash 11 */ 12 function pgc_generate_unique_id_hash() { 13 static $instance_counter = 0; 14 $instance_counter++; 15 16 // Combine timestamp (microseconds) + instance counter + random for good measure 17 // timestamp (8 bytes) + counter (4 bytes) = 12 bytes, highly unlikely to collide 18 $unique_data = microtime(true) . '-' . $instance_counter . '-' . wp_rand(1000, 9999); 19 20 return bin2hex(hash('sha256', $unique_data, true)); 21 } 22 23 /** 24 * Automatically resolve the calendar views based on user-provided attributes. 25 * 26 * Intelligently handles view configuration with the following logic: 27 * - If user provides list_type but not views: auto-adjust views to include it 28 * - If user provides fc_args but not views/list_type: use only dayGridMonth 29 * - If user provides views explicitly: use as-is, no auto-adjustment 30 * - Otherwise: use defaults (dayGridMonth, listCustom) 31 * 32 * @param array $shortcode_atts User-provided shortcode attributes 33 * @param array $parsed_args Parsed arguments with defaults applied 34 * @return string Resolved views string (comma-separated) 35 */ 36 function pgc_resolve_views($shortcode_atts, $parsed_args) { 37 $list_type = trim($parsed_args['list_type']); 38 $current_views = $parsed_args['views']; 39 40 // Determine what the user explicitly provided 41 $user_provided_views = isset($shortcode_atts['views']); 42 $user_provided_list_type = isset($shortcode_atts['list_type']); 43 $user_provided_fc_args = isset($shortcode_atts['fc_args']) && $shortcode_atts['fc_args'] !== '{}'; 44 45 // If user explicitly provided views, use them as-is 46 if ($user_provided_views) { 47 return $current_views; 48 } 49 50 // If user provided fc_args without views/list_type, use only dayGridMonth 51 if ($user_provided_fc_args && !$user_provided_list_type) { 52 return 'dayGridMonth'; 53 } 54 55 // If user provided list_type but not views, auto-adjust 56 if ($user_provided_list_type) { 57 if ($list_type === 'listCustom') { 58 // Ensure listCustom is in the views 59 $views = array_map('trim', explode(',', $current_views)); 60 $list_type_found = false; 61 62 foreach ($views as $view) { 63 if (stripos($view, $list_type) !== false) { 64 $list_type_found = true; 65 break; 66 } 67 } 68 69 if (!$list_type_found) { 70 $views[] = $list_type; 71 return implode(', ', $views); 72 } 73 74 return $current_views; 75 } else { 76 // Replace listCustom with the specified list_type 77 return 'dayGridMonth, ' . $list_type; 78 } 79 } 80 81 // Default: use existing views 82 return $current_views; 83 } 84 85 /** 86 * Automatically resolve the initial_view based on the provided views. 87 * 88 * Intelligently handles initial_view configuration: 89 * - If initial_view is in the views list: use it (valid choice, either user-specified or default) 90 * - If only one view is specified: use that view 91 * - If multiple views and default view (dayGridMonth) is in the list: use the default 92 * - If multiple views but default is NOT in the list: use the first view they provided 93 * 94 * @param string $views The resolved views string (comma-separated) 95 * @param string $initial_view The currently set initial_view value (default or user-provided) 96 * @return string The resolved initial_view 97 */ 98 function pgc_resolve_initial_view($views, $initial_view) { 99 // Parse views into individual view names 100 $view_list = array_map('trim', explode(',', $views)); 101 102 // If there's only one view, use it as the initial view 103 if (count($view_list) === 1) { 104 return $view_list[0]; 105 } 106 107 // For multiple views, check if the current initial_view is in the list 108 $initial_view_trimmed = trim($initial_view); 109 if (in_array($initial_view_trimmed, $view_list, true)) { 110 // It's valid, use it 111 return $initial_view_trimmed; 112 } 113 114 // initial_view is not in the views list, pick one intelligently 115 $default_view = 'dayGridMonth'; 116 $has_default_in_views = in_array($default_view, $view_list, true); 117 118 // If default view is in their list, use it 119 if ($has_default_in_views) { 120 return $default_view; 121 } 122 123 // If default view is NOT in their list, use their first view 124 return $view_list[0]; 125 }
Note: See TracChangeset
for help on using the changeset viewer.