PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.5.2
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.5.2
8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 8.5.4 8.5.3 8.5.2 8.5.0 All 532 releases
chatbot / includes / class-wpbot-gc-download.php

class-wpbot-gc-download.php in WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services 8.5.2, at includes/class-wpbot-gc-download.php

168 lines 6.0 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;
4 }
5
6 class WPBotGCDownload
7 {
8 private $download_url = 'https://github.com/qcloud/gc/raw/master/wpbotgc.zip';
9 private $filename = 'wpbotgc.zip';
10
11 public function __construct() {
12 add_action( 'wp_ajax_qcld_wp_chatbot_gc_client_download', array( $this, 'downloadgc' ) );
13 add_action( 'wp_ajax_qcld_wp_chatbot_gc_client_extract', array( $this, 'extractgc' ) );
14 }
15
16 /**
17 * Initialise WP_Filesystem and return the global instance.
18 */
19 private function get_filesystem() {
20 global $wp_filesystem;
21 if ( empty( $wp_filesystem ) ) {
22 require_once ABSPATH . 'wp-admin/includes/file.php';
23 WP_Filesystem();
24 }
25 return $wp_filesystem;
26 }
27
28 /**
29 * Create a directory using WP_Filesystem.
30 */
31 public function create_folder( $gcdirectory ) {
32 $fs = $this->get_filesystem();
33 if ( ! $fs->is_dir( $gcdirectory ) ) {
34 return $fs->mkdir( $gcdirectory, FS_CHMOD_DIR );
35 }
36 return true;
37 }
38
39 /**
40 * Create a blank index.php guard file using WP_Filesystem.
41 */
42 public function create_file( $filename ) {
43 $fs = $this->get_filesystem();
44 if ( $fs->exists( $filename ) ) {
45 return true;
46 }
47 return $fs->put_contents( $filename, '<?php //silence is golden', FS_CHMOD_FILE );
48 }
49
50 public function downloadgc() {
51 if ( ! current_user_can( 'manage_options' ) ) {
52 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Unauthorized access', 'chatbot' ) ) );
53 wp_die();
54 }
55
56 $nonce = sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) );
57 if ( ! wp_verify_nonce( $nonce, 'wp_chatbot' ) ) {
58 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Failed in Security check', 'chatbot' ) ) );
59 wp_die();
60 }
61
62 $fs = $this->get_filesystem();
63 $gcdirectory = QCLD_wpCHATBOT_GC_DIRNAME;
64
65 if ( ! $fs->is_dir( $gcdirectory ) ) {
66 $this->create_folder( $gcdirectory );
67 }
68
69 if ( ! $fs->exists( $gcdirectory . '/index.php' ) ) {
70 $this->create_file( $gcdirectory . '/index.php' );
71 }
72
73 if ( ! $fs->is_dir( $gcdirectory ) ) {
74 wp_send_json( array( 'status' => 'error', 'content' => esc_html__( 'Server does not allow creating files and folders.', 'chatbot' ) ) );
75 wp_die();
76 }
77
78 $zip_file = $gcdirectory . '/' . $this->filename;
79
80 $remote_response = wp_remote_get( $this->download_url, array(
81 'timeout' => 60,
82 'stream' => true,
83 'filename' => $zip_file,
84 ) );
85
86 if ( is_wp_error( $remote_response ) ) {
87 wp_send_json( array( 'status' => 'error', 'content' => esc_html( $remote_response->get_error_message() ) ) );
88 wp_die();
89 }
90
91 $http_code = wp_remote_retrieve_response_code( $remote_response );
92 if ( 200 !== $http_code ) {
93 wp_send_json( array( 'status' => 'error', 'content' => esc_html__( 'Remote server returned an unexpected response.', 'chatbot' ) ) );
94 wp_die();
95 }
96
97 wp_send_json( array( 'status' => 'success', 'content' => esc_html__( 'File downloaded successfully.', 'chatbot' ) ) );
98 wp_die();
99 }
100
101 public function extractgc() {
102 if ( ! current_user_can( 'manage_options' ) ) {
103 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Unauthorized access', 'chatbot' ) ) );
104 wp_die();
105 }
106
107 $nonce = sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) );
108 if ( ! wp_verify_nonce( $nonce, 'wp_chatbot' ) ) {
109 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Failed in Security check', 'chatbot' ) ) );
110 wp_die();
111 }
112
113 $fs = $this->get_filesystem();
114 $gcdirectory = QCLD_wpCHATBOT_GC_DIRNAME;
115 $gcfilename = $gcdirectory . '/' . $this->filename;
116
117 // Verify the zip exists before attempting to open it.
118 if ( ! $fs->exists( $gcfilename ) ) {
119 wp_send_json( array( 'status' => 'error', 'content' => esc_html__( 'File not found.', 'chatbot' ) ) );
120 wp_die();
121 }
122
123 $zip = new ZipArchive();
124 if ( true !== $zip->open( $gcfilename ) ) {
125 wp_send_json( array( 'status' => 'error', 'content' => esc_html__( 'Could not open zip archive.', 'chatbot' ) ) );
126 wp_die();
127 }
128
129 // Validate every entry: block path traversal and absolute paths.
130 $real_dest = realpath( $gcdirectory );
131 for ( $i = 0; $i < $zip->numFiles; $i++ ) {
132 $stat = $zip->statIndex( $i );
133 $entry = $stat['name'];
134
135 if (
136 strpos( $entry, '../' ) !== false ||
137 strpos( $entry, '..' . DIRECTORY_SEPARATOR ) !== false ||
138 '/' === substr( $entry, 0, 1 )
139 ) {
140 $zip->close();
141 $fs->delete( $gcfilename );
142 wp_send_json( array( 'status' => 'error', 'content' => esc_html__( 'Invalid zip structure — path traversal detected.', 'chatbot' ) ) );
143 wp_die();
144 }
145
146 // Ensure resolved path stays within the destination directory.
147 $resolved = realpath( $real_dest . DIRECTORY_SEPARATOR . $entry );
148 if ( $resolved !== false && strpos( $resolved, $real_dest ) !== 0 ) {
149 $zip->close();
150 $fs->delete( $gcfilename );
151 wp_send_json( array( 'status' => 'error', 'content' => esc_html__( 'Invalid zip structure — entry escapes destination.', 'chatbot' ) ) );
152 wp_die();
153 }
154 }
155
156 $zip->extractTo( $gcdirectory );
157 $zip->close();
158
159 // Remove the zip after successful extraction.
160 $fs->delete( $gcfilename );
161
162 wp_send_json( array( 'status' => 'success', 'content' => esc_html__( 'Files extracted successfully.', 'chatbot' ) ) );
163 wp_die();
164 }
165 }
166
167 new WPBotGCDownload();
168