PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / trunk
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent vtrunk
3.5.3 3.5.2 3.5.1 3.4.9 3.5.0 3.4.8 3.4.7 trunk 2.3.1 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6
supportcandy / includes / models / class-wpsc-attachment.php

class-wpsc-attachment.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent trunk, at includes/models/class-wpsc-attachment.php

1,372 lines 43.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly!
4 }
5
6 if ( ! class_exists( 'WPSC_Attachment' ) ) :
7
8 final class WPSC_Attachment {
9
10 /**
11 * Object data in key => val pair.
12 *
13 * @var array
14 */
15 private $data = array();
16
17 /**
18 * Set whether or not current object properties modified
19 *
20 * @var boolean
21 */
22 private $is_modified = false;
23
24 /**
25 * Schema for this model
26 *
27 * @var array
28 */
29 public static $schema = array();
30
31 /**
32 * Prevent fields to modify
33 *
34 * @var array
35 */
36 public static $prevent_modify = array();
37
38 /**
39 * Catche for search results for ticket list of attachments.
40 *
41 * @var array
42 */
43 private static $tl_search_items;
44
45 /**
46 * Initialize this class
47 *
48 * @return void
49 */
50 public static function init() {
51
52 // Apply schema for this model.
53 add_action( 'init', array( __CLASS__, 'apply_schema' ), 2 );
54
55 // Get object of this class.
56 add_filter( 'wpsc_load_ref_classes', array( __CLASS__, 'load_ref_class' ) );
57
58 // File upload.
59 add_action( 'wp_ajax_wpsc_file_upload', array( __CLASS__, 'file_upload' ) );
60 add_action( 'wp_ajax_nopriv_wpsc_file_upload', array( __CLASS__, 'file_upload' ) );
61
62 // Custom image in tinymce.
63 add_action( 'wp_ajax_wpsc_add_custom_image_tinymce', array( __CLASS__, 'add_custom_image_tinymce' ) );
64 add_action( 'wp_ajax_nopriv_wpsc_add_custom_image_tinymce', array( __CLASS__, 'add_custom_image_tinymce' ) );
65 add_action( 'wp_ajax_wpsc_edit_custom_image_tinymce', array( __CLASS__, 'edit_custom_image_tinymce' ) );
66 add_action( 'wp_ajax_nopriv_wpsc_edit_custom_image_tinymce', array( __CLASS__, 'edit_custom_image_tinymce' ) );
67
68 // Check download file.
69 add_action( 'init', array( __CLASS__, 'check_download_file' ), 100 );
70
71 // Upload tinymce image.
72 add_action( 'wp_ajax_wpsc_tinymce_upload_file', array( __CLASS__, 'tinymce_upload_file' ) );
73 add_action( 'wp_ajax_nopriv_wpsc_tinymce_upload_file', array( __CLASS__, 'tinymce_upload_file' ) );
74
75 // Attachment garbage collector.
76 add_action( 'wpsc_attach_garbage_collector', array( __CLASS__, 'garbage_collector' ) );
77 }
78
79 /**
80 * Change file upload path
81 *
82 * @param array $param - file upload array.
83 * @return array
84 */
85 public static function wpsc_upload_dir( $param ) {
86
87 $today = new DateTime();
88 $file_path = $param['basedir'] . '/wpsc/' . $today->format( 'Y' ) . '/' . $today->format( 'm' );
89 if ( ! file_exists( $file_path ) ) {
90 mkdir( $file_path, 0755, true );
91 }
92
93 $param['path'] = $file_path;
94
95 return $param;
96 }
97
98 /**
99 * Custom upload mime types
100 *
101 * @param array $existing_mimes - file upload array.
102 * @return array
103 */
104 public static function wpsc_custom_upload_mimes( $existing_mimes ) {
105
106 $settings = get_option( 'wpsc-gs-file-attachments', array() );
107
108 // Merge allowed-file-ext-mimes first.
109 if ( isset( $settings['allowed-file-ext-mimes'] ) ) {
110 $existing_mimes = array_merge( $existing_mimes, $settings['allowed-file-ext-mimes'] );
111 }
112
113 // Then apply mime-exceptions to give them priority.
114 if ( isset( $settings['mime-exceptions'] ) && is_array( $settings['mime-exceptions'] ) ) {
115 foreach ( $settings['mime-exceptions'] as $type ) {
116 $type_array = explode( ':', $type );
117 if ( count( $type_array ) === 2 ) {
118 $existing_mimes[ $type_array[0] ] = $type_array[1];
119 }
120 }
121 }
122
123 return $existing_mimes;
124 }
125
126 /**
127 * Apply schema for this model
128 *
129 * @return void
130 */
131 public static function apply_schema() {
132
133 $schema = array(
134 'id' => array(
135 'has_ref' => false,
136 'ref_class' => '',
137 'has_multiple_val' => false,
138 ),
139 'name' => array(
140 'has_ref' => false,
141 'ref_class' => '',
142 'has_multiple_val' => false,
143 ),
144 'file_path' => array(
145 'has_ref' => false,
146 'ref_class' => '',
147 'has_multiple_val' => false,
148 ),
149 'is_image' => array(
150 'has_ref' => false,
151 'ref_class' => '',
152 'has_multiple_val' => false,
153 ),
154 'is_active' => array(
155 'has_ref' => false,
156 'ref_class' => '',
157 'has_multiple_val' => false,
158 ),
159 'is_uploaded' => array(
160 'has_ref' => false,
161 'ref_class' => '',
162 'has_multiple_val' => false,
163 ),
164 'date_created' => array(
165 'has_ref' => true,
166 'ref_class' => 'datetime',
167 'has_multiple_val' => false,
168 ),
169 'source' => array(
170 'has_ref' => false,
171 'ref_class' => '',
172 'has_multiple_val' => false,
173 ),
174 'source_id' => array(
175 'has_ref' => false,
176 'ref_class' => '',
177 'has_multiple_val' => false,
178 ),
179 'ticket_id' => array(
180 'has_ref' => false,
181 'ref_class' => '',
182 'has_multiple_val' => false,
183 ),
184 'customer_id' => array(
185 'has_ref' => false,
186 'ref_class' => '',
187 'has_multiple_val' => false,
188 ),
189 );
190 self::$schema = apply_filters( 'wpsc_attachment_schema', $schema );
191
192 // Prevent modify.
193 $prevent_modify = array( 'id' );
194 self::$prevent_modify = apply_filters( 'wpsc_attachment_prevent_modify', $prevent_modify );
195 }
196
197 /**
198 * Model constructor
199 *
200 * @param int $id - Optional. Data record id to retrive object for.
201 */
202 public function __construct( $id = 0 ) {
203
204 global $wpdb;
205
206 $id = intval( $id );
207
208 if ( $id > 0 ) {
209
210 $attachment = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}psmsc_attachments WHERE id = " . $id, ARRAY_A );
211 if ( ! is_array( $attachment ) ) {
212 return;
213 }
214
215 foreach ( $attachment as $key => $val ) {
216 $this->data[ $key ] = $val !== null ? $val : '';
217 }
218 }
219 }
220
221 /**
222 * Convert object into an array
223 *
224 * @return array
225 */
226 public function to_array() {
227
228 return $this->data;
229 }
230
231 /**
232 * Magic get function to use with object arrow function
233 *
234 * @param string $var_name - variable name.
235 * @return mixed
236 */
237 public function __get( $var_name ) {
238
239 if ( ! isset( $this->data[ $var_name ] ) ||
240 $this->data[ $var_name ] == null ||
241 $this->data[ $var_name ] == ''
242 ) {
243 return self::$schema[ $var_name ]['has_multiple_val'] ? array() : '';
244 }
245
246 if ( self::$schema[ $var_name ]['has_multiple_val'] ) {
247
248 $response = array();
249 $values = $this->data[ $var_name ] ? explode( '|', $this->data[ $var_name ] ) : array();
250 foreach ( $values as $val ) {
251 $response[] = self::$schema[ $var_name ]['has_ref'] ?
252 WPSC_Functions::get_object( self::$schema[ $var_name ]['ref_class'], $val ) :
253 $val;
254 }
255 return $response;
256
257 } else {
258
259 return self::$schema[ $var_name ]['has_ref'] && $this->data[ $var_name ] ?
260 WPSC_Functions::get_object( self::$schema[ $var_name ]['ref_class'], $this->data[ $var_name ] ) :
261 $this->data[ $var_name ];
262 }
263 }
264
265 /**
266 * Magic function to use setting object field with arrow function
267 *
268 * @param string $var_name - (Required) property slug.
269 * @param mixed $value - (Required) value to set for a property.
270 * @return void
271 */
272 public function __set( $var_name, $value ) {
273
274 if (
275 ! isset( $this->data[ $var_name ] ) ||
276 in_array( $var_name, self::$prevent_modify )
277 ) {
278 return;
279 }
280
281 $data_val = '';
282 if ( self::$schema[ $var_name ]['has_multiple_val'] ) {
283
284 $data_vals = array_map(
285 fn( $val ) => is_object( $val ) ? WPSC_Functions::set_object( self::$schema[ $var_name ]['ref_class'], $val ) : $val,
286 $value
287 );
288
289 $data_val = $data_vals ? implode( '|', $data_vals ) : '';
290
291 } else {
292
293 $data_val = is_object( $value ) ? WPSC_Functions::set_object( self::$schema[ $var_name ]['ref_class'], $value ) : $value;
294 }
295
296 if ( $this->data[ $var_name ] == $data_val ) {
297 return;
298 }
299
300 $this->data[ $var_name ] = $data_val;
301 $this->is_modified = true;
302 }
303
304 /**
305 * Save changes made
306 *
307 * @return boolean
308 */
309 public function save() {
310
311 global $wpdb;
312
313 if ( ! $this->is_modified ) {
314 return true;
315 }
316
317 $data = $this->data;
318 $success = true;
319
320 if ( ! isset( $data['id'] ) ) {
321
322 $at = self::insert( $data );
323 if ( $at ) {
324 $this->data = $at->data;
325 $success = true;
326 } else {
327 $success = false;
328 }
329 } else {
330
331 unset( $data['id'] );
332 $success = $wpdb->update(
333 $wpdb->prefix . 'psmsc_attachments',
334 $data,
335 array( 'id' => $this->data['id'] )
336 );
337 }
338 $this->is_modified = false;
339 return $success ? true : false;
340 }
341
342 /**
343 * Insert new attachment
344 *
345 * @param array $data - insert data.
346 * @return WPSC_Attachment
347 */
348 public static function insert( $data ) {
349
350 global $wpdb;
351
352 $data['is_active'] = isset( $data['is_active'] ) ? $data['is_active'] : 0;
353
354 $success = $wpdb->insert(
355 $wpdb->prefix . 'psmsc_attachments',
356 $data
357 );
358
359 if ( ! $success ) {
360 return false;
361 }
362
363 $attachment = new WPSC_Attachment( $wpdb->insert_id );
364 return $attachment;
365 }
366
367 /**
368 * Make it inactive so that garbage collector will delete files associated in
369 * background and then delete the record. This will improve its performance.
370 *
371 * @param WPSC_Attachment $attachment - attachment object.
372 * @return boolean
373 */
374 public static function destroy( $attachment ) {
375
376 $attachment->is_active = 0;
377 $attachment->save();
378 return true;
379 }
380
381 /**
382 * Set data to create new object using direct data. Used in find method
383 *
384 * @param array $data - data to set for object.
385 * @return void
386 */
387 private function set_data( $data ) {
388
389 foreach ( $data as $var_name => $val ) {
390 $this->data[ $var_name ] = $val !== null ? $val : '';
391 }
392 }
393
394 /**
395 * Find records based on given filters
396 *
397 * @param array $filter - array containing array items like search, where, orderby, order, page_no, items_per_page, etc.
398 * @param boolean $is_object - return data as array or object. Default object.
399 * @return mixed
400 */
401 public static function find( $filter = array(), $is_object = true ) {
402
403 global $wpdb;
404
405 $sql = 'SELECT * FROM ' . $wpdb->prefix . 'psmsc_attachments ';
406 $where = self::get_where( $filter );
407
408 $filter['items_per_page'] = isset( $filter['items_per_page'] ) ? $filter['items_per_page'] : 5;
409 $filter['page_no'] = isset( $filter['page_no'] ) ? $filter['page_no'] : 1;
410 $filter['orderby'] = isset( $filter['orderby'] ) ? $filter['orderby'] : 'id';
411 $filter['order'] = isset( $filter['order'] ) ? $filter['order'] : 'ASC';
412
413 $order = WPSC_Functions::parse_order( $filter );
414 $limit = WPSC_Functions::parse_limit( $filter );
415
416 $sql = $sql . $where . $order . $limit;
417 $results = $wpdb->get_results( $sql, ARRAY_A );
418
419 // total results.
420 $sql = 'SELECT count(id) FROM ' . $wpdb->prefix . 'psmsc_attachments ';
421 $total_items = $wpdb->get_var( $sql . $where );
422
423 $response = WPSC_Functions::parse_response( $results, $total_items, $filter );
424
425 // Return array.
426 if ( ! $is_object ) {
427 return $response;
428 }
429
430 // create and return array of objects.
431 $temp_results = array();
432 foreach ( $response['results'] as $attachment ) {
433
434 $ob = new WPSC_Attachment();
435 $data = array();
436 foreach ( $attachment as $key => $val ) {
437 $data[ $key ] = $val;
438 }
439 $ob->set_data( $data );
440 $temp_results[] = $ob;
441 }
442 $response['results'] = $temp_results;
443
444 return $response;
445 }
446
447 /**
448 * Get where for find method
449 *
450 * @param array $filter - user filter.
451 * @return array
452 */
453 private static function get_where( $filter ) {
454
455 $where = array( '1=1' );
456
457 // Set user defined filters.
458 $meta_query = isset( $filter['meta_query'] ) ? $filter['meta_query'] : array();
459 if ( $meta_query ) {
460 $where[] = WPSC_Functions::parse_user_filters( __CLASS__, $meta_query );
461 }
462
463 // Search.
464 $search = WPSC_Functions::get_filter_search_str( $filter );
465 if ( $search ) {
466 $search_query = array(
467 'CONVERT(name USING utf8) LIKE \'%' . $search . '%\'',
468 );
469 $search_query = apply_filters( 'wpsc_attachment_search_query', $search_query, $filter );
470 $where[] = '( ' . implode( ' OR ', $search_query ) . ' )';
471 }
472
473 return 'WHERE ' . implode( ' AND ', $where ) . ' ';
474 }
475
476 /**
477 * Load current class to reference classes
478 *
479 * @param array $classes - Associative array of class names indexed by its slug.
480 * @return array
481 */
482 public static function load_ref_class( $classes ) {
483
484 $classes['wpsc_attachment'] = array(
485 'class' => __CLASS__,
486 'save-key' => 'id',
487 );
488 return $classes;
489 }
490
491 /**
492 * Clear records and actual files for attachments that are not active for more than 24 hrs.
493 * This uses cron-job for background running to improve performace of load-time while deleting attachments.
494 *
495 * @return void
496 */
497 public static function garbage_collector() {
498
499 global $wpdb;
500 $d = ( new DateTime() )->sub( new DateInterval( 'P1D' ) );
501
502 $attachments = self::find(
503 array(
504 'items_per_page' => 20,
505 'meta_query' => array(
506 'relation' => 'AND',
507 array(
508 'slug' => 'date_created',
509 'compare' => '<',
510 'val' => $d->format( 'Y-m-d H:i:s' ),
511 ),
512 array(
513 'relation' => 'OR',
514 array(
515 'slug' => 'is_active',
516 'compare' => '=',
517 'val' => '0',
518 ),
519 array(
520 'slug' => 'source',
521 'compare' => '=',
522 'val' => 'img_editor_tmp',
523 ),
524 ),
525 ),
526 )
527 )['results'];
528 foreach ( $attachments as $attachment ) {
529
530 $upload_dir = wp_upload_dir();
531 $file_path = $upload_dir['basedir'] . $attachment->file_path;
532 if ( file_exists( $file_path ) ) {
533 wp_delete_file( $file_path );
534 }
535 $wpdb->query( "DELETE FROM {$wpdb->prefix}psmsc_attachments WHERE id=" . $attachment->id );
536 }
537 }
538
539 /**
540 * Ajax callback for attachment file upload
541 *
542 * @return void
543 */
544 public static function file_upload() {
545
546 if ( check_ajax_referer( 'wpsc_file_upload', '_ajax_nonce', false ) != 1 ) {
547 wp_send_json_error( 'Unauthorized request!', 401 );
548 }
549
550 if ( ! WPSC_Text_Editor::is_allow_attachments() ) {
551 wp_send_json_error( new WP_Error( '001', 'Unauthorized' ), 401 );
552 }
553
554 $recaptcha = get_option( 'wpsc-recaptcha-settings' );
555 if ( $recaptcha['captcha-provider'] === 'google-recaptcha' && $recaptcha['recaptcha-version'] == 3 && $recaptcha['recaptcha-site-key'] && $recaptcha['recaptcha-secret-key'] ) {
556 WPSC_MS_Recaptcha::validate( 'file_upload' );
557 }
558
559 $file = isset( $_FILES['wpscFileAttachment'] ) ? $_FILES['wpscFileAttachment'] : false; // phpcs:ignore
560 if ( ! $file ) {
561 wp_send_json_error( 'File not found!', 400 );
562 }
563
564 $file_settings = get_option( 'wpsc-gs-file-attachments' );
565 $original_name = sanitize_file_name( $file['name'] );
566 $filename = time() . '_' . sanitize_file_name( $file['name'] );
567 $extension = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
568 $today = new DateTime();
569 $upload_dir = wp_upload_dir();
570
571 // Allowed file extension.
572 $allowed_file_extensions = explode( ',', $file_settings['allowed-file-extensions'] );
573 $allowed_file_extensions = array_map( 'trim', $allowed_file_extensions );
574 $allowed_file_extensions = array_map( 'strtolower', $allowed_file_extensions );
575 if ( ! ( in_array( $extension, $allowed_file_extensions ) ) ) {
576 wp_send_json_error( 'File extension not allowed!', 400 );
577 }
578
579 // Allowed file size.
580 $allowed_file_size = intval( $file_settings['attachments-max-filesize'] ) * 1000000;
581 if ( ! ( isset( $file['size'] ) && $file['size'] <= $allowed_file_size ) ) {
582 wp_send_json_error( 'File size exceeds allowed limit!', 400 );
583 }
584
585 // Init attachment data.
586 $data = array(
587 'name' => $original_name,
588 'date_created' => $today->format( 'Y-m-d H:i:s' ),
589 );
590
591 // Check for image type. Add a ".txt" extension to non-image file to prevent executing uploaded files on server.
592 $img_extensions = array( 'png', 'jpeg', 'jpg', 'bmp', 'pdf', 'gif' );
593 if ( ! in_array( $extension, $img_extensions ) ) {
594 $data['is_image'] = 0;
595 } else {
596 $data['is_image'] = 1;
597 }
598
599 $ext = pathinfo( $filename, PATHINFO_EXTENSION );
600 $file_name = substr( $filename, 0, -( strlen( $ext ) + 1 ) );
601 $filename = $file_name . '.' . strtolower( $ext );
602 $filepath_short = '/wpsc/' . $today->format( 'Y' ) . '/' . $today->format( 'm' ) . '/' . $filename;
603 $data['file_path'] = $filepath_short;
604
605 // Set up upload overrides.
606 $upload_overrides = array(
607 'test_form' => false,
608 );
609 $file['name'] = $filename;
610 add_filter( 'upload_dir', array( __CLASS__, 'wpsc_upload_dir' ) );
611 add_filter( 'upload_mimes', array( __CLASS__, 'wpsc_custom_upload_mimes' ) );
612 $uploaded_file = wp_handle_upload( $file, $upload_overrides );
613 // Insert record in database.
614 if ( $uploaded_file && empty( $uploaded_file['error'] ) ) {
615
616 $pos = strpos( $uploaded_file['file'], 'wpsc/' );
617 if ( $pos === false ) {
618 wp_send_json_error( 'Something went wrong!', 500 );
619 }
620 $new_path = substr( $uploaded_file['file'], $pos );
621 if ( $new_path[0] !== '/' ) {
622 $new_path = '/' . $new_path;
623 }
624 $data['file_path'] = $new_path;
625 $attachment = self::insert( $data );
626 if ( ! $attachment->id ) {
627 wp_send_json_error( 'Something went wrong!', 500 );
628 }
629
630 wp_send_json( array( 'id' => $attachment->id ) );
631
632 } else {
633
634 $error_message = isset( $uploaded_file['error'] ) ? $uploaded_file['error'] : 'Something went wrong!';
635 wp_send_json_error( $error_message, 500 );
636 }
637 }
638
639 /**
640 * Returns attachment ids to be used for search in ticket list
641 *
642 * @param string $search - search string.
643 * @return array
644 */
645 public static function get_tl_search_string( $search ) {
646
647 $search_items = array();
648 if ( is_array( self::$tl_search_items ) ) {
649 $search_items = self::$tl_search_items;
650 } else {
651 $attachments = self::find(
652 array(
653 'search' => $search,
654 'items_per_page' => 500,
655 'meta_query' => array(
656 'relation' => 'AND',
657 array(
658 'slug' => 'is_active',
659 'compare' => '=',
660 'val' => '1',
661 ),
662 ),
663 )
664 )['results'];
665 if ( $attachments ) {
666 foreach ( $attachments as $attachment ) {
667 $search_items[] = $attachment->id;
668 }
669 }
670 self::$tl_search_items = $search_items;
671 }
672
673 return $search_items;
674 }
675
676 /**
677 * Custom tinymce image popup
678 *
679 * @return void
680 */
681 public static function add_custom_image_tinymce() {
682
683 if ( check_ajax_referer( 'wpsc_add_custom_image_tinymce', '_ajax_nonce', false ) != 1 ) {
684 wp_send_json_error( 'Unauthorized request!', 401 );
685 }
686
687 $title = esc_attr__( 'Insert/edit image', 'supportcandy' );
688
689 $editor_id = isset( $_POST['editor_id'] ) ? sanitize_text_field( wp_unslash( $_POST['editor_id'] ) ) : '';
690 if ( ! $editor_id ) {
691 wp_send_json_error( 'Something went wrong!', 400 );
692 }
693
694 ob_start();?>
695 <form action="#" onsubmit="return false;" class="wpsc-insert-edit-image">
696 <div class="wpsc-input-group">
697 <div class="label-container">
698 <label for=""><?php esc_attr_e( 'Source', 'supportcandy' ); ?></label>
699 <span class="required-char">*</span>
700 </div>
701 <div style="display:flex;">
702 <input type="text" accept="image/*" id="wpsc-tinymce-image-url" class="wpsc-tinymce-image-url" style="flex-grow: 1;" autocomplete="off">
703 <button id="wpsc-tinymce-get-file-url" class="wpsc-button small secondary" style="margin-left: 2px; width:100px;" onclick="wpsc_tinymce_image_picker();"><?php esc_attr_e( 'Upload', 'supportcandy' ); ?></button>
704 <input type='file' accept="image/*" name='fileupload' id='wpsc-fileupload' style='display: none;'>
705 </div>
706 </div>
707 <div class="wpsc-input-group">
708 <div class="label-container">
709 <label for=""><?php esc_attr_e( 'Dimentions', 'supportcandy' ); ?></label>
710 <span class="required-char">*</span>
711 </div>
712 <div style="display: flex; align-items:center;">
713 <input type="text" id="wpsc-tinymce-image-width" aria-label="width" class="wpsc-image-dimention" style="width:70px; margin-right:5px;" autocomplete="off">
714 <span class="wpsc-image-dimention-x-sign" style="margin-right:5px;">x</span>
715 <input type="text" id="wpsc-tinymce-image-height" aria-label="height" class="wpsc-image-dimention" style="width:70px; margin-right:10px;" autocomplete="off">
716 <div class="checkbox-container">
717 <?php $unique_id = uniqid( 'wpsc_' ); ?>
718 <input id="<?php echo esc_attr( $unique_id ); ?>" type="checkbox" checked value="1"/>
719 <label for="<?php echo esc_attr( $unique_id ); ?>"><?php esc_attr_e( 'Constraint properties', 'supportcandy' ); ?></label>
720 </div>
721 </div>
722 </div>
723 <script>
724 jQuery(".wpsc-tinymce-image-url").change(function(){
725
726 var img = new Image();
727 img.src = jQuery(this).val();
728 img.onload = function() {
729 jQuery('#wpsc-tinymce-image-height').val(this.height);
730 jQuery('#wpsc-tinymce-image-width').val(this.width);
731 var aspectRatio = this.width/this.height;
732 //Get new height:
733 jQuery("#wpsc-tinymce-image-width").on("change", function(){
734
735 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
736 newWidth = jQuery(this).val();
737 newHeight = Math.round(newWidth/aspectRatio);
738 jQuery("#wpsc-tinymce-image-height").val(newHeight);
739 }
740 });
741 //Get new width:
742 jQuery("#wpsc-tinymce-image-height").on("change", function(){
743
744 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
745 newHeight = jQuery(this).val();
746 newWidth = Math.round(newHeight*aspectRatio);
747 jQuery("#wpsc-tinymce-image-width").val(newWidth);
748 }
749 });
750 }
751 });
752
753 /**
754 * Tinymce image picker
755 */
756 function wpsc_tinymce_image_picker() {
757
758 jQuery("#wpsc-fileupload").trigger("click");
759 jQuery("#wpsc-fileupload").unbind('change');
760
761 jQuery("#wpsc-fileupload").on("change", function() {
762 var file = this.files[0];
763 var dataform = new FormData();
764 dataform.append('file', file);
765 dataform.append('file_name', file.name);
766 dataform.append('action', 'wpsc_tinymce_upload_file');
767 dataform.append('_ajax_nonce', '<?php echo esc_attr( wp_create_nonce( 'wpsc_tinymce_upload_file' ) ); ?>');
768
769 jQuery.ajax({
770 url: supportcandy.ajax_url,
771 type: 'POST',
772 data: dataform,
773 processData: false,
774 contentType: false
775 }).done(function (res) {
776
777 jQuery('.wpsc-tinymce-image-url').val(res.imgURL);
778 var img = new Image();
779 img.src = res.imgURL;
780 img.onload = function() {
781
782 jQuery('#wpsc-tinymce-image-height').val(this.height);
783 jQuery('#wpsc-tinymce-image-width').val(this.width);
784 var aspectRatio = this.width/this.height;
785
786 //Get new height:
787 jQuery("#wpsc-tinymce-image-width").on("change", function() {
788
789 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
790 newWidth = jQuery(this).val();
791 newHeight = Math.round(newWidth/aspectRatio);
792 jQuery("#wpsc-tinymce-image-height").val(newHeight);
793 }
794 });
795
796 //Get new width:
797 jQuery("#wpsc-tinymce-image-height").on("change", function() {
798
799 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
800 newHeight = jQuery(this).val();
801 newWidth = Math.round(newHeight*aspectRatio);
802 jQuery("#wpsc-tinymce-image-width").val(newWidth);
803 }
804 });
805 };
806 });
807 });
808 }
809 </script>
810 </form>
811 <?php
812 $body = ob_get_clean();
813
814 ob_start();
815 ?>
816 <button class="wpsc-button small primary" onclick="wpsc_insert_editor_img('<?php echo esc_attr( $editor_id ); ?>');">
817 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
818 </button>
819 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
820 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
821 </button>
822 <?php
823 $footer = ob_get_clean();
824
825 $response = array(
826 'title' => $title,
827 'body' => $body,
828 'footer' => $footer,
829 );
830 wp_send_json( $response );
831 }
832
833 /**
834 * Custom tinymce image popup
835 *
836 * @return void
837 */
838 public static function edit_custom_image_tinymce() {
839
840 if ( check_ajax_referer( 'wpsc_edit_custom_image_tinymce', '_ajax_nonce', false ) != 1 ) {
841 wp_send_json_error( 'Unauthorized request!', 401 );
842 }
843
844 $title = esc_attr__( 'Edit image', 'supportcandy' );
845
846 $editor_id = isset( $_POST['editor_id'] ) ? sanitize_text_field( wp_unslash( $_POST['editor_id'] ) ) : '';
847 if ( ! $editor_id ) {
848 wp_send_json_error( 'Something went wrong!', 400 );
849 }
850
851 $height = isset( $_POST['height'] ) ? intval( $_POST['height'] ) : '';
852 if ( ! $height ) {
853 wp_send_json_error( 'Something went wrong!', 400 );
854 }
855
856 $width = isset( $_POST['width'] ) ? intval( $_POST['width'] ) : '';
857 if ( ! $width ) {
858 wp_send_json_error( 'Something went wrong!', 400 );
859 }
860
861 $src = isset( $_POST['src'] ) ? esc_url_raw( wp_unslash( $_POST['src'] ) ) : '';
862 if ( ! $src ) {
863 wp_send_json_error( 'Something went wrong!', 400 );
864 }
865
866 ob_start();
867 ?>
868 <form action="#" onsubmit="return false;" class="wpsc-insert-edit-image">
869 <div class="wpsc-input-group">
870 <div class="label-container">
871 <label for=""><?php esc_attr_e( 'Source', 'supportcandy' ); ?></label>
872 <span class="required-char">*</span>
873 </div>
874 <div style="display:flex;">
875 <input type="text" id="wpsc-tinymce-image-url" class="wpsc-tinymce-image-url" style="flex-grow: 1;" autocomplete="off" value="<?php echo esc_attr( $src ); ?>">
876 <button id="wpsc-tinymce-get-file-url" class="wpsc-button small secondary" style="margin-left: 2px; width:100px" onclick="wpsc_tinymce_image_picker();"><?php esc_attr_e( 'Upload', 'supportcandy' ); ?></button>
877 <input type='file' accept="image/*" name='fileupload' id='wpsc-fileupload' style='display: none;'>
878 </div>
879 </div>
880 <div class="wpsc-input-group">
881 <div class="label-container">
882 <label for=""><?php esc_attr_e( 'Dimentions', 'supportcandy' ); ?></label>
883 <span class="required-char">*</span>
884 </div>
885 <div style="display: flex; align-items:center;">
886 <input type="text" id="wpsc-tinymce-image-width" aria-label="width" class="wpsc-image-dimention" style="width:70px; margin-right:5px;" autocomplete="off" value="<?php echo esc_attr( $width ); ?>">
887 <span class="wpsc-image-dimention-x-sign" style="margin-right:5px;">x</span>
888 <input type="text" id="wpsc-tinymce-image-height" aria-label="height" class="wpsc-image-dimention" style="width:70px; margin-right:10px;" autocomplete="off" value="<?php echo esc_attr( $height ); ?>" >
889 <div class="checkbox-container">
890 <?php $unique_id = uniqid( 'wpsc_' ); ?>
891 <input id="<?php echo esc_attr( $unique_id ); ?>" type="checkbox" checked value="1"/>
892 <label for="<?php echo esc_attr( $unique_id ); ?>"><?php esc_attr_e( 'Constraint properties', 'supportcandy' ); ?></label>
893 </div>
894 </div>
895 </div>
896 <script>
897 jQuery(".wpsc-tinymce-image-url").change(function(){
898
899 var img = new Image();
900 img.src = jQuery(this).val();
901 img.onload = function() {
902 jQuery('#wpsc-tinymce-image-height').val(this.height);
903 jQuery('#wpsc-tinymce-image-width').val(this.width);
904 var aspectRatio = this.width/this.height;
905 //Get new height:
906 jQuery("#wpsc-tinymce-image-width").on("change", function(){
907
908 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
909 newWidth = jQuery(this).val();
910 newHeight = Math.round(newWidth/aspectRatio);
911 jQuery("#wpsc-tinymce-image-height").val(newHeight);
912 }
913 });
914 //Get new width:
915 jQuery("#wpsc-tinymce-image-height").on("change", function(){
916
917 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
918 newHeight = jQuery(this).val();
919 newWidth = Math.round(newHeight*aspectRatio);
920 jQuery("#wpsc-tinymce-image-width").val(newWidth);
921 }
922 });
923 }
924 });
925 var height = <?php echo esc_attr( $height ); ?>;
926 var width = <?php echo esc_attr( $width ); ?>;
927 var aspectRatio = width/height;
928 jQuery("#wpsc-tinymce-image-width").on("change", function(){
929
930 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
931 newWidth = jQuery(this).val();
932 newHeight = Math.round(newWidth/aspectRatio);
933 jQuery("#wpsc-tinymce-image-height").val(newHeight);
934 }
935 });
936 //Get new width:
937 jQuery("#wpsc-tinymce-image-height").on("change", function(){
938
939 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
940 newHeight = jQuery(this).val();
941 newWidth = Math.round(newHeight*aspectRatio);
942 jQuery("#wpsc-tinymce-image-width").val(newWidth);
943 }
944 });
945
946 /**
947 * Tinymce image picker
948 */
949 function wpsc_tinymce_image_picker() {
950
951 jQuery("#wpsc-fileupload").trigger("click");
952 jQuery("#wpsc-fileupload").unbind('change');
953
954 jQuery("#wpsc-fileupload").on("change", function() {
955 var file = this.files[0];
956 var dataform = new FormData();
957 dataform.append('file', file);
958 dataform.append('file_name', file.name);
959 dataform.append('action', 'wpsc_tinymce_upload_file');
960 dataform.append('_ajax_nonce', '<?php echo esc_attr( wp_create_nonce( 'wpsc_tinymce_upload_file' ) ); ?>');
961
962 jQuery.ajax({
963 url: supportcandy.ajax_url,
964 type: 'POST',
965 data: dataform,
966 processData: false,
967 contentType: false
968 }).done(function (res) {
969
970 jQuery('.wpsc-tinymce-image-url').val(res.imgURL);
971 var img = new Image();
972 img.src = res.imgURL;
973 img.onload = function() {
974
975 jQuery('#wpsc-tinymce-image-height').val(this.height);
976 jQuery('#wpsc-tinymce-image-width').val(this.width);
977 var aspectRatio = this.width/this.height;
978
979 //Get new height:
980 jQuery("#wpsc-tinymce-image-width").on("change", function() {
981
982 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
983 newWidth = jQuery(this).val();
984 newHeight = Math.round(newWidth/aspectRatio);
985 jQuery("#wpsc-tinymce-image-height").val(newHeight);
986 }
987 });
988
989 //Get new width:
990 jQuery("#wpsc-tinymce-image-height").on("change", function() {
991
992 if(jQuery("#<?php echo esc_attr( $unique_id ); ?>").prop('checked') == true){
993 newHeight = jQuery(this).val();
994 newWidth = Math.round(newHeight*aspectRatio);
995 jQuery("#wpsc-tinymce-image-width").val(newWidth);
996 }
997 });
998 };
999 });
1000 });
1001 }
1002 </script>
1003 </form>
1004 <?php
1005 $body = ob_get_clean();
1006
1007 ob_start();
1008 ?>
1009 <button class="wpsc-button small primary" onclick="wpsc_insert_editor_img('<?php echo esc_attr( $editor_id ); ?>');">
1010 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
1011 </button>
1012 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1013 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1014 </button>
1015 <?php
1016 $footer = ob_get_clean();
1017
1018 $response = array(
1019 'title' => $title,
1020 'body' => $body,
1021 'footer' => $footer,
1022 );
1023 wp_send_json( $response );
1024 }
1025
1026 /**
1027 * Check download file
1028 *
1029 * @return void
1030 */
1031 public static function check_download_file() {
1032
1033 if ( isset( $_REQUEST['wpsc_attachment'] ) ) { // phpcs:ignore
1034
1035 if ( WPSC_Functions::is_site_admin() && ! extension_loaded( 'fileinfo' ) ) {
1036 echo 'The fileinfo extension is not available. Please enable it in your PHP configuration.';
1037 exit;
1038 }
1039
1040 $current_user = WPSC_Current_User::$current_user;
1041 $has_auth = true;
1042 if ( isset( $_REQUEST['user'] ) && ! $current_user ) { // phpcs:ignore
1043
1044 $customer = new WPSC_Customer( intval( $_REQUEST['user'] ) ); // phpcs:ignore
1045 if ( ! $customer->id ) {
1046 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1047 }
1048
1049 $current_user = WPSC_Current_User::change_current_user( $customer->email );
1050 $has_auth = false;
1051 }
1052
1053 $attachment_id = intval( $_REQUEST['wpsc_attachment'] ); // phpcs:ignore
1054 $attachment = new WPSC_Attachment( $attachment_id );
1055 if ( ! $attachment->id ) {
1056 return;
1057 }
1058 $auth_code = isset($_REQUEST['auth_code']) ? sanitize_text_field( $_REQUEST['auth_code'] ) : ''; // phpcs:ignore
1059 $advanced = get_option( 'wpsc-ms-advanced-settings' );
1060 switch ( $attachment->source ) {
1061
1062 case 'cf':
1063 $cf = new WPSC_Custom_Field( $attachment->source_id );
1064 if ( ! $cf->id ) {
1065 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1066 }
1067
1068 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ) { // ticket field.
1069
1070 $ticket = new WPSC_Ticket( $attachment->ticket_id );
1071 if ( ! $ticket->id ) {
1072 $ticket = new WPSC_Archive_Ticket( $attachment->ticket_id );
1073 if ( ! $ticket->id ) {
1074 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1075 }
1076 }
1077
1078 if ( ! $has_auth ) {
1079 $auth_code = isset( $_REQUEST['auth_code'] ) ? sanitize_text_field( $_REQUEST['auth_code'] ) : ''; // phpcs:ignore
1080 if ( ! $auth_code || ! $ticket->auth_code || ! hash_equals( (string) $ticket->auth_code, $auth_code ) ) {
1081 wp_send_json_error( 'Unauthorized!', 401 );
1082 }
1083 }
1084
1085 if ( is_a( $ticket, 'WPSC_Ticket' ) || is_a( $ticket, 'WPSC_Archive_Ticket' ) ) {
1086 // Determine correct class based on ticket type.
1087 $ticket_class = is_a( $ticket, 'WPSC_Ticket' )
1088 ? 'WPSC_Individual_Ticket'
1089 : 'WPSC_Individual_Archive_Ticket';
1090
1091 // Assign current ticket to class static property.
1092 $ticket_class::$ticket = $ticket;
1093 $has_access = (
1094 ( $current_user->is_agent && $ticket_class::has_ticket_cap( 'view' ) ) ||
1095 $ticket_class::is_customer() ||
1096 ( ! $advanced['ticket-url-auth'] && $ticket->auth_code && hash_equals( (string) $ticket->auth_code, $auth_code ) )
1097 );
1098
1099 if ( ! $has_access ) {
1100 wp_send_json_error( __( 'Unauthorized!', 'supportcandy' ), 401 );
1101 }
1102 }
1103 self::file_download( $attachment );
1104
1105 } else { // customer field.
1106
1107 $customer = new WPSC_Customer( intval( $attachment->customer_id ) );
1108 $ticket_widgets = get_option( 'wpsc-ticket-widget', array() );
1109 $raised_by = $ticket_widgets['raised-by'];
1110
1111 if (
1112 $current_user->customer->id == $customer->id ||
1113 (
1114 $current_user->is_agent &&
1115 in_array( $current_user->agent->role, $raised_by['allowed-agent-roles'] )
1116 )
1117 ) {
1118 self::file_download( $attachment );
1119 }
1120 }
1121 break;
1122
1123 case 'reply':
1124 case 'report':
1125 $ticket = new WPSC_Ticket( $attachment->ticket_id );
1126 if ( ! $ticket->id ) {
1127 $ticket = new WPSC_Archive_Ticket( $attachment->ticket_id );
1128 if ( ! $ticket->id ) {
1129 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1130 }
1131 }
1132
1133 if ( ! $has_auth ) {
1134 $auth_code = isset( $_REQUEST['auth_code'] ) ? sanitize_text_field( $_REQUEST['auth_code'] ) : ''; // phpcs:ignore
1135 if ( ! $auth_code || ! $ticket->auth_code || ! hash_equals( (string) $ticket->auth_code, $auth_code ) ) {
1136 wp_send_json_error( 'Unauthorized!', 401 );
1137 }
1138 }
1139
1140 if ( is_a( $ticket, 'WPSC_Ticket' ) || is_a( $ticket, 'WPSC_Archive_Ticket' ) ) {
1141 // Determine correct class based on ticket type.
1142 $ticket_class = is_a( $ticket, 'WPSC_Ticket' )
1143 ? 'WPSC_Individual_Ticket'
1144 : 'WPSC_Individual_Archive_Ticket';
1145
1146 // Assign current ticket to class static property.
1147 $ticket_class::$ticket = $ticket;
1148 $has_access = (
1149 ( $current_user->is_agent && $ticket_class::has_ticket_cap( 'view' ) ) ||
1150 $ticket_class::is_customer() ||
1151 ( ! $advanced['ticket-url-auth'] && $ticket->auth_code && hash_equals( (string) $ticket->auth_code, $auth_code ) )
1152 );
1153
1154 if ( ! $has_access ) {
1155 wp_send_json_error( __( 'Unauthorized!', 'supportcandy' ), 401 );
1156 }
1157 }
1158 self::file_download( $attachment );
1159 break;
1160
1161 case 'note':
1162 $ticket = new WPSC_Ticket( $attachment->ticket_id );
1163 if ( ! $ticket->id ) {
1164 $ticket = new WPSC_Archive_Ticket( $attachment->ticket_id );
1165 if ( ! $ticket->id ) {
1166 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1167 }
1168 }
1169
1170 if ( ! $has_auth ) {
1171 $auth_code = isset( $_REQUEST['auth_code'] ) ? sanitize_text_field( $_REQUEST['auth_code'] ) : ''; // phpcs:ignore
1172 if ( ! $auth_code || ! $ticket->auth_code || ! hash_equals( (string) $ticket->auth_code, $auth_code ) ) {
1173 wp_send_json_error( 'Unauthorized!', 401 );
1174 }
1175 }
1176
1177 if ( is_a( $ticket, 'WPSC_Ticket' ) || is_a( $ticket, 'WPSC_Archive_Ticket' ) ) {
1178
1179 // Determine correct handler class dynamically.
1180 $ticket_class = is_a( $ticket, 'WPSC_Ticket' )
1181 ? 'WPSC_Individual_Ticket'
1182 : 'WPSC_Individual_Archive_Ticket';
1183
1184 // Assign the ticket.
1185 $ticket_class::$ticket = $ticket;
1186 if ( ! ( $current_user->is_agent && $ticket_class::has_ticket_cap( 'pn' ) ) ) {
1187 wp_send_json_error( __( 'Unauthorized!', 'supportcandy' ), 401 );
1188 }
1189 }
1190
1191 self::file_download( $attachment );
1192 break;
1193
1194 case 'img_editor':
1195 $ticket = new WPSC_Ticket( $attachment->ticket_id );
1196 if ( ! $ticket->id ) {
1197 $ticket = new WPSC_Archive_Ticket( $attachment->ticket_id );
1198 if ( ! $ticket->id ) {
1199 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1200 }
1201 }
1202
1203 if ( is_a( $ticket, 'WPSC_Ticket' ) || is_a( $ticket, 'WPSC_Archive_Ticket' ) ) {
1204
1205 // Determine class dynamically.
1206 $ticket_class = is_a( $ticket, 'WPSC_Ticket' )
1207 ? 'WPSC_Individual_Ticket'
1208 : 'WPSC_Individual_Archive_Ticket';
1209
1210 $ticket_class::$ticket = $ticket;
1211 if (
1212 ! (
1213 ( $current_user->is_agent && $ticket_class::has_ticket_cap( 'view' ) ) ||
1214 $ticket_class::is_customer() ||
1215 ( $ticket->auth_code && $auth_code && hash_equals( (string) $ticket->auth_code, $auth_code ) )
1216 )
1217 ) {
1218 wp_send_json_error( 'Unauthorized!', 401 );
1219 }
1220 self::file_download( $attachment );
1221 } else {
1222 wp_send_json_error( __( 'Invalid ticket type.', 'supportcandy' ), 400 );
1223 }
1224 break;
1225 case 'img_editor_tmp':
1226 // Not yet attached to any ticket/thread, so there is no auth-code
1227 // to check it against. Gate on the per-attachment nonce that was
1228 // handed only to whoever uploaded it.
1229 $view_nonce = isset( $_REQUEST['wpsc_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['wpsc_nonce'] ) ) : ''; // phpcs:ignore
1230 if ( ! $view_nonce || ! wp_verify_nonce( $view_nonce, self::get_img_editor_tmp_nonce_action( $attachment->id ) ) ) {
1231 wp_send_json_error( 'Unauthorized!', 401 );
1232 }
1233 self::file_download( $attachment );
1234 }
1235 }
1236 }
1237
1238 /**
1239 * Download attachment
1240 *
1241 * @param WPSC_Attachment $attachment - attachment object.
1242 * @return void
1243 */
1244 public static function file_download( $attachment ) {
1245
1246 // Turn off all output buffering.
1247 while ( ob_get_level() ) {
1248 ob_end_clean();
1249 }
1250
1251 $upload_dir = wp_upload_dir();
1252 $file_path = $upload_dir['basedir'] . $attachment->file_path;
1253 if ( ! file_exists( $file_path ) ) {
1254 echo 'File does not exists!';
1255 exit;
1256 }
1257
1258 // Check whether attachment is of image type.
1259 $attach_settings = get_option( 'wpsc-gs-file-attachments' );
1260 if ( $attachment->is_image && $attach_settings['image-download-behaviour'] == 'open-browser' ) {
1261 header( 'Content-Type: ' . mime_content_type( $file_path ) );
1262 readfile( $file_path ); // phpcs:ignore
1263 exit( 0 );
1264 }
1265
1266 header( 'Content-Description: File Transfer' );
1267 header( 'Cache-Control: public' );
1268 header( 'Content-Type: application/force-download' );
1269 header( 'Content-Disposition: attachment;filename="' . $attachment->name . '"' );
1270 header( 'Content-Length: ' . filesize( $file_path ) );
1271 flush();
1272 readfile( $file_path ); // phpcs:ignore
1273 exit( 0 );
1274 }
1275
1276 /**
1277 * Upload tinymce image file to database
1278 *
1279 * @return void
1280 */
1281 public static function tinymce_upload_file() {
1282
1283 if ( check_ajax_referer( 'wpsc_tinymce_upload_file', '_ajax_nonce', false ) != 1 ) {
1284 wp_send_json_error( 'Unauthorized request!', 401 );
1285 }
1286
1287 $file = isset( $_FILES['file'] ) ? $_FILES['file'] : false; // phpcs:ignore
1288 if ( ! $file ) {
1289 wp_send_json_error( 'File not found!', 400 );
1290 }
1291
1292 $file_settings = get_option( 'wpsc-gs-file-attachments' );
1293 $original_name = sanitize_file_name( $file['name'] );
1294 $filename = time() . '_' . sanitize_file_name( $file['name'] );
1295 $extension = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
1296 $today = new DateTime();
1297 $upload_dir = wp_upload_dir();
1298
1299 // Check file extension.
1300 $img_extensions = array( 'jpg', 'jpeg', 'png', 'gif' );
1301 if ( ! ( in_array( $extension, $img_extensions ) ) ) {
1302 wp_send_json_error( 'Invalid file extension!', 400 );
1303 }
1304
1305 // Allowed file size.
1306 $allowed_file_size = intval( $file_settings['attachments-max-filesize'] ) * 1000000;
1307 if ( ! ( isset( $file['size'] ) && $file['size'] <= $allowed_file_size ) ) {
1308 wp_send_json_error( 'File size exceeds allowed limit!', 400 );
1309 }
1310
1311 $filepath_short = '/wpsc/' . $today->format( 'Y' ) . '/' . $today->format( 'm' ) . '/' . $filename;
1312
1313 // Init attachment data.
1314 $data = array(
1315 'name' => $original_name,
1316 'file_path' => $filepath_short,
1317 'is_image' => 1,
1318 'date_created' => $today->format( 'Y-m-d H:i:s' ),
1319 'is_active' => 0,
1320 'source' => 'img_editor_tmp',
1321 );
1322
1323 // Set up upload overrides.
1324 $upload_overrides = array(
1325 'test_form' => false,
1326 );
1327 $file['name'] = $filename;
1328 add_filter( 'upload_dir', array( __CLASS__, 'wpsc_upload_dir' ) );
1329 $uploaded_file = wp_handle_upload( $file, $upload_overrides );
1330 // Insert record in database.
1331 if ( $uploaded_file && empty( $uploaded_file['error'] ) ) {
1332
1333 $pos = strpos( $uploaded_file['file'], '/wpsc/' );
1334 if ( $pos === false ) {
1335 wp_send_json_error( 'Something went wrong!', 500 );
1336 }
1337 $new_path = substr( $uploaded_file['file'], $pos );
1338 $data['file_path'] = $new_path;
1339 $attachment = self::insert( $data );
1340 if ( ! $attachment->id ) {
1341 wp_send_json_error( 'Something went wrong!', 500 );
1342 }
1343
1344 // Temporary in-editor images have no ticket yet to check an auth-code
1345 // against, so gate access with a per-attachment nonce instead, known
1346 // only to whoever just uploaded it via this response.
1347 $view_nonce = wp_create_nonce( self::get_img_editor_tmp_nonce_action( $attachment->id ) );
1348
1349 wp_send_json( array( 'imgURL' => home_url( '/' ) . '?wpsc_attachment=' . $attachment->id . '&wpsc_nonce=' . $view_nonce ) );
1350
1351 } else {
1352
1353 $error_message = isset( $uploaded_file['error'] ) ? $uploaded_file['error'] : 'Something went wrong!';
1354 wp_send_json_error( $error_message, 500 );
1355 }
1356 }
1357
1358 /**
1359 * Nonce action used to gate access to a not-yet-attached (img_editor_tmp)
1360 * in-editor image, since it isn't yet tied to any ticket/auth-code.
1361 *
1362 * @param int $attachment_id - attachment id.
1363 * @return string
1364 */
1365 private static function get_img_editor_tmp_nonce_action( $attachment_id ) {
1366 return 'wpsc_view_img_editor_tmp_' . $attachment_id;
1367 }
1368 }
1369 endif;
1370
1371 WPSC_Attachment::init();
1372