English | Italiano
by InRete.com

Caronte Scripting
Introduction -
The language -
Develope a Plug-in -


Develope a Plug-in

This is a little tutorial that indicates the guidelines for develope a plug-in in Caronte Antispam.
First is the choice of which type of plug-in to be developed, certainly make a little analysis on how it should work and which level of integration will have with Caronte Antispam.
In this case we will develope a plug-in for the virus analysis system of Caronte, choosing CLAMAV as antivirus of cooperation.
Let's enter in the heart of this tutorial.

The script to put beside to the heart of Caronte Antispam (/script/antispam/clamav.cs)

/// with the macro "#import" the precompiler of Caronte includes the support and allocates  
//  memory for the methods of the class.
// We needs CS_Socket for comunicate with CLAMAV and CS_Buffer to store the informations to be send and receive.
#import( class , CS_Socket ) #import( class , CS_Buffer )
/// define in ansi C some primitive constants
#define NULL 0 #define true 1 #define false 0 //LOG #define LOGL0 0 // no log #define LOGL1 1 #define LOGL2 2 #define LOGL3 3 #define LOGALL 4 // 1+2+3 + DEBUG //STATISTIC #define MOREMORE 1 #define LESSLESS 2 #define EQUAL_VALUE 3 #define MORE_VALUE 4 #define LESS_VALUE 5 #define MAX_VALUE 6 #define MIN_VALUE 7 //RE #define RE_CASELESS 1 #define RE_MULTILINE 2 #define RE_DOTALL 4 #define RE_EXTENDED 8 /// the instance of enviroment for ANTISPAM !!! // inherit all the basic functions and initializes the enviroment CS_ANTISPAM_SCRIPT this = new CS_ANTISPAM_SCRIPT($_this);
CS_Socket m_conn; CS_Socket m_conn_stream; int m_state = 0; int m_size = 0; string m_virus_name = ""; // register that it could be notified a value called "notify_virus_name" // to all the others scripts present in the enviroment. // the name "notify_virus_name" can change, for example it could be called also "notify_virus_name_clamav" // the notify is for courtesy to the other scripts, that could use our work.
this->RegisterGlobalVariable("notify_virus_name"); // function that obtains the ACK and the errors from CLAMAV on the relative port // remember that all the functions developed in Caronte language, to be viewed must be declared and structured // one after another, otherwise they can't see each other. // The class CS_Buffer is the only in Caronte scripting that can receive datas on a buffer socket. string GetLine(CS_Socket conn) { if (conn == NULL || !conn->IsOpen()) return ""; string res; CS_Buffer buffer = new CS_Buffer(); buffer->Allocate(50); int len = conn->Riceve(buffer->GetBuffer(),5000); if (len > 0) res = this->Replace(this->Replace( buffer->ToString() ,"\r",""), "\n",""); delete buffer; buffer = NULL; return res; } int ConnectToClamav() { if (m_conn != NULL || m_state > 0) return true; if (this->GetConfig("address","CLAMAV") == "" || this->GetConfig("port","CLAMAV") == "") return false; m_conn = new CS_Socket(); if (!m_conn->ConnectTo( this->GetConfig("address","CLAMAV"), this->GetConfig("port","CLAMAV"), this->GetConfig("adapter","CONFIG"))) { delete m_conn; m_conn = NULL; return false; } if (m_conn->Send("STREAM\n",this->StrLen("STREAM\n"),1000) <= 0) { delete m_conn; m_conn = NULL; return false; } string tmp = GetLine(m_conn); if (this->REeq(tmp,"^PORT (\\d+)",RE_CASELESS)) { string streaming_port = this->$1(); m_conn_stream = new CS_Socket(); if (!m_conn_stream->ConnectTo(this->GetConfig("address","CLAMAV"),streaming_port,this->GetConfig("adapter","CONFIG"))) { m_conn->Close(); delete m_conn; delete m_conn_stream; m_conn = NULL; m_conn_stream = NULL; return false; } m_state = 1; return true; } m_conn->Close(); delete m_conn; m_conn = NULL; return false; } void streamscan(string dati) { if (m_conn == NULL || !m_conn->IsOpen()) return; if (m_conn_stream == NULL || !m_conn_stream->IsOpen()) return; int t1 = this->GetTickCount(); int deadline = t1 + 1000; int bsend = 0; int size_send = this->StrLen(dati); int send_tot = 0; int tosend = size_send; while(t1 < deadline) { t1 = this->GetTickCount(); bsend = m_conn_stream->Send(dati,tosend,50); if (bsend <= -1) break; send_tot += bsend; if (send_tot == size_send) break; else if(send_tot != size_send && bsend > 0) { tosend = size_send - bsend; dati = this->SubStr(dati,bsend,tosend); } } m_size += size_send; } string Result() { if (m_conn == NULL || !m_conn->IsOpen()) return ""; if (m_conn_stream == NULL || !m_conn_stream->IsOpen()) return ""; m_conn_stream->Close(); m_state = 2; string tmp = GetLine(m_conn); if(this->REeq(tmp, "stream: (.+) FOUND",RE_CASELESS) && this->$1() != "") return this->$1(); return ""; } void CloseAll() { if (m_conn_stream != NULL) { if (m_conn_stream->IsOpen()) { m_conn_stream->Send("QUIT\n",this->StrLen("QUIT\n"),100); m_conn_stream->Close(); } delete m_conn_stream; m_conn_stream = NULL; } if (m_conn != NULL) { if (m_conn->IsOpen()) m_conn->Close(); delete m_conn; m_conn = NULL; } } void OnAllDataMessage(string part_msg, int is_end_msg) { if (this->CharToInt(this->GetConfig("enable","CLAMAV")) == false || m_state == 2) return; if (m_state == 0) if (ConnectToClamav() == false) return; if (m_state == 1) streamscan(part_msg); if (is_end_msg == true || m_size >= this->CharToInt(this->GetConfig("size","CLAMAV"))) { m_virus_name = Result(); if (m_virus_name != "") { this->SendToClient( this->Format(this->GetConfig("rfc554"), this->Format("VIRUS FOUND %s\r\n",m_virus_name)) ); this->WriteLog(LOGL1, this->Format("VIRUS FOUND %s",m_virus_name),"SYS"); this->StatisticValue(this->Format("f16_virus_[%s]",m_virus_name),18,0,1,MOREMORE); if (this->CharToInt(this->GetConfig("imbargo_enable","CLAMAV")) == true) { int time_embrago = this->Time() + (this->CharToInt(this->GetConfig("imbargo_type","CLAMAV")) * this->CharToInt(this->GetConfig("imbargo_time","CLAMAV"))); this->WriteLog(LOGL1, this->Format("ADD IP IMBARGO: %s\r\n",this->GetClientIP()),"SYS"); this->AddIpInferno(this->GetClientIP(),time_embrago); } this->CloseClientConnAfterSendingQueue(); this->DropBufferToMTA(); this->SetGlobalVariable("notify_email_is","REJECTED"); //registre dal core.cs this->SetGlobalVariable("notify_email_cause_rejected","virus_found"); //registrate dal core.cs this->SetGlobalVariable("notify_virus_name",m_virus_name); } else { this->WriteLog(LOGL1, "CLAMAV: Clean","SYS"); } CloseAll(); } } // Important: if the script is loaded at the start so it is in cache // the method "OnDestroyThis" is called and this allows to free memory and reset the global variables. void OnDestroyThis() { if (this != NULL) delete this; this = NULL; CloseAll(); }

