@@ -94,6 +94,17 @@ private function _verify_create_nonce(): void {
9494 }
9595 }
9696
97+ /**
98+ * Verify that the current user can edit a chart.
99+ *
100+ * @param int $chart_id Chart ID.
101+ */
102+ private function _verify_chart_access ( $ chart_id ): void {
103+ if ( ! current_user_can ( 'edit_post ' , $ chart_id ) ) {
104+ wp_send_json_error ( array ( 'message ' => __ ( 'Unauthorized. ' , 'visualizer ' ) ), 403 );
105+ }
106+ }
107+
97108 /**
98109 * Persist chart data + series from a source.
99110 *
@@ -159,6 +170,7 @@ public function getChartNonce(): void {
159170 if ( ! $ chart_id || ! get_post ( $ chart_id ) ) {
160171 wp_send_json_error ( array ( 'message ' => __ ( 'Chart not found. ' , 'visualizer ' ) ) );
161172 }
173+ $ this ->_verify_chart_access ( $ chart_id );
162174 wp_send_json_success (
163175 array (
164176 'upload_nonce ' => wp_create_nonce ( 'visualizer-ai-upload- ' . $ chart_id ),
@@ -180,6 +192,7 @@ public function fetchChart(): void {
180192 if ( ! $ chart || $ chart ->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
181193 wp_send_json_error ( array ( 'message ' => __ ( 'Chart not found. ' , 'visualizer ' ) ) );
182194 }
195+ $ this ->_verify_chart_access ( $ chart_id );
183196
184197 $ series = get_post_meta ( $ chart_id , Visualizer_Plugin::CF_SERIES , true );
185198 $ data = Visualizer_Module::get_chart_data ( $ chart , '' , false );
@@ -206,7 +219,7 @@ public function fetchChart(): void {
206219 /**
207220 * Determines whether a remote URL serves an XLSX file.
208221 *
209- * Uses wp_safe_remote_get() and checks ZIP magic number (PK\x03\x04).
222+ * Uses the shared remote-fetch policy and checks ZIP magic number (PK\x03\x04).
210223 *
211224 * @access private
212225 * @param string $url The remote URL to probe.
@@ -218,14 +231,15 @@ private static function _url_is_xlsx( $url ) {
218231 return false ;
219232 }
220233
221- $ response = wp_safe_remote_get (
234+ $ response = Visualizer_Remote_Fetch:: request (
222235 $ url ,
223236 array (
224- 'timeout ' => 15 ,
225- 'redirection ' => 5 ,
226- 'stream ' => true ,
227- 'filename ' => $ tmpfile ,
228- 'headers ' => array ( 'Range ' => 'bytes=0-3 ' ),
237+ 'timeout ' => 15 ,
238+ 'redirection ' => 5 ,
239+ 'stream ' => true ,
240+ 'filename ' => $ tmpfile ,
241+ 'headers ' => array ( 'Range ' => 'bytes=0-3 ' ),
242+ 'limit_response_size ' => 4 ,
229243 )
230244 );
231245
@@ -258,6 +272,7 @@ public function uploadData(): void {
258272 if ( ! get_post ( $ chart_id ) ) {
259273 wp_send_json_error ( array ( 'message ' => __ ( 'Chart not found. ' , 'visualizer ' ) ) );
260274 }
275+ $ this ->_verify_chart_access ( $ chart_id );
261276
262277 $ source_type = isset ( $ _POST ['source_type ' ] ) ? sanitize_key ( $ _POST ['source_type ' ] ) : 'csv_string ' ;
263278 $ source = null ;
@@ -297,17 +312,6 @@ public function uploadData(): void {
297312 }
298313 $ url = wp_unslash ( $ _POST ['file_url ' ] );
299314
300- // Allow local absolute paths in dev (same CSVs used by Classic).
301- if ( is_string ( $ url ) && file_exists ( $ url ) && is_readable ( $ url ) ) {
302- $ ext = strtolower ( pathinfo ( $ url , PATHINFO_EXTENSION ) );
303- if ( 'xlsx ' === $ ext && class_exists ( 'Visualizer_Source_Xlsx ' ) ) {
304- $ source = new Visualizer_Source_Xlsx ( $ url );
305- } else {
306- $ source = new Visualizer_Source_Csv ( $ url );
307- }
308- break ;
309- }
310-
311315 if ( function_exists ( 'wp_http_validate_url ' ) ) {
312316 $ validated_url = wp_http_validate_url ( (string ) $ url );
313317 $ url = false === $ validated_url ? false : (string ) $ validated_url ;
@@ -435,6 +439,7 @@ public function generateChart(): void {
435439 if ( ! $ chart_id || ! get_post ( $ chart_id ) ) {
436440 wp_send_json_error ( array ( 'message ' => __ ( 'Chart not found. ' , 'visualizer ' ) ) );
437441 }
442+ $ this ->_verify_chart_access ( $ chart_id );
438443
439444 $ prompt = isset ( $ _POST ['prompt ' ] ) ? sanitize_textarea_field ( wp_unslash ( $ _POST ['prompt ' ] ) ) : '' ;
440445 $ series = isset ( $ _POST ['series ' ] ) ? wp_unslash ( $ _POST ['series ' ] ) : '' ;
@@ -560,6 +565,7 @@ public function saveChart(): void {
560565 if ( ! $ chart_id || ! get_post ( $ chart_id ) ) {
561566 wp_send_json_error ( array ( 'message ' => __ ( 'Chart not found. ' , 'visualizer ' ) ) );
562567 }
568+ $ this ->_verify_chart_access ( $ chart_id );
563569 if ( empty ( $ code ) ) {
564570 wp_send_json_error ( array ( 'message ' => __ ( 'No chart code found. Generate a chart first. ' , 'visualizer ' ) ) );
565571 }
0 commit comments