PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.5.4
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.5.4
3.5.4 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
← All changes | includes/admin/tickets/class-wpsc-individual-ticket.php +64 -36 3.4.8 → 3.5.4 View file →
@@ -253,9 +253,9 @@
253 253 $auth_code = isset( $_REQUEST['auth-code'] ) ? sanitize_text_field( $_REQUEST['auth-code'] ) : ''; // phpcs:ignore
254 254 if ( ! $auth_code ) {
255 255 $auth_code = isset( $_REQUEST['auth_code'] ) ? sanitize_text_field( $_REQUEST['auth_code'] ) : ''; // phpcs:ignore
256 256 }
257 - if ( $auth_code && $ticket->auth_code == $auth_code ) {
257 + if ( $auth_code && $ticket->auth_code && hash_equals( (string) $ticket->auth_code, $auth_code ) ) {
258 258 self::$url_auth = true;
259 259 }
260 260
261 261 // Set view profile as 'customer' if the user is either a valid logged-in customer or a guest with a valid auth code.
@@ -1188,29 +1188,10 @@
1188 1188 </div>
1189 1189
1190 1190 <script>
1191 1191
1192 - jQuery(document).find('.thread-text').each(function(){
1193 - var height = parseInt(jQuery(this).height());
1194 - <?php
1195 - $advanced = get_option( 'wpsc-ms-advanced-settings', array() );
1196 - if ( $advanced['view-more'] ) {
1197 - ?>
1198 - if( height > 100){
1199 - jQuery(this).height(100);
1200 - jQuery(this).parent().find('.wpsc-ticket-thread-expander').text(supportcandy.translations.view_more);
1201 - jQuery(this).parent().find('.wpsc-ticket-thread-expander').show();
1202 - }
1203 - <?php
1204 - } else {
1205 - ?>
1206 - jQuery(this).parent().find('.thread-text').height('auto');
1207 - <?php
1208 - }
1209 - ?>
1192 + wpsc_init_thread_expanders(jQuery(document).find('.thread-text'));
1210 1193
1211 - });
1212 -
1213 1194 supportcandy.threads = {last_thread: <?php echo esc_attr( $last_id ); ?>}
1214 1195 </script>
1215 1196 <?php
1216 1197
@@ -1331,9 +1312,9 @@
1331 1312 ?>
1332 1313
1333 1314 </div>
1334 1315
1335 - <div class="thread-text">
1316 + <div class="thread-text<?php echo $advanced['view-more'] ? ' wpsc-collapsed' : ''; ?>">
1336 1317 <?php
1337 1318 if ( $thread->is_active ) {
1338 1319 echo wp_kses_post( $thread->body );
1339 1320 } else {
@@ -1697,10 +1678,10 @@
1697 1678 $validated_attachments = array();
1698 1679 foreach ( $attachments as $id ) {
1699 1680
1700 1681 $attachment = new WPSC_Attachment( $id );
1701 - if ( ! $attachment->id ||
1702 - ( $attachment->ticket_id && $attachment->is_active ) ) {
1682 + // Only the uploader may bind their own, not-yet-bound attachment.
1683 + if ( ! WPSC_Attachment::can_claim( $attachment ) ) {
1703 1684 continue;
1704 1685 }
1705 1686
1706 1687 $validated_attachments[] = $id;
@@ -1732,11 +1713,18 @@
1732 1713 $attachment->save();
1733 1714 endforeach;
1734 1715
1735 1716 // activate description editor img attachments.
1736 - if ( preg_match_all( '/' . preg_quote( home_url( '/' ), '/' ) . '\?wpsc_attachment=(\d*)(&auth_code=[^&\s]*)?/', $description, $matches ) ) {
1737 - foreach ( $matches[1] as $id ) {
1738 - $attachment = new WPSC_Attachment( $id );
1717 + if ( preg_match_all( '/' . preg_quote( home_url( '/' ), '/' ) . '\?wpsc_attachment=(\d*)(?:&auth_code=[^&\s"\']*)?(?:&(?:amp;)?wpsc_nonce=([a-f0-9]*))?/', $description, $matches ) ) {
1718 + foreach ( $matches[1] as $key => $id ) {
1719 + $attachment = new WPSC_Attachment( $id );
1720 + // Only the uploader may bind their own, not-yet-bound
1721 + // attachment, proven by the recorded uploader identity or
1722 + // by the per-attachment nonce carried in the image url.
1723 + $nonce = isset( $matches[2][ $key ] ) ? $matches[2][ $key ] : '';
1724 + if ( ! WPSC_Attachment::can_claim( $attachment, $nonce ) ) {
1725 + continue;
1726 + }
1739 1727 $attachment->is_active = 1;
1740 1728 $attachment->source_id = $thread->id;
1741 1729 $attachment->ticket_id = self::$ticket->id;
1742 1730 $attachment->source = 'img_editor';
@@ -1814,10 +1802,10 @@
1814 1802 $validated_attachments = array();
1815 1803 foreach ( $attachments as $id ) {
1816 1804
1817 1805 $attachment = new WPSC_Attachment( $id );
1818 - if ( ! $attachment->id ||
1819 - ( $attachment->ticket_id && $attachment->is_active ) ) {
1806 + // Only the uploader may bind their own, not-yet-bound attachment.
1807 + if ( ! WPSC_Attachment::can_claim( $attachment ) ) {
1820 1808 continue;
1821 1809 }
1822 1810
1823 1811 $validated_attachments[] = $id;
@@ -1849,11 +1837,18 @@
1849 1837 $attachment->save();
1850 1838 endforeach;
1851 1839
1852 1840 // activate description editor img attachments.
1853 - if ( preg_match_all( '/' . preg_quote( home_url( '/' ), '/' ) . '\?wpsc_attachment=(\d*)(&auth_code=[^&\s]*)?/', $description, $matches ) ) {
1854 - foreach ( $matches[1] as $id ) {
1855 - $attachment = new WPSC_Attachment( $id );
1841 + if ( preg_match_all( '/' . preg_quote( home_url( '/' ), '/' ) . '\?wpsc_attachment=(\d*)(?:&auth_code=[^&\s"\']*)?(?:&(?:amp;)?wpsc_nonce=([a-f0-9]*))?/', $description, $matches ) ) {
1842 + foreach ( $matches[1] as $key => $id ) {
1843 + $attachment = new WPSC_Attachment( $id );
1844 + // Only the uploader may bind their own, not-yet-bound
1845 + // attachment, proven by the recorded uploader identity or
1846 + // by the per-attachment nonce carried in the image url.
1847 + $nonce = isset( $matches[2][ $key ] ) ? $matches[2][ $key ] : '';
1848 + if ( ! WPSC_Attachment::can_claim( $attachment, $nonce ) ) {
1849 + continue;
1850 + }
1856 1851 $attachment->is_active = 1;
1857 1852 $attachment->source_id = $thread->id;
1858 1853 $attachment->ticket_id = self::$ticket->id;
1859 1854 $attachment->source = 'img_editor';
@@ -1974,9 +1969,21 @@
1974 1969 }
1975 1970
1976 1971 // description attachments.
1977 1972 $attachments = isset( $_POST['description_attachments'] ) ? array_filter( array_map( 'intval', $_POST['description_attachments'] ) ) : array();
1973 + $validated_attachments = array();
1974 + foreach ( $attachments as $id ) {
1978 1975
1976 + $attachment = new WPSC_Attachment( $id );
1977 + // Only the uploader may bind their own, not-yet-bound attachment.
1978 + if ( ! WPSC_Attachment::can_claim( $attachment ) ) {
1979 + continue;
1980 + }
1981 +
1982 + $validated_attachments[] = $id;
1983 + }
1984 + $attachments = $validated_attachments;
1985 +
1979 1986 // submit reply.
1980 1987 $thread = WPSC_Thread::insert(
1981 1988 array(
1982 1989 'ticket' => self::$ticket->id,
@@ -2001,11 +2008,18 @@
2001 2008 $attachment->save();
2002 2009 endforeach;
2003 2010
2004 2011 // activate description editor img attachments.
2005 - if ( preg_match_all( '/' . preg_quote( home_url( '/' ), '/' ) . '\?wpsc_attachment=(\d*)(&auth_code=[^&\s]*)?/', $description, $matches ) ) {
2006 - foreach ( $matches[1] as $id ) {
2007 - $attachment = new WPSC_Attachment( $id );
2012 + if ( preg_match_all( '/' . preg_quote( home_url( '/' ), '/' ) . '\?wpsc_attachment=(\d*)(?:&auth_code=[^&\s"\']*)?(?:&(?:amp;)?wpsc_nonce=([a-f0-9]*))?/', $description, $matches ) ) {
2013 + foreach ( $matches[1] as $key => $id ) {
2014 + $attachment = new WPSC_Attachment( $id );
2015 + // Only the uploader may bind their own, not-yet-bound
2016 + // attachment, proven by the recorded uploader identity or
2017 + // by the per-attachment nonce carried in the image url.
2018 + $nonce = isset( $matches[2][ $key ] ) ? $matches[2][ $key ] : '';
2019 + if ( ! WPSC_Attachment::can_claim( $attachment, $nonce ) ) {
2020 + continue;
2021 + }
2008 2022 $attachment->is_active = 1;
2009 2023 $attachment->source_id = $thread->id;
2010 2024 $attachment->ticket_id = self::$ticket->id;
2011 2025 $attachment->source = 'img_editor';
@@ -3032,8 +3046,14 @@
3032 3046 ) {
3033 3047 continue;
3034 3048 }
3035 3049
3050 + // Already part of this ticket, otherwise only the uploader may
3051 + // bind a not-yet-bound attachment to it.
3052 + if ( ! $attachment->ticket_id && ! WPSC_Attachment::can_claim( $attachment ) ) {
3053 + continue;
3054 + }
3055 +
3036 3056 $validated_attachments[] = $id;
3037 3057 }
3038 3058 $thread_attachments = $validated_attachments;
3039 3059
@@ -3061,9 +3081,15 @@
3061 3081
3062 3082 foreach ( $matches[1] as $id ) {
3063 3083
3064 3084 $attachment = new WPSC_Attachment( $id );
3065 - if ( $attachment->is_active ) {
3085 + // is_active is not an ownership test: a deleted thread
3086 + // clears it while leaving ticket_id in place. Bind only
3087 + // what already belongs to this ticket, or what the
3088 + // requester uploaded and nothing owns yet.
3089 + if ( ! $attachment->id ||
3090 + ( $attachment->ticket_id && $attachment->ticket_id != self::$ticket->id ) ||
3091 + ( ! $attachment->ticket_id && ! WPSC_Attachment::can_claim( $attachment ) ) ) {
3066 3092 continue;
3067 3093 }
3068 3094
3069 3095 $attachment->is_active = 1;
@@ -3586,8 +3612,10 @@
3586 3612 $thread_types['val'][] = 'log';
3587 3613 }
3588 3614
3589 3615 $filters['meta_query'][] = $thread_types;
3616 +
3617 + $filters = apply_filters( 'wpsc_it_load_older_threads_filters', $filters );
3590 3618
3591 3619 $response = WPSC_Thread::find( $filters );
3592 3620 $last_id = $response['results'][ count( $response['results'] ) - 1 ]->id;
3593 3621