// // Copyright 2009 // GPL v3 http://www.gnu.org/licenses/gpl.html $sVersion = "20091115"; // November 15th 2009 // More problem with BASEURL // It appears that a new URL is now used for call setup. // phone-to-phone.php // November 11th 2009 // Fixed a change done where all betamax use the /myaccount/ URL // instead of the old /clx/ URL // August 31st 2008 // Fixed a bug with creditcents for balances over €1000. // June 22nd 2008. (Uwe Gellhaus) // New .com clone (intervoip) , but different url base. // Version: 1.2 // Dated: 2007 July 18th. // Just a warning that text send here should be utf-8 encoded. // I've adjusted the example to help things there. // // Added CallForwarding feature. // Added Credit check and freeminutes to the functions instead of the example. // Added Callerid to sent SMS messages. (They must be registered with your provider using their program first) // // Now we parse out the Telecom Service Providers GMT time ($iTSPtime) in Unix time. (Epoch) // This is a help when sending immediate SMSes. // A known problem with Summer / Winter time has appeared. Finarea/Betamax don't seem to understand time correctly. // This version will work around that. // Function tariffwizard added. Just like the webpage !! Although I can't see much use for it :) // *********************************************************************************************************** // * All functions return arrays with $iResult (An integer) and $sDebug (A text string). // * In general $iResult should be 0 if the function worked sucessfully. // *********************************************************************************************************** // // Creditcents, sms with caller-id(+ delayed sms) ,call and tariffwizard implemented so far. // // Feedback appreciated to junk at simong dot net or a comment at http://www.voip-info.org/wiki/view/Finarea+SA // // You need php with curl and ssl for curl. // See http://www.php.net/curl // *** See an example usage at http://www.simong.net/finarea/ // Don't forget to set (Done in the example.php script) ... // $BASEURL = "https://myaccount.".$SERVICE.".com/clx"; // Where $SERVICE is the service name eg. voipstunt // OR $BASEURL = "https://www.".$SERVICE.".com/myaccount"; // Where $SERVICE is intervoip // // Then do a login followed by gomainpage BEFORE calling the other functions (call, sms etc.) $sCookie_File = "/tmp/".$_SERVER['REMOTE_ADDR'].":".$_SERVER['REMOTE_PORT'].".cookie"; // This is where to store the cookie file. Any better suggestions ? // **************** Some functions ***************************************************************************** function http_arraytoxform ($aData){ $sDebug = ""; $iResult = 0; reset ($aData); $sData = ""; $iCount = 0; while (list ($sKey, $sVal) = each ($aData)) { $sDebug .= "[$sKey] => [$sVal]
\n"; if ( $iCount == 0 ) { $sData .= ($sKey . "=" . $sVal); $iCount += 1; } else { $sData .= ("&" . $sKey . "=" . $sVal); } } return array($sData, $iResult, $sDebug); } function doRequest($sUrl, $sMethod="GET", $sVars="",$bRemoveCookie=FALSE) { global $sCookie_File; // A little unsafe maybe. $iResult = 0; $sDebug = "DEBUG: URL is [".$sUrl."] Method is [".$sMethod."]
\n"; $sResponse = ""; $pCh = curl_init(); if ($pCh) { curl_setopt($pCh, CURLOPT_URL, $sUrl); curl_setopt($pCh, CURLOPT_HEADER, 1); curl_setopt($pCh, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // Uses the browsers user-agent. Smart !! :) curl_setopt($pCh, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($pCh, CURLOPT_RETURNTRANSFER, 1); curl_setopt($pCh, CURLOPT_COOKIEJAR, $sCookie_File); curl_setopt($pCh, CURLOPT_COOKIEFILE, $sCookie_File); curl_setopt($pCh, CURLOPT_SSL_VERIFYPEER, false); // Verify the sites ssl cert, or not(false). // curl_setopt($AuthNetConn, CURLOPT_CAINFO, "path:/ca-bundle.crt"); // This points to your Certs authority bundle. // curl_setopt($pCh, CURLOPT_CONNECTTIMEOUT, 15); // Wait max 15 seconds for connection. // curl_setopt($pCh, CURLOPT_TIMEOUT, 30); // Wait max 30 for everything. if ($sMethod == 'POST') { curl_setopt($pCh, CURLOPT_POST, 1); curl_setopt($pCh, CURLOPT_POSTFIELDS, $sVars); } $sData = curl_exec($pCh); } else { $sResponse = "ERROR: Couldnt init curl"; $iResult = 1 ; $sDebug .= $sResponse; } if ($sData) { $sResponse = $sData; } else { $iResult = 2 ; $sResponse = "NO DATA \n"; $sResponse .= curl_error($ch); $sDebug .= $sResponse; } curl_close($pCh); if ( $bRemoveCookie === TRUE ){ // Remove cookie file unlink($sCookie_File); $sDebug .= "Cookie file [".$sCookie_File."] removed.
\n"; } return array($sResponse, $iResult, $sDebug); } /** * * This function must be used before any other. * **/ function login($sUSER, $sPASS){ global $BASEURL; $iResult = 0; $sDebug = ""; $sDebug .= "DEBUG:BASEURL[".$BASEURL."]
\n"; // u[".$sUSER."]p[".$sPASS."]
\n"; list($sXform, $iThisResult, $sThisDebug) = http_arraytoxform (array("username" => $sUSER, "password" => $sPASS)); list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/", "POST", $sXform); // Look for "logout.gif" If it exists then we managed to log-in. $bLOGGEDIN = strpos(strtolower($sContent),"logout.gif"); // strtolower makes the search case-insensitive (Like grep -i) // Convert the Boolean result to 1 and 0 (true false) if ( $bLOGGEDIN === FALSE ){ $bResult = 0; $iResult = 1; $sDebug .= "DEBUG: doRequest[".$sThisDebug."]
\n"; $sDebug .= "DEBUG: Content[".htmlentities ($sContent)."]
\n"; } else { $bResult = 1; $sDebug .= "DEBUG:[Login successfull]
\n"; } return array($bResult, $iResult, $sDebug); } /** * * This appears to be required after logging in. * And now this is where we get the Telecom Service Providers current time $iTSP (in Unix Epoch) * It is needed to generate the now time for sending immediate SMSes. * **/ function gomainpage() { global $BASEURL; $iResult = 0; $sDebug = ""; list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/index.php?part=menu&justloggedin=true"); $iTSPtime = 0; // Initialise variable. // Parse eg. 200 OK\r\nDate: Sun, 25 Mar 2007 19:52:26 GMT // Day , 01 May 2007 19:52:26 GMT preg_match('/200 OK\r\nDate: ([a-z|A-Z]{3}), ([0-9]+) ([a-z|A-Z]{3}) ([0-9]{4}) ([0-9]+:[0-9]+:[0-9]+) (GMT)/', htmlentities ($sContent), $aMatches); if ( count($aMatches) == 7){ // 0 - 6 // Unix epoch. GMT $iTSPtime = strtotime($aMatches[2]." ".$aMatches[3]." ".$aMatches[4]." ".$aMatches[5]." ". $aMatches[6]); } else { $sDebug .= "Couldn't get Telecom Server Time.
\n"; $iResult = 1; } //$sDebug .= "DEBUG:[".htmlentities ($sContent)."]
\n"; $sDebug .= "DEBUG : iTSPtime is [".$iTSPtime."] [".date('r',$iTSPtime)."]
\n"; return array($sContent, $iTSPtime, $iResult, $sDebug); } function freedays ($sMainPage) { $iResult = 0; $sDebug = ""; // Freedays remaining: $bResult = preg_match('/.*Freedays remaining\:\\([0-9]*).*\<\/span/', $sMainPage, $aMatches); // //print_r($aMatches); // DEBUG if ($bResult){ $iFreeDays = $aMatches[1]; } else { $iFreeDays = 0; } return array($iFreeDays, $iResult, $sDebug); } function creditcents ($sMainPage) { // Grep the remaining credit from the main page. // Almost the same as the fincheck shell script. $iResult = 0; $sDebug = ""; preg_match('/.*Remaining credit[^0-9]+([0-9.,]+).*/', $sMainPage, $aMatches); $iCreditCents = str_replace(",", "", $aMatches[1]); // Get rid of thousand separator (,) $iCreditCents = ($iCreditCents * 100); // Convert to cents return array($iCreditCents, $iResult, $sDebug); } function call($iSourceNum, $iDestNum){ global $BASEURL; $sResult = ""; $iResult = 0; $sDebug = ""; if (empty($iSourceNum)){ $sResult .= "No sourcenumber. "; // No source number $sDebug .= "$sResult"; $iResult = 1; } if (empty($iDestNum)){ $sResult .= "No destination number. "; // No dest number $sDebug .= "No destination number. "; $iResult = 2; } if ($iResult == 0){ list($sXform, $iThisResult, $sThisDebug) = http_arraytoxform (array("action"=>"initcall", "panel"=>"true", "anrphonenr"=>$iSourceNum, "bnrphonenr"=>$iDestNum)); //$sThisURL = $BASEURL."/webcalls2.php"; $sThisURL = $BASEURL."/phone-to-phone.php"; list($sContent, $iThisResult, $sThisDebug) = doRequest($sThisURL, "POST", $sXform); $sDebug .= "RequestURL= [".$sThisURL."] CONTENT [".htmlentities ($sContent)."]
\n"; // DEBUG } return array($sResult, $iResult, $sDebug); } // function sms($iDestNum,$sMsg,$iTime, $iGmtDiff=0,$iCallerId=0) // Where $iTime is the Unix time (Epoch) to send the SMS. // And You can use $iTSPtime from gomainpage function as $iTime to send NOW. // Otherwise it uses your servers time. And you better be in sync with Betamax servers. // And a fix here for the Finarea / Betamax Winter / Summer time problem. function sms($iDestNum,$sMsg,$iTime=0, $iGmtDiff=0,$iCallerId=0){ $bUSE_OLD_METHOD = FALSE; // Use the old websms page on immediate(NOW) SMSes. // NOTE: $iDestNum can be multiple numbers by comma separating them. global $BASEURL; $iResult = 0; $sDebug = ""; if (empty($iDestNum)){ $sThisMsg = "No destination number. "; // No dest number $sResult .= $sThisMsg; $sDebug .= $sThisMsg; $iResult += 1; } if (empty($sMsg)){ $sThisMsg = "No smstext. "; $sResult .= $sThisMsg; $sDebug .= $sThisMsg; $iResult += 2; } $bSMSSent = FALSE; if ( $iTime == 0) { // Immediate SMS $bDelaySMS = FALSE; if ($bUSE_OLD_METHOD === TRUE){ // Use the old method $sDebug .= "Sending immediate SMS the OLD way
\n"; list($sXform, $iThisResult, $sThisDebug) = http_arraytoxform (array("action"=>"send", "panel"=>"true", "message" => $sMsg, "bnrphonenumber"=>$iDestNum)); list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/websms.php", "POST", $sXform); $bSMSSent = TRUE; } else { $sThisMsg = "Sending immediate SMS.
\n"; $iTime = time(); // Using THIS servers time !! $sDebug .= $sThisMsg. "WARNING: Using this servers time[".$iTime."] [".date('r',$iTime)."].
\n"; } } else { // Timed SMS $bDelaySMS = TRUE; $sThisMsg = "Sending timed or immediate SMS using TSPtime.
\n"; $sDebug .= $sThisMsg; } if ( $bSMSSent == FALSE ){ // We didn't send an immediate SMS the OLD way. So lets send one now. // This script sends all messages using Betamax's version of GMT+1 // (Betamax has problems with GMT and Summertime breaks the GMT offset) // Get the Month, day, hour, minute and GMT offset, All converted to GMT+1 (As Betamax sees it. ie. wrongly !!) $iGMTTime = ($iTime + ($iGmtDiff * -1)); // Convert $iTime to GMT. if (date('I', $iTime) == 1 ){ // Summer time. TODO Check if a setlocale() or something is needed here. $iBetamaxGMTTime = ($iGMTTime + (60 * 60)); // +1 hour. WORKAROUND to Betamax problem. $sDebug .= "Summertime.
\n"; } else { // Wintertime. Now Betamax understands the GMT offsets. $iBetamaxGMTTime = $iGMTTime; $sDebug .= "Wintertime.
\n"; } // Now convert to GMT+1 (Or Betamax's GMT+1) WORKAROUND to Betamax problem. $iBetamaxTime = ($iBetamaxGMTTime + (60 * 60)); // 1 hour // Get the Month, day, hour, minute $iMonthToSend = gmstrftime ('%m',$iBetamaxTime); $iDayToSend = gmstrftime ('%d' ,$iBetamaxTime); $iHourToSend = gmstrftime ('%H' ,$iBetamaxTime); $iMinuteToSend = gmstrftime ('%M' ,$iBetamaxTime); $iGmtDiff = 1; // GMT+1 // // Send SMS list($sXform, $iThisResult, $sThisDebug) = http_arraytoxform (array("action"=>"send", "panel"=>"true", "message"=>$sMsg, "bnrphonenumber"=>$iDestNum, "day"=> $iDayToSend, "month"=>$iMonthToSend, "hour"=>$iHourToSend, "minute"=>$iMinuteToSend, "gmt"=>$iGmtDiff, "callerid"=>$iCallerId)); list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/websms2.php", "POST", $sXform); // } // END if ( $bSMSSent == FALSE // Parse $sContent for result, Cents left etc. // Attempt to check all went well ?? // It appears that the balance is returned on a successful POST. // Grep for updateBalance("1860000"). Equals 1860 cents $iThisResult = preg_match('/.*updateBalance\("([0-9]+).*/', $sContent, $aMatches); if ( $iThisResult == 0 ){ $sResult .= "Failed to send sms
"; // Parse out some known faults. $iThisFault = preg_match('/The send date and time is in the past./', $sContent, $aMatches); if ( $iThisFault ){ $iResult += 4; $sResult .= "ERROR: Send date/time is in the past. MM/DD HH:MM[".$iMonthToSend ."/". $iDayToSend ." ". $iHourToSend .":". $iMinuteToSend." GMT ".$iGmtDiff."]
\n"; } else { $iResult += 32; // Unknown SMS send fault. $sResult .= "ERROR: Unknown SMS send fault
\n"; } // $sResult .= "

