English | Italiano
by InRete.com

Costruire una Plug-in

Questo è un piccolo tutorial per indicare le linee guida nella realizzazione di una plug-in in Caronte Antispam.
La prima cosa da prendere in considerazione è il tipo di plug-in che si vuole realizzare facendo chiaramente una piccola analisi, sul suo funzionamento e quale livello di integrazione avrà con caronte Antispam.
In questo particolare caso andremo a realizzare una plug-in per il Sistema di analisi virus di Caronte scegliento CLAMAV come antivirus di cooperazione.
Ma entriamo nel vivo di questo tutorial.

Lo script da affiancare al cuore di Caronte Antispam (/scritp/antispam/clamav.cs)

/// con la macro "#import" il precompilatore di Caronte include il supporto e alloca 
//  memoria per i metodi della classe.
// ci servono CS_Socket per comunicare con clamav e CS_Buffer per immagazzinare le informazioni da inviare e ricevere.
#import( class , CS_Socket ) #import( class , CS_Buffer )
/// si definiscano in ansi C alcuni costanti primitive.
#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 /// l'istanza di ambiente per ANTISPAM !!! // si eredita tutte le funzioni base e si inizializza l'ambiente 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 = ""; // funzione che registra il fatto che si può notificare un valore con il nome "notify_virus_name" // a tutti gli altri script presenti in ambiente. // il nome "notify_virus_name" può variare ad esempio si potrebbe chiamare anche "notify_virus_name_clamav" // la notifica è per cortesia verso gli altri script che potrebbero usufruire del nostro lavoro.
this->RegisterGlobalVariable("notify_virus_name"); // funzione che ottiene le ACK o gli Errori da CLAMAV sulla relativa porta // ricordiamoci che tutte le funzioni in Carontese per essere viste devo essere dichiarate e strutturate // una dopo l'altra, altrimenti non riescono a vedersi. // la classe CS_Buffer è l'unica in Caronte scripting che può ricevere dati su un socket buffer. 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"); //registrate 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(); } } // Importante: se lo script è stato caricato all'inizio è quindi "in cache"
// viene richiamato il metodo "OnDestroyThis" e questo premette di liberare memoria e azzerare le variabili globali. void OnDestroyThis() { if (this != NULL) delete this; this = NULL; CloseAll(); }
Analizziamo il meccanismo.
L'ambiente ANTISPAM (proxy) durate la comunicazione tra client e server, "innalza" degli "eventi a funzioni", quella che a noi interessa per questa plug-in è

void OnAllDataMessage(string part_msg, int is_end_msg)

Questa evento funzione, come si intuisce dal nome, si "innalza" quando nella comunicazione si riceve il comando DATA con il primo buffer, se il messaggio è superiore al buffer
questo evento funzione si innalzerà più volte con il nuovo contenuto. Il secondo argomento della funzione ci indica se si è raggiunta la fine del messaggio.
Noi ci limitiamo nel trasmettere questo "buffer" a CLAMAV, regitrandoci ogni volta la sua lunghezza e lo "stadio" di trasmissione, per poi avere il "responso" finale.
Per vedere tutti gli eventi funzione che l'ambiente "ANTISPAM" e gli altri ambienti generano, consigliamo di controllare la documentazione.

Una volta creato lo script ci occorre le relative pagine di gestione nella Web G.U.I. di Caronte Antispam.
Una plug-in che si rispetti, anche con poche variabili di configurazione deve avere queste pagine, permettendo la gestione all'utilizzatore finale.
Nella nostra plug-in realizzeremo una sola "pagina" di gestione che potrà essere utilizzata sia lato amministratore che lato utente normale.
Chiaramente useremo le librerie script di Caronte Antispam Web G.U.I. e cercheremo il più possibile di seguirne la loro logica di funzionamento.

Creiamo la pagina "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");     

}

Da analizzare in questo script le fuzioni di libreria:

IsSecureSession(0);
Init_language(CARONTE_LING);

Aprendo i sorgenti della "\www\include\libhttp.htmch" la prima funzione "IsSecureSession(0);" verifica che la sessione sia sicura avendo effettuato il login e lo zero indica che la chiamata non proviene da un oggetto AJAX, quindi si può applicare un Header Redirect al web server se la sessione è insicura.
La seconda funzione "Init_language(CARONTE_LING);" inizializza la lingua e capiamo che alla nostra pagina di gestione manca il file contenente le traduzione, controllando sempre i sorgenti, ci accorgiamo che tale funzione legge completamente il contenuto di una direcotry "include/language/", prima chiedendo tutti i file in lingua "inglese" poi chiedendo quelli nella lingua indicata nella "conf" della web G.U.I. con la variabile "CARONTE_LING".

Quindi dobbiamo creare il nostro file lingua che installeremo in "/www/include/language/it/clamav.xml" e lo svlilupperemo in questo modo:

