PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.14
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.14
3.1.14 3.1.13 3.1.12 3.1.11 3.1.10 3.1.9 3.1.8 3.1.7 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 All 123 releases
← All changes | Inc/Core/Controllers/BoxImport.php +64 -7 3.1.9 → 3.1.14 View file →
@@ -1,8 +1,8 @@
1 1 <?php
2 2 /**
3 3 * @package FireBox
4 - * @version 3.1.9 Free
4 + * @version 3.1.14 Free
5 5 *
6 6 * @author FirePlugins <[email protected]>
7 7 * @link https://www.fireplugins.com
8 8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
@@ -55,8 +55,20 @@
55 55 {
56 56 return; // get out if we didn't click the Activate button
57 57 }
58 58
59 + /**
60 + * Importing creates campaigns from a file the user supplies, so it needs an
61 + * explicit capability check of its own. Today options.php also enforces
62 + * manage_options for this option group, but this method must not depend on
63 + * how it happens to be reached.
64 + */
65 + if (!current_user_can('edit_fireboxes'))
66 + {
67 + \FPFramework\Libs\AdminNotice::displayError(fpframework()->_('FPF_CANNOT_VERIFY_REQUEST'));
68 + return;
69 + }
70 +
59 71 if (!isset($_FILES['file']))
60 72 {
61 73 return;
62 74 }
@@ -149,8 +161,15 @@
149 161
150 162 // remote meta from item
151 163 unset($item['meta']);
152 164
165 + // Campaign settings are free-form, but they are always a map — never a scalar.
166 + if (!is_array($meta) && !is_object($meta))
167 + {
168 + $success = false;
169 + break;
170 + }
171 +
153 172 if (!isset($item['box']) || !is_array($item['box']))
154 173 {
155 174 $success = false;
156 175 break;
@@ -157,18 +176,43 @@
157 176 }
158 177
159 178 $box = $item['box'];
160 179
180 + /**
181 + * The .fbox file carries a full wp_posts row, and every key in it used to be
182 + * written straight to the database. Keep only the columns that actually
183 + * describe a campaign; everything else (post_type, post_author, guid,
184 + * post_parent, ...) is either forced below or dropped.
185 + */
186 + $box = array_intersect_key($box, array_flip([
187 + 'post_title',
188 + 'post_content',
189 + 'post_excerpt',
190 + 'post_name',
191 + 'menu_order'
192 + ]));
193 +
161 194 if (!isset($box['post_content']) || !is_string($box['post_content']))
162 195 {
163 196 $box['post_content'] = '';
164 197 }
165 198
166 - // remove ID
167 - $box['ID'] = '';
199 + $box['post_title'] = isset($box['post_title']) && is_string($box['post_title'])
200 + ? sanitize_text_field($box['post_title'])
201 + : '';
168 202
203 + $box['post_excerpt'] = isset($box['post_excerpt']) && is_string($box['post_excerpt'])
204 + ? sanitize_textarea_field($box['post_excerpt'])
205 + : '';
206 +
207 + $box['post_name'] = isset($box['post_name']) && is_string($box['post_name'])
208 + ? sanitize_title($box['post_name'])
209 + : '';
210 +
211 + $box['menu_order'] = isset($box['menu_order']) ? (int) $box['menu_order'] : 0;
212 +
169 213 $factory = new \FPFramework\Base\Factory();
170 -
214 +
171 215 $tz = wp_timezone();
172 216 $date_without_tz = $factory->getDate();
173 217 $date_with_tz = $factory->getDate()->setTimezone($tz);
174 218
@@ -174,8 +218,12 @@
174 218
175 219 $box['post_date'] = $date_with_tz->format('Y-m-d H:i:s');
176 220 $box['post_date_gmt'] = $date_without_tz->format('Y-m-d H:i:s');
177 221
222 + // These are ours to decide, never the file's.
223 + $box['post_type'] = 'firebox';
224 + $box['post_author'] = get_current_user_id();
225 +
178 226 \FireBox\Core\Helpers\Form\Form::ensureUniqueFormIDs($box['post_content']);
179 227
180 228 // set publish status
181 229 if (in_array($publish_all, [0, 1]))
@@ -181,11 +229,20 @@
181 229 if (in_array($publish_all, [0, 1]))
182 230 {
183 231 $box['post_status'] = ($publish_all == 0) ? 'draft' : 'publish';
184 232 }
185 -
186 - // insert new box
187 - if (!$new_box_id = firebox()->tables->box->insert((object) $box))
233 + else
234 + {
235 + $box['post_status'] = 'draft';
236 + }
237 +
238 + /**
239 + * Insert through wp_insert_post() rather than the raw table layer so that
240 + * kses, slug uniqueness and the usual save_post hooks all apply.
241 + */
242 + $new_box_id = wp_insert_post(wp_slash($box), true);
243 +
244 + if (is_wp_error($new_box_id) || !$new_box_id)
188 245 {
189 246 $success = false;
190 247 break;
191 248 }