Let's analyze the mechanism.
The enviroment ANTISPAM (proxy) during the comunication between client and server , "raises" events and functions, those that interests to us for this plug-in is

void OnAllDataMessage(string part_msg, int is_end_msg)

This event function, as guess by the name, raises when during the communication is received the command DATA with the first buffer, if the message is longer than the buffer, this event function raises more times with the new content. The second argument indicates if the end of message is reached.
We limit to transmit this "buffer" to CLAMAV, recording every time its lenght and the state of transmission, to have after the final response.
To take a look to all the events function that the enviroment "ANTISPAM" and the others generate, we advice to check the documentation.

Once developed the script , the relative pages of management in the Web G.U.I. of Caronte Antispam are needed.
A respectable plug-in , even with few parameters of configuration, must have these pages, allowing the management to the end-user.
In our plug-in, we develope only one "page" of management that could be used both administrative-side and normal user.
Certainly we will use the script libreries of Caronte Antispam Web G.U.I. and we will try as much as possible to follow their logic of functionality.

Develope the page "clamav_antivirus.htmcc"

#include "conf.htmch";
#include "include/libhttp.htmch";



void html()
{

 IsSecureSession(0);
 Init_language(CARONTE_LING);
 this->echo( IncludeHeader() );


 CaronteServerConn client = new CaronteServerConn(CARONTE_SERVER_NAME,CARONTE_SERVER_PORT,CARONTE_SERVER_KEY);
 client->SetTimeOut(CARONTE_TIME_OUT);
 if (!client->Connect())
 {
   delete client;
   MsgError(LANG->GetS("conn_error"));
 }

 CaronteRecordSet rs = new CaronteRecordSet(client);
 HashArray  var_html = new HashArray();

 ComputeConfig(client, rs, "CLAMAV" ,var_html);

if (m_user_level != 1)
{

  string tonf;
  string tonf2;

     if (var_html->GetI("CLAMAV-enable") == 1)
     {
        tonf = this->Replace(this->Replace(LANG->GetS("1008"),"<","&lt;"),">","&gt;");
        tonf2 = "<div class=\"v\">ON</div>"; 
        
     } else
       {
        tonf = this->Replace(this->Replace(LANG->GetS("1008d"),"<","&lt;"),">","&gt;");
        tonf2 = "<div class=\"r\">OFF</div>";
       }

 this->echo("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"adminlist\">");
 this->echo(" <tr class=\"imgheader\">");
 this->echo("  <td colspan=\"4\" align=\"center\">ClamAV Antivirus</td>");
 this->echo(" </tr>");
 this->echo("   <tr class=\"row1\">");
 this->echo("    <td align=\"center\" class=\"rowtd1\">" + tonf2 + "</td>");
 this->echo("     <td colspan=\"3\">" + tonf + "</td>");
 this->echo("   </tr>");
 this->echo("  </table><br>");
 
 delete var_html;
 var_html = NULL;

 client->Disconnect();
 delete rs;
 delete client;
 this->includeHTML("footer.html");  
 this->Exit();
}



if (var_html->GetI("CLAMAV-enable") == 1)
     var_html->AddValueS("checked1","checked");

if (var_html->GetI("CLAMAV-imbargo_enable") == 1) 
     var_html->AddValueS("checked2","checked");
 


if (var_html->GetI("CLAMAV-size") > 0)
{
   var_html->AddValueS("CLAMAV-size", this->Format("%d",var_html->GetI("CLAMAV-size") / 1024));
	
}


 var_html->AddValueS("CLAMAV-imbargo_type_combo",ComboTime("60",2));

 
 

 this->echo ( TemplateVarReplace(var_html, "js_clamav.htmch", 2) );
 this->echo ( TemplateVarReplace(var_html, "clamav.htmch", 1) );

delete var_html;
var_html = NULL;

client->Disconnect();
delete rs;
delete client;

 this->includeHTML("footer.html");     

}

   

