Question

I'm trying to create a kind of REGEX with dynamic variables with PHP using some pre-defined values stored in a Database table, in order to validate a Dial String from Asterisk. The database has a table for outgoing rules, which each user may create to be applied to his/her extension.

Variables in PHP can be like this:

$N = '[23456789]';
$Z = '\d*'; //(any digit, any occurrence)
$X = '[0-9]';
$x = '[0-9]';

numbers in the rule will be considered as number itself

symbols in the rule will be considered as symbol itself (only * and # will be accepted in the database as symbols)

The table is something like this:

+----+-----------+-------+-------------+------------+----------+-----------+--------+--------+
| id | extension | order | description | ruledigits | ruletype | subtract  | prefix | suffix |
+----+-----------+-------+-------------+------------+----------+-----------+--------+--------+
|  1 |      1005 |     1 |             | 9XX        | Block    | null      | null   | null   |
|  2 |      1005 |     2 |             | 302NXXXXXX | Mod      | null      | 1      | null   |
|  3 |      2005 |     1 |             | 00Z        | Mod      | 2         | 011    | null   |
+----+-----------+-------+-------------+------------+----------+-----------+--------+--------+

So, if 1005 Extension DIALS 908 (no more digits), that call should be blocked according to the Action field. if 1005 Extension Dials 3025555555 (no more digits), that Call will be prefixed with number 1.

Iif 1005 Extension Dials 00325698289115 (international), that Call will NOT me modified according to Rule # 3, since that rule ONLY applies to EXT 2005, so the CALL will be sent as it was Dialed to the Server.

If that same last Call was made by 2005, the number would MATCH the rule, since it begins with 00 and Z is ANY DIGIT ANY OCURRENCE. So, the dialed number will be Subtracted "2" digits from the beginning, and then prefixed with "011" before being sent to the trunk.

The important field here I think is ruledigits (and of course extension), which will be used by PHP for the ARRAY of rules per EXT. then the action will be read only if the condition was meet.

And the condition something like this, although this one only represents just 1 rule and case:

if(preg_match("/^1$N$X$N(555)$Z/", $number))
{
    // $number format matches
    echo "yes"; // apply the action according the table
}
else
{
    echo "no"; // no action applied, proceed with the call.
}

I would need condition(s) that must be created on the fly as soon as the actual Call (requesting the access to the database through a php script) finds that there are not just 1, but some rules created for THAT extension individually.

How can I make or design a General function that can Access the database "rules" table, and ARRAY the group of all the conditions created under the caller extension in order to apply them to the actual call?

Note: The field "ruledigits" on the table "rules" will only accept the following characters:
N, Z, *, #, or Any number.

Was it helpful?

Solution

Here's how I would personally approach using MySQL data to build Regex patterns for checking data:

//Simplified array
$dbResults = array(
    array(
        'id' => 1,
        'extension' => 1005,
        'order' => 1,
        'description' => 'rule 1',
        'ruledigits' => '9XX',
        'prefix' => null,
        'ruletype' => 'Block'
    ),
    array(
        'id' => 2,
        'extension' => 1005,
        'order' => 2,
        'description' => 'rule 2',
        'ruledigits' => '302NXXXXXX',
        'prefix' => 1,
        'ruletype' => 'Mod'
    ),
    array(
        'id' => 3,
        'extension' => 2005,
        'order' => 3,
        'description' => 'rule 3',
        'ruledigits' => '00Z',
        'prefix' => '001',
        'ruletype' => 'Mod'
    )
);
$regexParts = array(
    'N' => '[2-9]'
    ,'Z' => '\d*'
    ,'X' => '\d'
    ,'x' => '\d'
);
//Static test vars
$userExt = 1005;
$dialTests = array('00325698289115','908','3025555555');
echo 'Testing user extension: '.$userExt;
echo '<br /><br />';
//This loop is for testing purposes only, the contents are all the live system would use
foreach($dialTests as $testNo)
{
    $actionTaken = 'None';
    //By default, if nothing happens, make sure the final number is the original one we saw
    $finalNo = $testNo;
    foreach($dbResults as $row)
    {
        if($userExt != $row['extension']) continue;//If it's not the right extension, skip the rest of this loop iteration's code and move on to the next row
        $regex = '';
        $tokens = str_split($row['ruledigits']);//Turn the string into an array, so we can parse each character individually
        foreach($tokens as $token)
        {
            if(isset($regexParts[$token])) $regex .= $regexParts[$token];//If the letter has a special meaning, use that
            else $regex .= $token;//else just throw that exact letter/number in
        }
        if(preg_match('#^'.$regex.'$#',$testNo)>0)
        {
            $actionTaken = $row['ruletype'];//Log what action has been taken
            if($actionTaken=='Mod')
            {
                $finalNo = $row['prefix'].$testNo;//Do the mod action
            }
            else if($actionTaken=='Block')
            {
                $finalNo = false;//Nullify the final number, so we know to block the call later on
            }
        }
    }
    //Here we just dump some info for testing purposes
    echo $testNo.': Action taken = '.$actionTaken;
    if($actionTaken=='Block') echo ' - Call terminated.';
    if($actionTaken=='Mod') echo ' - New number = '.$finalNo;
    echo '<hr />';
}

View the output demo on phpfiddle (click Run/F9)

OTHER TIPS

You can use asterisk realtime architecture and correct view to match extensions table.

Or you can use mysql query with REGEXP/RLIKE construction.

https://dev.mysql.com/doc/refman/5.1/en/regexp.html

You can easy change asterisk regexp to general regexp by using simple rewrites like

  '.' -> '.*'
  'X' -> '[0-9]'

etc

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top