Difference between revisions of "Telephone scripts"

From Hackerspace ACKspace
Jump to: navigation, search
(added number lookup script)
(automated list of telehone scripts/snippets by displaying Category:Telephone snippet)
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Number lookup ==
+
These are scripts used by the [[Telephone system]].
We make use of the mod_cidlookup for ease of use, but not all features are functional in our implementation.
 
Every request is done via HTTP requests to a php script that will check if the number:
 
* is an extension (and returns the name for that)
 
* is stored in the local mySQL database, and return that
 
* can be found online by using reversed number lookup websites for landlines
 
* can be found online by using the national telecommunications authority database (opta.nl) for cell phones returning the associated cell provider
 
* can be categorized by a more coarse lookup, like continent, country, region, town or number block owner, stored in a local array (~500 entries)
 
  
The setting for mod_cidlookup is:
+
{{#ask: [[Category:Telephone snippet]]
<param name="url" value="http://webserviceprovider/lookup.php?number=${caller_id_number}"/>
+
| ?Description
 +
| ?Modification_date
 +
| sort=Modification_date
 +
| order=descending
 +
| format=embedded
 +
| embedformat=h6
 +
}}
  
=== lookup.php ===
+
[[Category:Telephony]]
This script returns some information about the caller, preferrably the name.
 
It uses a local MySQL database and fetches info from some sites.
 
 
 
<pre>
 
<?php
 
/*
 
* Copyright (c) 2012, ACKspace foundation
 
* All rights reserved.
 
*
 
* Redistribution and use in source and binary forms, with or without
 
* modification, are permitted provided that the following conditions are met:
 
*
 
* 1. Redistributions of source code must retain the above copyright notice, this
 
*    list of conditions and the following disclaimer.
 
* 2. Redistributions in binary form must reproduce the above copyright notice,
 
*    this list of conditions and the following disclaimer in the documentation
 
*    and/or other materials provided with the distribution.
 
*
 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
*
 
* The views and conclusions contained in the software and documentation are those
 
* of the authors and should not be interpreted as representing official policies,
 
* either expressed or implied, of the FreeBSD Project.
 
*/
 
 
 
define( "COUNTRY", "31" );
 
define( "REGION", "45" );
 
define( "PLUS", "00" );
 
define( "MYSQL_DB", "freeswitch_cidlookup" );
 
 
 
// Number dial plan, ~500 entries, shortened for wiki
 
$arrNumbers[1]['info'] = "(continent) Verenigde Staten";
 
$arrNumbers[1][4][4][1]['info'] = "Bermuda";
 
$arrNumbers[3]['info'] = "(continent) Europa";
 
$arrNumbers[3][1]['info'] = "(land) Nederland";
 
$arrNumbers[3][1][1][4]['info'] = "Testnetnummer van KPN Telecom";
 
$arrNumbers[3][1][4]['info'] = "(provincies) Oostelijk Noord-Brabant, Limburg";
 
$arrNumbers[3][1][4][5]['info'] = "(regio) Heerlen";
 
$arrNumbers[3][1][6]['info'] = "Mobiele nummers en Semafoondiensten";
 
$arrNumbers[3][1][6][1]['info'] = "Mobiele telefoon";
 
$arrNumbers[3][1][6][1][0]['info'] = "(GSM) KPN";
 
$arrNumbers[3][1][8][5]['info'] = "(type) Plaatsonafhankelijk/VoIP";
 
$arrNumbers[3][1][8][5][8][7]['info'] = "(VoIP) XS4ALL";
 
 
 
// Normalize the number
 
$arrNumberInfo = normalizeNumber( getVar( "number", true ) );
 
 
 
// Extension? try and get from dialplan
 
if ( $arrNumberInfo['type'] == "extension" )
 
{
 
    echo getExtension( $arrNumberInfo['local'] );
 
    exit;
 
}
 
 
 
if ( !function_exists( "mysql_connect" ))
 
{
 
    echo "ERROR";
 
    exit;
 
}
 
 
 
// Fetch the number from the database
 
if ( $strName = dbLookup( $arrNumberInfo ))
 
{
 
    echo $strName;
 
    exit;
 
}
 
 
 
// Nothing in the database?
 
// national number starting with 0[1-578]?
 
// Fetch number from website (check last get timestamp to prevent DoS
 
// put result in DB
 
if ( preg_match( "/^0[1-578].*/", $arrNumberInfo['national'] ) && $strName = fetchWebsiteResult( $arrNumberInfo['national'] ))
 