<?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>Configurazione Clamav Antivirus</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1165</name>
<value>Abilita Controllo Antivirus</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1166</name>
<value>Ip / Host:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1170</name>
<value>Peso Max Msg:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1168</name>
<value>Porta:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1174</name>
<value>Tempo di Embargo:</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1177</name>
<value>IP all'inferno</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1178</name>
<value>Se il messaggio contiene un Virus manda all'inferno l'IP</value>
<type>3</type>
</variable>
<variable>
<name>CLAMAV1179</name>
<value>TEST Configurazione ClamAV</value>
<type>3</type>
</variable>
<variable>
<name>1008</name>
<value>&lt;strong&gt;Antivirus&lt;/strong&gt;&lt;br&gt; Filtro attivato dall'amministratore del sistema.&lt;br&gt; Tutte le tue Email sono protette da &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; Il filtro attivo è a discrezione dell'amministratore di sistema. Caronte Antispam ha una particolare plug-in che sfrutta Clamav Antivirus per controllare la posta elettronica. Il tuo amministratore/provider puo' aver scelto altre soluzioni per controllare la presenza di virus nella tua posta elettronica.</value>
<type>4</type>
</variable>
</config>

proseguendo nell'analisi della nostra pagina GUI troviamo:

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

Questa classe ci permette di connettersi al cuore di Caronte tramite il servizio Remote Admin e prelevare o inserire i dati nella configurazione.
Troviamo anche:

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

Queste funzioni interne della libreria "libhttp.htmch" ci permettano, passando una classe HashArray e il file template con estezione ".htmch", di creare un sorgente HTML da poter restituire all'utente. Guardando sempre i sorgenti di libreria ci accorgiamo anche che la funzione "TemplateVarReplace" non si limita semplicemente ad aprire il file indicato ,cercare all'interno dei commenti HTML ,cosi strutturati: <!--@xxxxxx@--> e replicarli con il relativo dato (se trovati) del file xml di lingua, ma anche ad applicare dei comportamenti controllando il terzo parametro di funzione e il valore del child "type" dell'xml.
Ad esempio quel "2" indica alla funzione di inserire dei tag <script ...></script> e il replace indica poi un "type 4" <type>4</type> del child XML di lingua che è html da rendere attivo. Da questo riusciamo a capire anche il perchè della struttura XML. Le definizioni del type sono nella libreria nei relativi commenti.

Quindi dobbiamo creare questi file template in puro html inseririli in "/www/include/template/" e definire il nostro testo, come titoli e descrizioni, all'interno del file come dei commenti delimitati da "@xxxx@" che poi verranno replicati da queste funzioni.

Ma il nostro script "clamav.cs" aveva anche delle fuzioni che inserivano nelle statistiche gererali di Caronte, quanti e quali virus venivano bloccati.
Dobbiamo interagire anche con l'engine della GUI che permette di visualizzare le statistiche.
Bene, guardando sempre i sorgenti della libreria "libhttp.htmch" vediamo che basta inserire un file XML di configurazione della directory "/www/include/stats/" e strutturarlo cosi:

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

Automaticamente la "combobox" della pagina statistiche riportera il link indicato.
Dove "ajax_stats_virus.htmcc " sarà una pagina che permetterà di visualizzare le statitstiche di questa plug-in.
Per realizzarla, basta vedere un attimo le altre pagine statistiche in Caronte per capirne la logica.

Andiamo avanti...

Nel caso di questa plug-in useremo le procedure già esistenti in ambiente per leggere ed inserire la nostra configurazione una volta fatto "salva".
Andremo a realizzare anche una nostra procedura per creare un TOOLS e testare CLAMAV quando la plug-in sarà installata, quindi manipoleremo anche l'ambiente di ADMIN.

Questa è la nostra procedura "/script/admin/8001.cs"
molto simile allo script di analisi in quanto usa la stessa logica per testare CLAMAV.
8001.cs è il numero che andremo ad impegnare con la nostra procedura dentro la tabella delle procedure strutturate in admin.
Dalla 2000 alla 8000 sono libere a nostro uso e consumo, come riportato nella documentazione.

 

#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;

}


Tutto questo per verificare se il nostro Clamav Antivirus sta correndo e se funziona correttamente con le funzioni interne di Caronte Antispam.
Da notare la funzione "main" di questa procedura:

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

Le classi CAdminRequest e CAdminResponse sono intrinseche della procedura di ADMIN e Caronte le passa già come argomenti di funzione indicandoci che c'è sì una "richiesta" con i relativi dati ma occorre anche "rispondere" a tale richiesta.

Siamo arrivati alla fine ! Manca solamente l'installazione con il suo "setup".
Anche qui ci occorre un file XML e uno script.

Il file XML riporta le "informazioni" base che l'engine di installazione di Caronte Antispam usa per riconoscere la plug-in e si deve chiamare
OBBLIGATORIAMENTE "info.xml" con sempre l'obbligo di trovarsi all'interno della directory della 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>

Il file contiene informazioni di titolo generale, ma anche tag come "uniqueID" e "install_unistall_script"
questi due tag particolari servono per "identificare" la plug-in e sapere qual'e' lo script di installazione/disistallazione della plug.
Se l'utente decide di installare la plug-in, l'engine di Caronte farà correre il nostro script di installazione indicato in questi TAG e cosi strutturato per la nostra plugin:

#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); }

Per essere installata la plug-in deve avere una sua directory in "/script/admin/plugin/[clamav]" e i file necessari devono essere inseriti manualmente, ad esempio con un client FTP.



Start project 10-10-2003 - Copyright 2000-2015 C&G Servizi Web s.rl. Tutti i diritti riservati. P.IVA : 01404430470 .