Analysis in this script the library functions:

IsSecureSession(0);
Init_language(CARONTE_LING);

Opening the source codes of the "\www\include\libhttp.htmch" the first function , "IsSecureSession(0);" verifies that the session is secure , have done the login and the zero value indicates that the call doesn't come from an AJAX object, so it's possible to apply an Header Redirect to the web server if the session is not secure.
The second function "Init_language(CARONTE_LING);" initializes the language and we understand that to our management page missing the file that contains the translate, even checking the source codes, we notice that the function reads all the content of a directory "include/language/", first seek all the file in english after seek files in the language indicated in the "conf" of the web G.U.I. with the variable "CARONTE_LING".

So we have to create our language file that we will install in "/www/include/language/it/clamav.xml" and we develope in this way:

<?xml version="1.0" encoding="UTF-8" ?>
<config>
<variable>
<name>MENU_CLAMAV</name>
<value>ClamAV</value>
<type>3</type>
</variable>
<variable>
<name>MENU_CLAMAV_STB</name>
<value>Clamav Antivirus Configuration </value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1165</name>
<value>Enables Controllo Antivirus</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1166</name>
<value>Ip / Host:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1170</name>
<value>Max weight Msg:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1168</name>
<value>Port:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1174</name>
<value>Embargo Time:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1177</name>
<value>IP to the hell</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1178</name>
<value>If the message contains a virus , send the ip to the hell</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1179</name>
<value>Configuration TEST ClamAV</value>
<type>3</type>
</variable>
<variable>
<name>1008</name>
<value>&lt;strong&gt;Antivirus&lt;/strong&gt;&lt;br&gt; Filter activated by the administrator of the system.&lt;br&gt; All the email are protected by &lt;a href='http://www.clamav.net/' target='_blank' class='ln1'&gt;Clamav Antivirus&lt;/a&gt;</value>
<type>4</type>
</variable>
<variable>
<name>1008d</name>
<value>&lt;strong&gt;Antivirus&lt;/strong&gt;&lt;br&gt; The active filter is up to the administrator of the system. Caronte Antispam has a particular plug-in that use Clamav Antivirus to check the emails. Your administrator/provider could choice other solutions to check the presence of virus in your emails.</value>
<type>4</type>
</variable>
</config>