{
 
    echo $strName;
 
 
 
    // Add the name to the DB
 
    $arrNumberInfo['name'] = $strName;
 
    dbInsert( $arrNumberInfo );
 
    exit;
 
}
 
else if ( preg_match( "/^0[6].*/", $arrNumberInfo['national'] ) && $strName = fetchOptaResult( $arrNumberInfo['national'] ))
 
{
 
    // Number porting
 
    echo $strName;
 
 
 
    // Add the name to the DB, so we don't have to look it up anymore
 
    $arrNumberInfo['name'] = $strName;
 
    dbInsert( $arrNumberInfo );
 
    exit;
 
}
 
 
 
// Nothing on the website? Try and find the number in the array
 
if ( isset( $arrNumberInfo['international'] ))
 
{
 
    $strName = _getInfo( str_split( $arrNumberInfo['international'] ));
 
    echo $strName;
 
    exit;
 
}
 
 
 
/////////////////////////////////////////////////////////////////////
 
function fetchWebsiteResult( $_strNumber )
 
{
 
 
 
    if ( $strName = fetch_delefoondetective_nl( $_strNumber ))
 
        return $strName;
 
 
 
    if ( $strName = fetch_gevonden_cc( $_strNumber ))
 
        return $strName;
 
 
 
    if ( $strName = fetch_zoekenbel_nl( $_strNumber ))
 
        return $strName;
 
 
 
    if ( $strName = fetch_nummerzoeker_com( $_strNumber ))
 
        return $strName;
 
 
 
    if ( $strName = fetch_nummerid_com( $_strNumber ))
 
        return $strName;
 
 
 
    if ( $strName = fetch_gebeld_nl( $_strNumber ))
 
        return $strName;
 
 
 
    return false;
 
}
 
 
 
function fetchOptaResult( $_strNumber )
 
{
 
    $strPage = file_get_contents( "http://www.opta.nl/nl/nummers/nummers-zoeken/resultaat/?query=".$_strNumber."&page=1&portering=1" );
 
 
 
    if ( !preg_match( "/<strong>Huidige aanbieder<\/strong>.*?<p>(.*?)<\/p>/si", $strPage, $matches ))
 
        return false;
 
 
 
    return "(GSM) ".$matches[1];
 
}
 
 
 
function fetch_delefoondetective_nl( $_strNumber )
 
{
 
    $strPage = file_get_contents( "http://www.telefoondetective.nl/telefoonnummer/".$_strNumber."/" );
 
 
 
    if ( !preg_match( "/<div\sid=\"name\"><h\d>(.*?)<\/h\d><\/div>/i", $strPage, $matches ))
 
        return false;
 
 
 
    return $matches[1];
 
}
 
 
 
function fetch_gevonden_cc( $_strNumber )
 
{
 
    return false;
 
}
 
 
 
function fetch_zoekenbel_nl( $_strNumber )
 
{
 
    return false;
 
}
 
 
 
function fetch_nummerzoeker_com( $_strNumber )
 
{
 
    return false;
 
}
 
 
 
 
 
function fetch_nummerid_com( $_strNumber )
 
{
 
    return false;
 
}
 
 
 
function fetch_gebeld_nl( $_strNumber )
 
{
 
    return false;
 
}
 
 
 
function dbLookup( $_arrNumberInfo )
 
{
 
    if (!$db = mysql_connect( NULL, "username", "password" ))
 
        return false;
 
 
 
    // TODO: close db
 
    if (!mysql_select_db( MYSQL_DB, $db ))
 
        return false;
 
 
 
    // Prevent SQL injection on variables
 
    $country = mysql_real_escape_string( $_arrNumberInfo['country'] );
 
    $international = mysql_real_escape_string( $_arrNumberInfo['international'] );
 
 
 
    // Full number partial listing (experimental)
 
    $query = "SELECT name FROM telephone_names WHERE country_code=".$country." AND INSTR( '".$international."', number ) = 1 ORDER BY LENGTH(number), sortorder LIMIT 1";
 
 
 
    if (!$result = mysql_query( $query, $db ))
 
        return false;
 
 
 
    $row = mysql_fetch_row( $result );
 
    mysql_close( $db );
 
    return $row[0];
 
}
 
 
 
 
 
function dbInsert( $_arrNumberInfo )
 
