<?
/*********************** INCLUDES *********************************************/
  $includePath=realpath(dirname(__FILE__)."/../");
  require_once($includePath.'/config/cfg.php');
  require_once ($includePath.'/lib/phpagi/phpagi.php');
  define('MACRO_STDEXTEN','stdexten');
  define('MACRO_DIALOUT','dialout');
  define('MACRO_FAILOVER','dialout-fail-over');
/*********************** INITIALIZATION ***************************************/
  $agi = new AGI();
  // Extract rule context
  $extension = $agi->request["agi_extension"];
  $ruleContext = $agi->request["agi_context"];
  $res=$db->Execute("SELECT id,message_on_deny FROM cw_rule WHERE name='$ruleContext' AND type='1' ");
  $arr=$res->FetchRow();
  $ruleSetId=$arr["id"];
  if(intval($arr["message_on_deny"])==1) $message_on_deny=true; else $message_on_deny=false; 
  // Get AGI parameters
  // check if $_GET array is available. If not use $_SERVER
  if((is_array($_GET))&&(count($_GET)>0)){
    $entityId=$_GET["entity"];
    $entityGroup=$_GET["group"];
    $entityExt=$_GET["extension"];
  }
  else {
    // (WARNING: GET array may be null in many cases, parseArgv take $_SERVER content)
    parse_str($_SERVER["argv"][1], $var_GET);
    $entityId=$var_GET["entity"];
    $entityGroup=$var_GET["group"];
    $entityExt=$var_GET["extension"];
    //$entityExt=str_replace(".","",str_replace("_","",$var_GET["extension"]));
  }
  $entityExt=str_replace(".","",str_replace("_","",$entityExt));
  // Get Mandatory Channel
  $mandatoryChannel=$agi->get_variable("MANDATORYCHANNEL");
  $mandatoryChannel=$mandatoryChannel["data"];
  
  // Get dialer channel
  $dialerChannel=$agi->get_variable("CHANNEL");
  $dialerChannel=$dialerChannel["data"];
  agiError("-----------------------------------------------");
  agiError("Outgoing Rule Set: [$ruleSetId]$ruleContext (ext:$extension - grp: $entityGroup - entId: $entityId)");
  agiError("-----------------------------------------------");
  // Agi has been reloaded and there is no mandatory trunk?
  // ...it means that agi has been reloaded after a congestion (macro dialout-fail-over)...
  $skipTrunk=$agi->get_variable("SKIPPEDTRUNK");
  if(is_array($skipTrunk)) $skipTrunk=$skipTrunk["data"]; else $skipTrunk="";
  if(($mandatoryChannel=="")&&($skipTrunk!="")){
    //extract list of trunk to skip becose they are congested
    $skipTrunkArr=explode("&",$skipTrunk);
    agiError("CONGESTION: the trunk set before [".$skipTrunkArr[count($skipTrunkArr)-1]."] is congested!");
    agiError("  TRUNK TO SKIP : ".$skipTrunk);
    agiError("  CALLER CHENNEL : ".$dialerChannel);
    //get all trunk
    $allTrunks=$agi->get_variable("ALLTRUNK");
    $allTrunks=$allTrunks["data"];
  }
  // ...else agi runs for the first time or after the reload for the set of the mandatory trunk.
  else{
  	$skipTrunkArr=array();
    //get all trunk
    $allTrunks=$agi->get_variable("TRUNK");
    $allTrunks=$allTrunks["data"];
    //save all trunk on a channel var to reuse the list if trunk is congested
    $agi->set_variable("ALLTRUNK", $allTrunks);
    //extract caller info
    $callerNameArr=$agi->get_variable("CALLERID(name)");
    $callerNumArr=$agi->get_variable("CALLERID(num)");
    agiError("CALLER: ".$callerNameArr["data"]." <".$callerNumArr["data"]."> (CHANNEL: ".$dialerChannel.")");
  }
  