Continuing the analysis of our GUI page we find :

CaronteServerConn 
client = new CaronteServerConn(CARONTE_SERVER_NAME,CARONTE_SERVER_PORT,CARONTE_SERVER_KEY);
client->SetTimeOut(CARONTE_TIME_OUT);

This class allows to connect with the heart of Caronte using by the Remote Admin service and read or write datas in the configuration.
We also find:

this->echo ( TemplateVarReplace(var_html, "js_clamav.htmch", 2) );
this->echo ( TemplateVarReplace(var_html, "clamav.htmch", 1) );
   

These internal functions of the library "libhttp.htmch" allow us , passing an HashArray class and a template file with ".htmch" extension, to create a source HTML can return to the user. Always looking at the source of library we notice that also the function "TemplateVarReplace" doesn't limit simply to open the indicated file, look for HTML comments inside , structured as <!--@xxxxxx@-->, replace them with the relative data (if found) of the xml language file, but also applies behaviors, checking the third parameter of function and the value of the child "type" of the xml.
For example, "2" indicates to the function to insert tags <script ...></script> and the replace indicates a "type 4" <type>4</type> of the language XML child that is html to activate. From that we can understand also, why we choosed the XML structures .The type definitions are in the library with the relative comments.

So we have to create these template files in pure html, insert them in "/www/include/template/" and define our text, as titles and descriptions, inside the file as comments delimited by "@xxxx@" that after will be replaced by these functions.

But our script "clamav.cs" also had some functions that insert the general statistics of Caronte, how many and what kind of virus are blocked.
We have to interact also with the engine of the GUI that permits to visualize the statistics.
Well, always looking at the source of library "libhttp.htmch" we can see that it's enough to insert a configuration XML file of the directory "/www/include/stats/" and structure it as:

<?xml version="1.0" encoding="UTF-8" ?>
<config>
<page>
<combolabel>STATSf1_7a</combolabel>
<url>ajax_stats_virus.htmcc</url>
</page>
</config>

Automatically the "combobox" of the statistics page will report the link indicated.
Where "ajax_stats_virus.htmcc " will be a page that permits to visualize the statistics of this plug-in.
To develope it, just take a look to the others statistics pages in Carotne to understand the logic.

Go ahead ...