{
 
    if (!$db = mysql_connect( NULL, "username", "password" ))
 
        return false;
 
 
 
    // TODO: close db
 
    if (!mysql_select_db( "freeswitch_cidlookup", $db ))
 
        return false;
 
 
 
    // Prevent SQL injection on variables
 
    $country = mysql_real_escape_string( $_arrNumberInfo['country'] );
 
    $international = mysql_real_escape_string( $_arrNumberInfo['international'] );
 
    $name = mysql_real_escape_string( $_arrNumberInfo['name'] );
 
 
 
    $query = "INSERT INTO telephone_names (country_code,number,name) VALUES (".$country.",'".$international."','".$name."')";
 
 
 
    if (!$result = mysql_query( $query, $db ))
 
    {
 
        echo mysql_error( $db );
 
        return false;
 
    }
 
 
 
    mysql_close( $db );
 
 
 
    return true;
 
}
 
 
 
 
 
function getExtension( $_strExtension )
 
{
 
    return false;
 
    //return "Ext. ".$_strExtension;
 
}
 
 
 
function normalizeNumber( $_strNumber )
 
{
 
    $arrInfo = array();
 
 
 
    if ( preg_match( "/^([19]\d+)/", $_strNumber, $matches ))
 
    {
 
        $arrInfo['local'] = $matches[1];
 
        $arrInfo['type'] = 'extension';
 
        return $arrInfo;
 
    }
 
 
 
    $_strNumber = preg_replace( "/^([2345678])/", COUNTRY.REGION.'$1', $_strNumber );
 
 
 
    // Add country on national dials
 
    $_strNumber = preg_replace( "/^(0)([^0].*)/", COUNTRY.'$2', $_strNumber );
 
 
 
    // Replace + and 00 international symbols before parsing (include space for URI conversion
 
    $_strNumber = preg_replace( "/^( |\+|00)/", '', $_strNumber );
 
 
 
    $arrInfo['country'] = intval( substr( $_strNumber, 0, 2 ));
 
    $arrInfo['international'] = $_strNumber;
 
    $arrInfo['type'] = 'international';
 
 
 
    // National number?
 
    if ( $arrInfo['country'] == intval( COUNTRY ))
 
    {
 
        // only works with countries of 2 digits; replaces it with a 0
 
        $arrInfo['national'] = "0".substr( $_strNumber, 2 );
 
        $arrInfo['type'] = 'national';
 
    }
 
 
 
    return $arrInfo;
 
};
 
 
 
function GetInfo( $_strNumber )
 
{
 
    global $arrNumbers;
 
 
 
    $_strNumber = preg_replace( "/^([2345678])/", COUNTRY.REGION.'$1', $_strNumber );
 
 
 
    // Add country on national dials
 
    $_strNumber = preg_replace( "/^(0)([^0].*)/", COUNTRY.'$2', $_strNumber );
 
 
 
    // Replace + and 00 international symbols before parsing
 
    $_strNumber = preg_replace( "/^(\+|00)/", '', $_strNumber );
 
 
 
    return _getInfo( str_split( $_strNumber ));
 
};
 
 
 
function _getInfo( $_arrNumber )
 
{
 
    global $arrNumbers;
 
 
 
    $arrInfo = array();
 
 
 
    $arrNumberInfo = $arrNumbers;
 
    $nIndent = 0;
 
    $strDigits = "";
 
    $strDetailedInfo = "";
 
    foreach ( $_arrNumber as $digit )
 
    {
 
        if ( isset( $arrNumberInfo[$digit] ) )
 
        {
 
            $strDigits .= $digit;
 
            $arrNumberInfo = $arrNumberInfo[$digit];
 
            if ( isset( $arrNumberInfo['info'] ) )
 
            {
 
                $arrInfo[] = str_repeat( "-", $nIndent ) . $strDigits . " " . $arrNumberInfo['info'];
 
                $strDigits = "";
 
                $strDetailedInfo = $arrNumberInfo['info'];
 
            }
 
            $nIndent++;
 
        } else {
 
            break;
 
        }
 
    }
 
 
 
    return $strDetailedInfo;
 
}
 
 
 
////////////////////////////////////////////////////////////////////////////////
 
// Helpers
 
////////////////////////////////////////////////////////////////////////////////
 
function getVar( $_strVarName, $_bAllowGet = false )
 
{
 
    // If _POST var is set, return _POST var,
 
    // else, if _GET var is set and is allowed, return _GET var
 
    // else, requested var not found: return NULL
 
    if ( isset( $_POST[ $_strVarName ] ) )
 
        return $_POST[ $_strVarName ];
 
    else if ( isset( $_GET[ $_strVarName ] ) && ($_bAllowGet == true) )
 
        return $_GET[ $_strVarName ];
 
    else
 
        return NULL;
 
}
 
?>
 
</pre>
 
 
 
=== dialing out ===
 
