diff --git a/includes/telnet/magrathea.inc.php b/includes/telnet/magrathea.inc.php new file mode 100755 index 00000000..038ba84b --- /dev/null +++ b/includes/telnet/magrathea.inc.php @@ -0,0 +1,211 @@ + and Thralling Penguin, LLC + * @package AgileBill + * @version 1.4.93 + */ + +/** + * Magrathea-Telecom.co.uk Plug in + * + * @package magrathea + * @author Joseph Benden + * @version 0.1 + * @access public + */ +require_once(PATH_INCLUDES."telnet/telnet.inc.php"); + +class magrathea extends telnet { + + /** + * The TCP port number the Magrathea service listens on. + * @access private + * @var integer + */ + var $port = 777; + + + + /** + * Handle connecting and logging into Magrathea. Returns 0 on success. + * @param $hostname The hostname to connect to + * @param $username Username + * @param $password Password + */ + function login($hostname, $username, $password) { + $r = ""; $code = ""; $msg = ""; + $ret = $this->connect($hostname, $this->port, $username, $password); + if ($ret == 0) { + $ret = false; + $this->getresponse($r); + if ($this->use_usleep) usleep($this->sleeptime); + else sleep(1); + $this->loginprompt = $r; + $this->docommand("AUTH $username $password",$r); + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + # Logged in! + $ret = true; + } + } + } else { + $ret = false; + } + return $ret; + } + + /** + * Log out of the Magrathea system. + */ + function logout() { + $r = ""; $code = ""; $msg = ""; + $this->docommand("QUIT",$r); + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + return true; + } else { + # Log an error! + global $C_debug; + $C_debug->error('magrathea','logout','Error: '.$msg); + } + } + return false; + } + + /** + * Attempt to allocate a single phone number. False is returned on error, else a phone number is returned. + * @param $areacode The desired area code to find a possible number for, using underscores for wildcard characters. + */ + function allocate($areacode) { + $r = ""; $code = ""; $msg = ""; + $ret = $this->docommand("ALLO $areacode",$r); + $ret = false; + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + # got a number + $ret = ereg_replace("[^0-9]","",$msg); + } else { + # Log an error! + global $C_debug; + $C_debug->error('magrathea','allocate','Error: '.$msg); + return false; + } + } else { + global $C_debug; + $C_debug->error('magrathea','allocate',"Parse Response Error (code: $areacode): ".$msg); + return false; + } + return $ret; + } + + /** + * Attempt to activate a single phone number. Returns a boolean success indicator. + * @param $did The desired phone number to activate. + */ + function activate($did) { + $r = ""; $code = ""; $msg = ""; + $this->docommand("ACTI $did",$r); + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + # got a number + return true; + } else { + # Log an error! + global $C_debug; + $C_debug->error('magrathea','activate','Error: '.$msg); + } + } else { + global $C_debug; + $C_debug->error('magrathea','activate','(ACTI '.$did.') Error, couldnot parse: '.$r); + } + return false; + } + + /** + * Attempt to deactivate a single phone number. Returns a boolean success indicator. + * @param $did The desired telephone number to deactivate/disconnect. + */ + function deactivate($did) { + $r = ""; $code = ""; $msg = ""; + $this->docommand("DEAC $did",$r); + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + return true; + } else { + # Log an error! + global $C_debug; + $C_debug->error('magrathea','deactivate','Error: '.$msg); + } + } + return false; + } + + /** + * Attempt to reactivate a single phone number. Returns a boolean success indicator. + * @param $did The desired telephone number to reactivate/reconnect. + */ + function reactivate($did) { + $r = ""; $code = ""; $msg = ""; + $this->docommand("REAC $did",$r); + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + return true; + } else { + # Log an error! + global $C_debug; + $C_debug->error('magrathea','reactivate','Error: '.$msg); + } + } + return false; + } + + /** + * Set a given phone number's destination, over RFC 2833 DTMF SIP. Returns a boolean success indicator. + * @param $did The desired telephone number to provision. + * @param $sip_url The full URL to send the number to, ie: me@sip1.mydomain.com + */ + function set($did, $sip_url) { + $r = ""; $code = ""; $msg = ""; + $this->docommand("SET $did 1 S:".$sip_url,$r); + if ($this->parse_response($r, $code, $msg)) { + if ($code == 0) { + return true; + } else { + # Log an error! + global $C_debug; + $C_debug->error('magrathea','reactivate','Error: '.$msg); + } + } + return false; + } + + /** + * Parses the responses from Magrathea, pulling out the response code and the associated message. + * @param $r The response text + * @param $code A reference to a variable to store the parsed response code + * @param $msg A reference to a variable to store the parsed message + */ + function parse_response($r, &$code, &$msg) { + $code = intval(substr($r,0,1)); + $msg = substr($r,2); + #echo "Parsed code: $code \n Parsed msg: $msg \n"; + if ($code == 0) + return true; + return false; + } +} + +?> \ No newline at end of file diff --git a/includes/telnet/telnet.inc.php b/includes/telnet/telnet.inc.php new file mode 100755 index 00000000..1446aa76 --- /dev/null +++ b/includes/telnet/telnet.inc.php @@ -0,0 +1,216 @@ + and Thralling Penguin, LLC + * @package AgileBill + * @version 1.4.93 + */ + +/** + * Telnet class + * + * @package telnet + * @author Joseph Benden + * @version 0.1 + * @access public + */ +class telnet { + + /** + * Specifies the style of communications. 0 for socket line mode, 1 for telnet compatible mode. + * + * @access private + * @var boolean + */ + var $mode = 0; + + /** + * Whether or not to use microsleep. + * + * @access private + * @var boolean + */ + var $use_usleep = 0; + + /** + * Amount of time to sleep in between communications. + * + * @access private + * @var integer + */ + var $sleeptime = 125000; + + /** + * Amount of time to sleep after logging in to the remote server. + * + * @access private + * @var integer + */ + var $loginsleeptime = 1000000; + + /** + * Internal file descriptor + * + * @access private + * @var resource + */ + var $fp = NULL; + + /** + * Stored login prompt, used to tell if a username/password failed. + * + * @access private + * @var string + */ + var $loginprompt; + + + + + /** + * Connects to a remote telnet or socket line mode server. + * @param $server The remote servers IP address or hostname + * @param $port The remote servers TCP port + * @param $user The username + * @param $pass The password + * @return 0 for success + * @return 1 for an error whilst opening the network connection + * @return 2 for an unknown hostname resolution + * @return 3 for a login failure + * @return 4 for a PHP versioning error + */ + function connect($server, $port, $user, $pass) { + $rv=0; + $r = ""; + $vers=explode('.',PHP_VERSION); + $needvers=array(4,3,0); + $j=count($vers); + $k=count($needvers); + if ($k<$j) $j=$k; + for ($i=0;$i<$j;$i++) { + if (($vers[$i]+0)>$needvers[$i]) break; + if (($vers[$i]+0)<$needvers[$i]) return 4; + } + + # Make sure we're disconnected first + $this->disconnect(); + + if (strlen($server)) { + if (preg_match('/[^0-9.]/',$server)) { + $ip=gethostbyname($server); + if ($ip==$server) { + $ip=''; + $rv=2; + } + } else $ip=$server; + } else $ip='127.0.0.1'; + + if (strlen($ip)) { + if (($this->fp=fsockopen($ip, $port))) { + if ($this->mode == 1) { + fputs($this->fp,chr(0xFF).chr(0xFB).chr(0x1F).chr(0xFF).chr(0xFB). + chr(0x20).chr(0xFF).chr(0xFB).chr(0x18).chr(0xFF).chr(0xFB). + chr(0x27).chr(0xFF).chr(0xFD).chr(0x01).chr(0xFF).chr(0xFB). + chr(0x03).chr(0xFF).chr(0xFD).chr(0x03).chr(0xFF).chr(0xFC). + chr(0x23).chr(0xFF).chr(0xFC).chr(0x24).chr(0xFF).chr(0xFA). + chr(0x1F).chr(0x00).chr(0x50).chr(0x00).chr(0x18).chr(0xFF). + chr(0xF0).chr(0xFF).chr(0xFA).chr(0x20).chr(0x00).chr(0x33). + chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0x2C).chr(0x33). + chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0xFF).chr(0xF0). + chr(0xFF).chr(0xFA).chr(0x27).chr(0x00).chr(0xFF).chr(0xF0). + chr(0xFF).chr(0xFA).chr(0x18).chr(0x00).chr(0x58).chr(0x54). + chr(0x45).chr(0x52).chr(0x4D).chr(0xFF).chr(0xF0)); + } + if ($this->use_usleep) usleep($this->sleeptime); + else sleep(1); + + if ($this->mode == 1) { + fputs($this->fp,chr(0xFF).chr(0xFC).chr(0x01).chr(0xFF).chr(0xFC). + chr(0x22).chr(0xFF).chr(0xFE).chr(0x05).chr(0xFF).chr(0xFC).chr(0x21)); + } + if ($this->use_usleep) usleep($this->sleeptime); + else sleep(1); + + if ($this->mode == 1) { + # BEGIN actual LOGIN method + $this->getresponse($r); + $r=explode("\n",$r); + $this->loginprompt=$r[count($r)-1]; + + fputs($this->fp,"$user\r"); + if ($this->use_usleep) usleep($this->sleeptime); + else sleep(1); + + fputs($this->fp,"$pass\r"); + if ($this->use_usleep) usleep($this->loginsleeptime); + else sleep(1); + $this->getresponse($r); + $r=explode("\n",$r); + if (($r[count($r)-1]=='')||($this->loginprompt==$r[count($r)-1])) { + $rv=3; + $this->disconnect(); + } + # END LOGIN method + } + } else $rv=1; + } + return $rv; + } + + /** + * Disconnect from the remote server. + * @param $exit If the exit command is used prior to disconnecting. Default is yes. + */ + function disconnect($exit=1) { + $junk = ""; + if ($this->fp) { + if ($exit) $this->docommand('exit',$junk); + fclose($this->fp); + $this->fp=NULL; + } + } + + /** + * Execute a remote command and return the reply. + * @param $c The command to execute + * @param $r A reference to a variable which will receive the returned result + * @return True or false, if the connection is still alive + */ + function docommand($c,&$r) { + if ($this->fp) { + fputs($this->fp,"$c\r"); + if ($this->use_usleep) usleep($this->sleeptime); + else sleep(1); + $this->getresponse($r); + $r=preg_replace("/^.*?\n(.*)\n[^\n]*$/","$1",$r); + } + return $this->fp?1:0; + } + + /** + * Performs the socket operations required to read all available data from a remote connection. + * @param $r A reference to a variable which will receive the read data + */ + function getresponse(&$r) { + $r=''; + do { + $r.=fread($this->fp,1000); + $s=socket_get_status($this->fp); + } while ($s['unread_bytes']); + } + +} + +?> \ No newline at end of file