PluginProbe
The WP Remote WordPress Plugin / 6.02
The WP Remote WordPress Plugin v6.02
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
wpremote / callback / streams.php

streams.php in The WP Remote WordPress Plugin 6.02, at callback/streams.php

257 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fread
3 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
4 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fsockopen
5 // We use php method like fread, fwrite to read only a portion of a file, we don't have a direct method for partial reads since WP_Filesystem doesn't support a direct equivalent to fread, fwrite.
6 // The entire file deals with custom stream handling
7 // We need direct socket/file operations for this functionality
8 // WordPress filesystem alternatives wouldn't work for this use case
9 // It's better to disable these specific rules at file level than adding individual ignore comments
10 if (!defined('ABSPATH')) exit;
11 if (!class_exists('BVRespStream')) :
12
13 class BVStream extends BVCallbackBase {
14 public $bvb64stream;
15 public $bvb64cksize;
16 public $checksum;
17
18 function __construct($request) {
19 $this->bvb64stream = $request->bvb64stream;
20 $this->bvb64cksize = $request->bvb64cksize;
21 $this->checksum = $request->checksum;
22 }
23
24 public function writeChunk($chunk) {
25 }
26
27 public static function startStream($account, $request) {
28 $result = array();
29 $params = $request->params;
30 $stream = new BVRespStream($request);
31 if ($request->isAPICall()) {
32 $stream = new BVHttpStream($request);
33 if (!$stream->connect()) {
34 $apicallstatus = array(
35 "httperror" => "Cannot Open Connection to Host",
36 "streamerrno" => $stream->errno,
37 "streamerrstr" => $stream->errstr
38 );
39 return array("apicallstatus" => $apicallstatus);
40 }
41 if (array_key_exists('acbmthd', $params)) {
42 $qstr = http_build_query(array('bvapicheck' => $params['bvapicheck']));
43 $url = '/bvapi/'.$params['acbmthd']."?".$qstr;
44 if (array_key_exists('acbqry', $params)) {
45 $url .= "&".$params['acbqry'];
46 }
47 $stream->multipartChunkedPost($url);
48 } else {
49 return array("apicallstatus" => array("httperror" => "ApiCall method not present"));
50 }
51 }
52 return array('stream' => $stream);
53 }
54
55 public function writeStream($chunk) {
56 if (strlen($chunk) > 0) {
57 $bvb64_prefix = "";
58 if ($this->bvb64stream) {
59 $chunk_size = $this->bvb64cksize;
60 $chunk = $this->base64Encode($chunk, $chunk_size);
61 $bvb64_prefix .= "BVB64" . ":";
62 }
63
64 $hash_prefix = "";
65 if ($this->checksum == 'crc32') {
66 $hash_prefix .= "CRC32" . ":" . crc32($chunk) . ":";
67 } else if ($this->checksum == 'md5') {
68 $hash_prefix .= "MD5" . ":" . md5($chunk) . ":";
69 }
70
71 $chunk = $hash_prefix . $bvb64_prefix . strlen($chunk) . ":" . $chunk;
72
73 $this->writeChunk($chunk);
74 }
75 }
76 }
77
78 class BVRespStream extends BVStream {
79 public $bvboundry;
80
81 function __construct($request) {
82 parent::__construct($request);
83 $this->bvboundry = $request->bvboundry;
84 }
85
86 public function writeChunk($chunk) {
87 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- chunk should not be escaped
88 echo $this->bvboundry . "ckckckckck" . $chunk . $this->bvboundry . "ckckckckck";
89 }
90 public function endStream() {
91 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
92 echo $this->bvboundry . "rerererere";
93
94 return array();
95 }
96 }
97
98 class BVHttpStream extends BVStream {
99 var $user_agent = 'BVHttpStream';
100 var $host;
101 var $port;
102 var $timeout = 20;
103 var $conn;
104 var $errno;
105 var $errstr;
106 var $boundary;
107 var $apissl;
108
109 function __construct($request) {
110 parent::__construct($request);
111 $this->host = $request->params['apihost'];
112 $this->port = intval($request->params['apiport']);
113 $this->apissl = array_key_exists('apissl', $request->params);
114 }
115
116 public function connect() {
117 if ($this->apissl && function_exists('stream_socket_client')) {
118 $this->conn = stream_socket_client("ssl://".$this->host.":".$this->port, $errno, $errstr, $this->timeout);
119 } else {
120 $this->conn = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
121 }
122 if (!$this->conn) {
123 $this->errno = $errno;
124 $this->errstr = $errstr;
125 return false;
126 }
127 socket_set_timeout($this->conn, $this->timeout);
128 return true;
129 }
130
131 public function write($data) {
132 fwrite($this->conn, $data);
133 }
134
135 public function sendChunk($data) {
136 $this->write(sprintf("%x\r\n", strlen($data)));
137 $this->write($data);
138 $this->write("\r\n");
139 }
140
141 public function sendRequest($method, $url, $headers = array(), $body = null) {
142 $def_hdrs = array("Connection" => "keep-alive",
143 "Host" => $this->host);
144 $headers = array_merge($def_hdrs, $headers);
145 $request = strtoupper($method)." ".$url." HTTP/1.1\r\n";
146 if (null != $body) {
147 $headers["Content-length"] = strlen($body);
148 }
149 foreach($headers as $key=>$val) {
150 $request .= $key.":".$val."\r\n";
151 }
152 $request .= "\r\n";
153 if (null != $body) {
154 $request .= $body;
155 }
156 $this->write($request);
157 return $request;
158 }
159
160 public function post($url, $headers = array(), $body = "") {
161 if(is_array($body)) {
162 $b = "";
163 foreach($body as $key=>$val) {
164 $b .= $key."=".urlencode($val)."&";
165 }
166 $body = substr($b, 0, strlen($b) - 1);
167 }
168 $this->sendRequest("POST", $url, $headers, $body);
169 }
170
171 public function streamedPost($url, $headers = array()) {
172 $headers['Transfer-Encoding'] = "chunked";
173 $this->sendRequest("POST", $url, $headers);
174 }
175
176 public function multipartChunkedPost($url) {
177 $mph = array(
178 "Content-Disposition" => "form-data; name=bvinfile; filename=data",
179 "Content-Type" => "application/octet-stream"
180 );
181 $rnd = rand(100000, 999999); // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_rand
182 $this->boundary = "----".$rnd;
183 $prologue = "--".$this->boundary."\r\n";
184 foreach($mph as $key=>$val) {
185 $prologue .= $key.":".$val."\r\n";
186 }
187 $prologue .= "\r\n";
188 $headers = array('Content-Type' => "multipart/form-data; boundary=".$this->boundary);
189 $this->streamedPost($url, $headers);
190 $this->sendChunk($prologue);
191 }
192
193 public function writeChunk($data) {
194 $this->sendChunk($data);
195 }
196
197 public function closeChunk() {
198 $this->sendChunk("");
199 }
200
201 public function endStream() {
202 $epilogue = "\r\n\r\n--".$this->boundary."--\r\n";
203 $this->sendChunk($epilogue);
204 $this->closeChunk();
205
206 $result = array();
207 $resp = $this->getResponse();
208 if (array_key_exists('httperror', $resp)) {
209 $result["httperror"] = $resp['httperror'];
210 } else {
211 $result["respstatus"] = $resp['status'];
212 $result["respstatus_string"] = $resp['status_string'];
213 }
214 return array("apicallstatus" => $result);
215 }
216
217 public function getResponse() {
218 $response = array();
219 $response['headers'] = array();
220 $state = 1;
221 $conlen = 0;
222 stream_set_timeout($this->conn, 300);
223 while (!feof($this->conn)) {
224 $line = fgets($this->conn, 4096);
225 if (1 == $state) {
226 if (!WPRHelper::safePregMatch('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) {
227 $response['httperror'] = "Status code line invalid: ".htmlentities($line);
228 return $response;
229 }
230 $response['http_version'] = $m[1];
231 $response['status'] = $m[2];
232 $response['status_string'] = $m[3];
233 $state = 2;
234 } else if (2 == $state) {
235 # End of headers
236 if (2 == strlen($line)) {
237 if ($conlen > 0)
238 $response['body'] = fread($this->conn, $conlen);
239 return $response;
240 }
241 if (!WPRHelper::safePregMatch('/([^:]+):\\s*(.*)/', $line, $m)) {
242 // Skip to the next header
243 continue;
244 }
245 $key = strtolower(trim($m[1]));
246 $val = trim($m[2]);
247 $response['headers'][$key] = $val;
248 if ($key == "content-length") {
249 $conlen = intval($val);
250 }
251 }
252 }
253 return $response;
254 }
255 }
256 // phpcs:enable
257 endif;