/**********************************************************

The Spamhaus DROP (Don't Route Or Peer) lists are advisory
 "drop all traffic" lists, consisting of netblocks that are
 "hijacked" or leased by professional spam or cyber-crime 
 operations (used for dissemination of malware, trojan
 downloaders, botnet controllers). 
See: https://www.spamhaus.org/drop/

This script automates adding the IPs from the DROP and EDROP
 lists into Denied IP Addresses <http://www.communigate.ru/CommuniGatePro/Network.html#Denied>

Requires CommuniGate 6.1.12 or later.

Installation:
1) Upload the spamhaus_drop.sppr into the main domain PBX
 environment <http://www.communigate.ru/CommuniGatePro/PBXApp.html#Editor>

2) Login via CLI <http://www.communigate.ru/CommuniGatePro/CLI.html>
Authenticate as postmaster and submit this command: 
  UPDATESCHEDULEDTASK postmaster {id=setDROP;program=spamhaus_drop;when=now;period=day;}

Note: in Dynamic Cluster environment the script shold be
 installed to only one of the Front-Ends, not to all of them.
 Running on behalf of a postmaster from one node's main
 domain the scipt will update cluster-wide Denied IPs list
 which will effect for all cluster members.
Note: the HTTP service must be enabled for the postmaster account
 and for the main domain.

Revision: 06.07.2017
Support:
To contact author please email to roma@communigate.ru
**********************************************************/


const dropURL="https://www.spamhaus.org/drop/drop.txt";
const edropURL="https://www.spamhaus.org/drop/edrop.txt";



const dropHeader=";---- DROP list begin ----";
const dropTrailer=";---- DROP list end ----";
const dropTimestamp="; Last Update: ";

function getList(theURL) {
  var hRes=HTTPCall(theURL,NewDictionary());
  if(isDictionary(hRes) && hRes.responseCode == 403) {
    syslog("HTTP call failed, will retry: "+String(hRes));
    hRes=HTTPCall(theURL,NewDictionary());
  }
  if(!isDictionary(hRes) || hRes.responseCode != 200) {
    syslog("HTTP call failed: "+String(hRes));
    stop;
  }

  var newText="";
  var bodyText=String(hRes.body);
  var pb=0,pe;
  while( true ) {
    pe=FindSubstring(bodyText,"\n",pb);
    exitif (pe<=0);
    var ln=Substring(bodyText,pb,pe-pb);
    if(Substring(ln,0,5) != "10.0."  //some sanity check
       && Substring(ln,0,8) != "192.168." 
       && Substring(ln,0,7) != "172.16." 
       && Substring(ln,0,8) != "127.0.0." 
    ) {  
      newText+=ln+"\e";
    }
    pb=pe+1;
    while(pb<length(bodyText) && IsWhiteSpaces(Substring(bodyText,pb,1))) {pb+=1;};
  }
  return newText;
}

entry main {

  var errCode=ExecuteCLI("GetCurrentController");
  var cmdForIPs=(errCode) ? "DENIEDIPS" : "CLUSTERDENIEDIPS";

  errCode=ExecuteCLI("Get"+cmdForIPs);
  if(errCode) {
    syslog("Error in Get"+cmdForIPs+": " + errCode);
    stop;
  } 
  var ipList=Vars().executeCLIResult;
  var ipListTail="";
  
  var hPos=FindSubstring(ipList,dropHeader);
  if(hPos>=0) {
    var sPos=FindSubstring(ipList,dropTimestamp,hPos);
    if(sPos>0) {
      var ut=Date(Substring(ipList,sPos+length(dropTimestamp),19));
      if(ut+60*61>LocalTime()) {
        syslog("Won't update more than once per hour.");
        stop;
      }
    }
    var tPos=FindSubstring(ipList,dropTrailer,-1);
    if(tPos>=0) {
      tPos+=Length(dropTrailer+"\e");
      ipListTail=substring(ipList,tPos,length(ipList)-tPos) || "";
    }
    ipList=substring(ipList,0,hPos) || "";
  } 
  var newText=dropHeader+"\e";
  newText+=dropTimestamp+String(LocalTime())+"\e";
  newText+=getList(dropURL);
  newText+=getList(edropURL);
  newText+=dropTrailer+"\e";

//syslog("IP list="+ipList);

  errCode=ExecuteCLI("set"+cmdForIPs+" \""+ipList+newText+ipListTail+"\"");
  if(errCode) {
    syslog("Error in Set"+cmdForIPs+": " + errCode);
    stop;
  } 

}