/*********************** PAGE LOGIC *******************************************/
  $canContinue=true;
  $qry="SELECT * FROM cw_rule_outgoing WHERE rule=$ruleSetId ORDER BY priority";
  $res=$db->Execute($qry);
  while ($arr=$res->FetchRow()) {
    $id=$arr["id"];
    $rule=$arr["rule"];
    $priority=$arr["priority"];
    $timesegment=$arr["timesegment"];
    $group=$arr["group"];
    $entity=$arr["entity"];
    $resource=$arr["resource"];
    $provider=$arr["provider"];
    $action=$arr["action"];
    if(intval($arr["failover"])==1) $failover=true; else $failover=false;
    if(trim($arr["variables"])!='') $variables=explode("|",$arr["variables"]); else $variables=array();
    agiError("Rule: $id (entity: $entity, group: $group)");
    if ($resource!="0") $channel=_getTrunk($resource); else $channel=$allTrunks;
    if($channel!=""){ 
      agiError("  RULE TRUNK LIST: ".$channel);
      $channelArr=explode("&",$channel); 
      //delete congested trunk from allowed trunk list
      if((is_array($channelArr))&&(is_array($skipTrunkArr))&&(count($skipTrunkArr)>0)){
        foreach($skipTrunkArr as $s){
          $key=array_search($s,$channelArr);
          if($key!==false) unset($channelArr[$key]);
        }
      }
      if(is_array($channelArr)) $channel=implode("&",$channelArr);
      else $channel="";
      agiError("  CLEAN TRUNK LIST: ".$channel);
    }else{
      agiError("  RULE TRUNK LIST: no trunk are defined on rule");
      $channelArr=array();
    }
    // if mandatory channel is setted dial $extension as a phone number
    if ($mandatoryChannel!=""){
        $entityGroup=GROUP_OF_PHONENUMBER;
        $entityId="";
      }
    // check if some rule are triggered
    if(checkTime($timesegment)===false) continue;
    if  (
          ( 
            // if the rule match *
            ($group==GROUP_OF_ALL) or
            // if the rule (entity) refer to the extension's entity 
            ($entity==$entityId) or 
            // if the rule (group) refer to the extension's entity 
            (is_array(_getGroup($entityId)) AND in_array($group,_getGroup($entityId))) or
            // if the rule (entity) refer to the extension's group
            ($entityId=="" AND is_array(_getGroup($entity)) AND in_array($entityGroup,_getGroup($entity))) or 
            // if the rule (group) refer to the extension's group (happen only when rule match a GROUP_OF_NUMBERS)
            ($entityId=="" AND $entityGroup==_metaGroupFromGroup($group)) or
            // if the rule (group) refer to the extension's group 
            ($entityId=="" AND $entityGroup==$group)
          )
          AND
          ( 
            $canContinue===true
          )  
        ) 
      {
      agiError("  TRIGGERED RULE $id!");
      switch ($entityGroup) {
        case GROUP_OF_EXTENSION:
          agiError("  This is an extension: $entityExt");
          if ($action==RULE_ALLOW) {
            agiError("  ALLOWED");
            $channelName=_getChannelFromEntity($entityId);
            if(trim($channelName)!=""){
              _setRuleChannelVariables($variables);
              $agi->set_variable("DIAL_EXTENSION",$channelName);
              agiError("  ----------------> macro ".MACRO_STDEXTEN." (".$channelName.")");
              $agi->exec("macro ".MACRO_STDEXTEN, '');
            }else{
              agiError("  ERROR: Unknown channel for extension $extension (entity: $entityId)");
            }
            $canContinue=false;
          }
          if($action==RULE_DENY){
            agiError("  DENIED!");
            //$agi->text2wav ("You don't have the permission to call this extension");
            _congestion();
            $canContinue=false;
          } 
        break;
        case GROUP_OF_PHONENUMBER:
          agiError("  This is a phone number: $entityExt");
          $included = _isIncluded($extension,$entity,$group);
          // RULE_ALLOW
          if (($action==RULE_ALLOW)&&($included===true)) {
            //if (in_array($mandatoryChannel,$channelArr) or $resource=="0" or $mandatoryChannel=="") {
            if (in_array($mandatoryChannel,$channelArr) or $mandatoryChannel=="") {
              // check previous DENY rules
              $prevDenied["all"]=false;
              $prevDenied["list"]="";
              if($mandatoryChannel=="") // if $mandatoryChannel isn't setted --> dialout
                $prevDenied=_isPrevDenied($extension,$ruleSetId,$priority);
              // set channel and dialout
              if($prevDenied["all"]===true) $canContinue=true;
              else {
                if ($allTrunks==""){ // no trunk is defined in VoiceOne
                  agiError("  DENIED! (there are no defined outgoing trunks on VoiceOne)");
                  _congestion();
                  $canContinue=false;
                  break;
                }else{
                  if ($resource!="0" and $mandatoryChannel=="") {
                    $channel=_getDiffChannel($channel,$prevDenied["list"]);
                    if($channel!=""){
                      $agi->set_variable("TRUNK", $channel); 
                      agiError("  ALLOWED on Trunks: $channel");
                    } else {
                      agiError("  DENIED! (allowed trunks has been previously denied)");
                      _congestion($message_on_deny);
                      $canContinue=false;
                      break;
                    }     
                  } else if ($mandatoryChannel!="") {
                    $agi->set_variable("TRUNK", $mandatoryChannel);
                    agiError("  ALLOWED: set Trunk to the mandatory $mandatoryChannel");
                  } else {
                    $channel=_getDiffChannel($channel,$prevDenied["list"]);
                    if($channel!=""){
                      $agi->set_variable("TRUNK", $channel);
                      agiError("  ALLOWED on Trunks: $channel");
                    } else {
                      agiError("  DENIED! (allowed trunks has been previously denied or they are congested)");
                      _congestion();
                      $canContinue=false;
                      break;
                    }
                  } 
                } 
                // set the outgoing trunk
                $availableTrunks=$agi->get_variable("TRUNK");
                $outgoingChannel=_chanIsAvail($availableTrunks["data"]);
                $agi->set_variable("TRUNK", $outgoingChannel);
                if($skipTrunk!="") $skipTrunk.="&".$outgoingChannel; else $skipTrunk=$outgoingChannel; 
                $agi->set_variable("SKIPPEDTRUNK", $skipTrunk);
                if($outgoingChannel!=""){
                  $outgoingTrunk=_getTrunkFromChannel($outgoingChannel);
                  agiError("  AVAIL TRUNK: $outgoingChannel (on group $outgoingTrunk)");
                  // set caller Id
                  $callerId=_getCid($outgoingTrunk);
                  if($callerId["status"]=="ALLOWED"){
                    $agi->set_variable("CID_CLIR", $callerId["cid_clir"]);
                    $agi->set_variable("CID_NAME", $callerId["cid_name"]);
                    $agi->set_variable("CID_NUMBER", $callerId["cid_number"]);
                  }else{
                    // Channel try to set a denied cid setting
                    agiError("  DENIED! (User is trying to overwrite channel default CID settings [FORCE ON])"); 
                    _congestion();
                    $canContinue=false;
                    break;
                  }
                  //sanetize dialed number
                  agiError("  LOCATION: call to $extension");
                  $extension=_sanitizeCalledNumber($extension,$outgoingTrunk);
                }else{
                  agiError("  AVAIL TRUNK: none (DIAL OUT WILL FAILED)");
                }
                // dialout
                //$agi->text2wav ("You are calling the number $extension");
                _setRuleChannelVariables($variables);
                $agi->set_variable("DIAL_EXTENSION",$extension);
                if(($failover)&&($mandatoryChannel=="")){
                  agiError("  ----------------> macro ".MACRO_FAILOVER." ($extension)");
                  $agi->exec("macro ".MACRO_FAILOVER, '');
                }else{
                  agiError("  ----------------> macro ".MACRO_DIALOUT." ($extension)");
                  $agi->exec("macro ".MACRO_DIALOUT, '');
                }
                $canContinue=false;
              }
            } 
            else {
              $canContinue=true;
              agiError("  SKIPPED (allowed trunk list doesn't contain mandatory trunk)");
            }
          }
          // RULE_DENY
          else if(($action==RULE_DENY)&&($included===true)) {
            if(  
                ($mandatoryChannel!="" and (in_array($mandatoryChannel,$channelArr) or $resource=="0"))
                or 
                ($mandatoryChannel=="" and $resource=="0")  
              ){
              agiError("  DENIED!");
              _congestion($message_on_deny);
              $canContinue=false;
            }else{
              $canContinue=true;
              if($mandatoryChannel=="") agiError("  SKIPPED (rule denies one or more trunks but not all)");
              else agiError("  SKIPPED (rule denies one or more trunks but not mandatory trunk)");
            }
          }
          // not included
          else {
            $canContinue=true;
            agiError("  SKIPPED (extension matches no pattern)");
          }
        break;
        case GROUP_OF_RESOURCE:
          agiError("  This is a resource: $entityExt");
          if ($action==RULE_ALLOW) {
            $qry="SELECT * FROM cw_channel WHERE `id`=".$entityId;
            $resT=$db->Execute($qry);
            $arrT=$resT->FetchRow();
            $agi->set_variable("MANDATORYCHANNEL", $arrT["name"]);
            agiError("  ALLOWED (set MandatoryChannel to ".$arrT["name"].")");
            $newExtension=substr($extension,strlen($entityExt));
            //$agi->goto($ruleContext,$newExtension,1);
            $agi->setContext($ruleContext,$newExtension,1);
            $canContinue=false;
          }
          if ($action==RULE_DENY) {
            agiError("  DENIED!");
            _congestion($message_on_deny);
            $canContinue=false;
          }
        break;
        case GROUP_OF_APPLICATION:
          agiError("  This is an Application: $entityExt");
          if ($action==RULE_ALLOW) {
            agiError("  ALLOWED ");
            $qry="SELECT * FROM cw_application WHERE id=".$entityId;
            $resA=$db->Execute($qry);
            $arrA=$resA->FetchRow();

            if ($arrA["code"]!="") {
              $lineArr=explode("\n",$arrA["code"]);
              if (is_array($lineArr)) foreach($lineArr as $line) {
                agiError("  Executing code: $line");
                $agi->exec($line, '');
              }
            }
            if ($arrA["macro"]!="") {
              $arrMacro=prepareMacro($arrA["macro"],$arrA["parameter"]);
              _setRuleChannelVariables($variables);
              agiError("  ----------------> macro ".$arrMacro[0].$arrMacro[1]);
              $agi->exec("macro ".$arrMacro[0].$arrMacro[1], '');
            }
            $canContinue=false;
          }
          if ($action==RULE_DENY) {
            agiError("  DENIED!");
            _congestion();
            $canContinue=false;
          }
        break;
        case GROUP_OF_OFFICE:
          agiError("  This is an office: $entityExt");
          if ($action==RULE_ALLOW) {
            // set trunk
            $qry="SELECT * FROM cw_channel WHERE `key`=".$entityId;
            $resT=$db->Execute($qry);
            $arrT=$resT->FetchRow();
            $agi->set_variable("TRUNK", $arrT["name"]);
            agiError("  SET TRUNK: ".$arrT["name"]);
            // set caller Id
            $outgoingTrunk=_getTrunkFromChannel($arrT["name"]);
            $callerId=_getCid($outgoingTrunk);
            if($callerId["status"]=="ALLOWED"){
              $agi->set_variable("CID_CLIR", $callerId["cid_clir"]);
              $agi->set_variable("CID_NAME", $callerId["cid_name"]);
              $agi->set_variable("CID_NUMBER", $callerId["cid_number"]);
            }else{
              // Channel try to set a denied cid setting
              agiError("  DENIED! (User is trying to overwrite channel default CID settings [FORCE ON])"); 
              _congestion();
              $canContinue=false;
              break;
            }
            _setRuleChannelVariables($variables);
            $agi->set_variable("DIAL_EXTENSION",'s');
            agiError("  ----------------> macro ".MACRO_DIALOUT." (Office $entityExt)");
            $agi->exec("macro ".MACRO_DIALOUT, '');
            $canContinue=false;
          }
          if ($action==RULE_DENY) {
            agiError("  DENIED!");
            _congestion($message_on_deny);
            $canContinue=false;
          }
        break;
        default:
          agiError("  This is an Unknown entity");
        break;
      }
    }   
  }
  agiError("Exit from dial.php\n");
    
?>
