| @@ -77,8 +77,34 @@ | ||
| 77 | 77 | function collection() { |
| 78 | 78 | return "<b>Meow Collection</b>: This is only available in the Pro version. Please <a href='https://meowapps.com/products/meow-gallery-pro/'>upgrade to Meow Gallery Pro</a> to use this feature."; |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | + // Gallery and collection IDs are plain identifiers (generate_uniqid(), stored as varchar). | |
| 82 | + // Anything else is rejected, and rejected rather than stripped: stripping could turn a crafted | |
| 83 | + // ID into a different existing one. Security: esc_attr() does NOT escape "]", so an ID coming | |
| 84 | + // from a request and concatenated into a shortcode string could close the tag and run | |
| 85 | + // arbitrary shortcodes. Keep IDs on this charset and never build a shortcode string from them. | |
| 86 | + public static function sanitize_id( $id ) { | |
| 87 | + if ( !is_scalar( $id ) ) { | |
| 88 | + return ''; | |
| 89 | + } | |
| 90 | + $id = (string) $id; | |
| 91 | + return preg_match( '/^[A-Za-z0-9_-]+$/', $id ) ? $id : ''; | |
| 92 | + } | |
| 93 | + | |
| 94 | + // Renders a collection from its ID. Deliberately calls the handler directly instead of going | |
| 95 | + // through do_shortcode(): there is no shortcode string to inject into that way. | |
| 96 | + public function render_collection( $id, $is_preview = false ) { | |
| 97 | + $id = self::sanitize_id( $id ); | |
| 98 | + if ( $id === '' ) { | |
| 99 | + return "<p class='meow-error'><b>Meow Gallery:</b> This collection ID is not valid.</p>"; | |
| 100 | + } | |
| 101 | + if ( $this->pro_module && $this->pro ) { | |
| 102 | + return $this->pro->collection( array( 'id' => $id ), $is_preview ); | |
| 103 | + } | |
| 104 | + return $this->collection(); | |
| 105 | + } | |
| 106 | + | |
| 81 | 107 | public function can_access_settings() { |
| 82 | 108 | return apply_filters( 'mgl_allow_setup', current_user_can( 'manage_options' ) ); |
| 83 | 109 | } |
| 84 | 110 | |
| @@ -143,11 +169,11 @@ | ||
| 143 | 169 | if ( isset( $atts['meow'] ) && $atts['meow'] === 'false' ) { |
| 144 | 170 | return gallery_shortcode( $atts ); |
| 145 | 171 | } |
| 146 | 172 | |
| 147 | - // If the attributes contain "collection" then use the collection shortcode instead | |
| 173 | + // If the attributes contain "collection" then render that collection instead | |
| 148 | 174 | if ( isset( $atts['collection'] ) && !empty( $atts['collection'] ) ) { |
| 149 | - return do_shortcode( '[meow-collection id="' . $atts['collection'] . '"]' ); | |
| 175 | + return $this->render_collection( $atts['collection'] ); | |
| 150 | 176 | } |
| 151 | 177 | |
| 152 | 178 | $image_ids = array(); |
| 153 | 179 | $layout = ''; |
| @@ -174,9 +200,10 @@ | ||
| 174 | 200 | try { |
| 175 | 201 | $shortcode = $this->get_gallery_by_id( $shortcode_id ); |
| 176 | 202 | } |
| 177 | 203 | catch ( Exception $e ) { |
| 178 | - return "<p class='meow-error'><b>Meow Gallery:</b> This ID wasn't found in the Gallery Manager. (ID: $shortcode_id). " . $e->getMessage() . "</p>"; | |
| 204 | + $safe_id = esc_html( is_scalar( $shortcode_id ) ? $shortcode_id : '' ); | |
| 205 | + return "<p class='meow-error'><b>Meow Gallery:</b> This ID wasn't found in the Gallery Manager. (ID: $safe_id). " . esc_html( $e->getMessage() ) . "</p>"; | |
| 179 | 206 | } |
| 180 | 207 | |
| 181 | 208 | if ( !isset( $shortcode['medias'] ) || !isset( $shortcode['medias']['thumbnail_ids'])) { |
| 182 | 209 | return "<p class='meow-error'><b>Meow Gallery:</b> Thumbnail IDs not found.</p>"; |