4 * DirectAdmin Password Driver
6 * Driver to change passwords via DirectAdmin Control Panel
9 * @author Victor Benincasa <vbenincasa@gmail.com>
14 function password_save($curpass, $passwd){
16 $rcmail = rcmail::get_instance();
17 $Socket = new HTTPSocket;
19 $da_user = $_SESSION['username'];
20 $da_curpass = $curpass;
21 $da_newpass = $passwd;
22 $da_host = $rcmail->config->get('password_directadmin_host');
23 $da_port = $rcmail->config->get('password_directadmin_port');
25 $Socket->connect($da_host,$da_port);
26 $Socket->set_method('POST');
27 $Socket->query('/CMD_CHANGE_EMAIL_PASSWORD',
30 'oldpassword' => $da_curpass,
31 'password1' => $da_newpass,
32 'password2' => $da_newpass,
35 $response = $Socket->fetch_parsed_body();
37 //console("DA error response: $response[text] [$da_user]");
39 if($Socket->result_status_code <> 200)
40 return PASSWORD_CONNECT_ERROR;
41 elseif($response['error'] == 1){ //Error description: $response[text]
42 return PASSWORD_ERROR;
44 return PASSWORD_SUCCESS;
50 * Socket communication class.
52 * Originally designed for use with DirectAdmin's API, this class will fill any HTTP socket need.
54 * Very, very basic usage:
55 * $Socket = new HTTPSocket;
56 * echo $Socket->get('http://user:pass@somesite.com/somedir/some.file?query=string&this=that');
58 * @author Phi1 'l0rdphi1' Stier <l0rdphi1@liquenox.net>
66 /* all vars are private except $error, $query_cache, and $doFollowLocationHeader */
78 var $result_status_code;
80 var $lastTransferSpeed;
86 var $query_cache = array();
88 var $doFollowLocationHeader = TRUE;
91 var $extra_headers = array();
94 * Create server "connection".
97 function connect($host, $port = '' )
99 if (!is_numeric($port))
104 $this->remote_host = $host;
105 $this->remote_port = $port;
108 function bind( $ip = '' )
112 $ip = $_SERVER['SERVER_ADDR'];
115 $this->bind_host = $ip;
119 * Change the method being used to communicate.
121 * @param string|null request method. supports GET, POST, and HEAD. default is GET
123 function set_method( $method = 'GET' )
125 $this->method = strtoupper($method);
129 * Specify a username and password.
131 * @param string|null username. defualt is null
132 * @param string|null password. defualt is null
134 function set_login( $uname = '', $passwd = '' )
136 if ( strlen($uname) > 0 )
138 $this->remote_uname = $uname;
141 if ( strlen($passwd) > 0 )
143 $this->remote_passwd = $passwd;
151 * @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too.
152 * @param string|array query to pass to url
153 * @param int if connection KB/s drops below value here, will drop connection
155 function query( $request, $content = '', $doSpeedCheck = 0 )
157 $this->error = $this->warn = array();
158 $this->result_status_code = NULL;
160 // is our request a http:// ... ?
161 if (preg_match('!^http://!i',$request))
163 $location = parse_url($request);
164 $this->connect($location['host'],$location['port']);
165 $this->set_login($location['user'],$location['pass']);
167 $request = $location['path'];
168 $content = $location['query'];
170 if ( strlen($request) < 1 )
177 $array_headers = array(
178 'User-Agent' => "HTTPSocket/$this->version",
179 'Host' => ( $this->remote_port == 80 ? $this->remote_host : "$this->remote_host:$this->remote_port" ),
181 'Connection' => 'Close' );
183 foreach ( $this->extra_headers as $key => $value )
185 $array_headers[$key] = $value;
188 $this->result = $this->result_header = $this->result_body = '';
190 // was content sent as an array? if so, turn it into a string
191 if (is_array($content))
195 foreach ( $content as $key => $value )
197 $pairs[] = "$key=".urlencode($value);
200 $content = join('&',$pairs);
206 // instance connection
207 if ($this->bind_host)
209 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
210 socket_bind($socket,$this->bind_host);
212 if (!@socket_connect($socket,$this->remote_host,$this->remote_port))
220 $socket = @fsockopen( $this->remote_host, $this->remote_port, $sock_errno, $sock_errstr, 10 );
223 if ( !$socket || !$OK )
225 $this->error[] = "Can't create socket connection to $this->remote_host:$this->remote_port.";
229 // if we have a username and password, add the header
230 if ( isset($this->remote_uname) && isset($this->remote_passwd) )
232 $array_headers['Authorization'] = 'Basic '.base64_encode("$this->remote_uname:$this->remote_passwd");
235 // for DA skins: if $this->remote_passwd is NULL, try to use the login key system
236 if ( isset($this->remote_uname) && $this->remote_passwd == NULL )
238 $array_headers['Cookie'] = "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}";
241 // if method is POST, add content length & type headers
242 if ( $this->method == 'POST' )
244 $array_headers['Content-type'] = 'application/x-www-form-urlencoded';
245 $array_headers['Content-length'] = strlen($content);
247 // else method is GET or HEAD. we don't support anything else right now.
252 $request .= "?$content";
257 $query = "$this->method $request HTTP/1.0\r\n";
258 foreach ( $array_headers as $key => $value )
260 $query .= "$key: $value\r\n";
264 // if POST we need to append our content
265 if ( $this->method == 'POST' && $content )
267 $query .= "$content\r\n\r\n";
271 if ($this->bind_host)
273 socket_write($socket,$query);
276 while ( $out = socket_read($socket,2048) )
278 $this->result .= $out;
283 fwrite( $socket, $query, strlen($query) );
286 $this->lastTransferSpeed = 0;
287 $status = socket_get_status($socket);
291 while ( !feof($socket) && !$status['timed_out'] )
293 $chunk = fgets($socket,1024);
294 $length += strlen($chunk);
295 $this->result .= $chunk;
297 $elapsedTime = time() - $startTime;
299 if ( $elapsedTime > 0 )
301 $this->lastTransferSpeed = ($length/1024)/$elapsedTime;
304 if ( $doSpeedCheck > 0 && $elapsedTime > 5 && $this->lastTransferSpeed < $doSpeedCheck )
306 $this->warn[] = "kB/s for last 5 seconds is below 50 kB/s (~".( ($length/1024)/$elapsedTime )."), dropping connection...";
307 $this->result_status_code = 503;
313 if ( $this->lastTransferSpeed == 0 )
315 $this->lastTransferSpeed = $length/1024;
320 list($this->result_header, $this->result_body) = explode("\r\n\r\n", $this->result, 2);
322 if ($this->bind_host)
324 socket_close($socket);
331 $this->query_cache[] = $query;
334 $headers = $this->fetch_header();
336 // what return status did we get?
337 if (!$this->result_status_code)
339 preg_match("#HTTP/1\.. (\d+)#",$headers[0],$matches);
340 $this->result_status_code = $matches[1];
343 // did we get the full file?
344 if ( !empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body) )
346 $this->result_status_code = 206;
349 // now, if we're being passed a location header, should we follow it?
350 if ($this->doFollowLocationHeader)
352 if ($headers['location'])
354 $this->redirectURL = $headers['location'];
355 $this->query($headers['location']);
361 function getTransferSpeed()
363 return $this->lastTransferSpeed;
367 * The quick way to get a URL's content :)
370 * @param boolean return as array? (like PHP's file() command)
371 * @return string result body
373 function get($location, $asArray = FALSE )
375 $this->query($location);
377 if ( $this->get_status_code() == 200 )
381 return explode("\n", $this->fetch_body());
384 return $this->fetch_body();
391 * Returns the last status code.
396 * @return int status code
398 function get_status_code()
400 return $this->result_status_code;
404 * Adds a header, sent with the next query.
406 * @param string header name
407 * @param string header value
409 function add_header($key,$value)
411 $this->extra_headers[$key] = $value;
415 * Clears any extra headers.
418 function clear_headers()
420 $this->extra_headers = array();
424 * Return the result of a query.
426 * @return string result
428 function fetch_result()
430 return $this->result;
434 * Return the header of result (stuff before body).
436 * @param string (optional) header to return
437 * @return array result header
439 function fetch_header( $header = '' )
441 $array_headers = explode("\r\n", $this->result_header);
443 $array_return = array( 0 => $array_headers[0] );
444 unset($array_headers[0]);
446 foreach ( $array_headers as $pair )
448 list($key,$value) = explode(": ", $pair, 2);
449 $array_return[strtolower($key)] = $value;
454 return $array_return[strtolower($header)];
457 return $array_return;
461 * Return the body of result (stuff after header).
463 * @return string result body
465 function fetch_body()
467 return $this->result_body;
471 * Return parsed body in array format.
473 * @return array result parsed
475 function fetch_parsed_body()
477 parse_str($this->result_body,$x);