See DEBUG below.

\n"; $sThisMsg = "CONTENT [".htmlentities ($sContent)."]
\n"; // DEBUG $sDebug .= $sThisMsg. $sThisDebug; } else { $iCents = ($aMatches[1] / 1000); $sDebug .= "Credit cents left is [".$iCents."] or €[".($iCents / 100)."]
\n"; } // return array($sResult, $iCents, $iResult, $sDebug); } // END function sms function tariffwizard ($iDestNum) { // Check a telephone numbers cheapest Betamax service cost in cents per minute. // I wrote this by mistake, thinking that I could check this service providers call cost :) global $BASEURL; $sResult = ""; $iResult = 0; $sDebug = ""; list($sXform, $iThisResult, $sThisDebug) = http_arraytoxform (array("action"=>"showoverview", "telephonenr"=>$iDestNum)); list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/tariffwizard.php", "POST", $sXform); // Parse $sContent for Service, Provider type, Rate per minute, Callsetup and Additional info: // wizardlog.php?url=http%3A%2F%2Fwww.justvoip.com%2F&bnr= $iThisResult = preg_match('/wizardlog.php\?url=http\%3A\%2F\%2F([a-z.]+)\%2F\&bnr=/', $sContent, $aMatches); $sUrl = $aMatches[1]; // Provider type:\n Voip $iThisResult = preg_match('/Provider type:<\/b><\/td>\n.*(.*)<\/td>/', $sContent, $aMatches); $sProviderType = $aMatches[1]; // Rate per minute:\n 5 Ct/min $iThisResult = preg_match('/Rate per minute:<\/b><\/td>\n.*(.*)\ \;Ct\/min<\/td>/', $sContent, $aMatches); $iRatePerMinute = $aMatches[1]; // Callsetup:\n 0 Ct. $iThisResult = preg_match('/Callsetup:<\/b><\/td>\n.*(.*)\ \;Ct.<\/td>/', $sContent, $aMatches); $iCallSetup = $aMatches[1]; // Additional info: n/a $iThisResult = preg_match('/Additional info:<\/b><\/td>\n.*(.*)<\/td>/', $sContent, $aMatches); $sAdditionalInfo = $aMatches[1]; $sDebug .= "CONTENT [".htmlentities ($sContent)."]
\n"; // DEBUG return array($sUrl, $iRatePerMinute, $iCallSetup, $iResult, $sDebug); } // End function tarriffwizard // Callforward function callforward($iType=-1, $iDestNum=0){ // Where // $iType = -1 "Check", 0 "Never", 1 "Always" , 2 "When offline", // 3 "When offline or away" global $BASEURL; $iResult = 0; $sDebug = ""; if ( $iType == -1 ) { $sDebug .= "Checking current forwarding details.
\n"; list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/callforwarding.php"); $iResult += $iThisResult; $sDebug .= $sThisDebug; // Match current details //$iThisResult = preg_match('/Forward calls:.*option value=\"([0-9])\" selected.*forwardphone_0.*value=\"(\[0-9]*)\".*/s', $sContent, $aMatches); $iThisResult = preg_match('/Forward calls:.*option value=\"([0-9])\" selected.*forwardphone_0.*value=\"([+0-9]*)\".*/s', $sContent, $aMatches); } else { // Remove + . Otherwise it causes problems. Dont know why ?? $iDestNum = preg_replace('/^\+([0-9]*)/', '${1}',$iDestNum); $sDebug .= "Setting Forwarding type[".$iType."] Dest[".$iDestNum."]
\n"; list($sXform, $iThisResult, $sThisDebug) = http_arraytoxform (array("fromsignup" => "", "action" => "updatecallforwarding", "nextpage" => "", "forwardingcondition" => $iType, "forwardphone_0" => $iDestNum)); list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/callforwarding.php", "POST", $sXform); $iResult += $iThisResult; $sDebug .= $sThisDebug; // Match [Your callforwarding details have been changed.] $iThisResult = preg_match('/Your callforwarding details have been changed\./s', $sContent, $aMatches); } if ( $iThisResult ) { if ( $iType == -1 ) { $iCurrentType = $aMatches[1]; $iCurrentNumber = $aMatches[2]; } else { $iCurrentType = $iType; $iCurrentNumber = $iDestNum; } $sDebug .= "CONTENT [".htmlentities ($sContent)."]
\n"; // DEBUG } else { $iResult += 127; if ( $iType == -1 ) { $sDebug .= "Coundnt find current forwarding details.
\n"; print_r($aMatches); } else { $sDebug .= "Coundnt verify the new settings.
\n"; } $sDebug .= "CONTENT [".htmlentities ($sContent)."]
\n"; // DEBUG $iCurrentType = 0; $iCurrentNumber = ""; } // echo "Matches
\n"; // print_r($aMatches); // echo "
\n"; return array($iCurrentType, $iCurrentNumber, $iResult, $sDebug); } function _maketime($iHour, $iMinute, $iMonth, $iDay){ // Really just a shell for gmmktime. // Its a little help for those who don't understand Unix Epoch // and want help converting to the new sms function. return (gmmktime($iHour, $iMinute,0,$iMonth, $iDay)); } function logoff(){ global $BASEURL; list($sContent, $iThisResult, $sThisDebug) = doRequest($BASEURL."/index.php?part=logoff","",TRUE); return array($sContent,$iThisResult, $sThisDebug); } // ********************************************* End of functions ******************************************************* ?>