Changeset 9240

Show
Ignore:
Timestamp:
03/16/10 20:07:40 (2 years ago)
Author:
p_lindheimer
Message:

closes #4135, closes #4143, closes #4144, re #4110 trunk dialrules with new text boxes, schema, replaced fixlocalprefix, added native DAHDI

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/branches/2.8/core/agi-bin/fixlocalprefix

    r7630 r9240  
    1818// Copyright (C) 2004 Coalescent Systems Inc. (info@coalescentsystems.ca) 
    1919// 
     20 
    2021/* --------WARNING--------- 
    2122 *  
     
    2425 * to keep it from getting changed. 
    2526 
    26  
    27 This program takes a number, checks it against a list of patterns for a specific trunk, and modifies the number based 
    28 on the rules for that number. 
    29  
    30 Two variables are required: 
    31  
    32 DIAL_NUMBER - the number to be dialed (this will be modified, if necessary) 
    33 DIAL_TRUNK - the trunk number to use 
    34  
    35 The list of prefixes is contained in $localprefix_file (defined below, defaults to /etc/asterisk/localprefixes.conf). This 
    36 file has the format: 
    37  
    38   [trunk-1] 
    39   rule1=1613|NXXXXXX 
    40   rule2=1519|555XXXX 
    41   rule2=1519|54[0-9]XXXX 
    42    
    43   [trunk-2] 
    44   rule1=1613+NXXXXXX 
    45   rule2=1519+12XXXXX 
    46  
    47  
    48 The section read depends on the value of DIAL_TRUNK.  
    49  
    50 A | means to drop the number before the |. In this example, if DIAL_NUMBER is "16135551234" and DIAL_TRUNK is "1",  
    51 DIAL_NUMBER will become "5551234" (rule1). If DIAL_NUMBER is "15195551234", it will become "5551234" (rule2).  
    52 "15195435555" will become "5435555" (rule3). 
    53  
    54 A + means to prefix the beginning digits to the following pattern. In this example, if DIAL_NUMBER is 5551234, and  
    55 DIAL_TRUNK is "2", DIAL_NUMBER will become "16135551234". If DIAL_NUMBER is "1235555", it will match rule2 and 
    56 become "15191235555".  
    57  
    58 If no number is matched, DIAL_NUMBER is left untouched, and the script will exit with return value 0. If any errors  
    59 occur, DIAL_NUMBER is left untouched and the script will exit with return value 1. 
    60  
    61 There is no limit to the number of rules that may be defined. 
    62  
    63 You can also use #include filename.conf to include other files. Sections are preserved when including, which may 
    64 cause undesired behaviour if not planned for. For example: 
    65  
    66 localprefixes.conf: 
    67   [trunk-1] 
    68   #include t1.conf 
    69   rule1=1613|453XXXX 
    70   rule2=1613|384XXXX 
    71    
    72 t1.conf: 
    73   [trunk-2] 
    74   rule1=141|NXXXXXX 
    75    
    76 rule1 and rule2 defined in localprefixes.conf will actually belong to [trunk-2], and additionally, rule1 in  
    77 localprefixes.conf will override the rule1 defined in t1.conf. 
    78  
     27 ERROR: This script has been deprecated and no longer used, leaving to print out warnings 
     28        for a while in cae someone is using it out there. This has been replaced by 
     29        the creation of dialpan subroutines to perform the same operation. 
    7930*/ 
    8031 
    8132include("phpagi.php"); 
    8233 
    83 function get_var( $agi, $value) 
    84 { 
    85   $r = $agi->get_variable( $value ); 
    86    
    87   if ($r['result'] == 1) 
    88   { 
    89     $result = $r['data']; 
    90     return $result; 
    91   } 
    92   else 
    93     return ''; 
    94 } 
    95  
    96 function parse_conf($filename, &$conf, &$section) { 
    97   if (is_null($conf)) { 
    98     $conf = array(); 
    99   } 
    100   if (is_null($section)) { 
    101     $section = "general"; 
    102   } 
    103    
    104   if (file_exists($filename)) { 
    105     $fd = fopen($filename, "r"); 
    106     while ($line = fgets($fd, 1024)) { 
    107       if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) { 
    108         // name = value 
    109         // option line 
    110         $conf[$section][ $matches[1] ] = $matches[2]; 
    111       } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) { 
    112         // section name 
    113         $section = strtolower($matches[1]); 
    114       } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) { 
    115         // include another file 
    116          
    117         if ($matches[1][0] == "/") { 
    118           // absolute path 
    119           $filename = $matches[1]; 
    120         } else { 
    121           // relative path 
    122           $filename =  dirname($filename)."/".$matches[1]; 
    123         } 
    124          
    125         parse_conf($filename, $conf, $section); 
    126       } 
    127     } 
    128   } 
    129 } 
    130  
    131 function sanitizeNumber($number) { 
    132   global $agi; 
    133   if (strpos($number,"-") !== false) { 
    134     $agi->verbose("Stripping hyphens"); 
    135     $number = str_replace("-","",$number); 
    136   } 
    137   return $number;  
    138 } 
    139  
    140 function fixNumber($pattern, $number, &$agi) { 
    141   // valid chars in a pattern are 0-9XNZwW#*\.\[\]\-\+\| 
    142   $chars = '0-9XNZwW#*\.\[\]\-'; //escaped pcre-ready 
    143    
    144   // convert x n and z to uppercase 
    145   $regex = str_replace(array('x','n','z'), array('X','N','Z'), $pattern); 
    146   // sanitize the pattern - remove any non-pattern chars 
    147   $regex = preg_replace("/[^0-9XNZwW#*\.\[\]\-\+\|]/", "", $regex); 
    148   // Also kill the '-' characters outside of groups 
    149   $regex = preg_replace("/((?:\[[^\]]*\])*)([^\[\]\-]*)-?/", "$1$2", $regex); 
    150  
    151   $agi->verbose('Using pattern '.$regex, 4); 
    152   // attempt to grab the pieces of the pattern 
    153   if (preg_match('/^(([0-9XNZwW#*\.\[\]\-]+)\|)?(([0-9XNZwW#*\.\[\]\-]+)\+)?([0-9XNZwW#*\.\[\]\-]*)$/', $regex, $matches)) { 
    154     // one of NXXXXXX, 613|NXXXXXX   1+NXXXXXX    613|1+NXXXXXX,   
    155     // matches[2] = drop (eg 613),  matches[4] = prefix (eg 1),  matches[5] = rest of number (eg NXXXXX) 
    156      
    157     $drop = $matches[2]; 
    158     $prefix = $matches[4]; 
    159     $static = $matches[5]; 
    160   } else if (preg_match('/^(([0-9XNZwW#*\.\[\]\-]+)\+)?(([0-9XNZwW#*\.\[\]\-]+)\|)?([0-9XNZwW#*\.\[\]\-]*)$/', $regex, $matches)) { 
    161     // one of NXXXXXX,  613|NXXXXXX   1+NXXXXXX    1+613|NXXXXXX 
    162     // matches[2] = prefix (eg 1),  matches[4] = drop (eg 613),  matches[5] = rest of number (eg NXXXXX) 
    163      
    164     $drop = $matches[4]; 
    165     $prefix = $matches[2]; 
    166     $static = $matches[5]; 
    167   } else { 
    168     if (!is_null($agi)) { 
    169       $agi->verbose('Could not understand pattern "'.$pattern.'" ('.$regex.')', 1); 
    170     } 
    171     return false; 
    172   } 
    173    
    174   // convert asterisk pattern matching into perl regular expression 
    175   $regex = str_replace( 
    176       array( 
    177         "X", 
    178         "Z", 
    179         "N", 
    180         ".", 
    181         "*", 
    182       ), 
    183       array( 
    184         "[0-9]", 
    185         "[1-9]", 
    186         "[2-9]", 
    187         "[0-9#*]+", 
    188         "\*", 
    189       ), 
    190       // note, we're doing a subpattern match on the static portion so it can be extracted later 
    191       $drop.'('.$static.')'); 
    192    
    193   if (preg_match('/^'.$regex.'$/', $number, $matches)) { 
    194     return $prefix.$matches[1]; 
    195   } 
    196   return false; 
    197 } 
    198  
    19934/**********************************************************************************************************************/ 
    20035 
    20136$agi = new AGI(); 
    202  
    203 $localprefix_file = get_var($agi, "ASTETCDIR")."/localprefixes.conf"; 
    204  
    205 if (file_exists($localprefix_file)) { 
    206   parse_conf($localprefix_file, $conf, $section); 
    207   if (count($conf) == 0) { 
    208 //    $agi->verbose("Could not parse ".$localprefix_file); 
    209     exit(1); 
    210   } 
    211 } else { 
    212   $agi->verbose("Could not open ".$localprefix_file); 
    213   exit(1); 
    214 
    215  
    216 $r = $agi->get_variable("DIAL_NUMBER"); 
    217 if ($r["result"] == 0) { 
    218   $agi->verbose("DIAL_NUMBER not set -- nothing to do"); 
    219   exit(1); 
    220 
    221 $number = $r["data"]; 
    222  
    223 $number = sanitizeNumber($number); 
    224  
    225 $r = $agi->get_variable("DIAL_TRUNK"); 
    226 if ($r["result"] == 0) { 
    227   $agi->verbose("DIAL_TRUNK not set -- nothing to do"); 
    228   exit(1); 
    229 
    230 $trunk = $r["data"]; 
    231  
    232  
    233 if (isset($conf["trunk-$trunk"])) { 
    234   foreach ($conf["trunk-$trunk"] as $key=>$rule) { 
    235     // extract all ruleXX keys 
    236     //$agi->conlog("$key = $rule"); 
    237     if (preg_match("/^rule\d+$/",$key)) { 
    238       // $rule is a dial rule 
    239        
    240       if (($newnum = fixNumber($rule, $number, $agi)) !== false) { 
    241         $agi->verbose('Dialpattern '.$rule.' matched. '.$number.' -> '.$newnum, 2); 
    242         $agi->set_variable("DIAL_NUMBER", $newnum); 
    243          
    244         // reverted back form r2080 (r2081 on trac) so that any pattern match will end 
    245         // the loop. This needs to stay like this for backwards compatibility and often 
    246         // patterns are used to avoid matching substitution rules for exception cases. 
    247         exit(0); 
    248       } // else, it didn't match this rule 
    249     } // else, this isn't a rule 
    250   }  
    251 } // else, no config for this section 
    252  
    253 // we just exit with no changes to the variable. 
     37$agi->verbose("ERROR: This the fixlocalprefix script has been deprecated and does nothing"); 
    25438exit(0); 
    25539 
  • modules/branches/2.8/core/functions.inc.php

    r9226 r9240  
    9090      case 'features_featuremap_additional.conf': 
    9191        return $this->generate_featuremap_additional($version); 
    92         break; 
    93       case 'localprefixes.conf': 
    94         return $this->generate_localprefixes($version); 
    9592        break; 
    9693    } 
     
    568565      $output .= "channel=>$zapchannel\n"; 
    569566      $output .= $additional."\n"; 
    570     } 
    571     return $output; 
    572   } 
    573   function generate_localprefixes($ast_version) { 
    574     $output = ""; 
    575  
    576     $conf =  core_trunks_readDialRulesFile(); 
    577     foreach ($conf as $section=>$values) { 
    578       $output .=  "[".$section."]\n"; 
    579       foreach ($values as $key=>$value) { 
    580         $output .= $key."=".$value."\n"; 
    581       } 
    582       $output .= "\n"; 
    583567    } 
    584568    return $output; 
     
    13671351            continue; 
    13681352          } 
     1353          $trunkgroup = 'OUT_'.$trunkprops['trunkid']; 
    13691354          switch ($trunkprops['tech']) { 
    13701355            case 'dundi': 
     
    13731358              $ext->add($macro_name, 's', '', new ext_goto('1','${ARG1}')); 
    13741359 
    1375               $trunkgroup = 'OUT_'.$trunkprops['trunkid']; 
    13761360              $trunkcontext  = "from-trunk-".$trunkprops['tech']."-".$trunkprops['channelid']; 
    13771361              $ext->add($trunkcontext, '_.', '', new ext_set('GROUP()',$trunkgroup)); 
    13781362              $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk')); 
    13791363 
    1380               $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}')); 
    1381               $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}" = ""]', 'nomax')); 
    1382               $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_gotoif('$[${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}}]', 'hangit')); 
     1364              $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_set('OUTBOUND_GROUP', $trunkgroup)); 
     1365              $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_gotoif('$["${OUTMAXCHANS_'.$trunkprops['trunkid'].'}" = ""]', 'nomax')); 
     1366              $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_gotoif('$[${GROUP_COUNT('.$trunkgroup.')} >= ${OUTMAXCHANS_${DIAL_TRUNK}}]', 'hangit')); 
    13831367              if ($ast_lt_16) {  
    13841368                $ext->add($tcontext,$trunkprops['trunkid'],'nomax',new ext_execif('$["${CALLINGPRES_SV}" != ""]', 'SetCallerPres', '${CALLINGPRES_SV}')); 
     
    13871371              } 
    13881372              $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_set('DIAL_NUMBER','${FROM_DID}')); 
    1389               $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix')); 
     1373              $ext->add($tcontext,$trunkprops['trunkid'],'',new ext_gosubif('$["${PREFIX_TRUNK_'.$trunkprops['trunkid'].'}" != ""]','sub-flp-'.$trunkprops['trunkid'].',s,1')); 
    13901374              $ext->add($tcontext, $trunkprops['trunkid'], '', new ext_macro('dundi-${DIAL_TRUNK}','${OUTNUM}')); 
    13911375              $ext->add($tcontext,$trunkprops['trunkid'],'hangit',new ext_hangup()); 
     
    13971381            case 'iax2': 
    13981382            case 'sip': 
    1399               $trunkgroup = 'OUT_'.$trunkprops['trunkid']; 
    14001383              $trunkcontext  = "from-trunk-".$trunkprops['tech']."-".$trunkprops['channelid']; 
    14011384              $ext->add($trunkcontext, '_.', '', new ext_set('GROUP()',$trunkgroup)); 
     
    14361419          } 
    14371420          $ext->add($tcontext,$tcustom,'',new ext_set('DIAL_NUMBER','${FROM_DID}')); 
    1438           $ext->add($tcontext,$tcustom,'',new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix')); 
     1421          $ext->add($tcontext,$tcustom,'',new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','sub-flp-${DIAL_TRUNK},s,1')); 
    14391422          $ext->add($tcontext,$tcustom,'',new ext_dial('${EVAL(${TDIAL_STRING})}','300,${DIAL_TRUNK_OPTIONS}')); 
    14401423          $ext->add($tcontext,$tcustom,'hangit',new ext_hangup()); 
     
    14511434          } 
    14521435          $ext->add($tcontext,$texten,'',new ext_set('DIAL_NUMBER','${FROM_DID}')); 
    1453           $ext->add($tcontext,$texten,'',new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix')); 
     1436          $ext->add($tcontext,$texten,'',new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','sub-flp-${DIAL_TRUNK},s,1')); 
     1437 
    14541438          $ext->add($tcontext,$texten,'',new ext_dial('${TDIAL_STRING}/${OUTNUM}','300,${DIAL_TRUNK_OPTIONS}')); 
    14551439          $ext->add($tcontext,$texten,'hangit',new ext_hangup()); 
    14561440        } 
    14571441      } 
     1442 
     1443      $trunk_hash = core_trunks_list_dialrules(); 
     1444      if (is_array($trunk_hash) && count($trunk_hash)) { 
     1445        foreach ($trunk_hash as $trunkid => $patterns) { 
     1446          // First, generate the global referencing how many there are 
     1447          $ext->addGlobal("PREFIX_TRUNK_$trunkid",count($patterns)); 
     1448 
     1449          $context = 'sub-flp-'.$trunkid; 
     1450          $target = 'TARGET_FLP4'.$trunkid; 
     1451          $exten = 's'; 
     1452          foreach ($patterns as $pattern) { 
     1453            $prepend = $pattern['prepend_digits']; 
     1454            $offset =  strlen(preg_replace('/(\[[^\]]*\])/','X',$pattern['match_pattern_prefix'])); 
     1455 
     1456            $regex_base = $pattern['match_pattern_prefix'].$pattern['match_pattern_pass']; 
     1457 
     1458            // convert asterisk pattern matching into perl regular expression 
     1459            //  - two steps, use $ in place of + 
     1460            //  - next replace $ with + 
     1461            // if you don't do this, the str_replace() walks over itself 
     1462            $regex_intermediate = str_replace( 
     1463              array( 
     1464                "X", 
     1465                "Z", 
     1466                "N", 
     1467                ".", 
     1468                "*", 
     1469                "+", 
     1470              ), 
     1471              array( 
     1472                "[0-9]", 
     1473                "[1-9]", 
     1474                "[2-9]", 
     1475                "[0-9#*\$]$", 
     1476                "\*", 
     1477                "\+", 
     1478              ), 
     1479              $pattern['match_pattern_prefix'].$pattern['match_pattern_pass'] 
     1480            ); 
     1481            $regex = strtr($regex_intermediate,"$","+"); 
     1482 
     1483            if ($pattern['prepend_digits'] == '' && $offset == 0) { 
     1484              $ext->add($context, $exten, '', new ext_execif('$[${REGEX("^'.$regex.'$" ${DIAL_NUMBER})} = 1]','Return')); 
     1485            } else { 
     1486              $offset = $offset?':'.$offset:''; 
     1487              $ext->add($context, $exten, '', new ext_execif('$[${REGEX("^'.$regex.'$" ${DIAL_NUMBER})} = 1]','Set',$target.'='.$pattern['prepend_digits'].'${DIAL_NUMBER'.$offset.'}')); 
     1488              $ext->add($context, $exten, '', new ext_gotoif('$[${LEN(${'.$target.'})} != 0]', 'match')); 
     1489            } 
     1490 
     1491          } 
     1492          $ext->add($context, $exten, '', new ext_return('')); 
     1493          $ext->add($context, $exten, 'match', new ext_set('DIAL_NUMBER','${'.$target.'}')); 
     1494          $ext->add($context, $exten, '', new ext_return('')); 
     1495        } 
     1496      } 
     1497 
     1498 
    14581499      /* dialplan globals */ 
    14591500      // modules should NOT use the globals table to store anything! 
     
    15511592          $has_extension_state = true; 
    15521593        } 
    1553       } 
    1554  
    1555       // Let's create globals for each trunk to determine which one's have fixlocalprefix settings. 
    1556       // this allows us to skip calling the agi script if there are no rules to process saving 
    1557       // on performance 
    1558       // 
    1559       $conf = core_trunks_readDialRulesFile(); 
    1560       if (is_array($conf)) { 
    1561         foreach ($conf as $trunknum => $entries) { 
    1562           $trunkname = substr($trunknum,6); 
    1563           $ext->addGlobal("PREFIX_TRUNK_$trunkname",count($entries)); 
    1564         } 
    15651594      } 
    15661595 
     
    19151944      $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}')); 
    19161945      $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}')); 
    1917       $ext->add($context, $exten, 'skipoutcid', new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk 
     1946      $ext->add($context, $exten, 'skipoutcid', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','sub-flp-${DIAL_TRUNK},s,1'));  // this sets DIAL_NUMBER to the proper dial string for this trunk 
    19181947      $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number 
    19191948      $ext->add($context, $exten, '', new ext_set('custom', '${CUT(OUT_${DIAL_TRUNK},:,1)}'));  // Custom trunks are prefixed with "AMP:" 
     
    20482077      $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}')); 
    20492078      $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}')); 
    2050       $ext->add($context, $exten, 'skipoutcid', new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk 
     2079      $ext->add($context, $exten, 'skipoutcid', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','sub-flp-${DIAL_TRUNK},s,1'));  // manipulate DIAL_NUMBER 
    20512080      $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number 
    20522081 
     
    22182247      $ext->add($context, $exten, 'nomax', new ext_set('DIAL_NUMBER', '${ARG2}')); 
    22192248      $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}')); 
    2220       $ext->add($context, $exten, '', new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk 
     2249      $ext->add($context, $exten, '', new ext_gosubif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','sub-flp-${DIAL_TRUNK},s,1'));  // manimpulate DIAL_NUMBER 
    22212250      //  Replacement for asterisk's ENUMLOOKUP function 
    22222251      $ext->add($context, $exten, '', new ext_agi('enumlookup.agi')); 
     
    44914520 
    44924521 
    4493  
    4494  
    44954522/* begin page.trunks.php functions */ 
    44964523 
     
    47794806 
    47804807 
    4781 function core_trunks_addDialRules($trunknum, $dialrules) { 
    4782   global $db; 
    4783  
    4784   $rules_arr = array(); 
    4785   $i = 1; 
    4786   foreach ($dialrules as $rule) { 
    4787     $rules_arr[] = array($db->escapeSimple($rule),$i); 
    4788     $i++; 
    4789   } 
    4790   sql("DELETE FROM `trunks_dialpatterns` WHERE `trunkid` = $trunknum"); 
    4791   $compiled = $db->prepare("INSERT INTO `trunks_dialpatterns` (trunkid, rule, seq) VALUES ($trunknum,?,?)"); 
    4792   $result = $db->executeMultiple($compiled,$rules_arr); 
     4808function core_trunks_update_dialrules($trunknum, &$patterns, $delete = false) { 
     4809  global $db; 
     4810 
     4811  $trunknum =  $db->escapeSimple($trunknum); 
     4812  $filter_prepend = '/[^0-9+*#]/'; 
     4813  $filter_prefix = '/[^0-9.*#+xnzXNZ\-\[\]]/'; 
     4814  $filter_match =  '/[^0-9*#+xnzXNZ\-\[\]]/'; 
     4815 
     4816  $insert_pattern = array(); 
     4817  $seq = 0; 
     4818  foreach ($patterns as $pattern) { 
     4819    $match_pattern_prefix = $db->escapeSimple(preg_replace($filter_prefix,'',strtoupper(trim($pattern['match_pattern_prefix'])))); 
     4820    $match_pattern_pass = $db->escapeSimple(preg_replace($filter_match,'',strtoupper(trim($pattern['match_pattern_pass'])))); 
     4821    $prepend_digits = $db->escapeSimple(preg_replace($filter_prepend,'',strtoupper(trim($pattern['prepend_digits'])))); 
     4822    if ($match_pattern_prefix.$match_pattern_pass == '') { 
     4823      continue; 
     4824    } 
     4825    // if duplicate prepend, get rid of subsequent since they will never be checked 
     4826    $hash_index = md5($match_pattern_prefix.$match_pattern_pass); 
     4827    if (!isset($insert_pattern[$hash_index])) { 
     4828      $insert_pattern[$hash_index] = array($match_pattern_prefix, $match_pattern_pass, $prepend_digits, $seq); 
     4829      $seq++; 
     4830    } 
     4831  } 
     4832 
     4833  if ($delete) { 
     4834    sql('DELETE FROM `trunk_dialpatterns` WHERE `trunkid`='.q($trunknum)); 
     4835  } 
     4836  $compiled = $db->prepare('INSERT INTO `trunk_dialpatterns` (`trunkid`, `match_pattern_prefix`, `match_pattern_pass`, `prepend_digits`, `seq`) VALUES ('.$trunknum.',?,?,?,?)'); 
     4837  $result = $db->executeMultiple($compiled,$insert_pattern); 
    47934838  if(DB::IsError($result)) { 
    4794     die_freepbx($result->getDebugInfo()."<br><br>".'error adding to trunks_dialpatterns table');   
    4795   } 
    4796 
    4797  
    4798 function core_trunks_readDialRulesFile() { 
    4799   $rule_hash = array(); 
    4800   $sqlstr = "SELECT `trunkid`, `rule` FROM `trunks_dialpatterns` ORDER BY `trunkid`, `seq`"; 
    4801   $patterns = sql($sqlstr,"getAll",DB_FETCHMODE_ASSOC); 
    4802   $trunk_num = false; 
     4839    die_freepbx($result->getDebugInfo()."<br><br>".'error updating trunk_dialpatterns');   
     4840  } 
     4841
     4842 
     4843function core_trunks_list_dialrules() { 
     4844  $rule_hash = array(); 
     4845 
     4846  $patterns = core_trunks_get_dialrules(); 
    48034847  foreach ($patterns as $pattern) { 
    4804     if ($pattern['trunkid'] != $trunk_num) { 
    4805       $rule_num = 1; 
    4806       $trunk_num = $pattern['trunkid']; 
    4807     } 
    4808     $rule_hash['trunk-'.$pattern['trunkid']]['rule'.$rule_num++] = $pattern['rule']; 
     4848    //$rule_hash[$pattern['trunkid']][] = $pattern['prepend_digits'].'^'.$pattern['match_pattern_prefix'].'|'.$pattern['match_pattern_pass']; 
     4849    $rule_hash[$pattern['trunkid']][] = $pattern; 
    48094850  } 
    48104851  return $rule_hash; 
     
    49114952} 
    49124953 
    4913 function core_trunks_getDialRules($trunknum) { 
    4914   $conf = core_trunks_readDialRulesFile(); 
    4915   if (isset($conf["trunk-".$trunknum])) { 
    4916     return $conf["trunk-".$trunknum]; 
    4917   } 
    4918   return false; 
    4919 
     4954function core_trunks_get_dialrules($trunknum = false) { 
     4955  global $db; 
     4956  if ($trunknum === false) { 
     4957    $sql = "SELECT * FROM `trunk_dialpatterns` ORDER BY `trunkid`, `seq`"; 
     4958  } else { 
     4959    $trunknum = q($db->escapeSimple($trunknum)); 
     4960    $sql = "SELECT * FROM `trunk_dialpatterns` WHERE `trunkid` = $trunknum  ORDER BY `seq`"; 
     4961  } 
     4962  $patterns = sql($sql,"getAll",DB_FETCHMODE_ASSOC); 
     4963  return $patterns; 
     4964
     4965 
    49204966 
    49214967//get outbound routes for a given trunk 
     
    49314977} 
    49324978 
     4979function core_trunks_delete_dialrules($trunknum) { 
     4980  global $db; 
     4981  $trunknum = q($db->escapeSimple($trunknum)); 
     4982  sql("DELETE FROM `trunk_dialpatterns` WHERE `trunkid` = $trunknum"); 
     4983} 
     4984 
     4985 
     4986//----------------------------------------------------------------------------------------------------------------------------------------- 
     4987// The following APIs have all been removed and will result in crashes with traceback to obtain calling tree information 
     4988 
     4989function core_trunks_addDialRules($trunknum, $dialrules) { 
     4990  $trace = debug_backtrace(); 
     4991  $function = $trace[0]['function']; 
     4992  die_freepbx("function: $function has been deprecated and removed"); 
     4993} 
     4994 
    49334995function core_trunks_deleteDialRules($trunknum) { 
    4934   sql("DELETE FROM `trunks_dialpatterns` WHERE `trunkid` = $trunknum"); 
    4935 
     4996  $trace = debug_backtrace(); 
     4997  $function = $trace[0]['function']; 
     4998  die_freepbx("function: $function has been deprecated and removed"); 
     4999
     5000 
     5001function core_trunks_getDialRules($trunknum) { 
     5002  $trace = debug_backtrace(); 
     5003  $function = $trace[0]['function']; 
     5004  die_freepbx("function: $function has been deprecated and removed"); 
     5005
     5006 
     5007function core_trunks_readDialRulesFile() { 
     5008  $trace = debug_backtrace(); 
     5009  $function = $trace[0]['function']; 
     5010  die_freepbx("function: $function has been deprecated and removed"); 
     5011
     5012 
    49365013 
    49375014/* end page.trunks.php functions */ 
     
    51815258 
    51825259  $route_id =  $db->escapeSimple($route_id); 
    5183   $filter = '/[^0-9\-\.\[\]xXnNzZ]/'; 
     5260  $filter = '/[^0-9\*\#\+\-\.\[\]xXnNzZ]/'; 
    51845261  $insert_pattern = array(); 
    51855262  foreach ($patterns as $pattern) { 
    5186     $match_pattern_prefix = $db->escapeSimple(preg_replace($filter,'',strtoupper($pattern['match_pattern_prefix']))); 
    5187     $match_pattern_pass = $db->escapeSimple(preg_replace($filter,'',strtoupper($pattern['match_pattern_pass']))); 
    5188     $match_cid = $db->escapeSimple(preg_replace($filter,'',strtoupper($pattern['match_cid']))); 
    5189     $prepend_digits = $db->escapeSimple(preg_replace($filter,'',strtoupper($pattern['prepend_digits']))); 
     5263    $match_pattern_prefix = $db->escapeSimple(preg_replace($filter,'',strtoupper(trim($pattern['match_pattern_prefix'])))); 
     5264    $match_pattern_pass = $db->escapeSimple(preg_replace($filter,'',strtoupper(trim($pattern['match_pattern_pass'])))); 
     5265    $match_cid = $db->escapeSimple(preg_replace($filter,'',strtoupper(trim($pattern['match_cid'])))); 
     5266    $prepend_digits = $db->escapeSimple(preg_replace($filter,'',strtoupper(trim($pattern['prepend_digits'])))); 
     5267 
     5268    if ($match_pattern_pass.$match_pattern_pass.$match_cid == '') { 
     5269      continue; 
     5270    } 
    51905271 
    51915272    $hash_index = md5($match_pattern_prefix.$match_pattern_pass.$match_cid); 
    5192     $insert_pattern[$hash_index] = array($match_pattern_prefix, $match_pattern_pass, $match_cid, $prepend_digits); 
     5273    if (!isset($insert_pattern[$hash_index])) { 
     5274      $insert_pattern[$hash_index] = array($match_pattern_prefix, $match_pattern_pass, $match_cid, $prepend_digits); 
     5275    } 
    51935276  } 
    51945277 
  • modules/branches/2.8/core/install.php

    r8671 r9240  
    267267} 
    268268 
    269  
    270269// This next set of functions and code are used to migrate from the old 
    271270// global variable storage of trunk data to the new trunk table and trunk 
     
    279278        ereg("OUT_([0-9]+)",$unique_trunks[$b][0],$trunk_num2); 
    280279        return ($trunk_num1[1] >= $trunk_num2[1]? 1:-1); 
    281 } 
    282  
    283 // Get values from localprefix configuration file where values are stored 
    284 // for fixlocalprefix macro 
    285 // 
    286 function __parse_DialRulesFile($filename, &$conf, &$section) { 
    287   if (is_null($conf)) { 
    288     $conf = array(); 
    289   } 
    290   if (is_null($section)) { 
    291     $section = "general"; 
    292   } 
    293    
    294   if (file_exists($filename)) { 
    295     $fd = fopen($filename, "r"); 
    296     while ($line = fgets($fd, 1024)) { 
    297       if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) { 
    298         // name = value 
    299         // option line 
    300         $conf[$section][ $matches[1] ] = $matches[2]; 
    301       } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) { 
    302         // section name 
    303         $section = strtolower($matches[1]); 
    304       } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) { 
    305         // include another file 
    306          
    307         if ($matches[1][0] == "/") { 
    308           // absolute path 
    309           $filename = $matches[1]; 
    310         } else { 
    311           // relative path 
    312           $filename =  dirname($filename)."/".$matches[1]; 
    313         } 
    314         __parse_DialRulesFile($filename, $conf, $section); 
    315       } 
    316     } 
    317   } 
    318 } 
    319  
    320 function __order_DialRules($a, $b) { 
    321   return substr($a,4) > substr($b,4); 
    322280} 
    323281 
     
    519477} 
    520478 
    521 $sql = " 
    522 CREATE TABLE `trunks_dialpatterns`  
    523 (  
    524   `trunkid` INTEGER, 
    525   `rule` VARCHAR( 255 ) NOT NULL,  
    526   `seq` INTEGER, 
    527   PRIMARY KEY  (`trunkid`, `rule`, `seq`)  
    528 )  
    529 "; 
    530 outn(_("Checking if trunks_dialpatterns table exists..")); 
    531 $check = $db->query($sql); 
    532 if(DB::IsError($check) && $check->getCode() != DB_ERROR_ALREADY_EXISTS) { 
    533   die_freepbx("Can not create trunks_dialpatterns table"); 
    534 } else if(DB::IsError($check) && $check->getCode() == DB_ERROR_ALREADY_EXISTS) { 
    535   out(_("already exists")); 
    536 } else { 
    537   out(_("created")); 
    538   outn(_("loading table from localprefixes.conf..")); 
    539   $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf"; 
    540   $conf == array(); 
    541   __parse_DialRulesFile($localPrefixFile, $conf, $section); 
    542  
    543   $rules_arr = array(); 
    544   foreach ($conf as $tname => $rules) { 
    545     $tid = ltrim($tname,'trunk-'); 
    546     uksort($rules,'__order_DialRules'); //make sure they are in order 
    547     $seq = 1; 
    548     foreach ($rules as $rule) { 
    549       $rules_arr[] = array($tid,$rule,$seq); 
    550       $seq++; 
    551     } 
    552   } 
    553   $compiled = $db->prepare("INSERT INTO `trunks_dialpatterns` (trunkid, rule, seq) VALUES (?,?,?)"); 
    554   $result = $db->executeMultiple($compiled,$rules_arr); 
    555   if(DB::IsError($result)) { 
    556     die_freepbx($result->getDebugInfo().'error populating trunks_dialpatterns table');   
    557   } 
    558   out(_("loaded")); 
    559 } 
    560  
    561479outn(_("Checking if privacy manager options exists..")); 
    562480$check = $db->query('SELECT pmmaxretries FROM incoming'); 
  • modules/branches/2.8/core/module.xml

    r9210 r9240  
    1010  <canuninstall>no</canuninstall> 
    1111  <changelog> 
    12     *2.8.0.0beta1.1* #4132, #2833 
     12    *2.8.0.0beta1.1* #4132, #2833, #4068, #4135, #4143, #4144 
    1313    *2.8.0.0beta1.0* #4100, #4102, #4110 New Outbound Routing Schema and features 
    1414    *2.7.0.2* really fix #4092 
  • modules/branches/2.8/core/page.routing.php

    r9229 r9240  
    234234  if ($key > 0) { 
    235235    echo "\t\t<img src=\"images/resultset_up.png\" onclick=\"repositionRoute('{$tresult['route_id']}','up')\" alt='" .  _("Move Up") . 
    236       "' style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     236      "' style='cursor:pointer; float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
    237237  } else { 
    238238    echo "\t\t<img src='images/blank.gif' style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     
    242242  if ($key < ($positions-1)) { 
    243243    echo "\t\t<img src='images/resultset_down.png' onclick=\"repositionRoute('{$tresult['route_id']}','down')\" alt='" . _("Move Down") . 
    244       "'  style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     244      "'  style='cursor:pointer; float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
    245245  } else { 
    246246    echo "\t\t<img src='images/blank.gif' style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     
    250250  if ($key > 0) { 
    251251    echo "\t\t<img src=\"images/resultset_top.png\" onclick=\"repositionRoute('{$tresult['route_id']}','top')\" alt='" .  _("First") . 
    252       "' style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     252      "' style='cursor:pointer; float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
    253253  } else { 
    254254    echo "\t\t<img src='images/blank.gif' style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     
    258258  if ($key < ($positions-1)) { 
    259259    echo "\t\t<img src='images/resultset_bottom.png' onclick=\"repositionRoute('{$tresult['route_id']}','bottom')\" alt='" . _("Last") . 
    260       "'  style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     260      "'  style='cursor:pointer; float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
    261261  } else { 
    262262    echo "\t\t<img src='images/blank.gif' style='float:none; margin-left:0px; margin-bottom:0px;' width='12px' height='12px'>\n"; 
     
    421421      <b>[1237-9]</b>&nbsp;   <?php echo _("matches any digit in the brackets (example: 1,2,3,7,8,9)")?><br /> 
    422422      <b>.</b>&nbsp;&nbsp;&nbsp; <?php echo _("wildcard, matches one or more dialed digits")?> <br /> 
    423       <b><?php echo _("prepend")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("Digits to prepend to a successful match. If the dialed number matches the patterns specified by the subsequent columns, then thise will be prepended before sending to the trunks.")?><br /> 
    424       <b><?php echo _("prefix")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("Prefix to remove on a successful match. The dialed number is compared to this and the subsequent columns for a match. Upon a match, this prefix is removed from the dialed number before sending it to the trunks.")?><br /> 
    425       <b><?php echo _("match pattern")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("The dialed number will be compared against the  prefix + this match pattern. Upon a match, the match pattern portion of the dialed number will be sent to the trunks")?><br /> 
    426       <b><?php echo _("CallerID")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("If CallerID is supplied, the dialed number will only match the prefix + match pattern if the CallerID being transmitted matches this. When extensions make outbound calls, the CallerID will be their extension number and NOT their Outbound CID. The above special matching sequences can be used for CallerID matching similar to other number matches.")?><br /> 
     423      <b><?php echo _("prepend:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("Digits to prepend to a successful match. If the dialed number matches the patterns specified by the subsequent columns, then this will be prepended before sending to the trunks.")?><br /> 
     424      <b><?php echo _("prefix:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("Prefix to remove on a successful match. The dialed number is compared to this and the subsequent columns for a match. Upon a match, this prefix is removed from the dialed number before sending it to the trunks.")?><br /> 
     425      <b><?php echo _("match pattern:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("The dialed number will be compared against the  prefix + this match pattern. Upon a match, the match pattern portion of the dialed number will be sent to the trunks")?><br /> 
     426      <b><?php echo _("CallerID:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("If CallerID is supplied, the dialed number will only match the prefix + match pattern if the CallerID being transmitted matches this. When extensions make outbound calls, the CallerID will be their extension number and NOT their Outbound CID. The above special matching sequences can be used for CallerID matching similar to other number matches.")?><br /> 
    427427      </span></a> 
    428428      <hr></h5></td> 
     
    598598        </select> 
    599599         
    600         <img src="images/trash.png" style="float:none; margin-left:0px; margin-bottom:-3px;" title="Click here to remove this trunk" onclick="deleteTrunk(<?php echo $key ?>)"> 
     600        <img src="images/trash.png" style="cursor:pointer; float:none; margin-left:0px; margin-bottom:-3px;" title="Click here to remove this trunk" onclick="deleteTrunk(<?php echo $key ?>)"> 
    601601      <?php   // move up 
    602602      if ($key > 0) {?> 
     
    609609       
    610610      if ($key < ($positions-1)) {?> 
    611         <img src="images/resultset_down.png" onclick="repositionTrunk('<?php echo $key ?>','down')" alt="<?php echo _("Move Down")?>"  style="float:none; margin-left:0px; margin-bottom:0px;" width="12px" height="12px"> 
     611        <img src="images/resultset_down.png" onclick="repositionTrunk('<?php echo $key ?>','down')" alt="<?php echo _("Move Down")?>"  style="cursor:pointer; float:none; margin-left:0px; margin-bottom:0px;" width="12px" height="12px"> 
    612612      <?php  } else { ?> 
    613613        <img src="images/blank.gif" style="float:none; margin-left:0px; margin-bottom:0px;" width="9" height="11"> 
     
    681681 
    682682function patternsRemove(idx) { 
    683   $("#prepend_digit_"+idx+",#pattern_prefix_"+idx+",#pattern_pass_"+idx+",#match_cid_"+idx).each(function(){ 
    684     this.value = ''; 
    685   }).parent().parent().hide(); 
    686 
    687  
    688 /* Insert a sip_setting/sip_value pair of text boxes */ 
     683  $("#prepend_digit_"+idx).parent().parent().remove(); 
     684
     685 
    689686function addCustomField(prepend_digit, pattern_prefix, pattern_pass, match_cid) { 
    690687  var idx = $(".dial-pattern").size(); 
     
    699696  var dpt_match_cid = match_cid == '' ? 'dpt-title' : 'dpt-value'; 
    700697 
    701   $("#last_row").before('\ 
     698  var new_insert = $("#last_row").before('\ 
    702699  <tr>\ 
    703700    <td colspan="2">\ 
     
    706703    [<input title="<?php echo $mp_tit?>" type="text" size="16" id="pattern_pass_'+idx+'" name="pattern_pass['+idx+']" class="'+dpt_pattern_pass+'" value="'+pattern_pass+'" tabindex="'+tabindex2+'"> /\ 
    707704    <input title="<?php echo $ci_tit?>" type="text" size="14" id="match_cid_'+idx+'" name="match_cid['+idx+']" class="'+dpt_match_cid+'" value="'+match_cid+'" tabindex="'+tabindex3+'">]\ 
    708       <img src="images/trash.png" style="float:none; margin-left:0px; margin-bottom:-3px;" alt="<?php echo _("remove")?>" title="<?php echo _("Click here to remove this pattern")?>" onclick="patternsRemove('+idx+')">\ 
     705      <img src="images/trash.png" style="cursor:pointer; float:none; margin-left:0px; margin-bottom:-3px;" alt="<?php echo _("remove")?>" title="<?php echo _("Click here to remove this pattern")?>" onclick="patternsRemove('+idx+')">\ 
    709706    </td>\ 
    710707  </tr>\ 
    711   ')
    712   // There's almost always one blank field so make sure these are done 
    713   $(".dpt-title").toggleVal({ 
     708  ').prev()
     709 
     710  new_insert.find(".dpt-title").toggleVal({ 
    714711    populateFrom: "title", 
    715712    changedClass: "text-normal", 
    716713    focusClass: "text-normal" 
    717714  }); 
    718   // If any value were put in, handled those also 
    719715  if (pattern_pass != '' || pattern_prefix != '' || prepend_digit != '' || match_cid != '') { 
    720     $(".dpt-value").toggleVal({ 
     716    new_insert.find(".dpt-value").toggleVal({ 
    721717      changedClass: "text-red" 
    722718    }); 
  • modules/branches/2.8/core/page.trunks.php

    r9217 r9240  
    4242$failtrunk_enable = ($failtrunk == "")?'':'CHECKED'; 
    4343 
    44 if (isset($_REQUEST["dialrules"])) { 
    45   $dialrules = explode("\n",$_REQUEST["dialrules"]); 
    46  
    47   if (is_array($dialrules)) 
    48     foreach (array_keys($dialrules) as $key) { 
    49       //trim it 
    50       $dialrules[$key] = trim($dialrules[$key]); 
    51        
    52       // remove blanks 
    53       if ($dialrules[$key] == "") unset($dialrules[$key]); 
    54        
    55       // remove leading underscores (we do that on backend) 
    56       if ($dialrules[$key][0] == "_") $dialrules[$key] = substr($dialrules[$key],1); 
    57     } 
    58    
    59   // check for duplicates, and re-sequence 
    60   $dialrules = array_values(array_unique($dialrules)); 
    61 } else { 
    62   $dialrules = array(); 
    63 
     44// 
     45// Use a hash of the value inserted to get rid of duplicates 
     46$dialpattern_insert = array(); 
     47$p_idx = 0; 
     48$n_idx = 0; 
     49 
     50if (isset($_POST["prepend_digit"])) { 
     51  $prepend_digit = $_POST["prepend_digit"]; 
     52  $pattern_prefix = $_POST["pattern_prefix"]; 
     53  $pattern_pass = $_POST["pattern_pass"]; 
     54 
     55  foreach (array_keys($prepend_digit) as $key) { 
     56    if ($prepend_digit[$key]!='' || $pattern_prefix[$key]!='' || $pattern_pass[$key]!='') { 
     57 
     58      $dialpattern_insert[] = array( 
     59        'prepend_digits' => htmlspecialchars(trim($prepend_digit[$key])), 
     60        'match_pattern_prefix' => htmlspecialchars(trim($pattern_prefix[$key])), 
     61        'match_pattern_pass' => htmlspecialchars(trim($pattern_pass[$key])), 
     62      ); 
     63    } 
     64  } 
     65
     66 
    6467 
    6568//if submitting form, update database 
     
    6871    $trunknum = core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, trim($failtrunk), $disabletrunk, $trunk_name, $provider); 
    6972     
    70    core_trunks_addDialRules($trunknum, $dialrules); 
     73    core_trunks_update_dialrules($trunknum, $dialpattern_insert); 
    7174    needreload(); 
    7275    redirect_standard(); 
     
    7679     
    7780    // this can rewrite too, so edit is the same 
    78    core_trunks_addDialRules($trunknum, $dialrules); 
     81    core_trunks_update_dialrules($trunknum, $dialpattern_insert, true); 
    7982    needreload(); 
    8083    redirect_standard('extdisplay'); 
     
    8386   
    8487    core_trunks_del($trunknum); 
    85    core_trunks_deleteDialRules($trunknum); 
     88    core_trunks_delete_dialrules($trunknum); 
    8689    core_routing_trunk_del($trunknum); 
    8790    needreload(); 
     
    108111 
    109112      if (isset($xmldata['lca-data']['prefix'])) { 
    110          
     113        $hash_filter = array(); //avoid duplicates 
    111114        if ($action == 'populatenpanxx10') { 
    112115          // 10 digit dialing 
     
    114117          // - match local 10 digits 
    115118          // - add 1 to anything else 
    116           $dialrules[] = $matches[1].'NXXXXXX'; 
     119          $dialpattern_array[] = array( 
     120            'prepend_digits' => '', 
     121            'match_pattern_prefix' => '', 
     122            'match_pattern_pass' => htmlspecialchars($matches[1].'NXXXXXX'), 
     123          ); 
    117124          // add NPA to 7-digits 
    118125          foreach ($xmldata['lca-data']['prefix'] as $prefix) { 
    119             $dialrules[] = $prefix['npa'].'+'.$prefix['nxx'].'XXXX'; 
     126            if (isset($hash_filter[$prefix['npa'].'+'.$prefix['nxx']])) { 
     127              continue; 
     128            } else { 
     129              $hash_filter[$prefix['npa'].'+'.$prefix['nxx']] = true; 
     130            } 
     131            $dialpattern_array[] = array( 
     132              'prepend_digits' =>  htmlspecialchars($prefix['npa']), 
     133              'match_pattern_prefix' => '', 
     134              'match_pattern_pass' => htmlspecialchars($prefix['nxx'].'XXXX'), 
     135            ); 
    120136          } 
    121137          foreach ($xmldata['lca-data']['prefix'] as $prefix) { 
    122             $dialrules[] = $prefix['npa'].$prefix['nxx'].'XXXX'; 
     138            if (isset($hash_filter[$prefix['npa'].$prefix['nxx']])) { 
     139              continue; 
     140            } else { 
     141              $hash_filter[$prefix['npa'].$prefix['nxx']] = true; 
     142            } 
     143            $dialpattern_array[] = array( 
     144              'prepend_digits' =>  '', 
     145              'match_pattern_prefix' => '', 
     146              'match_pattern_pass' => htmlspecialchars($prefix['npa'].$prefix['nxx'].'XXXX'), 
     147            ); 
    123148          } 
    124149          // if a number was not matched as local, dial it with '1' prefix 
    125           $dialrules[] = '1+NXXNXXXXXX'; 
     150          $dialpattern_array[] = array( 
     151            'prepend_digits' =>  '', 
     152            'match_pattern_prefix' => '', 
     153            'match_pattern_pass' => '1+NXXNXXXXXX', 
     154          ); 
    126155        } else { 
    127156          // 7 digit dialing 
     
    130159          // - add 1 to everything else 
    131160          foreach ($xmldata['lca-data']['prefix'] as $prefix) { 
    132             $dialrules[] = $prefix['npa'].'|'.$prefix['nxx'].'XXXX'; 
     161            if (isset($hash_filter[$prefix['npa'].'|'.$prefix['nxx']])) { 
     162              continue; 
     163            } else { 
     164              $hash_filter[$prefix['npa'].'|'.$prefix['nxx']] = true; 
     165            } 
     166            $dialpattern_array[] = array( 
     167              'prepend_digits' =>  '', 
     168              'match_pattern_prefix' => htmlspecialchars( $prefix['npa']), 
     169              'match_pattern_pass' => htmlspecialchars($prefix['nxx'].'XXXX'), 
     170            ); 
    133171          } 
    134172          foreach ($xmldata['lca-data']['prefix'] as $prefix) { 
    135             $dialrules[] = $prefix['nxx'].'XXXX'; 
     173            if (isset($hash_filter[$prefix['nxx']])) { 
     174              continue; 
     175            } else { 
     176              $hash_filter[$prefix['nxx']] = true; 
     177            } 
     178            $dialpattern_array[] = array( 
     179              'prepend_digits' =>  '', 
     180              'match_pattern_prefix' => '', 
     181              'match_pattern_pass' => htmlspecialchars($prefix['nxx'].'XXXX'), 
     182            ); 
    136183          } 
    137           $dialrules[] = '1+NXXNXXXXXX'; 
    138           $dialrules[] = '1'.$matches[1].'+NXXXXXX'; 
     184          $dialpattern_array[] = array( 
     185            'prepend_digits' =>  '1', 
     186            'match_pattern_prefix' => '', 
     187            'match_pattern_pass' => 'NXXNXXXXXX', 
     188          ); 
     189          $dialpattern_array[] = array( 
     190            'prepend_digits' => htmlspecialchars('1'.$matches[1]), 
     191            'match_pattern_prefix' => '', 
     192            'match_pattern_pass' => 'NXXXXXX', 
     193          ); 
    139194        } 
    140195 
    141196        // check for duplicates, and re-sequence 
    142        $dialrules = array_values(array_unique($dialrules)); 
     197        unset($hash_filter); 
    143198      } else { 
    144199        $errormsg = _("Error fetching prefix list for: "). $_REQUEST["npanxx"]; 
     
    241296    $provider = $trunk_details['provider']; 
    242297    $trunk_name = htmlentities($trunk_details['name']); 
    243      
     298 
    244299    if ($tech!="enum") { 
    245300   
     
    264319      } 
    265320    } 
    266     if (count($dialrules) == 0) { 
    267       if ($temp = core_trunks_getDialRules($trunknum)) { 
    268         foreach ($temp as $key=>$val) { 
    269           // extract all ruleXX keys 
    270           if (preg_match("/^rule\d+$/",$key)) { 
    271             $dialrules[] = $val; 
    272           } 
    273         } 
    274       } 
    275       unset($temp); 
    276     } 
     321    if (count($dialpattern_array) == 0) { 
     322      $dialpattern_array = core_trunks_get_dialrules($trunknum); 
     323    } 
    277324    $upper_tech = strtoupper($tech); 
    278325    if (trim($trunk_name) == '') { 
     
    333380    echo "<h2>".sprintf(_("Add %s Trunk"),$upper_tech).($upper_tech == 'ZAP' && ast_with_dahdi()?" ("._("DAHDI compatibility mode").")":"")."</h2>"; 
    334381  }  
     382  if (!isset($dialpattern_array)) { 
     383    $dialpattern_array = array(); 
     384  } 
     385     
    335386switch ($tech) { 
    336387  case 'dundi': 
     
    360411      <tr> 
    361412        <td colspan="2"> 
    362           <h4><?php echo _("General Settings")?></h4> 
     413          <h4><?php echo _("General Settings")?><hr></h4> 
    363414        </td> 
    364415      </tr> 
     
    431482      </tr> 
    432483 
    433       <tr> 
    434         <td colspan="2"> 
    435           <h4><?php echo _("Outgoing Dial Rules")?></h4> 
    436         </td> 
    437       </tr> 
    438       <tr> 
    439         <td valign="top"> 
    440           <a href=# class="info"><?php echo _("Dial Rules")?><span><?php echo _("A Dial Rule controls how calls will be dialed on this trunk. It can be used to add or remove prefixes. Numbers that don't match any patterns defined here will be dialed as-is. Note that a pattern without a + or | (to add or remove a prefix) will not make any changes but will create a match. Only the first matched rule will be executed and the remaining rules will not be acted on.")?><br /><br /><b><?php echo _("Rules:")?></b><br /> 
    441   <strong>X</strong>&nbsp;&nbsp;&nbsp; <?php echo _("matches any digit from 0-9")?><br /> 
    442   <strong>Z</strong>&nbsp;&nbsp;&nbsp; <?php echo _("matches any digit from 1-9")?><br /> 
    443   <strong>N</strong>&nbsp;&nbsp;&nbsp; <?php echo _("matches any digit from 2-9")?><br /> 
    444   <strong>[1237-9]</strong>&nbsp;   <?php echo _("matches any digit or letter in the brackets (in this example, 1,2,3,7,8,9)")?><br /> 
    445   <strong>.</strong>&nbsp;&nbsp;&nbsp; <?php echo _("wildcard, matches one or more characters (not allowed before a | or +)")?><br /> 
    446   <strong>|</strong>&nbsp;&nbsp;&nbsp; <?php echo _("removes a dialing prefix from the number (for example, 613|NXXXXXX would match when some dialed \"6135551234\" but would only pass \"5551234\" to the trunk)")?> 
    447   <strong>+</strong>&nbsp;&nbsp;&nbsp; <?php echo _("adds a dialing prefix from the number (for example, 1613+NXXXXXX would match when some dialed \"5551234\" and would pass \"16135551234\" to the trunk)")?><br /><br /> 
    448   <?php echo _("You can also use both + and |, for example: 01+0|1ZXXXXXXXXX would match \"016065551234\" and dial it as \"0116065551234\" Note that the order does not matter, eg. 0|01+1ZXXXXXXXXX does the same thing."); ?> 
    449           </span></a>: 
    450         </td><td valign="top"> 
    451           <textarea id="dialrules" cols="20"  tabindex="<?php echo ++$tabindex;?>" rows="<?php   
    452             if (is_array($dialrules)) { 
    453               $rows = count($dialrules)+1;  
    454               echo (($rows < 5) ? 5 : (($rows > 20) ? 20 : $rows) ); 
    455             } else { 
    456               echo "5"; 
    457             } ?>" name="dialrules"><?php if(is_array($dialrules)) { echo implode("\n",$dialrules); } ?></textarea><br> 
    458            
    459           <input type="submit" style="font-size:10px;" value="<?php echo _("Clean & Remove duplicates")?>"  tabindex="<?php echo ++$tabindex;?>"/> 
    460         </td> 
    461       </tr> 
     484    <tr> 
     485      <td colspan="2"><h4> 
     486      <a href=# class="info"><?php echo _("Dialed Number Manipulation Rules")?><span> 
     487      <?php echo _("These rules can manipulate the dialed number before sending it out this trunk. If no rule applies, the number is not changed. The original dialed number is passed down from the route where some manipulation may have already occured. This trunk has the option to further manipulate the number. If the number matches the combined values in the <b>prefix</b> plus the <b>match pattern</b> boxes, the rule will be applied and all subsequent rules ignored.<b /> Upon a match, the <b>prefix</b>, if defined, will be stripped. Next the <b>prepend</b> will be inserted in front of the <b>match pattern</b> and the resulting number will be sent to the trunk. All fields are optional.")?><br /><br /><b><?php echo _("Rules:")?></b><br /> 
     488      <b>X</b>&nbsp;&nbsp;&nbsp; <?php echo _("matches any digit from 0-9")?><br /> 
     489      <b>Z</b>&nbsp;&nbsp;&nbsp; <?php echo _("matches any digit from 1-9")?><br /> 
     490      <b>N</b>&nbsp;&nbsp;&nbsp; <?php echo _("matches any digit from 2-9")?><br /> 
     491      <b>[1237-9]</b>&nbsp;   <?php echo _("matches any digit in the brackets (example: 1,2,3,7,8,9)")?><br /> 
     492      <b>.</b>&nbsp;&nbsp;&nbsp; <?php echo _("wildcard, matches one or more dialed digits")?> <br /> 
     493      <b><?php echo _("prepend:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("Digits to prepend upon a successful match. If the dialed number matches the patterns in the <b>prefix</b> and <b>match pattern</b> boxes, this will be prepended before sending to the trunk.")?><br /> 
     494      <b><?php echo _("prefix:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("Prefix to remove upon a successful match. If the dialed number matches this plus the <b>match pattern</b> box, this prefix is removed before adding the optional <b>prepend</b> box and sending the results to the trunk.")?><br /> 
     495      <b><?php echo _("match pattern:")?></b>&nbsp;&nbsp;&nbsp; <?php echo _("The dialed number will be compared against the <b>prefix</b> plus this pattern. Upon a match, this portion of the number will be sent to the trunks after removing the <b>prefix</b> and appending the <b>prepend</b> digits")?><br /> 
     496      <?php echo _("You can completely replace a number by matching on the <b>prefix</b> only, replacing it with a <b>prepend</b> and leaving the <b>match pattern</b> blank."); ?> 
     497      </span></a> 
     498      <hr></h4></td> 
     499    </tr> 
     500 
     501    <tr><td colspan="2"> 
     502      <input type="button" id="dial-pattern-add"  value="<?php echo _("Add More Dial Pattern Fields")?>" /> 
     503      <input type="button" id="dial-pattern-clear"  value="<?php echo _("Clear all Fields")?>" /> 
     504    </td></tr> 
     505    <tr><td colspan="2"><div class="dialpatterns"><table> 
     506<?php 
     507  $pp_tit = _("prepend"); 
     508  $pf_tit = _("prefix"); 
     509  $mp_tit = _("match pattern"); 
     510  foreach ($dialpattern_array as $idx => $pattern) { 
     511    $tabindex++; 
     512    $dpt_class = $pattern['prepend_digits'] == '' ? 'dpt-title' : 'dpt-value'; 
     513    echo <<< END 
     514    <tr> 
     515      <td colspan="2"> 
     516        (<input title="$pp_tit" type="text" size="5" id="prepend_digit_$idx" name="prepend_digit[$idx]" class="dial-pattern dp-prepend $dpt_class" value="{$pattern['prepend_digits']}" tabindex="$tabindex">) + 
     517END; 
     518    $tabindex++; 
     519    $dpt_class = $pattern['match_pattern_prefix'] == '' ? 'dpt-title' : 'dpt-value'; 
     520    echo <<< END 
     521        <input title="$pf_tit" type="text" size="4" id="pattern_prefix_$idx" name="pattern_prefix[$idx]" class="dp-prefix $dpt_class" value="{$pattern['match_pattern_prefix']}" tabindex="$tabindex"> | 
     522END; 
     523    $tabindex++; 
     524    $dpt_class = $pattern['match_pattern_pass'] == '' ? 'dpt-title' : 'dpt-value'; 
     525    echo <<< END 
     526        <input title="$mp_tit" type="text" size="16" id="pattern_pass_$idx" name="pattern_pass[$idx]" class="dp-match $dpt_class" value="{$pattern['match_pattern_pass']}" tabindex="$tabindex"> 
     527END; 
     528?> 
     529        <img src="images/trash.png" style="cursor:pointer; float:none; margin-left:0px; margin-bottom:-3px;" alt="<?php echo _("remove")?>" title="<?php echo _('Click here to remove this pattern')?>" onclick="patternsRemove(<?php echo _("$idx") ?>)"> 
     530      </td> 
     531    </tr> 
     532<?php 
     533  } 
     534  $next_idx = count($dialpattern_array); 
     535?> 
     536    <tr> 
     537      <td colspan="2"> 
     538        (<input title="<?php echo $pp_tit?>" type="text" size="5" id="prepend_digit_<?php echo $next_idx?>" name="prepend_digit[<?php echo $next_idx?>]" class="dp-prepend dial-pattern dpt-title" value="" tabindex="<?php echo ++$tabindex;?>">) + 
     539        <input title="<?php echo $pf_tit?>" type="text" size="4" id="pattern_prefix_<?php echo $next_idx?>" name="pattern_prefix[<?php echo $next_idx?>]" class="dp-prefix dpt-title" value="" tabindex="<?php echo ++$tabindex;?>"> | 
     540        <input title="<?php echo $mp_tit?>" type="text" size="16" id="pattern_pass_<?php echo $next_idx?>" name="pattern_pass[<?php echo $next_idx?>]" class="dp-match dpt-title" value="" tabindex="<?php echo ++$tabindex;?>"> 
     541        <img src="images/trash.png" style="cursor:pointer; float:none; margin-left:0px; margin-bottom:-3px;" alt="<?php echo _("remove")?>" title="<?php echo _("Click here to remove this pattern")?>" onclick="patternsRemove(<?php echo _("$next_idx") ?>)"> 
     542 
     543      </td> 
     544    </tr> 
     545    <tr id="last_row"></tr>  
     546    </table></div></tr></td> 
     547<?php 
     548  $tabindex += 2000; // make room for dynamic insertion of new fields 
     549?> 
    462550      <tr> 
    463551        <td> 
     
    529617      function populateAlwaysAdd() { 
    530618        do { 
    531          var localpattern = <?php echo 'prompt("'._("What is the local dialing pattern?\\n\\n(ie. NXXNXXXXXX for US/CAN 10-digit dialing, NXXXXXX for 7-digit)").'"'?>,"NXXXXXX"); 
     619          var localpattern = <?php echo 'prompt("'._("What is the local dialing pattern?\\n\\n(ie. NXXNXXXXXX for US/CAN 10-digit dialing, NXXXXXX for 7-digit)").'"'?>,<?php echo _("NXXXXXX")?>); 
    532620          if (localpattern == null) return; 
    533621        } while (!localpattern.match('^[0-9#*ZXN\.]+$') && <?php echo '!alert("'._("Invalid pattern. Only 0-9, #, *, Z, N, X and . are allowed.").'")'?>); 
     
    538626        } while (!localprefix.match('^[0-9#*]+$') && <?php echo '!alert("'._("Invalid prefix. Only dialable characters (0-9, #, and *) are allowed.").'")'?>); 
    539627 
    540         dialrules = document.getElementById('dialrules'); 
    541         if (dialrules.value[dialrules.value.length-1] != '\n') { 
    542           dialrules.value = dialrules.value + '\n'; 
    543         } 
    544         dialrules.value = dialrules.value + localprefix + '+' + localpattern + '\n'; 
     628        addCustomField(localprefix,'',localpattern); 
    545629      } 
    546630       
     
    552636         
    553637        do { 
    554          var localpattern = <?php echo 'prompt("'._("What is the dialing pattern for local numbers after")?> "+localprefix+"? \n\n<?php echo _("(ie. NXXNXXXXXX for US/CAN 10-digit dialing, NXXXXXX for 7-digit)").'"'?>,"NXXXXXX"); 
     638          var localpattern = <?php echo 'prompt("'._("What is the dialing pattern for local numbers after")?> "+localprefix+"? \n\n<?php echo _("(ie. NXXNXXXXXX for US/CAN 10-digit dialing, NXXXXXX for 7-digit)").'"'?>,<?php echo _("NXXXXXX")?>); 
    555639          if (localpattern == null) return; 
    556640        } while (!localpattern.match('^[0-9#*ZXN\.]+$') && <?php echo '!alert("'._("Invalid pattern. Only 0-9, #, *, Z, N, X and . are allowed.").'")'?>); 
    557641         
    558         dialrules = document.getElementById('dialrules'); 
    559         if (dialrules.value[dialrules.value.length-1] != '\n') { 
    560           dialrules.value = dialrules.value + '\n'; 
    561         } 
    562         dialrules.value = dialrules.value + localprefix + '|' + localpattern + '\n'; 
     642        addCustomField('',localprefix,localpattern); 
    563643      } 
    564644       
     
    581661      } 
    582662      </script> 
    583 <?php /* //DIALRULES 
    584       <tr> 
    585         <td> 
    586           <a href=# class="info">Dial rules<span>The area code this trunk is in.</span></a>:  
    587         </td><td>&nbsp; 
    588           <select id="dialrulestype" name="dialrulestype" onChange="changeRulesType();"> 
    589 <?php  
    590           $rules = array( "asis" => "Don't change number", 
    591               "always" => "Always dial prefix+areacode", 
    592               "local" => "Local 7-digit dialing", 
    593               "local10" => "Local 10-digit dialing"); 
    594  
    595           foreach ($rules as $value=>$display) { 
    596             echo "<option value=\"".$value."\" ".(($value == $dialrulestype) ? "SELECTED" : "").">".$display."</option>"; 
    597           } 
    598 ?> 
    599           </select> 
    600            
    601         </td> 
    602       </tr> 
    603       <tr> 
    604         <td> 
    605           <a href=# class="info"><?php echo _("Local dialing pattern<span>The dialing pattern to make a 'local' call.</span>")</a>:  
    606         </td><td> 
    607           <input id="localpattern" type="text" size="10" maxlength="20" name="localpattern" value="<?php echo $localpattern ?>"/> 
    608            
    609         </td> 
    610       </tr> 
    611       <tr> 
    612         <td> 
    613           <a href=# class="info"><?php echo _("Long-distance dial prefix<span>The prefix for dialing long-distance numbers. In north america, this should be \"1\".</span>")?></a>:  
    614         </td><td> 
    615           <input id="lddialprefix" type="text" size="3" maxlength="6" name="lddialprefix" value="<?php echo $lddialprefix ?>"/> 
    616            
    617         </td> 
    618       </tr> 
    619       <tr> 
    620         <td> 
    621           <a href=# class="info"><?php echo _("Local LD prefix<span>The area code this trunk is in. Any 7-digit numbers that don't match a number in the below list will have dialprefix+areacode added to them. </span>")?></a>:  
    622         </td><td> 
    623           <input id="areacode" type="text" size="3" maxlength="6" name="areacode" value="<?php echo $areacode ?>"/> 
    624            
    625         </td> 
    626       </tr> 
    627       <tr> 
    628         <td valign="top"> 
    629           <a href=# class="info"><?php echo _("Local prefixes<span>This should be a list of local areacodes + prefixes to use for local dialing.</span>")?></a>:  
    630         </td><td valign="top">&nbsp; 
    631           <textarea id="localprefixes" cols="8" rows="<?php  $rows = count($localprefixes)+1; echo (($rows < 5) ? 5 : (($rows > 20) ? 20 : $rows) ); ?>" name="localprefixes"><?php echo  implode("\n",$localprefixes);?></textarea><br> 
    632             
    633           <input id="npanxx" name="npanxx" type="hidden" /><br> 
    634           <a href=# class="info"><?php echo _("Populate with local rules<span>Do a lookup from http://members.dandy.net/~czg/search.html to find all local-reachable area codes and phone numbers.</span>")?></a>: <input type="button" value="Go" onClick="checkPopulate();" /> 
    635           <br><br> 
    636         </td> 
    637       </tr> 
    638       <script language="javascript"> 
    639        
    640       function checkPopulate() { 
    641         //var npanxx = prompt("What is your areacode + prefix (NPA-NXX)?", document.getElementById('areacode').value); 
    642         var npanxx = <?php echo 'prompt("'._("What is your areacode + prefix (NPA-NXX)?").'")'?>; 
    643          
    644         if (npanxx.match("^[2-9][0-9][0-9][-]?[2-9][0-9][0-9]$")) { 
    645           document.getElementById('npanxx').value = npanxx; 
    646           trunkEdit.action.value = "populatenpanxx"; 
    647           trunkEdit.submit(); 
    648         } else if (npanxx != null) { 
    649           <?php echo 'alert("'._("Invalid format for NPA-NXX code (must be format: NXXNXX)").'")'?>; 
    650         } 
    651       } 
    652        
    653       function changeRulesType() { 
    654         switch(document.getElementById('dialrulestype').value) { 
    655           case "always": 
    656             document.getElementById('lddialprefix').disabled = false; 
    657             document.getElementById('areacode').disabled = false; 
    658             document.getElementById('localprefixes').disabled = true; 
    659           break; 
    660           case "local": 
    661           case "local10": 
    662             document.getElementById('lddialprefix').disabled = false; 
    663             document.getElementById('areacode').disabled = false; 
    664             document.getElementById('localprefixes').disabled = false; 
    665           break; 
    666           case "asis": 
    667           default: 
    668             document.getElementById('lddialprefix').disabled = true; 
    669             document.getElementById('areacode').disabled = true; 
    670             document.getElementById('localprefixes').disabled = true; 
    671           break; 
    672         } 
    673       } 
    674       changeRulesType(); 
    675       </script> 
    676 */?> 
     663 
    677664      <tr> 
    678665        <td> 
     
    685672      <tr> 
    686673        <td colspan="2"> 
    687          <h4><?php echo _("Outgoing Settings")?></h4> 
     674        <h4><?php echo _("Outgoing Settings")?><hr></h4> 
    688675        </td> 
    689676      </tr> 
     
    814801<!-- 
    815802 
     803$(document).ready(function(){ 
     804  /* Add a Custom Var / Val textbox */ 
     805  $("#dial-pattern-add").click(function(){ 
     806    addCustomField('','','',''); 
     807  }); 
     808  $("#dial-pattern-clear").click(function(){ 
     809    clearAllPatterns(); 
     810  }); 
     811  $(".dpt-title").toggleVal({ 
     812    populateFrom: "title", 
     813    changedClass: "text-normal", 
     814    focusClass: "text-normal" 
     815  }); 
     816  $(".dpt-value").toggleVal({ 
     817    changedClass: "text-red" 
     818  }); 
     819});  
     820 
     821function patternsRemove(idx) { 
     822  $("#prepend_digit_"+idx).parent().parent().remove(); 
     823} 
     824 
     825function addCustomField(prepend_digit, pattern_prefix, pattern_pass) { 
     826  var idx = $(".dial-pattern").size(); 
     827  var idxp = idx - 1; 
     828  var tabindex = parseInt($("#pattern_pass_"+idxp).attr('tabindex')) + 1; 
     829  var tabindex1 = tabindex + 2; 
     830  var tabindex2 = tabindex + 3; 
     831  var dpt_prepend_digit = prepend_digit == '' ? 'dpt-title' : 'dpt-value'; 
     832  var dpt_pattern_prefix = pattern_prefix == '' ? 'dpt-title' : 'dpt-value'; 
     833  var dpt_pattern_pass = pattern_pass == '' ? 'dpt-title' : 'dpt-value'; 
     834 
     835  var new_insert = $("#last_row").before('\ 
     836  <tr>\ 
     837    <td colspan="2">\ 
     838    (<input title="<?php echo $pp_tit?>" type="text" size="5" id="prepend_digit_'+idx+'" name="prepend_digit['+idx+']" class="dp-prepend dial-pattern '+dpt_prepend_digit+'" value="'+prepend_digit+'" tabindex="'+tabindex+'">) +\ 
     839    <input title="<?php echo $pf_tit?>" type="text" size="4" id="pattern_prefix_'+idx+'" name="pattern_prefix['+idx+']" class="dp-prefix '+dpt_pattern_prefix+'" value="'+pattern_prefix+'" tabindex="'+tabindex1+'"> |\ 
     840    <input title="<?php echo $mp_tit?>" type="text" size="16" id="pattern_pass_'+idx+'" name="pattern_pass['+idx+']" class="dp-match '+dpt_pattern_pass+'" value="'+pattern_pass+'" tabindex="'+tabindex2+'">\ 
     841      <img src="images/trash.png" style="cursor:pointer; float:none; margin-left:0px; margin-bottom:-3px;" alt="<?php echo _("remove")?>" title="<?php echo _("Click here to remove this pattern")?>" onclick="patternsRemove('+idx+')">\ 
     842    </td>\ 
     843  </tr>\ 
     844  ').prev(); 
     845 
     846  new_insert.find(".dpt-title").toggleVal({ 
     847    populateFrom: "title", 
     848    changedClass: "text-normal", 
     849    focusClass: "text-normal" 
     850  }); 
     851  if (pattern_pass != '' || pattern_prefix != '' || prepend_digit != '') { 
     852    new_insert.find(".dpt-value").toggleVal({ 
     853      changedClass: "text-red" 
     854    }); 
     855  } 
     856 
     857  return idx; 
     858} 
     859 
     860function clearPatterns() { 
     861  $(".dpt-title").each(function() { 
     862    if($(this).val() == $(this).data("defText")) { 
     863      $(this).val(""); 
     864    } 
     865  }); 
     866  return true; 
     867} 
     868 
     869function clearAllPatterns() { 
     870  $(".dpt-value").addClass('dpt-title').removeClass('dpt-value'); 
     871  $(".toggleval").each(function() { 
     872    $(this).val(""); 
     873  }); 
     874  $(".dpt-title").toggleVal({ 
     875    populateFrom: "title", 
     876    changedClass: "text-normal", 
     877    focusClass: "text-normal" 
     878  }); 
     879  return true; 
     880} 
     881 
     882// all blanks are ok 
     883function validatePatterns() { 
     884  var culprit; 
     885  var msgInvalidDialPattern; 
     886  defaultEmptyOK = true; 
     887 
     888  // TODO: need to validate differently for prepend, prefix and match fields. The prepend 
     889  //      must be a dialable digit. The prefix can be any pattern but not contain "." and 
     890  //      the pattern can contain a "." also 
     891  //$filter_prepend = '/[^0-9\+\*\#/'; 
     892  //$filter_match = '/[^0-9\-\+\*\#\.\[\]xXnNzZ]/'; 
     893  //$filter_prefix = '/[^0-9\-\+\*\#\[\]xXnNzZ]/'; 
     894  //defaultEmptyOK = false; 
     895  /* TODO: get some sort of check in for dialpatterns 
     896  if (!isDialpattern(theForm.dialpattern.value)) 
     897    return warnInvalid(theForm.dialpattern, msgInvalidDialPattern); 
     898    */ 
     899 
     900  $(".dp-prepend").each(function() { 
     901    if ($.trim(this.value) == '') { 
     902    } else if (this.value.search('[^0-9*#+\s]+') >= 0) { 
     903      culprit = this; 
     904      return false; 
     905    } 
     906  }); 
     907  if (!culprit) { 
     908    $(".dp-prefix").each(function() { 
     909      if ($.trim($(this).val()) == '') { 
     910      } else if (!isDialpattern(this.value) || this.value.search('[._]+') >= 0) { 
     911        culprit = this; 
     912        return false; 
     913      } 
     914    }); 
     915  } 
     916  if (!culprit) { 
     917    $(".dp-match").each(function() { 
     918      if ($.trim(this.value) == '') { 
     919      } else if (!isDialpattern(this.value) || this.value.search('[_]+') >= 0) { 
     920        culprit = this; 
     921        return false; 
     922      } 
     923    }); 
     924  } 
     925 
     926  if (culprit != undefined) { 
     927    msgInvalidDialPattern = "<?php echo _('Dial pattern is invalid'); ?>"; 
     928    // now we have to put it back... 
     929    // do I have to turn it off first though? 
     930    $(".dpt-title").each(function() { 
     931      if ($.trim($(this).val()) == '') { 
     932        $(this).toggleVal({ 
     933          populateFrom: "title", 
     934          changedClass: "text-normal", 
     935          focusClass: "text-normal" 
     936        }); 
     937      } 
     938    }); 
     939    return warnInvalid(culprit, msgInvalidDialPattern); 
     940  } else { 
     941    return true; 
     942  } 
     943} 
     944 
    816945var theForm = document.trunkEdit; 
    817946 
     
    839968  if (!isInteger(theForm.maxchans.value)) 
    840969    return warnInvalid(theForm.maxchans, msgInvalidMaxChans); 
    841    
    842   if (!isDialrule(theForm.dialrules.value)) 
    843     return warnInvalid(theForm.dialrules, msgInvalidDialRules); 
    844970   
    845971  if (!isDialIdentifierSpecial(theForm.dialoutprefix.value)) 
     
    870996  <?php } ?> 
    871997 
    872   theForm.action.value = act; 
    873   return true; 
     998  clearPatterns(); 
     999  if (validatePatterns()) { 
     1000    theForm.action.value = act; 
     1001    return true; 
     1002  } else { 
     1003    return false; 
     1004  } 
    8741005} 
    8751006