This default dialplan snippet does a caller id lookup, and updates the callee name which will be visible on the local extension
 
 
 
<pre>
 
<extension name="National_numbers">
 
    <condition field="destination_number" expression="^0([1-578]\d{8})$">
 
        <action application="set" data="effective_caller_id_number=${outbound_caller_id}"/>
 
        <action application="export" data="callee_id_name=${cidlookup(0031$1)}" />
 
        <action application="bridge" data="sofia/gateway/myLandLineProvider/31$1"/>
 
    </condition>
 
</extension>
 
</pre>
 
 
 
=== incoming calls ===
 
This public dialplan snippet somewhat at the top sets the number (if any) first, checks if it has an international prefix, does a lookup for incoming calls and will set the name accordingly.
 
 
 
The second part will strip any leading + sign
 
 
 
<pre>
 
<extension name="fix_cidnam" continue="true">
 
    <!--make sure the module is loaded, or else loading it will kill our call!-->
 
    <!-- Simple case: name=number or name is empty -->
 
    <!-- and number is a 10digit (excluding optional leading 1), in nanpa nxx-nxx-xxxx form -->
 
    <!-- will skipurl lookup if not a 10digit # (don't lookup INTL), and instead just query the SQL -->
 
    <condition field="${module_exists(mod_cidlookup)}" expression="true"/>
 
    <condition field="caller_id_name" expression="^${caller_id_number}$|^$"/>
 
    <condition field="caller_id_number" expression="^(\+|00)(\d+)$">
 
        <action application="cidlookup" data="00$2"/>
 
        <anti-action application="cidlookup" data="${caller_id_number}"/>
 
    </condition>
 
</extension>
 
 
 
<extension name="fix_cidnam_plus" continue="true">
 
    <!-- if the name starts with + followed by digits, strip the
 
        + and then pass the number -->
 
    <condition field="caller_id_name" expression="^\+(1[2-9]\d\d[2-9]\d{6})$">
 
        <action application="cidlookup" data="$1"/>
 
    </condition>
 
</extension>
 
</pre>
 
 
 
=== todo ===
 
items stored in the database will not be updated anymore. The only way to refresh the number's information is to remove the entry manually which will cause a new lookup the next time that number is requested.
 

Latest revision as of 11:26, 15 September 2017

These are scripts used by the Telephone system.

Telephone system:Number lookup

This script uses mod_cidlookup combined with a custom php page. It tests the number against a SQLite database, several reversed number lookup websites, the national telecommunications authority database and a coarse array of areas of the world, which are called in order of granularity. The script can be called both on outgoing and incoming calls

Telephone system:Space state

This script sets the spacestate variable according to what the webservice API returns. It then can be used in the dialplan to, for example, play a sound file or do call forwarding. Currently it is used to build a sound phrase for playing it as a greeting within our IVR

Telephone system:FreeSWITCH tricks

This page provides a couple of tricks to ease working and debugging with FreeSWITCH

Phone:+31979922

The telephone number (+31979922) is part of the SpacePhone ENUM project, and works in two ways:

  • Be accessible to other people having only a numeric keypad, without any costs.
  • Call other in-country spaces with a short-hand number, in our case: 922 for ACKspace
Telephone system:shoutcast streams

The most efficient way to have shoutcast streams as MOH is to set up a muted conference. This way, the fist connection will be made when the first listener joins, and no extra streams will be opened.

Telephone system:tijdmelding

Dit script is een bescheiden ode aan de bekende tijdmelding, die inmiddels al 25 jaar dezelfde stem draagt, al 87 jaar bestaat (met 83 jaar gesproken tijdmelding).

Telephone system:fail2ban

If you have a FreeSWITCH instance running on the public net, changes are people will try to exploit it. Fail2ban tries to mitigate this. This is a re-attempt since the alternative perl autoblock script would freeze/hang.

Telephone system:Simple intercom

This is a dialplan sample of using the secondary phone line put on auto answer, and bridge them in a conference call.

Telephone system:Closing announcement

This collection of scripts was used to broadcast (closing) announcements using cron jobs

Telephone system:autopatch

To connect the PABX to an external communications channel, one needs a tiny bit of hardware and some scripting to get it working. A proof of concept is made that used the PMRs in the space and a couple of components on a perf-board.

Telephone system:Betamax credit

This collection of scripts will allow the user to hear the credit available on the Betamax services (VoipBuster, Intervoip, etc.), when dialing 1244 (the number for prepaid services as defined by Ministry of Economic affairs).

Telephone system:Cisco phone deployment

Some notes and configuration snippets for deploying the Cisco 79xx series phones