PluginProbe
CSS & JavaScript Toolbox / 8.0.3
CSS & JavaScript Toolbox v8.0.3
trunk 0.3 0.8 10 10.1 11 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 11.9.1 12 12.0 12.0.1 12.0.3 12.0.4 12.0.5 12.0.6 12.0.7 6.0 6.0.11 All 60 releases
← All changes | controllers/blocks-ajax.php +41 -104 trunk8.0.3 View file →
@@ -10,13 +10,13 @@
10 10 cssJSToolbox::import('framework:mvc:controller-ajax.inc.php');
11 11
12 12 /**
13 13 * Serve blocks page Ajax requests.
14 -*
14 +*
15 15 * The Actions resident here is global for only the blocks page, its not
16 16 * for a specific/single block. You can find single block
17 17 * actions in block-ajax.php file.
18 -*
18 +*
19 19 * @deprecated DONT ADD MORE ACTIONS HERE!
20 20 * @author Ahmed Said
21 21 * @version 6
22 22 */
@@ -23,16 +23,16 @@
23 23 class CJTBlocksAjaxController extends CJTAjaxController {
24 24
25 25 /**
26 26 * put your comment there...
27 - *
27 + *
28 28 * @var mixed
29 29 */
30 30 protected $controllerInfo = array('model' => 'blocks');
31 -
31 +
32 32 /**
33 33 * Initialize controller object.
34 - *
34 + *
35 35 * @see CJTController for more details
36 36 * @return void
37 37 */
38 38 public function __construct() {
@@ -43,25 +43,25 @@
43 43 $this->registryAction('save_blocks');
44 44 $this->registryAction('saveOrder');
45 45 $this->registryAction('loadBlock');
46 46 }
47 -
47 +
48 48 /**
49 49 * Create new block.
50 - *
50 + *
51 51 * Once this method is called a new block is saved into
52 52 * the database.
53 - *
53 + *
54 54 * Call this method using GET method with the following parameters.
55 55 * - array ids Ids for all the available blocks.
56 56 * - [name] string Block name.
57 57 * - [state] string Block state.
58 58 * - [location] string Block hook location.
59 - *
59 + *
60 60 * Response body is array with the following elements.
61 61 * - integer id New block id.
62 62 * - string view Block HTML code.
63 - *
63 + *
64 64 * @return void
65 65 */
66 66 public function createBlockAction($blockId = null, $blockType = null, $pinPoint = null, $viewName = null) {
67 67 $response = array();
@@ -66,19 +66,10 @@
66 66 public function createBlockAction($blockId = null, $blockType = null, $pinPoint = null, $viewName = null) {
67 67 $response = array();
68 68 // If viewName not provided read it from request vars.
69 69 if (!$viewName) {
70 - $viewName = filter_input(INPUT_GET, 'viewName', FILTER_UNSAFE_RAW);
71 - $viewName = is_string($viewName) ? sanitize_text_field($viewName) : null;
70 + $viewName = filter_input(INPUT_GET, 'viewName', FILTER_SANITIZE_STRING);
72 71 }
73 - // $viewName is interpolated into a filesystem path by CJTController::getView(),
74 - // which require_once's "views/blocks/{$viewName}/view.php". Restrict it to the
75 - // known block views so traversal sequences can never reach that include.
76 - $allowedBlockViews = array('cjt-block', 'block', 'metabox', 'create-metabox');
77 - if ($viewName && !in_array($viewName, $allowedBlockViews, true)) {
78 - $this->httpCode = '403 Forbidden';
79 - return;
80 - }
81 72 // Prepare parameters.
82 73 $defaultBlockName = 'block_' . hexdec(substr(md5(time()), 0, 6));
83 74 $wordpressMYSQLTime = current_time('mysql');
84 75 // Block data to insert.
@@ -99,10 +90,8 @@
99 90 if (array_key_exists($name, $_GET)) {
100 91 $blockData[$name] = $_GET[$name];
101 92 }
102 93 }
103 - // Harden the block name server-side (CVE-2025-13533 defence in depth).
104 - $blockData['name'] = self::sanitizeBlockName($blockData['name']);
105 94 // Import block model.
106 95 require_once CJTOOLBOX_MODELS_PATH . '/block.php';
107 96 $block = new CJTBlockModel($blockData);
108 97 // Add block.
@@ -110,9 +99,9 @@
110 99 $blockId = $blocksModel->add($block->getValues(), true);
111 100 $blocksModel->save();
112 101 // Read newly added block from database.
113 102 $newBlockData = $blocksModel->getBlock($blockId, array('returnCodeFile' => true));
114 -
103 +
115 104 if ($newBlockData === null) {
116 105 throw new Exception('Could not add new block!!!');
117 106 }
118 107 else {
@@ -123,25 +112,25 @@
123 112 // Push vars into the view.
124 113 $blockView->setBlock($block);
125 114 $response['view'] = $blockView->getTemplate('new');
126 115 }
127 - $response['id'] = $blockId;
116 + $response['id'] = $blockId;
128 117 // Set response object.
129 - $this->response = $response;
118 + $this->response = $response;
130 119 }
131 120 }
132 -
121 +
133 122 /**
134 123 * Get view content through ajax request.
135 - *
124 + *
136 125 * The method is useful for requesting Popup forms through ajax (e.g ThickBox).
137 126 * You can request any view specified in the $allowedViews array.
138 - *
127 + *
139 128 * Call this method using GET method with the following parameters.
140 129 * - viewName string Name of the view.
141 - *
130 + *
142 131 * Response body is the view content string.
143 - *
132 + *
144 133 * @return void
145 134 */
146 135 public function getViewAction() {
147 136 // Some views required objects to be pushed into it before displaying
@@ -150,10 +139,9 @@
150 139 $allowedViews = array(
151 140 'blocks/new' => array(),
152 141 );
153 142 // Prepare parameters.
154 - $viewName = filter_input(INPUT_GET, 'viewName', FILTER_UNSAFE_RAW);
155 - $viewName = is_string($viewName) ? sanitize_text_field($viewName) : '';
143 + $viewName = filter_input(INPUT_GET, 'viewName', FILTER_SANITIZE_STRING);
156 144 if (array_key_exists($viewName, $allowedViews) === FALSE) {
157 145 $this->httpCode = '403 Forbidden';
158 146 }
159 147 else {
@@ -179,9 +167,9 @@
179 167 }
180 168
181 169 /**
182 170 * put your comment there...
183 - *
171 + *
184 172 */
185 173 public function loadBlockAction() {
186 174 // Block Id.
187 175 $blockId = (int) $_GET['blockId'];
@@ -191,78 +179,52 @@
191 179 // Return View content.
192 180 $view->getTemplate('default');
193 181 $this->response = $view->structuredContent;
194 182 }
195 -
183 +
196 184 /**
197 185 * put your comment there...
198 - *
186 + *
199 187 */
200 - public function saveBlocksAction()
201 - {
188 + public function saveBlocksAction() {
202 189 $response = array();
203 -
204 190 // Blocks are sent ins single array list.
205 - $blocksToSave = filter_input( INPUT_POST, 'blocks', FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
206 - $calculatePinPoint = ( bool ) filter_input( INPUT_POST, 'calculatePinPoint', FILTER_SANITIZE_NUMBER_INT );
207 - $createRevision = ( bool ) filter_input( INPUT_POST, 'createRevision', FILTER_SANITIZE_NUMBER_INT );
208 -
209 - // For any reason that cause Client/JavaScript to send empty blocks,
191 + $blocksToSave = filter_input(INPUT_POST, 'blocks', FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
192 + $calculatePinPoint = (bool) filter_input(INPUT_POST, 'calculatePinPoint', FILTER_SANITIZE_NUMBER_INT);
193 + $createRevision = (bool) filter_input(INPUT_POST, 'createRevision', FILTER_SANITIZE_NUMBER_INT);
194 + // For any reason that cause Client/Javascript to send empty blocks,
210 195 // make sure we're save.
211 - if ( is_array( $blocksToSave ) && ! empty( $blocksToSave ) )
212 - {
213 -
214 - foreach ( $blocksToSave as $id => $postedblockPartialData )
215 - {
196 + if (is_array($blocksToSave) && !empty($blocksToSave)) {
197 + foreach ($blocksToSave as $id => $postedblockPartialData) {
216 198 // Push block id into block data.
217 - $blockData = ( object ) $postedblockPartialData;
199 + $blockData = (object) $postedblockPartialData;
218 200 $blockData->id = $id;
219 -
220 - // Harden the block name server-side (CVE-2025-13533 defence in depth).
221 - if ( isset( $blockData->name ) ) {
222 - $blockData->name = self::sanitizeBlockName( $blockData->name );
223 - }
224 -
225 201 // Recalculate pinPoint field value.
226 - ! $calculatePinPoint or ( CJTBlockModel::arrangePins( $blockData ) && CJTBlockModel::calculateBlockPinPoint( $blockData ) );
227 -
202 + !$calculatePinPoint or (CJTBlockModel::arrangePins($blockData) && CJTBlockModel::calculateBlockPinPoint($blockData));
228 203 // Create block revision.
229 - ! $createRevision or $this->model->addRevision( $id, $blockData->activeFileId );
230 -
204 + !$createRevision or $this->model->addRevision($id, $blockData->activeFileId);
231 205 // Set lastModified field to current time.
232 - $blockData->lastModified = current_time( 'mysql' );
233 -
206 + $blockData->lastModified = current_time('mysql');
234 207 // Update database.
235 - $this->model->update( $blockData, $calculatePinPoint );
208 + $this->model->update($blockData, $calculatePinPoint);
236 209 $this->model->save();
237 -
238 210 // Send the changes properties back to client.
239 - $updatedBlockData = $this->model->getBlock($id, null, array('*'), ARRAY_A);
240 -
241 - foreach ( $updatedBlockData as $property => $value )
242 - {
243 - $response[ $id ][ $property ][ 'value' ] = $value;
211 + foreach ($postedblockPartialData as $property => $value) {
212 + $response[$id][$property]['value'] = $value;
244 213 }
245 -
246 214 }
247 -
248 215 }
249 -
250 216 // Delete other blocks.
251 - empty( $_POST[ 'deletedBlocks' ] ) or $this->model->delete( $_POST[ 'deletedBlocks' ] );
252 -
217 + empty($_POST['deletedBlocks']) or $this->model->delete($_POST['deletedBlocks']);
253 218 // Save changes.
254 219 $this->model->save();
255 -
256 - // Return
257 220 // Set response.
258 221 $this->response = $response;
259 -
260 222 }
261 -
223 +
262 224 /**
263 225 * put your comment there...
264 - *
226 + *
265 227 */
266 228 public function saveOrderAction() {
267 229 // Read order.
268 230 $order = array('normal' => $_GET['order']);
@@ -269,31 +231,6 @@
269 231 // Centralized orders to be shared between all users!
270 232 $this->model->setOrder($order);
271 233 $this->response = array('order' => $order, 'state' => 'saved');
272 234 }
273 -
274 - /**
275 - * Sanitize a code-block name coming from the request.
276 - *
277 - * Defence-in-depth for the stored-XSS issue (CVE-2025-13533): the client-side UI
278 - * already restricts block names to A-Z, 0-9, space, '-' and '_', but that check is
279 - * trivially bypassed (e.g. via an HTTP proxy). We enforce the exact same contract
280 - * server-side so characters that could break out of an HTML attribute/element -
281 - * such as < > " ' - can never be persisted. Output is still escaped at every sink
282 - * as the primary defence; this simply keeps the stored data clean.
283 - *
284 - * @param mixed $name Raw name value from the request.
285 - * @return string Sanitized name (never empty).
286 - */
287 - public static function sanitizeBlockName($name) {
288 - // Keep only the documented allowed characters.
289 - $name = preg_replace('/[^A-Za-z0-9 _-]/', '', (string) $name);
290 - // Collapse to a trimmed value and guard against an empty result.
291 - $name = trim($name);
292 - if ($name === '') {
293 - $name = 'block_' . hexdec(substr(md5((string) time()), 0, 6));
294 - }
295 - // Respect the 50 char column/UI limit.
296 - return substr($name, 0, 50);
297 - }
298 -
235 +
299 236 } // End class.