Mercurial > hg > rc1
comparison plugins/password/drivers/directadmin.php @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 15:50:29 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e000243b222 |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * DirectAdmin Password Driver | |
5 * | |
6 * Driver to change passwords via DirectAdmin Control Panel | |
7 * | |
8 * @version 2.1 | |
9 * @author Victor Benincasa <vbenincasa@gmail.com> | |
10 * | |
11 * Copyright (C) 2005-2013, The Roundcube Dev Team | |
12 * | |
13 * This program is free software: you can redistribute it and/or modify | |
14 * it under the terms of the GNU General Public License as published by | |
15 * the Free Software Foundation, either version 3 of the License, or | |
16 * (at your option) any later version. | |
17 * | |
18 * This program is distributed in the hope that it will be useful, | |
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 * GNU General Public License for more details. | |
22 * | |
23 * You should have received a copy of the GNU General Public License | |
24 * along with this program. If not, see http://www.gnu.org/licenses/. | |
25 */ | |
26 | |
27 class rcube_directadmin_password | |
28 { | |
29 public function save($curpass, $passwd) | |
30 { | |
31 $rcmail = rcmail::get_instance(); | |
32 $Socket = new HTTPSocket; | |
33 | |
34 $da_user = $_SESSION['username']; | |
35 $da_curpass = $curpass; | |
36 $da_newpass = $passwd; | |
37 $da_host = $rcmail->config->get('password_directadmin_host'); | |
38 $da_port = $rcmail->config->get('password_directadmin_port'); | |
39 | |
40 if (strpos($da_user, '@') === false) { | |
41 return array('code' => PASSWORD_ERROR, 'message' => 'Change the SYSTEM user password through control panel!'); | |
42 } | |
43 | |
44 $da_host = str_replace('%h', $_SESSION['imap_host'], $da_host); | |
45 $da_host = str_replace('%d', $rcmail->user->get_username('domain'), $da_host); | |
46 | |
47 $Socket->connect($da_host,$da_port); | |
48 $Socket->set_method('POST'); | |
49 $Socket->query('/CMD_CHANGE_EMAIL_PASSWORD', | |
50 array( | |
51 'email' => $da_user, | |
52 'oldpassword' => $da_curpass, | |
53 'password1' => $da_newpass, | |
54 'password2' => $da_newpass, | |
55 'api' => '1' | |
56 )); | |
57 $response = $Socket->fetch_parsed_body(); | |
58 | |
59 //DEBUG | |
60 //rcube::console("Password Plugin: [USER: $da_user] [HOST: $da_host] - Response: [SOCKET: ".$Socket->result_status_code."] [DA ERROR: ".strip_tags($response['error'])."] [TEXT: ".$response[text]."]"); | |
61 | |
62 if($Socket->result_status_code != 200) | |
63 return array('code' => PASSWORD_CONNECT_ERROR, 'message' => $Socket->error[0]); | |
64 elseif($response['error'] == 1) | |
65 return array('code' => PASSWORD_ERROR, 'message' => strip_tags($response['text'])); | |
66 else | |
67 return PASSWORD_SUCCESS; | |
68 } | |
69 } | |
70 | |
71 | |
72 /** | |
73 * Socket communication class. | |
74 * | |
75 * Originally designed for use with DirectAdmin's API, this class will fill any HTTP socket need. | |
76 * | |
77 * Very, very basic usage: | |
78 * $Socket = new HTTPSocket; | |
79 * echo $Socket->get('http://user:pass@somehost.com:2222/CMD_API_SOMEAPI?query=string&this=that'); | |
80 * | |
81 * @author Phi1 'l0rdphi1' Stier <l0rdphi1@liquenox.net> | |
82 * @updates 2.7 and 2.8 by Victor Benincasa <vbenincasa @ gmail.com> | |
83 * @package HTTPSocket | |
84 * @version 2.8 | |
85 */ | |
86 class HTTPSocket { | |
87 | |
88 var $version = '2.8'; | |
89 | |
90 /* all vars are private except $error, $query_cache, and $doFollowLocationHeader */ | |
91 | |
92 var $method = 'GET'; | |
93 | |
94 var $remote_host; | |
95 var $remote_port; | |
96 var $remote_uname; | |
97 var $remote_passwd; | |
98 | |
99 var $result; | |
100 var $result_header; | |
101 var $result_body; | |
102 var $result_status_code; | |
103 | |
104 var $lastTransferSpeed; | |
105 | |
106 var $bind_host; | |
107 | |
108 var $error = array(); | |
109 var $warn = array(); | |
110 var $query_cache = array(); | |
111 | |
112 var $doFollowLocationHeader = TRUE; | |
113 var $redirectURL; | |
114 | |
115 var $extra_headers = array(); | |
116 | |
117 /** | |
118 * Create server "connection". | |
119 * | |
120 */ | |
121 function connect($host, $port = '' ) | |
122 { | |
123 if (!is_numeric($port)) | |
124 { | |
125 $port = 2222; | |
126 } | |
127 | |
128 $this->remote_host = $host; | |
129 $this->remote_port = $port; | |
130 } | |
131 | |
132 function bind( $ip = '' ) | |
133 { | |
134 if ( $ip == '' ) | |
135 { | |
136 $ip = $_SERVER['SERVER_ADDR']; | |
137 } | |
138 | |
139 $this->bind_host = $ip; | |
140 } | |
141 | |
142 /** | |
143 * Change the method being used to communicate. | |
144 * | |
145 * @param string|null request method. supports GET, POST, and HEAD. default is GET | |
146 */ | |
147 function set_method( $method = 'GET' ) | |
148 { | |
149 $this->method = strtoupper($method); | |
150 } | |
151 | |
152 /** | |
153 * Specify a username and password. | |
154 * | |
155 * @param string|null username. default is null | |
156 * @param string|null password. default is null | |
157 */ | |
158 function set_login( $uname = '', $passwd = '' ) | |
159 { | |
160 if ( strlen($uname) > 0 ) | |
161 { | |
162 $this->remote_uname = $uname; | |
163 } | |
164 | |
165 if ( strlen($passwd) > 0 ) | |
166 { | |
167 $this->remote_passwd = $passwd; | |
168 } | |
169 | |
170 } | |
171 | |
172 /** | |
173 * Query the server | |
174 * | |
175 * @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too. | |
176 * @param string|array query to pass to url | |
177 * @param int if connection KB/s drops below value here, will drop connection | |
178 */ | |
179 function query( $request, $content = '', $doSpeedCheck = 0 ) | |
180 { | |
181 $this->error = $this->warn = array(); | |
182 $this->result_status_code = NULL; | |
183 | |
184 // is our request a http(s):// ... ? | |
185 if (preg_match('/^(http|https):\/\//i',$request)) | |
186 { | |
187 $location = parse_url($request); | |
188 $this->connect($location['host'],$location['port']); | |
189 $this->set_login($location['user'],$location['pass']); | |
190 | |
191 $request = $location['path']; | |
192 $content = $location['query']; | |
193 | |
194 if ( strlen($request) < 1 ) | |
195 { | |
196 $request = '/'; | |
197 } | |
198 | |
199 } | |
200 | |
201 $array_headers = array( | |
202 'User-Agent' => "HTTPSocket/$this->version", | |
203 'Host' => ( $this->remote_port == 80 ? parse_url($this->remote_host,PHP_URL_HOST) : parse_url($this->remote_host,PHP_URL_HOST).":".$this->remote_port ), | |
204 'Accept' => '*/*', | |
205 'Connection' => 'Close' ); | |
206 | |
207 foreach ( $this->extra_headers as $key => $value ) | |
208 { | |
209 $array_headers[$key] = $value; | |
210 } | |
211 | |
212 $this->result = $this->result_header = $this->result_body = ''; | |
213 | |
214 // was content sent as an array? if so, turn it into a string | |
215 if (is_array($content)) | |
216 { | |
217 $pairs = array(); | |
218 | |
219 foreach ( $content as $key => $value ) | |
220 { | |
221 $pairs[] = "$key=".urlencode($value); | |
222 } | |
223 | |
224 $content = join('&',$pairs); | |
225 unset($pairs); | |
226 } | |
227 | |
228 $OK = TRUE; | |
229 | |
230 // instance connection | |
231 if ($this->bind_host) | |
232 { | |
233 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); | |
234 socket_bind($socket,$this->bind_host); | |
235 | |
236 if (!@socket_connect($socket,$this->remote_host,$this->remote_port)) | |
237 { | |
238 $OK = FALSE; | |
239 } | |
240 | |
241 } | |
242 else | |
243 { | |
244 $socket = @fsockopen( $this->remote_host, $this->remote_port, $sock_errno, $sock_errstr, 10 ); | |
245 } | |
246 | |
247 if ( !$socket || !$OK ) | |
248 { | |
249 $this->error[] = "Can't create socket connection to $this->remote_host:$this->remote_port."; | |
250 return 0; | |
251 } | |
252 | |
253 // if we have a username and password, add the header | |
254 if ( isset($this->remote_uname) && isset($this->remote_passwd) ) | |
255 { | |
256 $array_headers['Authorization'] = 'Basic '.base64_encode("$this->remote_uname:$this->remote_passwd"); | |
257 } | |
258 | |
259 // for DA skins: if $this->remote_passwd is NULL, try to use the login key system | |
260 if ( isset($this->remote_uname) && $this->remote_passwd == NULL ) | |
261 { | |
262 $array_headers['Cookie'] = "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}"; | |
263 } | |
264 | |
265 // if method is POST, add content length & type headers | |
266 if ( $this->method == 'POST' ) | |
267 { | |
268 $array_headers['Content-type'] = 'application/x-www-form-urlencoded'; | |
269 $array_headers['Content-length'] = strlen($content); | |
270 } | |
271 // else method is GET or HEAD. we don't support anything else right now. | |
272 else | |
273 { | |
274 if ($content) | |
275 { | |
276 $request .= "?$content"; | |
277 } | |
278 } | |
279 | |
280 // prepare query | |
281 $query = "$this->method $request HTTP/1.0\r\n"; | |
282 foreach ( $array_headers as $key => $value ) | |
283 { | |
284 $query .= "$key: $value\r\n"; | |
285 } | |
286 $query .= "\r\n"; | |
287 | |
288 // if POST we need to append our content | |
289 if ( $this->method == 'POST' && $content ) | |
290 { | |
291 $query .= "$content\r\n\r\n"; | |
292 } | |
293 | |
294 // query connection | |
295 if ($this->bind_host) | |
296 { | |
297 socket_write($socket,$query); | |
298 | |
299 // now load results | |
300 while ( $out = socket_read($socket,2048) ) | |
301 { | |
302 $this->result .= $out; | |
303 } | |
304 } | |
305 else | |
306 { | |
307 fwrite( $socket, $query, strlen($query) ); | |
308 | |
309 // now load results | |
310 $this->lastTransferSpeed = 0; | |
311 $status = socket_get_status($socket); | |
312 $startTime = time(); | |
313 $length = 0; | |
314 while ( !feof($socket) && !$status['timed_out'] ) | |
315 { | |
316 $chunk = fgets($socket,1024); | |
317 $length += strlen($chunk); | |
318 $this->result .= $chunk; | |
319 | |
320 $elapsedTime = time() - $startTime; | |
321 | |
322 if ( $elapsedTime > 0 ) | |
323 { | |
324 $this->lastTransferSpeed = ($length/1024)/$elapsedTime; | |
325 } | |
326 | |
327 if ( $doSpeedCheck > 0 && $elapsedTime > 5 && $this->lastTransferSpeed < $doSpeedCheck ) | |
328 { | |
329 $this->warn[] = "kB/s for last 5 seconds is below 50 kB/s (~".( ($length/1024)/$elapsedTime )."), dropping connection..."; | |
330 $this->result_status_code = 503; | |
331 break; | |
332 } | |
333 | |
334 } | |
335 | |
336 if ( $this->lastTransferSpeed == 0 ) | |
337 { | |
338 $this->lastTransferSpeed = $length/1024; | |
339 } | |
340 | |
341 } | |
342 | |
343 list($this->result_header,$this->result_body) = preg_split("/\r\n\r\n/",$this->result,2); | |
344 | |
345 if ($this->bind_host) | |
346 { | |
347 socket_close($socket); | |
348 } | |
349 else | |
350 { | |
351 fclose($socket); | |
352 } | |
353 | |
354 $this->query_cache[] = $query; | |
355 | |
356 | |
357 $headers = $this->fetch_header(); | |
358 | |
359 // what return status did we get? | |
360 if (!$this->result_status_code) | |
361 { | |
362 preg_match("#HTTP/1\.. (\d+)#",$headers[0],$matches); | |
363 $this->result_status_code = $matches[1]; | |
364 } | |
365 | |
366 // did we get the full file? | |
367 if ( !empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body) ) | |
368 { | |
369 $this->result_status_code = 206; | |
370 } | |
371 | |
372 // now, if we're being passed a location header, should we follow it? | |
373 if ($this->doFollowLocationHeader) | |
374 { | |
375 if ($headers['location']) | |
376 { | |
377 $this->redirectURL = $headers['location']; | |
378 $this->query($headers['location']); | |
379 } | |
380 } | |
381 } | |
382 | |
383 function getTransferSpeed() | |
384 { | |
385 return $this->lastTransferSpeed; | |
386 } | |
387 | |
388 /** | |
389 * The quick way to get a URL's content :) | |
390 * | |
391 * @param string URL | |
392 * @param boolean return as array? (like PHP's file() command) | |
393 * @return string result body | |
394 */ | |
395 function get($location, $asArray = FALSE ) | |
396 { | |
397 $this->query($location); | |
398 | |
399 if ( $this->get_status_code() == 200 ) | |
400 { | |
401 if ($asArray) | |
402 { | |
403 return preg_split("/\n/",$this->fetch_body()); | |
404 } | |
405 | |
406 return $this->fetch_body(); | |
407 } | |
408 | |
409 return FALSE; | |
410 } | |
411 | |
412 /** | |
413 * Returns the last status code. | |
414 * 200 = OK; | |
415 * 403 = FORBIDDEN; | |
416 * etc. | |
417 * | |
418 * @return int status code | |
419 */ | |
420 function get_status_code() | |
421 { | |
422 return $this->result_status_code; | |
423 } | |
424 | |
425 /** | |
426 * Adds a header, sent with the next query. | |
427 * | |
428 * @param string header name | |
429 * @param string header value | |
430 */ | |
431 function add_header($key,$value) | |
432 { | |
433 $this->extra_headers[$key] = $value; | |
434 } | |
435 | |
436 /** | |
437 * Clears any extra headers. | |
438 * | |
439 */ | |
440 function clear_headers() | |
441 { | |
442 $this->extra_headers = array(); | |
443 } | |
444 | |
445 /** | |
446 * Return the result of a query. | |
447 * | |
448 * @return string result | |
449 */ | |
450 function fetch_result() | |
451 { | |
452 return $this->result; | |
453 } | |
454 | |
455 /** | |
456 * Return the header of result (stuff before body). | |
457 * | |
458 * @param string (optional) header to return | |
459 * @return array result header | |
460 */ | |
461 function fetch_header( $header = '' ) | |
462 { | |
463 $array_headers = preg_split("/\r\n/",$this->result_header); | |
464 $array_return = array( 0 => $array_headers[0] ); | |
465 unset($array_headers[0]); | |
466 | |
467 foreach ( $array_headers as $pair ) | |
468 { | |
469 list($key,$value) = preg_split("/: /",$pair,2); | |
470 $array_return[strtolower($key)] = $value; | |
471 } | |
472 | |
473 if ( $header != '' ) | |
474 { | |
475 return $array_return[strtolower($header)]; | |
476 } | |
477 | |
478 return $array_return; | |
479 } | |
480 | |
481 /** | |
482 * Return the body of result (stuff after header). | |
483 * | |
484 * @return string result body | |
485 */ | |
486 function fetch_body() | |
487 { | |
488 return $this->result_body; | |
489 } | |
490 | |
491 /** | |
492 * Return parsed body in array format. | |
493 * | |
494 * @return array result parsed | |
495 */ | |
496 function fetch_parsed_body() | |
497 { | |
498 parse_str($this->result_body,$x); | |
499 return $x; | |
500 } | |
501 | |
502 } |