In case of this plug-in we use the procedures existing in the enviroment for read and write our configuration once done "save".
We are going to develope also a procedure to create a TOOL and test CLAMAV when the plug-in will be installed, so we will manipulate also the ADMIN enviroment.

This is our procedure"/script/admin/8001.cs"
very similar to the script of analysis because it uses the same logic for test CLAMAV.
8001 .cs is the number that we are going to bind with our procedure inside the table of procedures structured in admin.
From 2000 to 8000 are free to our use and consumption, as wrote in the documentation.

#import( class , HashArray )
#import( class , CS_Socket )
#import( class , CS_Buffer )

#include "lib.cs"

CS_ADMIN_SCRIPT this = new CS_ADMIN_SCRIPT($_this);


string GetLine(CS_Socket conn)
{
  if (conn == NULL || !conn->IsOpen())
	  return "";
  
    
  string res;
  CS_Buffer buffer = new CS_Buffer();
  buffer->Allocate(256);
  int len = conn->Riceve(buffer->GetBuffer(),10000);
  if (len > 0)
    res = this->Replace(this->Replace( buffer->ToString() ,"\r",""), "\n","");
  delete buffer;
  buffer = NULL;


 return res;

}

int SendMsg(CS_Socket conn, string msg)
{

  if (conn == NULL || !conn->IsOpen())
	  return 0;
 
  int t1 = this->GetTickCount();
  int deadline = t1 + 10000;
  int bsend = 0;
  int size_send = this->StrLen(msg);
  int send_tot = 0;
  int tosend = size_send;

   while(t1 < deadline) 
  {

    t1 = this->GetTickCount();


    bsend = conn->Send(msg,tosend,300);
    if (bsend <= -1)
	   return 0;

   send_tot += bsend;
   if (send_tot == size_send)
		 return 1;
   else if(send_tot != size_send && bsend > 0)
     {
       tosend =  size_send - bsend; 
       msg = this->SubStr(msg,bsend,tosend);
     } 

  }
  
return 0;  
}


int Main(CAdminRequest pRequest, CAdminResponse pResponse)
{
 
    //CR_TEST_clamav
  
    if (pRequest->GetColCount() == 2) 
    {
    
    HashArray fields;
    fields =  pRequest->GetRow();
    if (fields->GetS("c1") != "" && fields->GetI("c2") > 0 && fields->GetI("c2") < 65536)
    {
     CS_Socket conn = new CS_Socket();
     int start_time = this->GetTickCount();
     string res;
     pResponse->Addnew();
     pResponse->SetFieldAt(1,"Connect to: " + fields->GetS("c1") + " Port: " + fields->GetS("c2") + " ...");
     pResponse->SetFieldAt(2,"0");
     pResponse->SetFieldAt(3,"N");
    
     if (!conn->ConnectTo( fields->GetS("c1"), fields->GetS("c2"), this->GetConfig("adapter_ip","CONFIG")))  
     {   
     delete conn;
     conn = NULL;
     pResponse->Addnew();
     pResponse->SetFieldAt(1,"Connection FAILED !!!");
     pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
     pResponse->SetFieldAt(3,"E");
     pResponse->Send(pRequest->GetCmd(),CR_ACK);
     return CONTINUE_SCRIPT;
     }
     pResponse->Addnew();
     pResponse->SetFieldAt(1,"connected");
     pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
     pResponse->SetFieldAt(3,"O");


     /////////
     start_time = this->GetTickCount();
     if (!SendMsg(conn,"STREAM\r\n"))
     {
       
       pResponse->Addnew();
       pResponse->SetFieldAt(1,"sending the command [STREAM]  failed");
       pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
       pResponse->SetFieldAt(3,"E");
       conn->Close();
       delete conn;
       conn = NULL;
       pResponse->Send(pRequest->GetCmd(),CR_ACK);
       return CONTINUE_SCRIPT;
     
     }
     pResponse->Addnew();
     pResponse->SetFieldAt(1,"Send command [STREAM] o.k");
     pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
     pResponse->SetFieldAt(3,"O");

     start_time = this->GetTickCount();
     res = GetLine(conn);
     if (res == "")
     {
       pResponse->Addnew();
       pResponse->SetFieldAt(1,"the server did not respond !!!");
       pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
       pResponse->SetFieldAt(3,"E");
       conn->Close();
       delete conn;
       conn = NULL;
       pResponse->Send(pRequest->GetCmd(),CR_ACK);
       return CONTINUE_SCRIPT;
     }
     pResponse->Addnew();
     pResponse->SetFieldAt(1,res);
     pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
     pResponse->SetFieldAt(3,"N");
     /////////
     start_time = this->GetTickCount();
     if (!SendMsg(conn,"QUIT\n"))
     {
       
       pResponse->Addnew();
       pResponse->SetFieldAt(1,"sending the command [QUIT]  failed");
       pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
       pResponse->SetFieldAt(3,"E");
       conn->Close();
       delete conn;
       conn = NULL;
       pResponse->Send(pRequest->GetCmd(),CR_ACK);
       return CONTINUE_SCRIPT;
     
     }
     pResponse->Addnew();
     pResponse->SetFieldAt(1,"Send command [QUIT] o.k");
     pResponse->SetFieldAt(2,this->Format("%d",this->GetTickCount() - start_time));
     pResponse->SetFieldAt(3,"O");

     conn->Close();
     delete conn;
     conn = NULL;
    }
    pResponse->Send(pRequest->GetCmd(),CR_ACK);
    

  }    
   return CONTINUE_SCRIPT;

}
   


