PluginProbe
CSS & JavaScript Toolbox / 6.0.6
CSS & JavaScript Toolbox v6.0.6
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 +43 -120 trunk6.0.6 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() {
@@ -41,27 +41,26 @@
41 41 $this->registryAction('create_block');
42 42 $this->registryAction('get_view');
43 43 $this->registryAction('save_blocks');
44 44 $this->registryAction('saveOrder');
45 - $this->registryAction('loadBlock');
46 45 }
47 -
46 +
48 47 /**
49 48 * Create new block.
50 - *
49 + *
51 50 * Once this method is called a new block is saved into
52 51 * the database.
53 - *
52 + *
54 53 * Call this method using GET method with the following parameters.
55 54 * - array ids Ids for all the available blocks.
56 55 * - [name] string Block name.
57 56 * - [state] string Block state.
58 57 * - [location] string Block hook location.
59 - *
58 + *
60 59 * Response body is array with the following elements.
61 60 * - integer id New block id.
62 61 * - string view Block HTML code.
63 - *
62 + *
64 63 * @return void
65 64 */
66 65 public function createBlockAction($blockId = null, $blockType = null, $pinPoint = null, $viewName = null) {
67 66 $response = array();
@@ -66,19 +65,10 @@
66 65 public function createBlockAction($blockId = null, $blockType = null, $pinPoint = null, $viewName = null) {
67 66 $response = array();
68 67 // If viewName not provided read it from request vars.
69 68 if (!$viewName) {
70 - $viewName = filter_input(INPUT_GET, 'viewName', FILTER_UNSAFE_RAW);
71 - $viewName = is_string($viewName) ? sanitize_text_field($viewName) : null;
69 + $viewName = filter_input(INPUT_GET, 'viewName', FILTER_SANITIZE_STRING);
72 70 }
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 71 // Prepare parameters.
82 72 $defaultBlockName = 'block_' . hexdec(substr(md5(time()), 0, 6));
83 73 $wordpressMYSQLTime = current_time('mysql');
84 74 // Block data to insert.
@@ -99,20 +89,18 @@
99 89 if (array_key_exists($name, $_GET)) {
100 90 $blockData[$name] = $_GET[$name];
101 91 }
102 92 }
103 - // Harden the block name server-side (CVE-2025-13533 defence in depth).
104 - $blockData['name'] = self::sanitizeBlockName($blockData['name']);
105 93 // Import block model.
106 94 require_once CJTOOLBOX_MODELS_PATH . '/block.php';
107 95 $block = new CJTBlockModel($blockData);
108 96 // Add block.
109 97 $blocksModel =& $this->model;
110 - $blockId = $blocksModel->add($block->getValues(), true);
98 + $blockId = $blocksModel->add($block->getValues());
111 99 $blocksModel->save();
112 100 // Read newly added block from database.
113 - $newBlockData = $blocksModel->getBlock($blockId, array('returnCodeFile' => true));
114 -
101 + $newBlockData = $blocksModel->getBlock($blockId);
102 +
115 103 if ($newBlockData === null) {
116 104 throw new Exception('Could not add new block!!!');
117 105 }
118 106 else {
@@ -123,25 +111,25 @@
123 111 // Push vars into the view.
124 112 $blockView->setBlock($block);
125 113 $response['view'] = $blockView->getTemplate('new');
126 114 }
127 - $response['id'] = $blockId;
115 + $response['id'] = $blockId;
128 116 // Set response object.
129 - $this->response = $response;
117 + $this->response = $response;
130 118 }
131 119 }
132 -
120 +
133 121 /**
134 122 * Get view content through ajax request.
135 - *
123 + *
136 124 * The method is useful for requesting Popup forms through ajax (e.g ThickBox).
137 125 * You can request any view specified in the $allowedViews array.
138 - *
126 + *
139 127 * Call this method using GET method with the following parameters.
140 128 * - viewName string Name of the view.
141 - *
129 + *
142 130 * Response body is the view content string.
143 - *
131 + *
144 132 * @return void
145 133 */
146 134 public function getViewAction() {
147 135 // Some views required objects to be pushed into it before displaying
@@ -150,10 +138,9 @@
150 138 $allowedViews = array(
151 139 'blocks/new' => array(),
152 140 );
153 141 // Prepare parameters.
154 - $viewName = filter_input(INPUT_GET, 'viewName', FILTER_UNSAFE_RAW);
155 - $viewName = is_string($viewName) ? sanitize_text_field($viewName) : '';
142 + $viewName = filter_input(INPUT_GET, 'viewName', FILTER_SANITIZE_STRING);
156 143 if (array_key_exists($viewName, $allowedViews) === FALSE) {
157 144 $this->httpCode = '403 Forbidden';
158 145 }
159 146 else {
@@ -179,90 +166,51 @@
179 166 }
180 167
181 168 /**
182 169 * put your comment there...
183 - *
170 + *
184 171 */
185 - public function loadBlockAction() {
186 - // Block Id.
187 - $blockId = (int) $_GET['blockId'];
188 - // Get block content.
189 - $view = CJTView::getInstance('blocks/cjt-block');
190 - $view->setBlock(CJTModel::create('blocks')->getBlock($blockId, array('returnCodeFile' => true)));
191 - // Return View content.
192 - $view->getTemplate('default');
193 - $this->response = $view->structuredContent;
194 - }
195 -
196 - /**
197 - * put your comment there...
198 - *
199 - */
200 - public function saveBlocksAction()
201 - {
172 + public function saveBlocksAction() {
202 173 $response = array();
203 -
174 + // Single block model class.
175 + require_once CJTOOLBOX_MODELS_PATH . '/block.php';
204 176 // 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,
177 + $blocksToSave = filter_input(INPUT_POST, 'blocks', FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
178 + $calculatePinPoint = (bool) filter_input(INPUT_POST, 'calculatePinPoint', FILTER_SANITIZE_NUMBER_INT);
179 + $createRevision = (bool) filter_input(INPUT_POST, 'createRevision', FILTER_SANITIZE_NUMBER_INT);
180 + // For any reason that cause Client/Javascript to send empty blocks,
210 181 // make sure we're save.
211 - if ( is_array( $blocksToSave ) && ! empty( $blocksToSave ) )
212 - {
213 -
214 - foreach ( $blocksToSave as $id => $postedblockPartialData )
215 - {
182 + if (is_array($blocksToSave) && !empty($blocksToSave)) {
183 + foreach ($blocksToSave as $id => $postedblockPartialData) {
216 184 // Push block id into block data.
217 - $blockData = ( object ) $postedblockPartialData;
185 + $blockData = (object) $postedblockPartialData;
218 186 $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 187 // Recalculate pinPoint field value.
226 - ! $calculatePinPoint or ( CJTBlockModel::arrangePins( $blockData ) && CJTBlockModel::calculateBlockPinPoint( $blockData ) );
227 -
188 + !$calculatePinPoint or CJTBlockModel::calculateBlockPinPoint($blockData);
228 189 // Create block revision.
229 - ! $createRevision or $this->model->addRevision( $id, $blockData->activeFileId );
230 -
190 + !$createRevision or $this->model->addRevision($id);
231 191 // Set lastModified field to current time.
232 - $blockData->lastModified = current_time( 'mysql' );
233 -
192 + $blockData->lastModified = current_time('mysql');
234 193 // Update database.
235 - $this->model->update( $blockData, $calculatePinPoint );
194 + $this->model->update($blockData, $calculatePinPoint);
236 195 $this->model->save();
237 -
238 196 // 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;
197 + foreach ($postedblockPartialData as $property => $value) {
198 + $response[$id][$property]['value'] = $value;
244 199 }
245 -
246 200 }
247 -
248 201 }
249 -
250 202 // Delete other blocks.
251 - empty( $_POST[ 'deletedBlocks' ] ) or $this->model->delete( $_POST[ 'deletedBlocks' ] );
252 -
203 + empty($_POST['deletedBlocks']) or $this->model->delete($_POST['deletedBlocks']);
253 204 // Save changes.
254 205 $this->model->save();
255 -
256 - // Return
257 206 // Set response.
258 207 $this->response = $response;
259 -
260 208 }
261 -
209 +
262 210 /**
263 211 * put your comment there...
264 - *
212 + *
265 213 */
266 214 public function saveOrderAction() {
267 215 // Read order.
268 216 $order = array('normal' => $_GET['order']);
@@ -269,31 +217,6 @@
269 217 // Centralized orders to be shared between all users!
270 218 $this->model->setOrder($order);
271 219 $this->response = array('order' => $order, 'state' => 'saved');
272 220 }
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 -
221 +
299 222 } // End class.