All of that to verify if our CLAMAV Antivirus is running and if it is working correctly with our internal functions of Caronte Antispam.
To notice the function "main" of this procedure:

int Main(CAdminRequest pRequest, CAdminResponse pResponse) { ...

The classes CAdminRequest and CAdminResponse are intrinsic to the procedure of ADMIN and Caronte passes them already as function arguments indicating that yes there is a "requirement" with their data but must also "respond" to this request.

We have reached the end! It's missing only the installation with it's "setup ".
Even here an XML file and a script are needed.

The XML file contains the basic "informations" that the installation engine of Caronte Antispam uses to recognize the plug-in ,MANDATORY it must be called "info.xml" with the obligation to be inside the directory of the plug-in (es /scritps/admin/plugin/clamav/info.xml ) :

<?xml version="1.0" encoding="UTF-8" ?>
<info>
<plugin>
<uniqueID>ClamAV_Antivirus_by_ceg</uniqueID>
<pluginname>ClamAV Antivirus</pluginname>
<authorname>Alessandro Cappellini</authorname>
<companyname>C&amp;G Servizi web s.r.l.</companyname>
<description>ClamAV Antivirus plugin for Caronte Antispam</description>
<version>1.0.0</version>
<copyright>Copyright (C) 2008</copyright>
<comments>http://www.caronteantispam.it</comments>
<install_unistall_script>install.cs</install_unistall_script>
</plugin>
</info>

The file contains generic informations , but also tags as "uniqueID"and"install_unistall_script" these two particular tags are needed to "identify" the plug-in and know which is the script of installation/uninstallation of the plug-in.
If the user decides to install the plug-in, the engine of Caronte launches our script of installation indicated in these TAG and structured for our plug-in in this way:

#import( class , HashArray )
#import( class , CS_FileSystem )
CS_ADMIN_SCRIPT this = new CS_ADMIN_SCRIPT($_this); string filedes[14]; string filesrc[14]; filedes[0] = "{ROOT}/scripts/antispam/clamav.cs"; filedes[1] = "{ROOT}/scripts/admin/8001.cs"; filedes[2] = "{ROOT_WWW}/img/clamav_ico.gif"; filedes[3] = "{ROOT_WWW}/img/clamav-logo.png"; filedes[4] = "{ROOT_WWW}/ajax_stats_virus.htmcc"; filedes[5] = "{ROOT_WWW}/clamav_antivirus.htmcc"; filedes[6] = "{ROOT_WWW}/ajax_test_clamav.htmcc"; filedes[7] = "{ROOT_WWW}/include/stats/STATSf1_7a.xml"; filedes[8] = "{ROOT_WWW}/include/language/it/clamav.xml"; filedes[9] = "{ROOT_WWW}/include/language/en/clamav.xml"; filedes[10] = "{ROOT_WWW}/include/user_menu/clamav.xml"; filedes[11] = "{ROOT_WWW}/include/admin_menu/clamav.xml"; filedes[12] = "{ROOT_WWW}/include/template/clamav.htmch"; filedes[13] = "{ROOT_WWW}/include/template/js_clamav.htmch"; filesrc[0] = "{plugin_path}/clamav.cs"; filesrc[1] = "{plugin_path}/8001.cs"; filesrc[2] = "{plugin_path}/clamav_ico.gif"; filesrc[3] = "{plugin_path}/clamav-logo.png"; filesrc[4] = "{plugin_path}/ajax_stats_virus.htmcc"; filesrc[5] = "{plugin_path}/clamav_antivirus.htmcc"; filesrc[6] = "{plugin_path}/ajax_test_clamav.htmcc"; filesrc[7] = "{plugin_path}/include/stats/STATSf1_7a.xml"; filesrc[8] = "{plugin_path}/include/it/clamav.xml"; filesrc[9] = "{plugin_path}/include/en/clamav.xml"; filesrc[10] = "{plugin_path}/include/user_menu/clamav.xml"; filesrc[11] = "{plugin_path}/include/admin_menu/clamav.xml"; filesrc[12] = "{plugin_path}/include/template/clamav.htmch"; filesrc[13] = "{plugin_path}/include/template/js_clamav.htmch"; void install(string dir, string cid) { CS_FileSystem sys = new CS_FileSystem(); string ROOT_WWW = this->GetConfig("path","WEBGUI"); for (int i = 0; i < 14; i++) { filedes[i] = this->Replace(filedes[i],"{ROOT}",sys->AppPath()); filedes[i] = this->Replace(filedes[i],"{ROOT_WWW}",ROOT_WWW); filesrc[i] = this->Replace(filesrc[i],"{plugin_path}",dir); sys->CopyFile(filesrc[i],filedes[i],1); //overwrite } delete sys; HashArray myconfig = new HashArray(); if (this->GetConfigToArray(myconfig,"CS_SCRIPT") == 1) { for (int i = 0; i < myconfig->GetRecordCount(); i++) { if (this->REeq(myconfig->GetKeyByIndex(i),"cs_(\\d+?)",0) == 1) { if (this->Split(myconfig->GetS(myconfig->GetKeyByIndex(i)),'|',1) == "clamav.cs") { //reinstall !!!!!! delete myconfig; return; } } } this->SetConfig("CLAMAV","enable","0"); this->AddAntispamScript("clamav.cs",-1); this->WaitForReplaceConfig(); this->SaveConfig(); this->SetLevelReBootConfig(0); this->SetRebootConfig(1); } } void uninstall(string dir, string cid) { this->DeleteAntispamScript("clamav.cs"); this->WaitForReplaceConfig(); this->SaveConfig(); this->SetLevelReBootConfig(0); CS_FileSystem sys = new CS_FileSystem(); string ROOT_WWW = this->GetConfig("path","WEBGUI"); for (int i = 0; i < 14; i++) { filedes[i] = this->Replace(filedes[i],"{ROOT}",sys->AppPath()); filedes[i] = this->Replace(filedes[i],"{ROOT_WWW}",ROOT_WWW); sys->UnLink(filedes[i]); } delete sys; this->SetRebootConfig(1); }


To install a plug-in, it must have an own directory in "/script/admin/plugin/[clamav]" and the necessary files must be inserted manually, for example using an FTP client.



Start project 10-10-2003 - Copyright © 2000-2015 C&G Servizi Web s.rl. All rights reserved. VAT N. : 01404430470 .