diff --git a/apps/maarch_entreprise/define.php b/apps/maarch_entreprise/define.php
index 461dee76a1fbaefe02d26cc7af6ee8e0c0e9752d..e08ee41280d93b6f5783f1b3d8e3a582e328aed9 100755
--- a/apps/maarch_entreprise/define.php
+++ b/apps/maarch_entreprise/define.php
@@ -30,5 +30,5 @@ if (!defined('V2_ENABLED')) {
 	define('V2_ENABLED', false);
 }
 if (!defined('PROD_MODE')) {
-	define('PROD_MODE', true);
+	define('PROD_MODE', false);
 }
diff --git a/apps/maarch_entreprise/xml/config.xml.default b/apps/maarch_entreprise/xml/config.xml.default
index 249c15f3a60cc7aab06f6d4fb3110bca81ed70c4..c4f16a5eafa753b1854d31b4feb233ae930464fe 100755
--- a/apps/maarch_entreprise/xml/config.xml.default
+++ b/apps/maarch_entreprise/xml/config.xml.default
@@ -307,4 +307,8 @@
         <moduleid>export_seda</moduleid>
         <comment>_EXPORT_SEDA_COMMENT</comment>
     </MODULES>
+    <MODULES>
+        <moduleid>convert</moduleid>
+        <comment>_CONVERT_COMMENT</comment>
+    </MODULES>
 </ROOT>
diff --git a/composer.json b/composer.json
index 38bce39374a68153f0bef2539f752e189cd88193..4f3eb6251c39f1591668221a97c4a71f6733ad45 100755
--- a/composer.json
+++ b/composer.json
@@ -5,6 +5,7 @@
     	    "Apps\\": "apps/maarch_entreprise/",
             "Attachments\\": "modules/attachments/",
             "Baskets\\": "modules/basket/",
+            "Convert\\": "modules/convert/",
             "Entities\\": "modules/entities/",
             "Notes\\": "modules/notes/",
             "Notifications\\": "modules/notifications/",
diff --git a/core/Controllers/HistoryController.php b/core/Controllers/HistoryController.php
index 0ccad66a54603f2cf839caac402c6f12caac8fb9..63d01d80b7a69642a2498b7ced32b7717256f57d 100755
--- a/core/Controllers/HistoryController.php
+++ b/core/Controllers/HistoryController.php
@@ -219,4 +219,20 @@ class HistoryController
 
         return $response->withJson($return);
     }
+
+    /*
+    timestart : timestamp Debut
+    timeend : timestamp Fin
+    level : level log4php
+    message : message dans les logs
+    */
+    public function executionTimeLog($timestart, $timeend, $level, $message){
+        if (empty($timeend)){
+            $timeend = microtime(true);
+        }
+        $time = $timeend - $timestart;
+
+        self::$level(['message' => $message.'. Done in ' . number_format($time, 3) . ' secondes.']);
+
+    }
 }
diff --git a/core/Models/DocserverModelAbstract.php b/core/Models/DocserverModelAbstract.php
index e175e21e6151529e3cd803382ea6284a680d9f95..847ea6d495423d5649f47005426ae3a9226b35f4 100755
--- a/core/Models/DocserverModelAbstract.php
+++ b/core/Models/DocserverModelAbstract.php
@@ -139,4 +139,35 @@ class DocserverModelAbstract
 
         return $aReturn;
     }
+
+    /**
+     * Get docservers to insert a new doc converted.
+     * Can return null if no corresponding object.
+     * @param  $collId  string Collection identifier
+     * @param  string $typeId [description]
+     * @return docservers 
+     */
+    public function findTargetDs(array $aArgs = [])
+    {
+        ValidatorModel::notEmpty($aArgs, ['collId']);
+        ValidatorModel::stringType($aArgs, ['collId']);
+
+        if (empty($aArgs['typeId'])) {
+            $aArgs['typeId'] = 'CONVERT';
+        }
+
+        $aReturn = DatabaseModel::select([
+            'select'    => ['*'],
+            'table'     => ['docservers'],
+            'where'     => [
+                "is_readonly = 'N' and enabled = 'Y' and " . 
+                "coll_id = ? and docserver_type_id = ?"
+                        ],
+            'data'      => [$aArgs['collId'], $aArgs['typeId']],
+            'order_by'  => ['priority_number'],
+            'limit'     => 1,
+        ]);
+
+        return $aReturn;
+    }
 }
diff --git a/core/Models/ResDocserverModel.php b/core/Models/ResDocserverModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b7bfcb9104e0917a0c8868688efbb3cc085cbba
--- /dev/null
+++ b/core/Models/ResDocserverModel.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief Res and docserver association Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+
+namespace Core\Models;
+
+class ResDocserverModel extends ResDocserverModelAbstract
+{
+    // Do your stuff in this class
+}
diff --git a/core/Models/ResDocserverModelAbstract.php b/core/Models/ResDocserverModelAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ae989b0d076aa9451e391fe451ee7d60a697557
--- /dev/null
+++ b/core/Models/ResDocserverModelAbstract.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief Res Docserver association Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+
+namespace Core\Models;
+
+class ResDocserverModelAbstract
+{
+
+    /**
+     * Retrieve the path of source file to process
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process 
+     * @param string $adrType type of the address
+     * $resTable, $adrTable, $resId, $adrType = 'DOC'
+     * @return string
+     */
+    public static function getSourceResourcePath(array $aArgs = [])
+    {
+        ValidatorModel::notEmpty($aArgs, ['resTable']);
+        ValidatorModel::notEmpty($aArgs, ['adrTable']);
+        ValidatorModel::notEmpty($aArgs, ['resId']);
+        
+        if (!isset($aArgs['adrType'])) {
+            $aArgs['adrType'] = 'DOC';
+        }
+
+        if ($aArgs['adrType'] == 'DOC') {
+            $table = $aArgs['resTable'];
+            $where = ['res_id=?'];
+            $data  = [$aArgs['resId']];
+        } else {   
+            $table = $aArgs['adrTable'];
+            $where = ['res_id = ?', 'adr_type = ?'];
+            $data  = [$aArgs['resId'], $aArgs['adrType']];
+        }
+
+        $aReturn = DatabaseModel::select([
+            'select'    => [$table.'.path', $table.'.filename', $table.'.offset_doc', 'docservers.path_template'],
+            'table'     => [$table, 'docservers'],
+            'where'     => $where,
+            'data'      => $data,
+            'left_join' => [$table.'.docserver_id = docservers.docserver_id']
+        ]);
+
+        if (empty($aReturn)) {
+            return false;
+        }
+
+        $resPath            = '';
+        $resFilename        = '';
+        if (isset($aReturn[0]['path'])) {
+            $resPath = $aReturn[0]['path'];
+        }
+        if (isset($aReturn[0]['filename'])) {
+            $resFilename = $aReturn[0]['filename'];
+        }
+        if (isset($aReturn[0]['offset_doc']) 
+            && $aReturn[0]['offset_doc'] <> ''
+            && $aReturn[0]['offset_doc'] <> ' '
+        ) {
+            $sourceFilePath = $aReturn[0]['path'] 
+                . $aReturn[0]['filename'] 
+                . DIRECTORY_SEPARATOR . $aReturn[0]['offset_doc'];
+        } else {
+            $sourceFilePath = $resPath . $resFilename;
+        }
+        $resPathTemplate = '';
+        if (isset($aReturn[0]['path_template'])) {
+            $resPathTemplate = $aReturn[0]['path_template'];
+        }
+
+        $sourceFilePath = $resPathTemplate . $sourceFilePath;
+        $sourceFilePath = str_replace('#', DIRECTORY_SEPARATOR, $sourceFilePath);
+
+        return $sourceFilePath;
+    }
+}
diff --git a/modules/attachments/Test/ReconciliationControllerTest.php b/modules/attachments/Test/ReconciliationControllerTest.php
index 6fe2c30fe82daa3eab28df39584b0e6d8b2431ef..bb5e9cf096d4a85450dff2185e6b2d8f119e3323 100755
--- a/modules/attachments/Test/ReconciliationControllerTest.php
+++ b/modules/attachments/Test/ReconciliationControllerTest.php
@@ -120,6 +120,6 @@ class ReconciliationControllerTest extends TestCase
 
         $response = $action->storeAttachmentResource($aArgs);
 
-        $this->assertTrue($response;
+        $this->assertTrue($response);
     }
 }
\ No newline at end of file
diff --git a/modules/convert/Controllers/ProcessConvertController.php b/modules/convert/Controllers/ProcessConvertController.php
new file mode 100644
index 0000000000000000000000000000000000000000..f616fea024bc0f45e621020fa5fee301301489e3
--- /dev/null
+++ b/modules/convert/Controllers/ProcessConvertController.php
@@ -0,0 +1,591 @@
+<?php
+
+/**
+ * Copyright Maarch since 2008 under licence GPLv3.
+ * See LICENCE.txt file at the root folder for more details.
+ * This file is part of Maarch software.
+ *
+ */
+
+/**
+* @brief process convert class
+*
+* <ul>
+* <li>Services to process the convertion of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+namespace Convert\Controllers;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Convert\Models\ProcessFulltextModel;
+use Core\Models\DocserverModel;
+use Core\Models\ResDocserverModel;
+
+require_once 'core/class/class_functions.php';
+require_once 'core/class/class_db_pdo.php';
+// require_once 'core/class/class_db.php';
+// require_once 'core/docservers_tools.php';
+// require_once 'core/class/docservers_controler.php';
+// require_once 'core/services/ManageDocservers.php';
+
+//include_once('html2text/html2text.php');
+
+class ProcessConvertController
+{
+    protected $libreOfficeExecutable;
+
+    //public function __construct($libreOfficeExecutable = 'cloudooo')
+    public function __construct($libreOfficeExecutable = 'soffice')
+    //public function __construct($libreOfficeExecutable = 'unoconv')
+    {
+        $this->libreOfficeExecutable = $libreOfficeExecutable;
+    }
+
+    /**
+     * Ask for conversion
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @param array $tgtfmt array of target format
+     * @return array $returnArray the result
+     */
+    public function convert(array $args=[])
+    {
+        $timestart = microtime(true);
+        // HistoryController::info(['message'=>'debut convert', 'code'=>111, ]);
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        $dbConv = new \Database($GLOBALS['configFile']);
+        
+        //retrieve path of the resource
+        $stmtConv = $dbConv->query("select * from " . $resTable 
+            . " where res_id = ?", array($resId)
+        );
+        $line = $stmtConv->fetchObject();
+        
+        if ($line->res_id <> '') {
+            $resourcePath = ResDocserverModel::getSourceResourcePath(
+                [
+                    'resTable' => $resTable, 
+                    'adrTable' => $adrTable, 
+                    'resId' => $line->res_id,
+                    'adrType' => 'DOC'
+                ]
+            );
+        }
+        if (!file_exists($resourcePath)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'file not exists : ' . $resourcePath,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the resource on tmp directory
+        $fileNameOnTmp = $tmpDir . rand() . rand();
+        if (!copy($resourcePath, $fileNameOnTmp)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'copy on tmp failed',
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //now do the conversion !
+        if (strtoupper($line->format) <> 'PDF') {
+            $resultOfConversion = $this->launchConvert(
+                $fileNameOnTmp, 
+                'pdf', 
+                $tmpDir,
+                pathinfo($resourcePath, PATHINFO_EXTENSION)
+            );
+        } else {
+            //echo $fileNameOnTmp;
+            copy($fileNameOnTmp, $fileNameOnTmp . '.pdf');
+            $resultOfConversion = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        }
+        
+        if ($resultOfConversion['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfConversion;
+        }
+        //find the target docserver
+        $targetDs = DocserverModel::findTargetDs(['collId' => $collId]);
+        if (empty($targetDs)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'Ds of collection not found:' . $collId,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        
+        //copy the result on docserver
+        // HistoryController::info(['message'=>'avant cp ds', 'code'=>1112, ]);
+        $resultCopyDs = $ManageDocservers->copyResOnDS($fileNameOnTmp . '.pdf', $targetDs);
+        if ($resultCopyDs['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultCopyDs;
+        }
+        // HistoryController::info(['message'=>'avant update', 'code'=>19, ]);
+        //update the \Database
+        $resultOfUpDb = $this->updateDatabase(
+            $collId,
+            $resTable, 
+            $adrTable, 
+            $resId,
+            $targetDs,
+            $resultCopyDs['value']['destinationDir'],
+            $resultCopyDs['value']['fileDestinationName']
+        );
+        // HistoryController::info(['message'=>var_export($resultOfUpDb, true), 'code'=>111111, ]);
+        // HistoryController::info(['message'=>$collId, 'code'=>2, ]);
+        // HistoryController::info(['message'=>$resTable, 'code'=>3, ]);
+        // HistoryController::info(['message'=>$adrTable, 'code'=>4, ]);
+        // HistoryController::info(['message'=>$resId, 'code'=>5, ]);
+        // HistoryController::info(['message'=>'apres res_id', 'code'=>6, ]);
+        // HistoryController::info(['message'=>$targetDs, 'code'=>6, ]);
+        // HistoryController::info(['message'=>var_export($resultCopyDs, true), 'code'=>7, ]);
+
+        if ($resultOfUpDb['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfUpDb;
+        }
+
+        unlink($fileNameOnTmp);
+        unlink($fileNameOnTmp . '.pdf');
+
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        HistoryController::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessConvertAbstract_Service::convert');
+        return $returnArray;
+    }
+
+    /**
+     * Launch the conversion
+     *
+     * @param string $srcfile source file
+     * @param string $tgtfmt target format
+     * @param string $tgtdir target dir
+     * @param string $srcfmt source format
+     * @return array $returnArray the result
+     */
+    public function launchConvert(
+        $srcfile, 
+        $tgtfmt, 
+        $tgtdir=false, 
+        $srcfmt=null
+    ) {
+        $timestart=microtime(true);
+
+        $processHtml = false;
+        $executable='';
+        
+        HistoryController::info(['message'=>'[TIMER] Debut Convert_ProcessConvertAbstract_Service::launchConvert']);
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            $processHtml = true;
+            HistoryController::info(['message'=>'[TIMER] srcfmt ' . $srcfmt]);
+            copy($srcfile, str_ireplace('.maarch', '.', $srcfile) . '.html');
+            if (file_exists('/usr/bin/mywkhtmltopdf')) {
+                $command = "mywkhtmltopdf " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.pdf');
+            } else {
+                $envVar = "export DISPLAY=FRPAROEMINT:0.0 ; ";
+                $command = $envVar . "wkhtmltopdf " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.pdf');
+            }
+            $executable='wkhtmltopdf';
+        } else {
+            $executable='soffice';
+            HistoryController::info(['message'=>'[TIMER] let LO do it ' . $this->libreOfficeExecutable]);
+            if ($this->libreOfficeExecutable == "cloudooo") {
+                $serverAddress = "http://192.168.21.40:8011";
+                $tokens = array();
+                require_once 'apps/maarch_entreprise/tools/phpxmlrpc/lib/xmlrpc.inc';
+                require_once 'apps/maarch_entreprise/tools/phpxmlrpc/lib/xmlrpcs.inc';
+                require_once 'apps/maarch_entreprise/tools/phpxmlrpc/lib/xmlrpc_wrappers.inc';
+                $fileContent = file_get_contents($srcfile, FILE_BINARY);
+                $encodedContent = base64_encode($fileContent);
+                $params = array();
+                array_push($params, new PhpXmlRpc\Value($encodedContent));
+                array_push($params, new PhpXmlRpc\Value($srcfmt));
+                array_push($params, new PhpXmlRpc\Value($tgtfmt));
+                array_push($params, new PhpXmlRpc\Value(false));
+                $v = new PhpXmlRpc\Value($params, "array");
+            } elseif ($this->libreOfficeExecutable == "unoconv") {
+                $tokens = array('"' . $this->libreOfficeExecutable . '"');
+                $tokens[] = "-f";
+                $tokens[] = $tgtfmt;
+                $tokens[] = '-o "' . $srcfile . '.' . $tgtfmt . '"';
+                $tokens[] = '"' . $srcfile . '"';
+            } else {
+                $tokens = array('"' . $this->libreOfficeExecutable . '"');
+                $tokens[] = "--headless";
+                $tokens[] = "--convert-to";
+                $tokens[] = $tgtfmt;
+                $tokens[] = '"' . $srcfile . '"';
+                if (!$tgtdir) {
+                    $tgtdir = dirname($srcfile);
+                }
+                $tokens[] = '--outdir "' . $tgtdir . '"';
+            }
+            
+            if (!$srcfmt) {
+                $tokens[] = $srcfmt;
+            }
+
+            $command = implode(' ', $tokens);
+
+            $output = array();
+            $return = null;
+            $this->errors = array();
+        }
+        //echo $command . '<br />';exit;
+        if ($this->libreOfficeExecutable == "cloudooo" && !$processHtml) {
+            HistoryController::info(['message'=>'[TIMER] commande : cloudooo url ' . $serverAddress]);
+            HistoryController::info(['message'=>'[TIMER] Debut Convert_ProcessConvertAbstract_Service::launchConvert__exec']);
+            $req = new PhpXmlRpc\Request('convertFile', $v);
+            //HistoryController::info(['message'=>'[TIMER] commande : cloudooo url ' . $serverAddress]);
+            HistoryController::info(['message'=>'[TIMER] Fin Convert_ProcessConvertAbstract_Service::launchConvert__exec']);
+            $client = new PhpXmlRpc\Client($serverAddress);
+            $resp = $client->send($req);
+            if (!$resp->faultCode()) {
+                $encoder = new PhpXmlRpc\Encoder();
+                $value = $encoder->decode($resp->value());
+                $theFile = fopen($srcfile . '.' . $tgtfmt, 'w+');
+                fwrite($theFile, base64_decode($value));
+                fclose($theFile);
+                $returnArray = array(
+                    'status' => '0',
+                    'value' => '',
+                    'error' => '',
+                );
+            } else {
+                //print "An error occurred: ";
+                //print "Code: " . htmlspecialchars($resp->faultCode()) 
+                //    . " Reason: '" . htmlspecialchars($resp->faultString()) . "'\n";
+                $returnArray = array(
+                    'status' => '1',
+                    'value' => '',
+                    'error' => "Code: " . htmlspecialchars($resp->faultCode()) 
+                        . " Reason: '" . htmlspecialchars($resp->faultString()),
+                );
+            }
+        } else {
+            $timestart_command = microtime(true);
+            exec("timeout -k 5m 3m " . $command, $output, $return);
+            HistoryController::debug(['message'=>'[TIMER] commande : ' . $command]);
+            HistoryController::executionTimeLog($timestart_command, '', 'info', '[TIMER] ' . $executable . ' - Convert_ProcessConvertAbstract_Service::launchConvert__exec');
+            if ($return === 0) {
+                $returnArray = array(
+                    'status' => '0',
+                    'value' => '',
+                    'error' => '',
+                );
+            } else {
+                $returnArray = array(
+                    'status' => '1',
+                    'value' => '',
+                    'error' => $return . $output,
+                );
+            }
+        }
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            $returnArray = array();
+            unlink(str_ireplace('.maarch', '.', $srcfile) . '.html');
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        }
+        HistoryController::executionTimeLog($timestart, '', 'info', '[TIMER] Fin Convert_ProcessConvertAbstract_Service::launchConvert');
+        return $returnArray;
+    }
+
+    /**
+     * Updating the database with the location information of the document on the
+     * new docserver
+     * @param string $collId collection
+     * @param string $resTable res table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process
+     * @param docserver $docserver docserver object
+     * @param string $path location of the resource on the docserver
+     * @param string $fileName file name of the resource on the docserver
+     * @return array $returnArray the result
+     */
+    private function updateDatabase(
+        $collId, 
+        $resTable, 
+        $adrTable, 
+        $resId,
+        $docserver,
+        $path, 
+        $fileName
+    ) {
+        try {
+            $docserver->path_template = str_replace(
+                DIRECTORY_SEPARATOR, 
+                '#', 
+                $docserver->path_template
+            );
+            $path = str_replace($docserver->path_template, '', $path);
+            $dbConv = new \Database($GLOBALS['configFile']);
+            $query = "update convert_stack set status = 'P' where "
+               . " coll_id = ? and res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $collId,
+                    $resId
+                )
+            );
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? order by adr_priority";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "select docserver_id, path, filename, offset_doc, fingerprint"
+                       . " from " . $resTable . " where res_id = ?";
+                $stmt = $dbConv->query($query, array($resId));
+                $recordset = $stmt->fetchObject();
+                // HistoryController::info(['message'=>$recordset, 'code'=>8, ]);
+                $resDocserverId = $recordset->docserver_id;
+                $resPath = $recordset->path;
+                $resFilename = $recordset->filename;
+                $resOffsetDoc = $recordset->offset_doc;
+                $fingerprintInit = $recordset->fingerprint;
+                $query = "select adr_priority_number from docservers "
+                       . " where docserver_id = ?";
+                $stmt = $dbConv->query($query, array($resDocserverId));
+                $recordset = $stmt->fetchObject();
+                $query = "insert into " . $adrTable . " (res_id, "
+                       . "docserver_id, path, filename, offset_doc, fingerprint, "
+                       . "adr_priority) values (?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $resDocserverId,
+                        $resPath,
+                        $resFilename,
+                        $resOffsetDoc,
+                        $fingerprintInit,
+                        $recordset->adr_priority_number
+                    )
+                );
+            }
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? and adr_type = 'CONV'";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "insert into " . $adrTable . " (res_id, docserver_id, "
+                   . "path, filename, offset_doc, fingerprint, adr_priority, adr_type) values (" 
+                   . "?, ?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        'CONV'
+                    )
+                );
+            } else {
+                $query = "update " . $adrTable . " set docserver_id = ?, "
+                   . " path = ?, filename = ?, offset_doc = ?, fingerprint = ?, adr_priority = ?"
+                   . " where res_id = ? and adr_type = ? ";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        $resId,
+                        'CONV'
+                    )
+                );
+            }
+            if ($_SESSION['user']['UserId'] <> '') {
+                $user = $_SESSION['user']['UserId'];
+            } else {
+                $user = 'CONVERT_BOT';
+            }
+            $query = "insert into history (table_name, record_id, "
+                   . "event_type, user_id, event_date, info, id_module) values (" 
+                   . "?, ?, 'ADD', '" . $user . "', " 
+                   . $dbConv->current_datetime() 
+                   . ", ?, 'convert')";
+            $stmt = $dbConv->query( 
+                $query, 
+                array(
+                    $resTable,
+                    $resId,
+                    "process convert done"
+                )
+            );
+
+            $queryCpt = "select coalesce(custom_t9, '0') as custom_t9 from " . $resTable 
+                . " where res_id = ?";
+            $stmtCpt = $dbConv->query($queryCpt, array($resId));
+            $rsCpt = $stmtCpt->fetchObject();
+            $cptConvert = $rsCpt->custom_t9 + 1;
+
+            $query = "update " . $resTable 
+                . " set convert_result = '1', is_multi_docservers = 'Y', custom_t9 = '" . $cptConvert . "' where "
+                . " res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $resId
+                )
+            );
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } catch (Exception $e) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $e->getMessage(),
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+     * Updating the database with the error code
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @param string $result error code
+     * @return nothing
+     */
+    private function manageErrorOnDb(
+        $resTable, 
+        $resId,
+        $result
+    ) {
+        $dbConv = new \Database($GLOBALS['configFile']);
+        $query = "update " . $resTable 
+            . " set convert_result = ? where "
+            . " res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $result,
+                $resId
+            )
+        );
+    }
+
+    /**
+     * Test if the record is already processed by convert module
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @return boolean
+     */
+    public function isAlreadyProcessedByConvert(
+        $resTable, 
+        $resId
+    ) {
+        $dbConv = new \Database($GLOBALS['configFile']);
+        $query = "select convert_result from " . $resTable 
+            . "  where res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $resId
+            )
+        );
+        $rs = $stmt->fetchObject();
+        if (
+            empty($rs->convert_result) || 
+            $rs->convert_result == '0'
+        ) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/convert/Controllers/ProcessFulltextController.php b/modules/convert/Controllers/ProcessFulltextController.php
new file mode 100644
index 0000000000000000000000000000000000000000..58f331853f2c13c6b69408d09ee062cec163c9df
--- /dev/null
+++ b/modules/convert/Controllers/ProcessFulltextController.php
@@ -0,0 +1,739 @@
+<?php
+
+/**
+ * Copyright Maarch since 2008 under licence GPLv3.
+ * See LICENCE.txt file at the root folder for more details.
+ * This file is part of Maarch software.
+ *
+ */
+
+/**
+* @brief process fulltext class
+*
+* <ul>
+* <li>Services to process the fulltext of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+namespace Convert\Controllers;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Convert\Models\ProcessFulltextModel;
+use Core\Models\ResDocserverModel;
+
+require_once 'core/class/class_functions.php';
+require_once 'core/class/class_db_pdo.php';
+// require_once 'core/class/class_db.php';
+// require_once 'core/docservers_tools.php';
+// require_once 'core/class/docservers_controler.php';
+// require_once 'core/services/ManageDocservers.php';
+
+//include_once('html2text/html2text.php');
+
+class ProcessFulltextController
+{
+    protected $pdftotext;
+
+    public function __construct($pdftotext = 'pdftotext')
+    {
+        // Storing text in lucene index
+        set_include_path('apps/maarch_entreprise/tools/' 
+            . PATH_SEPARATOR . get_include_path()
+        );
+
+        if(!@include('Zend/Search/Lucene.php')) {
+            set_include_path($GLOBALS['MaarchDirectory'].'apps/maarch_entreprise/tools/' 
+                . PATH_SEPARATOR . get_include_path()
+            );
+
+            require_once("Zend/Search/Lucene.php");
+        }
+
+        $this->pdftotext = $pdftotext;
+    }
+
+    /**
+     * Ask for fulltext
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @param array $tgtfmt array of target format
+     * @return array $returnArray the result
+     */
+    public function fulltext(array $args=[])
+    {
+        $timestart = microtime(true);
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        if(isset($args['path_to_lucene']) && !empty($args['path_to_lucene'])){
+            $indexFileDirectory = $args['path_to_lucene'];
+        } else {
+            $countColl = count($_SESSION['collections']);
+            for ($i=0;$i<$countColl;$i++) {
+                if ($_SESSION['collections'][$i]['id'] == $collId) {
+                    $indexFileDirectory 
+                        = $_SESSION['collections'][$i]['path_to_lucene_index'];
+                }
+            }
+        }
+
+        $dbConv = new \Database($GLOBALS['configFile']);
+        
+        //retrieve path of the resource
+        $stmtConv = $dbConv->query("select * from " . $resTable 
+            . " where res_id = ?", array($resId)
+        );
+        $line = $stmtConv->fetchObject();
+        
+        if ($line->res_id <> '')  {
+            $resourcePath = ResDocserverModel::getSourceResourcePath(
+                [
+                    'resTable' => $resTable, 
+                    'adrTable' => $adrTable, 
+                    'resId' => $line->res_id, 
+                    'adrType' => 'CONV'
+                ]
+            );
+        }
+        if (!file_exists($resourcePath)) {
+            $returnArray = array(
+                'status' => '2',
+                'value' => '',
+                'error' => 'file not already converted in pdf for fulltext. path :' 
+                    . $resourcePath . ", adrType : CONV, adr_table : " . $adrTable,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the resource on tmp directory
+        $fileNameOnTmp = $tmpDir . rand() . rand();
+        if (!copy($resourcePath, $fileNameOnTmp)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'copy on tmp failed for fulltext. Copy ' . $resourcePath . ' to ' . $fileNameOnTmp,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //now do the fulltext !
+        if (!empty($args['zendIndex'])) {
+            $resultOfConversion = $this->launchFulltext(
+                $fileNameOnTmp, 
+                $resId, 
+                $indexFileDirectory, 
+                $tmpDir,
+                $args['zendIndex']
+            );
+        } else {
+            $resultOfConversion = $this->launchFulltext(
+                $fileNameOnTmp, 
+                $resId, 
+                $indexFileDirectory, 
+                $tmpDir
+            );
+        }
+        
+        if ($resultOfConversion['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            HistoryController::executionTimeLog(
+                $timestart, 
+                '', 
+                'debug', 
+                '[TIMER] Convert_ProcessFulltextAbstract_Service::fulltext aucunContenuAIndexer'
+            );
+            return $resultOfConversion;
+        }
+        //find the target docserver
+        $targetDs = $ManageDocservers->findTargetDs($collId, 'FULLTEXT');
+        if (empty($targetDs)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'Ds of collection and ds type not found for fulltext:' 
+                    . $collId . ' FULLTEXT',
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the result on docserver
+        $resultCopyDs = $ManageDocservers->copyResOnDS($fileNameOnTmp . '.txt', $targetDs);
+        if ($resultCopyDs['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultCopyDs;
+        }
+        //update the database
+        $resultOfUpDb = $this->updateDatabase(
+            $collId,
+            $resTable, 
+            $adrTable, 
+            $resId,
+            $targetDs,
+            $resultCopyDs['value']['destinationDir'],
+            $resultCopyDs['value']['fileDestinationName'],
+            $args['zendIndex']
+        );
+        if ($resultOfUpDb['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfUpDb;
+        }
+
+        unlink($fileNameOnTmp);
+        unlink($fileNameOnTmp . '.txt');
+
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        HistoryController::executionTimeLog(
+            $timestart, 
+            '', 
+            'debug', 
+            '[TIMER] Convert_ProcessFulltextAbstract_Service::fulltext'
+        );
+        return $returnArray;
+    }
+
+    /**
+     * Launch the fulltext process
+     *
+     * @param string $srcfile source file
+     * @param string $tgtdir target dir
+     * @param string $srcfmt source format
+     * @return array $returnArray the result
+     */
+    private function launchFulltext(
+        $srcfile, 
+        $resId,
+        $indexFileDirectory, 
+        $tgtdir=false,
+        $zendIndex=''
+    ) {
+        if (!empty($zendIndex)) {
+            $return = $this->prepareIndexFullTextPdf(
+                $srcfile, 
+                $tgtdir, 
+                $indexFileDirectory,
+                $resId,
+                $zendIndex
+            );
+        } else {
+            $return = $this->prepareIndexFullTextPdf(
+                $srcfile, 
+                $tgtdir, 
+                $indexFileDirectory,
+                $resId
+            );
+        }
+        
+        if ($return === 0) {
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } else {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $return . $output,
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+    * Read a txt file
+    * @param  $file string path of the file to read
+    * @return string contents of the file
+    */
+    private function readFileF($file)
+    {
+        $result = "";
+        if (is_file($file)) {
+            $fp = fopen($file, "r");
+            $result = fread($fp, filesize($file));
+            fclose($fp);
+        }
+        return $result;
+    }
+
+    private function prepareIndexFullTextPdf($pathToFile, $tmpDir, $indexFileDirectory, $resId, $zendIndex)
+    {
+        $timestart = microtime(true);
+        if (is_file($pathToFile)) {
+            $tmpFile = $tmpDir . basename($pathToFile) . ".txt";
+            $timestart_fulltext = microtime(true);
+            $resultExtraction = exec("pdftotext " . escapeshellarg($pathToFile)
+                    . " " . escapeshellarg($tmpFile) 
+                );
+            HistoryController::executionTimeLog($timestart_fulltext, '', 'debug', '[TIMER] Convert_ProcessFulltextAbstract_Service::prepareIndexFullTextPdf__exec');
+            
+            $fileContent = trim($this->readFileF($tmpFile));
+            
+            if (!empty($zendIndex)) {
+                $result = $this->launchIndexFullTextWithZendIndex(
+                        $fileContent, 
+                        $indexFileDirectory, 
+                        $resId, 
+                        $zendIndex
+                );
+            } else {
+                // TODO : will be done only by the batch convert in OnlyIndexes mode
+                //$result = $this->launchIndexFullText($fileContent, $indexFileDirectory, $resId);
+                $result = 0;
+            }
+            
+        } else {
+            $result = 'file not found ' . $pathToFile;
+        }
+        HistoryController::executionTimeLog(
+            $timestart, 
+            '', 
+            'debug', 
+            '[TIMER] Convert_ProcessFulltextAbstract_Service::prepareIndexFullTextPdf'
+        );
+        return $result;
+    }
+
+    /**
+    * Return zend index object for batch mode
+    * @param  $indexFileDirectory string directory of the lucene index
+    * @return zend index object
+    */
+    public function createZendIndexObject($tempIndexFileDirectory, $numberOfIndexes = 1000) 
+    {
+        //echo 'createZendIndexObject : ' . $numberOfIndexes . PHP_EOL;
+        $func = new functions();
+        $indexFileDirectory = (string) $tempIndexFileDirectory; 
+        // with version 1.12, we need a string, not an XML element
+        
+        if (!is_dir($indexFileDirectory)) {
+            $index = Zend_Search_Lucene::create($indexFileDirectory);
+        } else {
+            if ($func->isDirEmpty($indexFileDirectory)) {
+                $index = Zend_Search_Lucene::create($indexFileDirectory);
+            } else {
+                $index = Zend_Search_Lucene::open($indexFileDirectory);
+            }
+        }
+        $index->setFormatVersion(Zend_Search_Lucene::FORMAT_2_3); 
+        // we set the lucene format to 2.3
+        Zend_Search_Lucene_Analysis_Analyzer::setDefault(
+            new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
+        );
+
+        //$index->MaxBufferedDocs();
+        $index->setMaxBufferedDocs($numberOfIndexes);
+
+        return $index;
+    }
+
+    /**
+    * Commit the zend index at the end of the batch
+    * @return nothing
+    */
+    public function commitZendIndex($index) 
+    {
+        //echo 'the commit' . PHP_EOL;
+        $index->commit();
+    }
+
+    /**
+    * Retrieve the text of a pdftext and launch the lucene engine
+    * @param  $pathToFile string path of the file to index
+    * @param  $indexFileDirectory string directory of the lucene index
+    * @param  $id integer id of the document to index
+    * @return integer user exit code is stored in fulltext_result column of the
+    * document in "res_x"
+    */
+    private function launchIndexFullText($fileContent, $tempIndexFileDirectory, $Id) 
+    {
+        // $IndexFileDirectory is replace by tempIndexFileDirectory
+        $func = new functions();
+        $fileContent = $func->normalize($fileContent);
+        $fileContent = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $fileContent);
+        $indexFileDirectory = (string) $tempIndexFileDirectory; 
+        // with version 1.12, we need a string, not an XML element
+        $result = -1;
+        if (strlen($fileContent) > 2) {
+            if (!is_dir($indexFileDirectory)) {
+                //$_ENV['logger']->write($indexFileDirectory . " not exists !", "ERROR", 2);
+                $index = Zend_Search_Lucene::create($indexFileDirectory);
+            } else {
+                if ($func->isDirEmpty($indexFileDirectory)) {
+                    //$_ENV['logger']->write($indexFileDirectory . " empty !");
+                    $index = Zend_Search_Lucene::create($indexFileDirectory);
+                } else {
+                    $index = Zend_Search_Lucene::open($indexFileDirectory);
+                }
+            }
+            $index->setFormatVersion(Zend_Search_Lucene::FORMAT_2_3); 
+            // we set the lucene format to 2.3
+            Zend_Search_Lucene_Analysis_Analyzer::setDefault(
+                new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
+            );
+            // we need utf8 for accents
+            $term = new Zend_Search_Lucene_Index_Term($Id, 'Id');
+            foreach ($index->termDocs($term) as $id) {
+                $index->delete($id);
+            }
+            //echo $fileContent;
+            $doc = new Zend_Search_Lucene_Document();
+            $doc->addField(Zend_Search_Lucene_Field::UnIndexed('Id', (integer) $Id));
+            $doc->addField(Zend_Search_Lucene_Field::UnStored(
+                'contents', $fileContent)
+            );
+            //$func->show_array($doc);
+            $index->addDocument($doc);
+            $index->commit();
+            //$func->show_array($index);
+            //$index->optimize();
+            $result = 0;
+        } else {
+            $result = 1;
+        }
+        return $result;
+    }
+
+    /**
+    * Retrieve the text of a pdftext and launch the lucene engine
+    * @param  $pathToFile string path of the file to index
+    * @param  $indexFileDirectory string directory of the lucene index
+    * @param  $id integer id of the document to index
+    * @return integer user exit code is stored in fulltext_result column of the
+    * document in "res_x"
+    */
+    private function launchIndexFullTextWithZendIndex($fileContent, $tempIndexFileDirectory, $Id, $index) 
+    {
+        //echo 'launchIndexFullTextWithZendIndex' . PHP_EOL;
+        // $IndexFileDirectory is replace by tempIndexFileDirectory
+        $func = new functions();
+        $fileContent = $func->normalize($fileContent);
+        $fileContent = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $fileContent);
+
+        // with version 1.12, we need a string, not an XML element
+        $result = -1;
+        if (strlen($fileContent) > 2) {
+            try {
+                // we need utf8 for accents
+                $term = new Zend_Search_Lucene_Index_Term($Id, 'Id');
+                foreach ($index->termDocs($term) as $id) {
+                    $index->delete($id);
+                }
+                //echo $fileContent;
+                $doc = new Zend_Search_Lucene_Document();
+                $doc->addField(Zend_Search_Lucene_Field::UnIndexed('Id', (integer) $Id));
+                $doc->addField(Zend_Search_Lucene_Field::UnStored(
+                    'contents', $fileContent)
+                );
+                //$func->show_array($doc);
+                $index->addDocument($doc);
+                //$index->commit();
+                //$func->show_array($index);
+                //$index->optimize();
+                $result = 0;
+            } catch (Exception $e) {
+                $result = $e->getMessage();
+            }
+            
+        } else if (strlen($fileContent) >= 0){
+            $result = 0;
+        }
+        return $result;
+    }
+
+    /**
+     * Updating the database with the location information of the document on the
+     * new docserver
+     * @param string $collId collection
+     * @param string $resTable res table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process
+     * @param docserver $docserver docserver object
+     * @param string $path location of the resource on the docserver
+     * @param string $fileName file name of the resource on the docserver
+     * @return array $returnArray the result
+     */
+    private function updateDatabase(
+        $collId, 
+        $resTable, 
+        $adrTable, 
+        $resId,
+        $docserver,
+        $path, 
+        $fileName,
+        $zendIndex = ''
+    ) {
+        try {
+            $docserver->path_template = str_replace(
+                DIRECTORY_SEPARATOR, 
+                '#', 
+                $docserver->path_template
+            );
+            $path = str_replace($docserver->path_template, '', $path);
+            $dbConv = new \Database($GLOBALS['configFile']);
+            $query = "update convert_stack set status = 'P' where "
+               . " coll_id = ? and res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $collId,
+                    $resId
+                )
+            );
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? order by adr_priority";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "select docserver_id, path, filename, offset_doc, fingerprint"
+                       . " from " . $resTable . " where res_id = ?";
+                $stmt = $dbConv->query($query, array($resId));
+                $recordset = $stmt->fetchObject();
+                $resDocserverId = $recordset->docserver_id;
+                $resPath = $recordset->path;
+                $resFilename = $recordset->filename;
+                $resOffsetDoc = $recordset->offset_doc;
+                $fingerprintInit = $recordset->fingerprint;
+                $query = "select adr_priority_number from docservers "
+                       . " where docserver_id = ?";
+                $stmt = $dbConv->query($query, array($resDocserverId));
+                $recordset = $stmt->fetchObject();
+                $query = "insert into " . $adrTable . " (res_id, "
+                       . "docserver_id, path, filename, offset_doc, fingerprint, "
+                       . "adr_priority) values (?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $resDocserverId,
+                        $resPath,
+                        $resFilename,
+                        $resOffsetDoc,
+                        $fingerprintInit,
+                        $recordset->adr_priority_number
+                    )
+                );
+            }
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? and adr_type = 'TXT'";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "insert into " . $adrTable . " (res_id, docserver_id, "
+                   . "path, filename, offset_doc, fingerprint, adr_priority, adr_type) values (" 
+                   . "?, ?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        'TXT'
+                    )
+                );
+            } else {
+                $query = "update " . $adrTable . " set docserver_id = ?, "
+                   . " path = ?, filename = ?, offset_doc = ?, fingerprint = ?, adr_priority = ?"
+                   . " where res_id = ? and adr_type = ? ";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        $resId,
+                        'TXT'
+                    )
+                );
+            }
+            if ($_SESSION['user']['UserId'] <> '') {
+                $user = $_SESSION['user']['UserId'];
+            } else {
+                $user = 'CONVERT_BOT';
+            }
+            $query = "insert into history (table_name, record_id, "
+                   . "event_type, user_id, event_date, info, id_module) values (" 
+                   . "?, ?, 'ADD', '" . $user . "', " 
+                   . $dbConv->current_datetime() 
+                   . ", ?, 'convert')";
+            $stmt = $dbConv->query( 
+                $query, 
+                array(
+                    $resTable,
+                    $resId,
+                    "process fulltext done"
+                )
+            );
+
+            $queryCpt = "select coalesce(custom_t15, '0') as custom_t15 from " . $resTable 
+                . " where res_id = ?";
+            $stmtCpt = $dbConv->query($queryCpt, array($resId));
+            $rsCpt = $stmtCpt->fetchObject();
+            $cptFullText = $rsCpt->custom_t15 + 1;
+
+            if (!empty($zendIndex)) {
+                $query = "update " . $resTable 
+                    . " set fulltext_result = '1', is_multi_docservers = 'Y', custom_t15 = '" 
+                    . $cptFullText . "' where "
+                    . " res_id = ?";
+            } else {
+                $query = "update " . $resTable 
+                    . " set fulltext_result = '0', is_multi_docservers = 'Y', custom_t15 = '" 
+                    . $cptFullText . "' where "
+                    . " res_id = ?";
+            }
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $resId
+                )
+            );
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } catch (Exception $e) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $e->getMessage(),
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+     * Updating the database with the error code
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @param string $result error code
+     * @return nothing
+     */
+    private function manageErrorOnDb(
+        $resTable, 
+        $resId,
+        $result
+    ) {
+        $dbConv = new \Database($GLOBALS['configFile']);
+
+        $queryCpt = "select coalesce(custom_t15, '0') as custom_t15 from " . $resTable 
+                . " where res_id = ?";
+        $stmtCpt = $dbConv->query($queryCpt, array($resId));
+        $rsCpt = $stmtCpt->fetchObject();
+        $cptFullText = $rsCpt->custom_t15 + 1;
+        
+        $query = "update " . $resTable 
+            . " set fulltext_result = ?, custom_t15 = '" . $cptFullText . "' where "
+            . " res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $result,
+                $resId
+            )
+        );
+    }
+
+    public static function optimizeLuceneIndex(array $args=[]){
+        $timestart = microtime(true);
+        // Prés-requis :
+        self::checkRequired($args, ['collId']);
+        self::checkString($args, ['collId']); 
+        
+        $collId = $args['collId'];
+
+        $countColl = count($_SESSION['collections']);
+        for ($i=0;$i<$countColl;$i++) {
+            if ($_SESSION['collections'][$i]['id'] == $collId) {
+                $path_to_lucene = $_SESSION['collections'][$i]['path_to_lucene_index'];
+            }
+        }
+
+        if(!empty($path_to_lucene)){
+            exec(
+                'php '.$_SESSION['config']['corepath'] . 
+                'modules/convert/optimizeLuceneIndex.php ' . 
+                $path_to_lucene . ' ' . 
+                $_SESSION['config']['corepath'] . ' > /dev/null 2>&1 &'
+            );
+        }
+        HistoryController::executionTimeLog(
+            $timestart, 
+            '', 
+            'debug', 
+            '[TIMER] Convert_ProcessFulltextAbstract_Service::optimizeLuceneIndex'
+        );
+
+        return true;
+    }
+
+}
diff --git a/modules/convert/Models/ProcessConvertModel.php b/modules/convert/Models/ProcessConvertModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..e8abb657f83f02783a37bff000f090aaea728a6a
--- /dev/null
+++ b/modules/convert/Models/ProcessConvertModel.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief Process Convert Model
+* @author dev@maarch.org
+* @ingroup convert
+*/
+
+namespace Convert\Models;
+
+class ProcessConvertModel extends ProcessConvertModelAbstract
+{
+    // Do your stuff in this class
+}
diff --git a/modules/convert/Models/ProcessConvertModelAbstract.php b/modules/convert/Models/ProcessConvertModelAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7612a59fe6b6d2afd32bf3a5c98331ad998e986
--- /dev/null
+++ b/modules/convert/Models/ProcessConvertModelAbstract.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief ProcessConvert Model
+* @author dev@maarch.org
+* @ingroup convert
+*/
+
+namespace Convert\Models;
+
+class ProcessConverttextModelAbstract
+{
+    public static function getById(array $aArgs = [])
+    {
+        ValidatorModel::notEmpty($aArgs, ['resId']);
+        ValidatorModel::intVal($aArgs, ['resId']);
+
+        $aReturn = DatabaseModel::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['res_letterbox'],
+            'where'     => ['res_id = ?'],
+            'data'      => [$aArgs['resId']]
+        ]);
+
+        if (empty($aReturn[0])) {
+            return [];
+        }
+
+        return $aReturn[0];
+    }
+}
diff --git a/modules/convert/Models/ProcessFulltextModel.php b/modules/convert/Models/ProcessFulltextModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce546d414fe74e3225d65f93554701f3ccb4ef9b
--- /dev/null
+++ b/modules/convert/Models/ProcessFulltextModel.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief Process Fulltext Model
+* @author dev@maarch.org
+* @ingroup convert
+*/
+
+namespace Convert\Models;
+
+class ProcessFulltextModel extends ProcessFulltextModelAbstract
+{
+    // Do your stuff in this class
+}
diff --git a/modules/convert/Models/ProcessFulltextModelAbstract.php b/modules/convert/Models/ProcessFulltextModelAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..61c3af97fb8dc8e3b226a255b85dde416cd7c45d
--- /dev/null
+++ b/modules/convert/Models/ProcessFulltextModelAbstract.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief ProcessFulltext Model
+* @author dev@maarch.org
+* @ingroup convert
+*/
+
+namespace Convert\Models;
+
+class ProcessFulltextModelAbstract
+{
+    public static function getById(array $aArgs = [])
+    {
+        ValidatorModel::notEmpty($aArgs, ['resId']);
+        ValidatorModel::intVal($aArgs, ['resId']);
+
+        $aReturn = DatabaseModel::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['res_letterbox'],
+            'where'     => ['res_id = ?'],
+            'data'      => [$aArgs['resId']]
+        ]);
+
+        if (empty($aReturn[0])) {
+            return [];
+        }
+
+        return $aReturn[0];
+    }
+}
diff --git a/modules/convert/Test/ProcessConvertTest.php b/modules/convert/Test/ProcessConvertTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac409db3a46dbe2b14b01091496362d4f6dd0a3d
--- /dev/null
+++ b/modules/convert/Test/ProcessConvertTest.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+namespace MaarchTest;
+use PHPUnit\Framework\TestCase;
+use MaarchTest\DocserverControllerTest;
+
+class ProcessConvertTest extends TestCase
+{
+    public function testconvert ()
+    {
+        $action = new \Convert\Controllers\ProcessConvertController();
+
+        $aArgs = [
+            'collId' => 'letterbox_coll', 
+            'resTable' => 'res_letterbox', 
+            'adrTable' => 'adr_x', 
+            'resId' => 100, 
+            'tmpDir' => $_SESSION['config']['tmppath']
+        ];
+
+        $response = $action->convert($aArgs);
+        var_dump($response);
+
+        $this->assertArrayHasKey('status', $response);
+    }
+}
diff --git a/modules/convert/Test/ProcessFulltextTest.php b/modules/convert/Test/ProcessFulltextTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..74dd04e2e407fbfb8a8251f347d7c881281e8f1f
--- /dev/null
+++ b/modules/convert/Test/ProcessFulltextTest.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+namespace MaarchTest;
+use PHPUnit\Framework\TestCase;
+use MaarchTest\DocserverControllerTest;
+
+class ProcessFulltextTest extends TestCase
+{
+
+    public function testfulltext ()
+    {
+        $action = new \Convert\Controllers\ProcessFulltextController();
+
+        $aArgs = [
+            'collId' => 'letterbox_coll', 
+            'resTable' => 'res_letterbox', 
+            'adrTable' => 'adr_x', 
+            'resId' => 100,
+            'tmpDir' => $_SESSION['config']['tmppath']
+        ];
+
+        $response = $action->fulltext($aArgs);
+
+        $this->assertArrayHasKey('status', $response);
+    }
+}
diff --git a/modules/convert/ajax_convert.php b/modules/convert/ajax_convert.php
new file mode 100644
index 0000000000000000000000000000000000000000..c6975a255fb10bca08b644b62e708e33f6657704
--- /dev/null
+++ b/modules/convert/ajax_convert.php
@@ -0,0 +1,35 @@
+<?php
+
+// sample for attachments in allMode :
+// http://urltomaarch/apps/maarch_entreprise/index.php?page=ajax_convert&module=convert&id=1&collId=attachments_coll
+
+$func = new functions();
+
+for ($i=0;$i<count($_SESSION['collections']);$i++) {
+    if ($_SESSION['collections'][$i]['id'] == $_REQUEST['collId']) {
+        $resTable = $_SESSION['collections'][$i]['table'];
+        $adrTable = $_SESSION['collections'][$i]['adr'];
+    }
+}
+
+// echo $_REQUEST['collId'] . '<br />';
+// echo $resTable . PHP_EOL . '<br />';
+// echo $adrTable . PHP_EOL . '<br />';
+// echo $_REQUEST['id'] . PHP_EOL . '<br />';
+
+$params = array(
+    'collId' => $_REQUEST['collId'], 
+    'resTable' => $resTable, 
+    'adrTable' => $adrTable, 
+    'resId' => $_REQUEST['id'],
+    'tmpDir' => $_SESSION['config']['tmppath']
+);
+
+require_once 'core/services/ManageDocservers.php';
+$ManageDocservers = new Core_ManageDocservers_Service();
+
+require_once 'modules/convert/services/ManageConvert.php';
+$ManageConvertService = new Convert_ManageConvert_Service();
+$resultOfConversion = $ManageConvertService->convertAll($params);
+
+//var_dump($resultOfConversion);
diff --git a/modules/convert/batch/LoggerLog4php.php b/modules/convert/batch/LoggerLog4php.php
new file mode 100644
index 0000000000000000000000000000000000000000..5859a92f31f19d495f57e40a68d2ac6f65cda317
--- /dev/null
+++ b/modules/convert/batch/LoggerLog4php.php
@@ -0,0 +1,314 @@
+<?php
+
+/** Logger class
+ *
+ * @author Laurent Giovannoni <dev@maarch.org>
+ **/
+
+class Logger4Php
+{
+
+    /**
+     * Array of errors levels
+     *
+     * @protected
+     **/
+    protected $error_levels = array('DEBUG' => 0, 'INFO' => 1, 'NOTICE' => 2, 'WARNING' => 3, 'ERROR' => 4);
+
+    /**
+     * Maps each handler with its log threshold.
+     *
+     * @protected
+     **/
+    protected $mapping;
+
+    /**
+     * Minimum log level
+     *
+     * @protected
+     **/
+    protected $threshold_level;
+
+    /**
+     * Path to log4Php library
+     *
+     * @protected
+     **/
+    protected $log4PhpLibrary;
+
+    /**
+     * Name of the logger
+     *
+     * @protected
+     **/
+    protected $log4PhpLogger;
+
+    /**
+     * Name of the business code
+     *
+     * @protected
+     **/
+    protected $log4PhpBusinessCode;
+
+    /**
+     * Path of the param of log4php
+     *
+     * @protected
+     **/
+    protected $log4PhpConfigPath;
+
+    /**
+     * Name of the batch
+     *
+     * @protected
+     **/
+    protected $log4PhpBatchName;
+
+    /** Class constructor
+     *
+     * Inits the threshold level
+     *
+     * @param $threshold_level (string) Threshold level (set to 'INFO' by default)
+     **/
+    function __construct($threshold_level = 'WARNING')
+    {
+        $this->threshold_level = $threshold_level;
+        $this->mapping = array_fill(0, count($this->error_levels), array());
+    }
+
+    /** Writes error message in current handlers
+     *
+     * writes only if the error level is greater or equal the threshold level
+     *
+     * @param $msg (string) Error message
+     * @param $error_level (string) Error level (set to 'INFO' by default)
+     * @param $error_code (integer) Error code (set to 0 by default)
+     **/
+    public function write($msg, $error_level = 'INFO', $error_code = 0, $other_params = array())
+    {
+        if (!array_key_exists($error_level, $this->error_levels)) {
+            $error_level = 'INFO';
+        }
+        $foundLogger = false;
+        if ($this->error_levels[$error_level] >= $this->error_levels[$this->threshold_level]) {
+            for ($i=$this->error_levels[$error_level];$i>=0;$i--) {
+                foreach ($this->mapping[$i] as $handler) {
+                    $handler->write($msg, $error_level, $error_code, $other_params);
+                    if (
+                        get_class($handler) == 'FileHandler'
+                        && (isset($this->log4PhpLibrary)
+                        && !empty($this->log4PhpLibrary))
+                    ) {
+                        if ($error_code == 0) {
+                            $result = 'OK';
+                        } else {
+                            $result = 'KO';
+                            $msg = '%error_code:' . $error_code . '% ' . $msg;
+                        }
+                        require_once($this->log4PhpLibrary);
+                        $remote_ip = '127.0.0.1';
+                        Logger::configure($this->log4PhpConfigPath);
+                        $logger = Logger::getLogger($this->log4PhpLogger);
+                        $searchPatterns = array('%ACCESS_METHOD%',
+                            '%RESULT%',
+                            '%BUSINESS_CODE%',
+                            '%HOW%',
+                            '%WHAT%',
+                            '%REMOTE_IP%',
+                            '%BATCH_NAME%'
+                        );
+                        $replacePatterns = array('Script',
+                            $result,
+                            $this->log4PhpBusinessCode,
+                            'UP',
+                            $msg,
+                            $remote_ip,
+                            $this->log4PhpBatchName
+                        );
+                        $logLine = str_replace($searchPatterns,
+                            $replacePatterns,
+                            '[%ACCESS_METHOD%][%RESULT%]'
+                            . '[%BUSINESS_CODE%][%HOW%][%WHAT%][%BATCH_NAME%]'
+                        );
+                        $this->writeLog4php($logger, $logLine, $error_level);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *
+     * write a log entry with a specific log level
+     * @param object $logger Log4php logger
+     * @param string $logLine Line we want to trace
+     * @param enum $level Log level
+     */
+    function writeLog4php($logger, $logLine, $level) {
+        switch ($level) {
+            case 'DEBUG':
+                $logger->debug($logLine);
+                break;
+            case 'INFO':
+                $logger->info($logLine);
+                break;
+            case 'WARNING':
+                $logger->warn($logLine);
+                break;
+            case 'ERROR':
+                $logger->error($logLine);
+                break;
+            case 'FATAL':
+                $logger->fatal($logLine);
+                break;
+        }
+    }
+
+    /** Adds a new handler in the current handlers array
+     *
+     * @param $handler (object) Handler object
+     **/
+    public function add_handler(&$handler, $error_level = NULL)
+    {
+        if(!isset($handler))
+            return false;
+
+        if(!isset($error_level) || !array_key_exists($error_level, $this->error_levels))
+        {
+            $error_level = $this->threshold_level;
+        }
+
+        $this->mapping[$this->error_levels[$error_level]][] = $handler;
+        return true;
+    }
+
+    /** Adds a new handler in the current handlers array
+     *
+     * @param $handler (object) Handler object
+     **/
+    public function change_handler_log_level(&$handler, $log_level )
+    {
+        if (!isset($handler) || !isset($log_level))
+            return false;
+
+        if (!array_key_exists($log_level, $this->error_levels)) {
+           return false;
+        }
+
+        for ($i=0; $i<count($this->mapping);$i++) {
+            for($j=0;$j<count($this->mapping[$i]);$j++) {
+                if($handler == $this->mapping[$i][$j]) {
+                    unset($this->mapping[$i][$j]);
+                }
+            }
+        }
+        $this->mapping = array_values($this->mapping);
+        $this->mapping[$this->error_levels[$log_level]][] = $handler;
+        return true;
+    }
+
+    /** Sets treshold level
+     *
+     * @param $treshold (string) treshold level
+     **/
+    public function set_threshold_level($treshold)
+    {
+        if (isset($treshold) && array_key_exists($treshold, $this->error_levels)) {
+            $this->threshold_level = $treshold;
+            return true;
+        }
+        $this->threshold_level = 'WARNING';
+        return false;
+    }
+
+    /** Sets log4Php library path
+     *
+     * @param $log4PhpLibrary (string) path
+     **/
+    public function set_log4PhpLibrary($log4PhpLibrary)
+    {
+        if (isset($log4PhpLibrary) && !empty($log4PhpLibrary)) {
+            if (file_exists($log4PhpLibrary)) {
+                $this->log4PhpLibrary = $log4PhpLibrary;
+                return true;
+            } else {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /** Sets log4php logger name
+     *
+     * @param $log4PhpLogger (string) logger name
+     **/
+    public function set_log4PhpLogger($log4PhpLogger)
+    {
+        if (isset($log4PhpLogger) && !empty($log4PhpLogger)) {
+            $this->log4PhpLogger = $log4PhpLogger;
+            return true;
+        }
+        $this->log4PhpLogger = 'loggerTechnique';
+        return false;
+    }
+
+    /** Sets log4php path to log4php xml config
+     *
+     * @param $log4PhpPath (string) path to log4php xml config
+     **/
+    public function set_log4PhpConfigPath($log4PhpConfigPath)
+    {
+        if (isset($log4PhpConfigPath) && !empty($log4PhpConfigPath)) {
+            if (file_exists($log4PhpConfigPath)) {
+                $this->log4PhpConfigPath = $log4PhpConfigPath;
+                return true;
+            } else {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /** Sets log4php business code
+     *
+     * @param $log4PhpBusinessCode (string) business code
+     **/
+    public function set_log4PhpBusinessCode($log4PhpBusinessCode)
+    {
+        if (isset($log4PhpBusinessCode) && !empty($log4PhpBusinessCode)) {
+            $this->log4PhpBusinessCode = $log4PhpBusinessCode;
+            return true;
+        }
+        $this->log4PhpBusinessCode = 'Maarch';
+        return false;
+    }
+
+    /** Sets log4php batch name
+     *
+     * @param $log4PhpBatchName (string) BatchName
+     **/
+    public function set_log4PhpBatchName($log4PhpBatchName)
+    {
+        if (isset($log4PhpBatchName) && !empty($log4PhpBatchName)) {
+            $this->log4PhpBatchName = $log4PhpBatchName;
+            return true;
+        }
+        $this->log4PhpBatchName = 'MaarchBatch';
+        return false;
+    }
+
+    /** Class destructor
+     *
+     * Calls handlers destructors
+     **/
+    function __destruct()
+    {
+        for($i=0; $i<count($this->mapping);$i++)
+        {
+            foreach($this->mapping[$i] as $handler)
+            {
+                unset($handler);
+            }
+        }
+    }
+}
diff --git a/modules/convert/batch/batch_tools.php b/modules/convert/batch/batch_tools.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5abba1c524f9a67cff99270dd296dd954e49983
--- /dev/null
+++ b/modules/convert/batch/batch_tools.php
@@ -0,0 +1,303 @@
+<?php
+
+/*
+ *   Copyright 2008-2016 Maarch
+ *
+ *   This file is part of Maarch Framework.
+ *
+ *   Maarch Framework is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Maarch Framework is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Maarch Framework. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @brief API to manage batchs
+ *
+ * @file
+ * @author Laurent Giovannoni
+ * @date $date$
+ * @version $Revision$
+ * @ingroup convert
+ */
+
+/**
+ * Execute a sql query
+ *
+ * @param object $dbConn connection object to the database
+ * @param string $queryTxt path of the file to include
+ * @param boolean $transaction for rollback if error
+ * @return true if ok, exit if ko and rollback if necessary
+ */
+function Bt_doQuery($dbConn, $queryTxt, $param=array(), $transaction=false)
+{
+    if (count($param) > 0) {
+        $stmt = $dbConn->query($queryTxt, $param);
+    } else {
+        $stmt = $dbConn->query($queryTxt);
+    }
+    if (!$stmt) {
+        if ($transaction) {
+            $GLOBALS['logger']->write('ROLLBACK', 'INFO');
+            $dbConn->query('ROLLBACK');
+        }
+        $GLOBALS['logger']->write('SQL query error:' . $queryTxt, 'WARNING');
+    }
+    $GLOBALS['logger']->write('SQL query:' . $queryTxt, 'DEBUG');
+    return $stmt;
+}
+
+/**
+ * Exit the batch with a return code, message in the log and
+ * in the database if necessary
+ *
+ * @param int $returnCode code to exit (if > O error)
+ * @param string $message message to the log and the DB
+ * @return nothing, exit the program
+ */
+function Bt_exitBatch($returnCode, $message='', $logLevel='')
+{
+    if (file_exists($GLOBALS['lckFile'])) {
+        unlink($GLOBALS['lckFile']);
+    }
+    if ($returnCode > 0) {
+        $GLOBALS['totalProcessedResources']--;
+        if ($GLOBALS['totalProcessedResources'] == -1) {
+            $GLOBALS['totalProcessedResources'] = 0;
+        }
+        if($returnCode < 100) {
+            if (file_exists($GLOBALS['errorLckFile'])) {
+                unlink($GLOBALS['errorLckFile']);
+            }
+            $semaphore = fopen($GLOBALS['errorLckFile'], "a");
+            fwrite($semaphore, '1');
+            fclose($semaphore);
+        }
+        if($logLevel == 'WARNING'){
+            $GLOBALS['logger']->write($message, 'WARNING', $returnCode);
+        } else {
+            $GLOBALS['logger']->write($message, 'ERROR', $returnCode);
+        }
+        Bt_logInDataBase($GLOBALS['totalProcessedResources'], 1, 'return code:'
+                         . $returnCode . ', ' . $message);
+    } elseif ($message <> '') {
+        $GLOBALS['logger']->write($message, 'INFO', $returnCode);
+        Bt_logInDataBase($GLOBALS['totalProcessedResources'], 0, 'return code:'
+                         . $returnCode . ', ' . $message);
+    }
+
+    $query = "delete from convert_stack "
+                   . " where coll_id = ? ";
+    $stmt = Bt_doQuery(
+        $GLOBALS['db'], 
+        $query,
+        array(
+            $GLOBALS['collection']
+        )
+    );
+    
+    exit($returnCode);
+}
+
+/**
+* Insert in the database the report of the batch
+* @param long $totalProcessed total of resources processed in the batch
+* @param long $totalErrors total of errors in the batch
+* @param string $info message in db
+*/
+function Bt_logInDataBase($totalProcessed=0, $totalErrors=0, $info='')
+{
+    $query = "insert into history_batch(module_name, batch_id, event_date, "
+           . "total_processed, total_errors, info) values(?, ?, "
+           . $GLOBALS['db']->current_datetime() . ", ?, ?, ?)";
+    $stmt = $GLOBALS['dbLog']->query(
+        $query, 
+        array(
+            $GLOBALS['batchName'],
+            $GLOBALS['wb'],
+            $totalProcessed,
+            $totalErrors,
+            substr(str_replace('\\', '\\\\', str_replace("'", "`", $info)), 0, 999)
+        )
+    );
+}
+
+/**
+ * Get the batch if of the batch
+ *
+ * @return nothing
+ */
+function Bt_getWorkBatch()
+{
+    $req = "select param_value_int from parameters where id = ?";
+    $stmt = $GLOBALS['db']->query($req, array($GLOBALS['batchName'] . "_id"));
+    while ($reqResult = $stmt->fetchObject()) {
+        $GLOBALS['wbCompute'] = $reqResult->param_value_int + 1;
+    }
+    if ($GLOBALS['wbCompute'] == '') {
+        $req = "insert into parameters(id, param_value_int) values "
+             . "(?, 1)";
+        $stmt = $GLOBALS['db']->query($req, array($GLOBALS['batchName'] . "_id"));
+        $GLOBALS['wbCompute'] = 1;
+    }
+}
+
+/**
+ * Update the database with the new batch id of the batch
+ *
+ * @return nothing
+ */
+function Bt_updateWorkBatch()
+{
+    $req = "update parameters set param_value_int = ? where id = ?";
+    $stmt = $GLOBALS['db']->query($req, array($GLOBALS['wbCompute'], $GLOBALS['batchName'] . "_id"));
+}
+
+/**
+ * Include the file requested if exists
+ *
+ * @param string $file path of the file to include
+ * @return nothing
+ */
+function Bt_myInclude($file)
+{
+    if (file_exists($file)) {
+        include_once ($file);
+    } else {
+        throw new IncludeFileError($file);
+    }
+}
+
+/**
+ * Get the current date to process
+ *
+ * @return nothing
+ */
+function Bt_getCurrentDateToProcess()
+{
+    $req = "select param_value_date from parameters where id = ?";
+    $stmt = $GLOBALS['db']->query(
+        $req, 
+        array(
+            $GLOBALS['batchName'] . "_" . $GLOBALS['collection'] . "_current_date"
+        )
+    );
+    $reqResult = $stmt->fetchObject();
+    if ($reqResult->param_value_date == '') {
+        $req = "insert into parameters(id, param_value_date) values (?, ?)";
+        $stmt = $GLOBALS['db']->query(
+            $req, 
+            array(
+                $GLOBALS['batchName'] . "_" . $GLOBALS['collection'] . "_current_date",
+                $GLOBALS['startDateRecovery']
+            )
+        );
+        $GLOBALS['currentDate'] = $GLOBALS['startDateRecovery'];
+    } else {
+        $resultDate = formatDateFromDb($reqResult->param_value_date);
+        if (
+            $GLOBALS['func']->compare_date(
+                $GLOBALS['startDateRecovery'], 
+                $resultDate
+            ) == 'date1'
+        ) {
+            $GLOBALS['currentDate'] = $GLOBALS['startDateRecovery'];
+        } else {
+            $GLOBALS['currentDate'] = $resultDate;
+        }
+    }
+}
+
+/**
+ * Update the database with the current date to process
+ *
+ * @return nothing
+ */
+function Bt_updateCurrentDateToProcess()
+{
+    $req = "update parameters set param_value_date  = ? where id = ?";
+    $stmt = $GLOBALS['db']->query(
+        $req,
+        array(
+            $GLOBALS['currentDate'], 
+            $GLOBALS['batchName'] . "_" . $GLOBALS['collection'] . "_current_date"
+        )
+    );
+}
+
+/**
+ * Compute the end current date to process
+ *
+ * @return nothing
+ */
+function Bt_getEndCurrentDateToProcess()
+{
+    $dateArray = array();
+    $tabDate = explode('/' , $GLOBALS['currentDate']);
+    $theDate  = $tabDate[2] . '-' . $tabDate[1] . '-' . $tabDate[0];
+    $dateArray = date_parse($theDate);
+    $GLOBALS['endCurrentDate'] = strftime(
+        "%d/%m/%Y", mktime(0, 0, 0, $dateArray['month'] +1 , 0, $dateArray['year'])
+    );
+}
+
+/**
+ * Compute the next month currentDate
+ *
+ * @return nothing
+ */
+function Bt_computeNextMonthCurrentDate()
+{
+    $tabDate = array();
+    $tabDate = explode('/' , $GLOBALS['currentDate']);
+    $theDate = $tabDate[2] . '-' . $tabDate[1] . '-' . $tabDate[0];
+    $GLOBALS['currentDate'] = date("d/m/Y", strtotime('+1 month', strtotime($theDate)));
+    Bt_getEndCurrentDateToProcess();
+}
+
+/**
+ * Compute the creation date clause
+ *
+ * @return nothing
+ */
+function Bt_computeCreationDateClause()
+{
+    $GLOBALS['creationDateClause'] = '';
+    if ($GLOBALS['currentDate'] <> '') {
+        $GLOBALS['creationDateClause'] = " and (creation_date >= '" . $GLOBALS['currentDate'] . "'";
+        if ($GLOBALS['endCurrentDate'] <> '') {
+            $GLOBALS['creationDateClause'] .= " and creation_date <= '" . $GLOBALS['endCurrentDate'] . "'";
+        }
+        $GLOBALS['creationDateClause'] .= ")";
+    }
+}
+
+/**
+* Formats a datetime to a dd/mm/yyyy format (date)
+*
+* @param    $date datetime The date to format
+* @return   datetime The formated date
+*/
+function formatDateFromDb($date)
+{
+    $lastDate = '';
+    if ($date <> "") {
+        if (strpos($date," ")) {
+            $date_ex = explode(" ",$date);
+            $theDate = explode("-",$date_ex[0]);
+            $lastDate = $theDate[0] . "/" . $theDate[1] . "/" . $theDate[2];
+        } else {
+            $theDate = explode("-",$date);
+            $lastDate = $theDate[0] . "/" . $theDate[1] . "/" . $theDate[2];
+        }
+    }
+    return $lastDate;
+}
diff --git a/modules/convert/batch/config/config.xml b/modules/convert/batch/config/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3416184920d9818d1da2acc25142cd0abe50518e
--- /dev/null
+++ b/modules/convert/batch/config/config.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/oem_V2/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/oem_V2/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>50</StackSizeLimit>
+        <ApacheUserAndGroup>lgi:lgi</ApacheUserAndGroup>
+        <UnoconvPath>unoconv</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>soffice</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>false</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>sipol_v2</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/letterbox_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/attachments_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_version_coll</Id>
+        <Table>res_version_attachments</Table>
+        <View>res_version_attachments</View>
+        <Adr>adr_attachments_version</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/attachments_version_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>calendar_coll</Id>
+        <Table>calendar_event_attachments</Table>
+        <View>calendar_event_attachments</View>
+        <Adr>calendar_event_adr_attachments</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/calendar_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>folder_coll</Id>
+        <Table>res_folder</Table>
+        <View>res_folder</View>
+        <Adr>adr_folder</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/folder_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>chrono_coll</Id>
+        <Table>res_chrono</Table>
+        <View>res_chrono</View>
+        <Adr>adr_chrono</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/chrono_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>reprise_coll</Id>
+        <Table>res_reprise</Table>
+        <View>res_reprise</View>
+        <Adr>adr_reprise</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/reprise_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/oem_V2/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/config.xml.default b/modules/convert/batch/config/config.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..fd5098bec5f8b7b968d3efaba22db21ca6326aa2
--- /dev/null
+++ b/modules/convert/batch/config/config.xml.default
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>100</StackSizeLimit>
+        <ApacheUserAndGroup>www-data:www-data</ApacheUserAndGroup>
+        <UnoconvPath>C:\xampp\htdocs\unoconv\</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>C:\Program Files\OpenOffice.org 4\program\</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>false</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_oem</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/config_only_convert.xml b/modules/convert/batch/config/config_only_convert.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0025d92aa56006c24aa02876b1ce9b36fc7fa5f2
--- /dev/null
+++ b/modules/convert/batch/config/config_only_convert.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/oem_V2/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/oem_V2/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>1000</StackSizeLimit>
+        <ApacheUserAndGroup>lgi:lgi</ApacheUserAndGroup>
+        <UnoconvPath>unoconv</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>soffice</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>false</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+        <OnlyIndexes>false</OnlyIndexes>
+        <ProcessIndexesSize>50</ProcessIndexesSize>
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>sipol_v2</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/letterbox_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_attachments</View>
+        <Adr>adr_attachments</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/attachments_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_version_coll</Id>
+        <Table>res_version_attachments</Table>
+        <View>res_version_attachments</View>
+        <Adr>adr_attachments_version</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/attachments_version_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>calendar_coll</Id>
+        <Table>calendar_event_attachments</Table>
+        <View>calendar_event_attachments</View>
+        <Adr>calendar_event_adr_attachments</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/calendar_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>folder_coll</Id>
+        <Table>res_folder</Table>
+        <View>res_folder</View>
+        <Adr>adr_folder</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/folder_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>chrono_coll</Id>
+        <Table>res_chrono</Table>
+        <View>res_chrono</View>
+        <Adr>adr_chrono</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/chrono_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>reprise_coll</Id>
+        <Table>res_reprise</Table>
+        <View>res_reprise</View>
+        <Adr>adr_reprise</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/reprise_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/oem_V2/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/config_only_indexes.xml b/modules/convert/batch/config/config_only_indexes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..edf18cd3b20eac3ad27e50ef579c7bfad3180f4c
--- /dev/null
+++ b/modules/convert/batch/config/config_only_indexes.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/oem_V2/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/oem_V2/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>1000</StackSizeLimit>
+        <ApacheUserAndGroup>lgi:lgi</ApacheUserAndGroup>
+        <UnoconvPath>unoconv</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>soffice</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>false</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+        <OnlyIndexes>true</OnlyIndexes>
+        <ProcessIndexesSize>50</ProcessIndexesSize>
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>sipol_v2</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/letterbox_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_attachments</View>
+        <Adr>adr_attachments</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/attachments_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_version_coll</Id>
+        <Table>res_version_attachments</Table>
+        <View>res_version_attachments</View>
+        <Adr>adr_attachments_version</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/attachments_version_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>calendar_coll</Id>
+        <Table>calendar_event_attachments</Table>
+        <View>calendar_event_attachments</View>
+        <Adr>calendar_event_adr_attachments</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/calendar_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>folder_coll</Id>
+        <Table>res_folder</Table>
+        <View>res_folder</View>
+        <Adr>adr_folder</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/folder_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>chrono_coll</Id>
+        <Table>res_chrono</Table>
+        <View>res_chrono</View>
+        <Adr>adr_chrono</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/chrono_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>reprise_coll</Id>
+        <Table>res_reprise</Table>
+        <View>res_reprise</View>
+        <Adr>adr_reprise</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/reprise_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/oem_V2/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/config_reprise_oem.xml.default b/modules/convert/batch/config/config_reprise_oem.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..afc01e3555a31ff866c91149dbdcc9b638f35bc3
--- /dev/null
+++ b/modules/convert/batch/config/config_reprise_oem.xml.default
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>50</StackSizeLimit>
+        <ApacheUserAndGroup>maarch:maarch</ApacheUserAndGroup>
+        <UnoconvPath>unoconv</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>soffice</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>false</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_dev</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>reprise_coll</Id>
+        <Table>res_reprise</Table>
+        <View>res_reprise</View>
+        <Adr>adr_reprise</Adr>
+        <path_to_lucene_index>/opt/maarch/docservers/indexes/reprise_coll/</path_to_lucene_index>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>false</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/parallel/config_0.xml.default b/modules/convert/batch/config/parallel/config_0.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..ee8a91e98a81a21eb176c685008772fce77422a0
--- /dev/null
+++ b/modules/convert/batch/config/parallel/config_0.xml.default
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>100</StackSizeLimit>
+        <ApacheUserAndGroup>www-data:www-data</ApacheUserAndGroup>
+        <UnoconvPath>C:\xampp\htdocs\unoconv\</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>C:\Program Files\OpenOffice.org 4\program\</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>(0|1)$</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_oem</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/parallel/config_1.xml.default b/modules/convert/batch/config/parallel/config_1.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..6c554dced9053e5eb3781034c2f1bbd88719d99e
--- /dev/null
+++ b/modules/convert/batch/config/parallel/config_1.xml.default
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>100</StackSizeLimit>
+        <ApacheUserAndGroup>www-data:www-data</ApacheUserAndGroup>
+        <UnoconvPath>C:\xampp\htdocs\unoconv\</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>C:\Program Files\OpenOffice.org 4\program\</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>(2|3)$</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_oem</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/parallel/config_2.xml.default b/modules/convert/batch/config/parallel/config_2.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..6f13ac4dd5d2a30cc5a734d5df07bfc5ea08b9e9
--- /dev/null
+++ b/modules/convert/batch/config/parallel/config_2.xml.default
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>100</StackSizeLimit>
+        <ApacheUserAndGroup>www-data:www-data</ApacheUserAndGroup>
+        <UnoconvPath>C:\xampp\htdocs\unoconv\</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>C:\Program Files\OpenOffice.org 4\program\</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>(4|5)$</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_oem</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/parallel/config_3.xml.default b/modules/convert/batch/config/parallel/config_3.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..ae050eb47b267c3207e2017ca58c198239bd503d
--- /dev/null
+++ b/modules/convert/batch/config/parallel/config_3.xml.default
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>100</StackSizeLimit>
+        <ApacheUserAndGroup>www-data:www-data</ApacheUserAndGroup>
+        <UnoconvPath>C:\xampp\htdocs\unoconv\</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>C:\Program Files\OpenOffice.org 4\program\</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>(6|7)$</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_oem</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/config/parallel/config_4.xml.default b/modules/convert/batch/config/parallel/config_4.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..7dc4b7d8ab61851d74ca23727ad5fe8e97993c20
--- /dev/null
+++ b/modules/convert/batch/config/parallel/config_4.xml.default
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/maarch_oem/</MaarchDirectory>
+        <TmpDirectory>/var/www/html/maarch_oem/modules/convert/batch/tmp/</TmpDirectory>
+        <LogLevel>INFO</LogLevel>  <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <StackSizeLimit>100</StackSizeLimit>
+        <ApacheUserAndGroup>www-data:www-data</ApacheUserAndGroup>
+        <UnoconvPath>C:\xampp\htdocs\unoconv\</UnoconvPath> <!-- only for Windows -->
+        <OpenOfficePath>C:\Program Files\OpenOffice.org 4\program\</OpenOfficePath> <!-- only for Windows -->
+        <UnoconvOptions>--port 8100</UnoconvOptions>
+        <RegExResId>(8|9)$</RegExResId>
+        <StartDateRecovery>false</StartDateRecovery> <!-- false or date dd/mm/yyyy -->
+        <CurrentMonthOnly>false</CurrentMonthOnly> <!-- true or false -->
+    </CONFIG>
+    <CONVERT>
+        <OutputFormat>pdf</OutputFormat>
+        <InputFormat>odt,ott,odm,html,oth,ods,ots,odg,otg,odp,otp,odf,doc,docx,xls,xlsx,ppt,pptx,tiff,tif,png,jpeg,jpg,gif</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>html</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONVERT>
+        <OutputFormat>png</OutputFormat>
+        <InputFormat>odt,ods,doc,docx,xls,xlsx,ppt,pptx</InputFormat>
+    </CONVERT>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>maarch_oem</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <COLLECTION>
+        <Id>letterbox_coll</Id>
+        <Table>res_letterbox</Table>
+        <View>res_view_letterbox</View>
+        <Adr>adr_letterbox</Adr>
+    </COLLECTION>
+    <COLLECTION>
+        <Id>attachments_coll</Id>
+        <Table>res_attachments</Table>
+        <View>res_view_attachments</View>
+        <Adr>adr_attachments</Adr>
+    </COLLECTION>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>Convert</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/maarch_oem/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/convert/batch/fill_stack.php b/modules/convert/batch/fill_stack.php
new file mode 100644
index 0000000000000000000000000000000000000000..47ebbe5f654a6669d3cc06aa71b0f505f4a2fb06
--- /dev/null
+++ b/modules/convert/batch/fill_stack.php
@@ -0,0 +1,252 @@
+<?php
+
+/*
+ *   Copyright 2008-2016 Maarch
+ *
+ *   This file is part of Maarch Framework.
+ *
+ *   Maarch Framework is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Maarch Framework is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Maarch Framework. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @brief Batch to convert
+ *
+ * @file
+ * @author  Laurent Giovannoni  <dev@maarch.org>
+ * @date $date$
+ * @version $Revision$
+ * @ingroup convert
+ */
+
+/**
+ * *****   LIGHT PROBLEMS without an error semaphore
+ *  101 : Configuration file missing
+ *  102 : Configuration file does not exist
+ *  103 : Error on loading config file
+ *  104 : SQL Query Error
+ *  105 : a parameter is missin
+ *  106 : Maarch_CLITools is missing
+ *  107 : Stack full for the policy and the cycle requested
+ *  108 : Problem with the php include path
+ *  109 : An instance of the batch for the required policy and cyle is already
+ *        in progress
+ *  110 : Problem with collection parameter
+ *  111 : No resource found
+ * ****   HEAVY PROBLEMS with an error semaphore
+ *  11  : Cycle not found
+ *  12  : Previous cycle not found
+ *  13  : Error persists
+ *  14  : Cycle step not found
+ */
+
+date_default_timezone_set('Europe/Paris');
+// load the config and prepare to process
+include('load_fill_stack.php');
+
+//TODO ONLY FOR DEBUG
+// $query = "truncate table convert_stack";
+// $stmt = Bt_doQuery(
+//     $GLOBALS['db'], 
+//     $query
+// );
+// $query = "truncate table adr_letterbox";
+// $stmt = Bt_doQuery(
+//     $GLOBALS['db'], 
+//     $query
+// );
+// $query = "update res_letterbox set convert_result = 0";
+// $stmt = Bt_doQuery(
+//     $GLOBALS['db'], 
+//     $query
+// );
+
+/******************************************************************************/
+/* beginning */
+$state = 'CONTROL_STACK';
+while ($state <> 'END') {
+    if (isset($GLOBALS['logger'])) {
+        $GLOBALS['logger']->write('STATE:' . $state, 'INFO');
+    }
+    switch ($state) {
+        /**********************************************************************/
+        /*                          CONTROL_STACK                             */
+        /* Checking if the stack is full                                      */
+        /**********************************************************************/
+        case 'CONTROL_STACK' :
+            $query = "select * from convert_stack "
+                   . " where coll_id = ? and regex = ?";
+            $stmt = Bt_doQuery(
+                $GLOBALS['db'], 
+                $query, 
+                array($GLOBALS['collection'], $GLOBALS['regExResId'])
+            );
+            if ($stmt->rowCount() > 0) {
+                Bt_exitBatch(107, 'stack is full for collection:'
+                             . $GLOBALS['collection'] . ', regex:'
+                             . $GLOBALS['regExResId']
+                             , 'WARNING');
+                break;
+            }
+            $state = 'SELECT_RES';
+            break;
+        /**********************************************************************/
+        /*                          SELECT_RES                                */
+        /* Selects candidates                                                 */
+        /**********************************************************************/
+        case 'SELECT_RES' :
+            $orderBy = ' order by res_id ';
+            if ($GLOBALS['stackSizeLimit'] <> '') {
+                $limit = ' LIMIT ' . $GLOBALS['stackSizeLimit'];
+            }
+
+            if ($GLOBALS['OnlyIndexes']) {
+                $where_clause = " convert_result = '1' and ( (fulltext_result = '0' or fulltext_result = '' "
+                    . "or fulltext_result is null) or (fulltext_result= '-1' and (cast(coalesce(custom_t15, '0') as integer) < 3))) ";
+                $where_clause .= $GLOBALS['creationDateClause'] 
+                    . $GLOBALS['whereRegex'];
+            } else {
+                $where_clause = " (convert_result = '0' or convert_result = '' " 
+                    . "or convert_result is null) or (convert_result= '-1' and (cast(coalesce(custom_t9, '0') as integer) < 3)) "
+                    . $GLOBALS['creationDateClause']
+                    . $GLOBALS['whereRegex'];
+            }
+            
+            $query = $GLOBALS['db']->limit_select(
+                0, 
+                $GLOBALS['stackSizeLimit'], 
+                'res_id', 
+                $GLOBALS['table'], 
+                $where_clause, 
+                $orderBy
+            );
+            $stmt = Bt_doQuery($GLOBALS['db'], $query);
+            $resourcesArray = array();
+
+            if ($stmt->rowCount() > 0) {
+                while ($resoucesRecordset = $stmt->fetchObject()) {
+                    array_push(
+                        $resourcesArray,
+                            array('res_id' => $resoucesRecordset->res_id)
+                    );
+                }
+            } else {
+                if ($GLOBALS['creationDateClause'] <> '') {
+                    $GLOBALS['logger']->write('No resource found for collection', 'INFO');
+                    // test if we have to change the current date
+                    if ($GLOBALS['currentMonthOnly'] == 'false') {
+                        if ($GLOBALS['OnlyIndexes']) {
+                            $queryTestDate = " convert_result = '1' and ( (fulltext_result = '0' or fulltext_result = '' "
+                                    . "or fulltext_result is null) or (fulltext_result= '-1' and (cast(coalesce(custom_t15, '0') as integer) < 3))) ";
+                            $queryTestDate .= $GLOBALS['creationDateClause'];
+                        } else {
+                            $queryTestDate = " select count(res_id) as totalres from " 
+                                . $GLOBALS['table'] . " (convert_result = '0' or convert_result = '' " 
+                                . "or convert_result is null) or (convert_result= '-1' and (cast(coalesce(custom_t9, '0') as integer) < 3)) "
+                                . $GLOBALS['creationDateClause'];
+                        }
+                        $stmt = Bt_doQuery(
+                            $GLOBALS['db'], 
+                            $queryTestDate
+                        );
+                        $resultTotal = $stmt->fetchObject();
+                        if ($resultTotal->totalres == 0) {
+                            Bt_computeNextMonthCurrentDate();
+                            Bt_computeCreationDateClause();
+                            Bt_updateCurrentDateToProcess();
+                            if ($GLOBALS['OnlyIndexes']) {
+                                $where_clause = " convert_result = '1' and ( (fulltext_result = '0' or fulltext_result = '' "
+                                    . "or fulltext_result is null) or (fulltext_result= '-1' and (cast(coalesce(custom_t15, '0') as integer) < 3))) ";
+                                $where_clause .= $GLOBALS['creationDateClause']
+                                    . $GLOBALS['whereRegex'];
+                            } else {
+                                $where_clause = " (convert_result = '0' or convert_result = '' " 
+                                    . "or convert_result is null) or (convert_result= '-1' and (cast(coalesce(custom_t9, '0') as integer) < 3)) "
+                                    . $GLOBALS['creationDateClause']
+                                    . $GLOBALS['whereRegex'];
+                            }
+
+                            $query = $GLOBALS['db']->limit_select(
+                                0, 
+                                $GLOBALS['stackSizeLimit'], 
+                                'res_id', 
+                                $GLOBALS['table'], 
+                                $where_clause, 
+                                $orderBy
+                            );
+                            $stmt = Bt_doQuery(
+                                $GLOBALS['db'], 
+                                $query
+                            );
+                            $resourcesArray = array();
+                            if ($stmt->rowCount() > 0) {
+                                while ($resoucesRecordset = $stmt->fetchObject()) {
+                                    array_push(
+                                        $resourcesArray,
+                                            array('res_id' => $resoucesRecordset->res_id)
+                                        );
+                                }
+                            } else {
+                                $GLOBALS['logger']->write('No resource found for collection', 'INFO');
+                            }
+                        }
+                    }
+                } else {
+                    $GLOBALS['logger']->write('No resource found for collection', 'INFO');
+                }
+            }
+            $state = 'FILL_STACK';
+            break;
+        /**********************************************************************/
+        /*                          FILL_STACK                                */
+        /* Fill the stack of candidates                                       */
+        /**********************************************************************/
+        case 'FILL_STACK' :
+            for ($cptRes = 0;$cptRes < count($resourcesArray);$cptRes++) {
+                $query = "insert into convert_stack"
+                       . " (coll_id, res_id, status, work_batch, regex) "
+                       . "values (?, ?, 'I', ?, ?)";
+                $stmt = Bt_doQuery(
+                    $GLOBALS['db'], 
+                    $query, 
+                    array(
+                        $GLOBALS['collection'],
+                        $resourcesArray[$cptRes]["res_id"],
+                        $GLOBALS['wb'],
+                        $GLOBALS['regExResId']
+                    )
+                );
+                //history
+                $query = "insert into " . HISTORY_TABLE
+                       . " (table_name, record_id, event_type, user_id, "
+                       . "event_date, info, id_module) values (?, ?, 'ADD', 'CONVERT_BOT', "
+                       . $GLOBALS['db']->current_datetime()
+                       . ", ?, 'convert')";
+                $stmt = Bt_doQuery(
+                    $GLOBALS['db'], 
+                    $query,
+                    array(
+                        $GLOBALS['table'],
+                        $resourcesArray[$cptRes]["res_id"],
+                        "convert fill stack for collection:" . $GLOBALS['collection']
+                    )
+                );
+                $GLOBALS['totalProcessedResources']++;
+            }
+            $state = 'END';
+            break;
+    }
+}
+$GLOBALS['logger']->write('End of process fill stack', 'INFO');
+include('process_stack.php');
+exit($GLOBALS['exitCode']);
diff --git a/modules/convert/batch/load_fill_stack.php b/modules/convert/batch/load_fill_stack.php
new file mode 100644
index 0000000000000000000000000000000000000000..559abc01086b4150e9b7d9ba66b6b4e4a3e16ce5
--- /dev/null
+++ b/modules/convert/batch/load_fill_stack.php
@@ -0,0 +1,391 @@
+<?php
+
+/*
+ *   Copyright 2008-2016 Maarch
+ *
+ *   This file is part of Maarch Framework.
+ *
+ *   Maarch Framework is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Maarch Framework is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Maarch Framework. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @brief Library to convert
+ *
+ * @file
+ * @author  Laurent Giovannoni  <dev@maarch.org>
+ * @date $date$
+ * @version $Revision$
+ * @ingroup convert
+ */
+
+/**
+* @brief Class to include the file error
+*
+* @ingroup convert
+*/
+class IncludeFileError extends Exception
+{
+    public function __construct($file) 
+    {
+        $this->file = $file;
+        parent :: __construct('Include File \'$file\' is missing!', 1);
+    }
+}
+
+try {
+    include('Maarch_CLITools/ArgsParser.php');
+    include('LoggerLog4php.php');
+    include('Maarch_CLITools/FileHandler.php');
+    include('Maarch_CLITools/ConsoleHandler.php');
+} catch (IncludeFileError $e) {
+    echo 'Maarch_CLITools required ! \n (pear.maarch.org)\n';
+    exit(106);
+}
+include('batch_tools.php');
+// Globals variables definition
+$state = '';
+$configFile = '';
+$MaarchDirectory = '';
+$batchDirectory = '';
+$batchName = 'convert';
+$TmpDirectory = '';
+$table = '';
+$adrTable = '';
+$view = '';
+$coll = '';
+$creationDateClause = '';
+$currentStep = '';
+$docservers = Array();
+$docserverSourcePath = '';
+$docserverSourceFingerprint = '';
+$databasetype = '';
+$exitCode = 0;
+$running_date = date('Y-m-d H:i:s');
+$func = '';
+$db = '';
+$db2 = '';
+$db3 = '';
+$docserverControler = '';
+$wb = '';
+$wbCompute = '';
+$stackSizeLimit = '';
+$docserversFeatures = array();
+$lckFile = '';
+$errorLckFile = '';
+$totalProcessedResources = 0;
+$apacheUserAndGroup =  '';
+$regExResId = 'false';
+$startDateRecovery = 'false';
+$currentDate = 'false';
+$endCurrentDate = 'false';
+$currentMonthOnly = 'false';
+$OnlyIndexes = 'false';
+$ProcessIndexesSize = 1000;
+$whereRegex = '';
+$log4PhpEnabled = false;
+
+// Defines scripts arguments
+$argsparser = new ArgsParser();
+// The config file
+$argsparser->add_arg(
+    'config', 
+    array(
+        'short' => 'c',
+        'long' => 'config',
+        'mandatory' => true,
+        'help' => 'Config file path is mandatory.',
+    )
+);
+// The res collection target
+$argsparser->add_arg(
+    'collection', 
+    array(
+        'short' => 'coll',
+        'long' => 'collection',
+        'mandatory' => true,
+        'help' => 'Collection target is mandatory.',
+    )
+);
+// The path of the log directory
+$argsparser->add_arg(
+    'logs', 
+    array(
+        'short' => 'logs',
+        'long' => 'logs',
+        'mandatory' => false,
+        'help' => '',
+    )
+);
+// Parsing script options
+try {
+    $options = $argsparser->parse_args($GLOBALS['argv']);
+    // If option = help then options = false and the script continues ...
+    if ($options == false) {
+        exit(0);
+    }
+} catch (MissingArgumentError $e) {
+    if ($e->arg_name == 'config') {
+        $GLOBALS['logger']->write('Configuration file missing', 'ERROR', 101);
+        exit(101);
+    }
+    if ($e->arg_name == 'collection') {
+        $GLOBALS['logger']->write('Collection missing', 'ERROR', 1);
+        exit(105);
+    }
+}
+// Log management
+$GLOBALS['logger'] = new Logger4Php();
+$GLOBALS['logger']->set_threshold_level('DEBUG');
+$console = new ConsoleHandler();
+$GLOBALS['logger']->add_handler($console);
+if (!empty($options['logs'])) {
+    $logFile = $options['logs'] . '/' . date('Y-m-d_H-i-s') . '.log';
+} else {
+    $logFile = 'logs' . '/' . date('Y-m-d_H-i-s') . '.log';
+}
+$file = new FileHandler($logFile);
+$GLOBALS['logger']->add_handler($file);
+$GLOBALS['logger']->write('STATE:INIT', 'INFO');
+$txt = '';
+foreach (array_keys($options) as $key) {
+    if (isset($options[$key]) && $options[$key] == false) {
+        $txt .= $key . '=false,';
+    } else {
+        $txt .= $key . '=' . $options[$key] . ',';
+    }
+}
+$GLOBALS['logger']->write($txt, 'DEBUG');
+$GLOBALS['configFile'] = $options['config'];
+$GLOBALS['collection'] = $options['collection'];
+$GLOBALS['logger']->write($txt, 'INFO');
+// Tests existence of config file
+if (!file_exists($GLOBALS['configFile'])) {
+    $GLOBALS['logger']->write('Configuration file ' . $GLOBALS['configFile'] 
+                              . ' does not exist', 'ERROR', 102);
+    exit(102);
+}
+// Loading config file
+$GLOBALS['logger']->write('Load xml config file:' . $GLOBALS['configFile'], 
+                          'INFO');
+$xmlconfig = simplexml_load_file($GLOBALS['configFile']);
+if ($xmlconfig == FALSE) {
+    $GLOBALS['logger']->write('Error on loading config file:' 
+                              . $GLOBALS['configFile'], 'ERROR', 103);
+    exit(103);
+}
+// Load the config vars
+$CONFIG = $xmlconfig->CONFIG;
+$lang = (string) $CONFIG->Lang;
+$GLOBALS['MaarchDirectory'] = (string) $CONFIG->MaarchDirectory;
+$GLOBALS['batchDirectory'] = $GLOBALS['MaarchDirectory'] . 'modules/convert/batch';
+$GLOBALS['tmpDirectoryRoot'] = (string) $CONFIG->TmpDirectory;
+$MaarchApps = (string) $CONFIG->MaarchApps;
+$logLevel = (string) $CONFIG->LogLevel;
+$GLOBALS['logger']->set_threshold_level($logLevel);
+$DisplayedLogLevel = (string) $CONFIG->DisplayedLogLevel;
+$GLOBALS['apacheUserAndGroup'] = (string) $CONFIG->ApacheUserAndGroup;
+$GLOBALS['stackSizeLimit'] = (string) $CONFIG->StackSizeLimit;
+$GLOBALS['databasetype'] = (string) $xmlconfig->CONFIG_BASE->databasetype;
+$GLOBALS['unoconvPath'] = (string) $CONFIG->UnoconvPath;
+$GLOBALS['openOfficePath'] = (string) $CONFIG->OpenOfficePath;
+$GLOBALS['unoconvOptions'] = (string) $CONFIG->UnoconvOptions;
+
+$GLOBALS['regExResId'] = (string) $CONFIG->RegExResId;
+$GLOBALS['startDateRecovery'] = (string) $CONFIG->StartDateRecovery;
+$GLOBALS['currentMonthOnly'] = (string) $CONFIG->CurrentMonthOnly;
+$GLOBALS['OnlyIndexes'] = (string) $CONFIG->OnlyIndexes;
+
+if ($GLOBALS['OnlyIndexes'] == 'true') {
+    $GLOBALS['OnlyIndexes'] = true;
+} else {
+    $GLOBALS['OnlyIndexes'] = false;
+}
+
+$GLOBALS['ProcessIndexesSize'] = (string) $CONFIG->ProcessIndexesSize;
+
+if ($GLOBALS['regExResId'] <> 'false') {
+    if ($GLOBALS['databasetype'] == 'POSTGRESQL') {
+        $GLOBALS['whereRegex'] = " and cast(res_id as character varying(255)) ~ '" 
+            . $GLOBALS['regExResId'] . "' ";
+    } elseif ($GLOBALS['databasetype'] == 'ORACLE') {
+        $GLOBALS['whereRegex'] = " and REGEXP_LIKE (to_char(res_id), '" 
+            . $GLOBALS['regExResId'] . "') ";
+    }
+}
+
+$arrayOfInputs = array();
+$GLOBALS['convertFormats'] = array();
+$i = 0;
+foreach ($xmlconfig->CONVERT as $convert) {
+    $outputFormat = (string) $convert->OutputFormat;
+    $arrayOfInputs = explode(',', (string) $convert->InputFormat);
+    $cptInputs = count($arrayOfInputs);
+    for ($j=0;$j<$cptInputs;$j++) {
+        if (!empty($GLOBALS['convertFormats'][$arrayOfInputs[$j]])) {
+            $GLOBALS['convertFormats'][$arrayOfInputs[$j]] .= "_" . $outputFormat;
+        } else {
+            $GLOBALS['convertFormats'][$arrayOfInputs[$j]] .= $outputFormat;
+        }
+    }
+    $i++;
+}
+
+//var_dump($GLOBALS['convertFormats']);
+
+$i = 0;
+foreach ($xmlconfig->COLLECTION as $col) {
+    $GLOBALS['collections'][$i] = array (
+        'id'             => (string) $col->Id, 
+        'table'          => (string) $col->Table, 
+        'view'           => (string) $col->View, 
+        'adr'            => (string) $col->Adr,
+        'path_to_lucene' => (string) $col->path_to_lucene_index
+    );
+    if ($GLOBALS['collections'][$i]['id'] == $GLOBALS['collection']) {
+        $GLOBALS['table']          = $GLOBALS['collections'][$i]['table'];
+        $GLOBALS['adrTable']       = $GLOBALS['collections'][$i]['adr'];
+        $GLOBALS['view']           = $GLOBALS['collections'][$i]['view'];
+        $GLOBALS['path_to_lucene'] = $GLOBALS['collections'][$i]['path_to_lucene'];
+    }
+    $i++;
+}
+
+set_include_path(get_include_path() . PATH_SEPARATOR 
+    . $GLOBALS['MaarchDirectory']);
+//log4php params
+$log4phpParams = $xmlconfig->LOG4PHP;
+if ((string) $log4phpParams->enabled == 'true') {
+    $GLOBALS['logger']->set_log4PhpLibrary(
+        $GLOBALS['MaarchDirectory'] 
+            . 'apps/maarch_entreprise/tools/log4php/Logger.php'
+    );
+    $GLOBALS['logger']->set_log4PhpLogger((string) $log4phpParams->Log4PhpLogger);
+    $GLOBALS['logger']->set_log4PhpBusinessCode((string) $log4phpParams->Log4PhpBusinessCode);
+    $GLOBALS['logger']->set_log4PhpConfigPath((string) $log4phpParams->Log4PhpConfigPath);
+    $GLOBALS['logger']->set_log4PhpBatchName('convert');
+}
+
+if ($GLOBALS['table'] == '' 
+    || $GLOBALS['adrTable'] == '' 
+    || $GLOBALS['view'] == ''
+) {
+    $GLOBALS['logger']->write('Collection:' . $GLOBALS['collection'].' unknow'
+                              , 'ERROR', 110);
+    exit(110);
+}
+if (file_exists($GLOBALS['MaarchDirectory'] . 'modules/convert/lang/' . $lang . '.php')
+) {
+    include($GLOBALS['MaarchDirectory'] . 'modules/convert/lang/' . $lang . '.php');
+}
+/*if ($logLevel == 'DEBUG') {
+    error_reporting(E_ALL);
+}*/
+$GLOBALS['logger']->change_handler_log_level($file, $logLevel);
+$GLOBALS['logger']->change_handler_log_level($console, $DisplayedLogLevel);
+unset($xmlconfig);
+
+// Include library
+try {
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_functions.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_db.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_db_pdo.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_core_tools.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/core_tables.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/docservers_controler.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/docservers_tools.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/docserver_types_controler.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'modules/convert/services/ManageConvert.php');
+} catch (IncludeFileError $e) {
+    $GLOBALS['logger']->write(
+        'Problem with the php include path:' 
+        . get_include_path(), 'ERROR', 111
+    );
+    exit(111);
+}
+if (!is_dir($GLOBALS['tmpDirectoryRoot'])) {
+    $GLOBALS['logger']->write(
+        'Problem with the tmp dir:' . $GLOBALS['tmpDirectory'], 'ERROR', 17
+    );
+    exit(17);
+}
+
+$coreTools = new core_tools();
+$coreTools->load_lang($lang, $GLOBALS['MaarchDirectory'], $MaarchApps);
+session_start();
+$_SESSION['modules_loaded']    = array();
+$GLOBALS['func']               = new functions();
+$GLOBALS['db']                 = new Database($GLOBALS['configFile']);
+$GLOBALS['db2']                = new Database($GLOBALS['configFile']);
+$GLOBALS['db3']                = new Database($GLOBALS['configFile']);
+$GLOBALS['dbLog']              = new Database($GLOBALS['configFile']);
+$GLOBALS['docserverControler'] = new docservers_controler();
+$GLOBALS['processConvert']     = new Convert_ManageConvert_Service($GLOBALS['openOfficePath']);
+$GLOBALS['processIndexes']     = new Convert_ProcessFulltext_Service();
+
+$configFileName = basename($GLOBALS['configFile'], '.xml');
+$GLOBALS['errorLckFile'] = $GLOBALS['batchDirectory'] . '/' 
+                         . $GLOBALS['batchName'] . '_' . $GLOBALS['collection']  
+                         . '_' .  $configFileName
+                         . '_error.lck';
+$GLOBALS['lckFile'] = $GLOBALS['batchDirectory'] . '/' 
+                    . $GLOBALS['batchName'] . '_' . $GLOBALS['collection'] 
+                    . '_' . $configFileName
+                    . '.lck';
+if (file_exists($GLOBALS['errorLckFile'])) {
+    $GLOBALS['logger']->write(
+        'Error persists, please solve this before launching a new batch', 
+        'ERROR', 29
+    );
+    exit(29);
+}
+if (file_exists($GLOBALS['lckFile'])) {
+    $GLOBALS['logger']->write(
+        'An instance of the batch :' . $GLOBALS['batchName'] . '_' 
+            . $GLOBALS['collection'] . '_' . $configFileName 
+            . ' is already in progress',
+        'ERROR', 109
+    );
+    exit(109);
+}
+
+if ($GLOBALS['currentMonthOnly'] == 'true') {
+    $GLOBALS['currentDate'] = date(
+        "d/m/Y", 
+        mktime(0, 0, 0, date("m"), 1, date("Y"))
+    );
+    Bt_getEndCurrentDateToProcess();
+    Bt_computeCreationDateClause();
+    $GLOBALS['logger']->write('current begin date to process : ' 
+        . $GLOBALS['currentDate'], 'INFO');
+} elseif ($GLOBALS['startDateRecovery'] <> 'false') {
+    Bt_getCurrentDateToProcess();
+    Bt_updateCurrentDateToProcess();
+    Bt_getEndCurrentDateToProcess();
+    Bt_computeCreationDateClause();
+    $GLOBALS['logger']->write('current begin date to process : ' 
+        . $GLOBALS['currentDate'], 'INFO');
+}
+
+$semaphore = fopen($GLOBALS['lckFile'], 'a');
+fwrite($semaphore, '1');
+fclose($semaphore);
+Bt_getWorkBatch();
+$GLOBALS['wb'] = rand() . $GLOBALS['wbCompute'];
+Bt_updateWorkBatch();
+$GLOBALS['logger']->write('Batch number:' . $GLOBALS['wb'], 'INFO');
+$GLOBALS['tmpDirectory'] = $GLOBALS['tmpDirectoryRoot'] . '/' 
+                         . $GLOBALS['wb'] . '/';
+if (!is_dir($GLOBALS['tmpDirectory'])) {
+    mkdir($GLOBALS['tmpDirectory'], 0777);
+}
diff --git a/modules/convert/batch/process_stack.php b/modules/convert/batch/process_stack.php
new file mode 100644
index 0000000000000000000000000000000000000000..969d610b8b3b0df9f6133d289cba9fa9bb6884a3
--- /dev/null
+++ b/modules/convert/batch/process_stack.php
@@ -0,0 +1,244 @@
+<?php
+
+/*
+ *  Copyright 2008-2016 Maarch
+ *
+ *  This file is part of Maarch Framework.
+ *
+ *  Maarch Framework is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Maarch Framework is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @brief Batch to process the stack
+ *
+ * @file
+ * @author  Laurent Giovannoni  <dev@maarch.org>
+ * @date $date$
+ * @version $Revision$
+ * @ingroup convert
+ */
+
+/**
+ * *****   LIGHT PROBLEMS without an error semaphore
+ *  101 : Configuration file missing
+ *  102 : Configuration file does not exist
+ *  103 : Error on loading config file
+ *  104 : SQL Query Error
+ *  105 : a parameter is missing
+ *  106 : Maarch_CLITools is missing
+ *  107 : Stack empty for the request
+ *  108 : There are still documents to be processed
+ *  109 : An instance of the batch for the required collection already
+ *        in progress
+ *  110 : Problem with collection parameter
+ *  111 : Problem with the php include path
+ *  112 : Problem with the setup of esign
+ * ****   HEAVY PROBLEMS with an error semaphore
+ *  12  : Docserver type not found
+ *  13  : Docserver not found
+ *  14  : ...
+ *  15  : Error to copy file on docserver
+ *  16  : ...
+ *  17  : Tmp dir not exists
+ *  18  : Problem to create path on docserver, maybe batch number 
+ *        already exists
+ *  19  : Tmp dir not empty
+ *  20  : ...
+ *  21  : Problem to create directory on the docserver
+ *  22  : Problem during transfert of file (fingerprint control)
+ *  23  : Problem with compression
+ *  24  : Problem with extract
+ *  25  : Pb with fingerprint of the source
+ *  26  : File deletion impossible
+ *  27  : Resource not found
+ *  28  : The docserver will be full at 95 percent
+ *  29  : Error persists
+ *  30  : Esign problem
+ */
+
+date_default_timezone_set('Europe/Paris');
+
+/******************************************************************************/
+/* beginning */
+$GLOBALS['state'] = "CONTROL_STACK";
+while ($GLOBALS['state'] <> "END") {
+    if (isset($GLOBALS['logger'])) {
+        $GLOBALS['logger']->write("STATE:" . $GLOBALS['state'], 'DEBUG');
+    }
+    switch($GLOBALS['state']) {
+        /**********************************************************************/
+        /*                          CONTROL_STACK                             */
+        /* Checking the stack is empty for the required parameters            */
+        /**********************************************************************/
+        case "CONTROL_STACK" :
+            $query = "select * from convert_stack"
+                   . " where coll_id = ? and work_batch = ?";
+            $stmt = Bt_doQuery(
+                $GLOBALS['db'], 
+                $query,
+                array(
+                    $GLOBALS['collection'],
+                    $GLOBALS['wb']
+                )
+            );
+            Bt_updateWorkBatch();
+            $GLOBALS['logger']->write("Batch number:" . $GLOBALS['wb'], 'INFO');
+            $query = "update convert_stack" 
+                   . " set status = 'I' where status = 'W'"
+                   . " and work_batch = ?";
+            $stmt = Bt_doQuery($GLOBALS['db'], $query, array($GLOBALS['wb']));
+            if ($GLOBALS['OnlyIndexes']) {
+                //echo 'avant createZendIndexObject : ' . $GLOBALS['ProcessIndexesSize'] . PHP_EOL;
+                $GLOBALS['zendIndex'] = 
+                    $GLOBALS['processIndexes']->createZendIndexObject(
+                        $GLOBALS['path_to_lucene'], $GLOBALS['ProcessIndexesSize']
+                    );
+                //$GLOBALS['zendIndex']->setMergeFactor(10);
+                //print_r($GLOBALS['zendIndex']);
+            }
+            $GLOBALS['state'] = "GET_DOCSERVERS";
+            break;
+        /**********************************************************************/
+        /*                          GET_DOCSERVERS                            */
+        /* Get the list of the docservers of the collection                   */
+        /**********************************************************************/
+        case "GET_DOCSERVERS" :
+            //retrieve docservers of the collection to process
+            $query = "select * from docservers " 
+                           . " where coll_id = ?";
+            $stmt = Bt_doQuery(
+                $GLOBALS['db2'], 
+                $query, 
+                array($GLOBALS['collection'])
+            );
+            if ($stmt->rowCount() == 0) {
+                 Bt_exitBatch(13, 'Docserver not found');
+                break;
+            } else {
+                while($docserversRecordset = $stmt->fetchObject()) {
+                    $GLOBALS['docservers'][$docserversRecordset->docserver_id] 
+                        = $GLOBALS['func']->object2array($docserversRecordset);
+                }
+            }
+            $GLOBALS['state'] = "A_RECORD";
+            break;
+        /**********************************************************************/
+        /*                          A_RECORD                                  */
+        /* Process a record                                                   */
+        /**********************************************************************/
+        case "A_RECORD" :
+            $GLOBALS['totalProcessedResources']++;
+            $query = "select * from convert_stack "
+                   . " where coll_id = ? "
+                   . " and status = 'I' "
+                   . " and work_batch = ? limit 1";
+            $stmt = Bt_doQuery(
+                $GLOBALS['db'], 
+                $query,
+                array(
+                    $GLOBALS['collection'],
+                    $GLOBALS['wb']
+                )
+            );
+            if ($stmt->rowCount() == 0) {
+                if ($GLOBALS['OnlyIndexes']) {
+                    $GLOBALS['processIndexes']->commitZendIndex($GLOBALS['zendIndex']);
+                }
+                $GLOBALS['state'] = "END";
+                $GLOBALS['logger']->write('No more records to process', 'INFO');
+                break;
+            } else {
+                $stackRecordset = $stmt->fetchObject();
+                $currentRecordInStack = array();
+                $currentRecordInStack = $GLOBALS['func']->object2array(
+                    $stackRecordset
+                );
+                $GLOBALS['logger']->write(
+                    "current record:" . $currentRecordInStack['res_id'],
+                    'DEBUG'
+                );
+                $GLOBALS['state'] = "CONVERT_IT";
+            }
+            break;
+        /**********************************************************************/
+        /*                          CONVERT_IT                                */
+        /* Removes the address of the resource in the database                */
+        /**********************************************************************/
+        case "CONVERT_IT" :
+            if ($GLOBALS['OnlyIndexes']) {
+                $resultConvert = $GLOBALS['processIndexes']->fulltext(
+                    array(
+                        'collId'         => $GLOBALS['collection'], 
+                        'resTable'       => $GLOBALS['table'], 
+                        'adrTable'       => $GLOBALS['adrTable'], 
+                        'resId'          => $currentRecordInStack['res_id'],
+                        'tmpDir'         => $GLOBALS['tmpDirectory'],
+                        'path_to_lucene' => $GLOBALS['path_to_lucene'],
+                        'zendIndex'      => $GLOBALS['zendIndex']
+                    )
+                );
+            } else {
+                $resultConvert = $GLOBALS['processConvert']->convertAll(
+                    array(
+                        'collId'         => $GLOBALS['collection'], 
+                        'resTable'       => $GLOBALS['table'], 
+                        'adrTable'       => $GLOBALS['adrTable'], 
+                        'resId'          => $currentRecordInStack['res_id'],
+                        'tmpDir'         => $GLOBALS['tmpDirectory'],
+                        'path_to_lucene' => $GLOBALS['path_to_lucene'],
+                        //'zendIndex'      => $GLOBALS['zendIndex']
+                    )
+                );
+            }
+            
+            $logInfo = "Problem with the record:" . $currentRecordInStack['res_id']
+                    . " details " . $resultConvert['error'];
+                    
+            if ($resultConvert['status'] == '2') {
+                $GLOBALS['logger']->write($logInfo, 'WARNING');
+
+            } elseif ($resultConvert['status'] <> '0') {
+                $GLOBALS['logger']->write($logInfo, 'ERROR');
+            }
+            $GLOBALS['state'] = "UPDATE_DATABASE";
+            break;
+        
+        /**********************************************************************/
+        /*                          UPDATE_DATABASE                           */
+        /* Updating the database                                              */
+        /**********************************************************************/
+        case "UPDATE_DATABASE" :
+            $query = "delete from convert_stack "
+                   . " where coll_id = ? "
+                   . " and res_id = ?";
+            $stmt = Bt_doQuery(
+                $GLOBALS['db'], 
+                $query,
+                array(
+                    $GLOBALS['collection'],
+                    $currentRecordInStack['res_id']
+                )
+            );
+            $GLOBALS['state'] = "A_RECORD";
+            break;
+    }
+}
+
+$GLOBALS['logger']->write('End of process', 'INFO');
+Bt_logInDataBase(
+    $GLOBALS['totalProcessedResources'], 0, 'process without error'
+);
+Ds_washTmp($GLOBALS['tmpDirectory']);
+unlink($GLOBALS['lckFile']);
+exit($GLOBALS['exitCode']);
diff --git a/modules/convert/batch/scripts/launch_convert_all_coll.sh b/modules/convert/batch/scripts/launch_convert_all_coll.sh
new file mode 100644
index 0000000000000000000000000000000000000000..1f55da8f17626a4c0aa8fd7430bf866945c6448a
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_convert_all_coll.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+Mypath='/var/www/html/oem_V2/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/oem_V2/modules/convert/batch/config'
+
+#rm convert_letterbox_coll_config.lck
+#rm convert_letterbox_coll_config_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll letterbox_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll attachments_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll attachments_version_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll calendar_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll folder_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll chrono_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll reprise_coll
diff --git a/modules/convert/batch/scripts/launch_convert_attachments.sh b/modules/convert/batch/scripts/launch_convert_attachments.sh
new file mode 100644
index 0000000000000000000000000000000000000000..82c23ff2cf19054342a45a1acf415c9305541bce
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_convert_attachments.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/config'
+
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll attachments_coll
\ No newline at end of file
diff --git a/modules/convert/batch/scripts/launch_convert_attachments.sh.default b/modules/convert/batch/scripts/launch_convert_attachments.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..82c23ff2cf19054342a45a1acf415c9305541bce
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_convert_attachments.sh.default
@@ -0,0 +1,6 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/config'
+
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll attachments_coll
\ No newline at end of file
diff --git a/modules/convert/batch/scripts/launch_convert_letterbox.sh b/modules/convert/batch/scripts/launch_convert_letterbox.sh
new file mode 100644
index 0000000000000000000000000000000000000000..1e01fa3d4668da961d27d7dcdc1c45ba24346df9
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_convert_letterbox.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/config'
+
+rm convert_letterbox_coll_config.lck
+rm convert_letterbox_coll_config_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll letterbox_coll
diff --git a/modules/convert/batch/scripts/launch_convert_letterbox.sh.default b/modules/convert/batch/scripts/launch_convert_letterbox.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..e218e5a72836398cc7032a35fd6fe723b428f337
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_convert_letterbox.sh.default
@@ -0,0 +1,6 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/config'
+
+php $Mypath/fill_stack.php -c $ConfigPath/config.xml -coll letterbox_coll
\ No newline at end of file
diff --git a/modules/convert/batch/scripts/launch_convert_reprise.sh.default b/modules/convert/batch/scripts/launch_convert_reprise.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..44f8126f75d4fa83fea08dc80987089a6dbd16a5
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_convert_reprise.sh.default
@@ -0,0 +1,9 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/config'
+
+rm convert_reprise_coll_config.lck
+rm convert_reprise_coll_config_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config_reprise_oem.xml -coll reprise_coll
diff --git a/modules/convert/batch/scripts/launch_fulltext_all_coll.sh b/modules/convert/batch/scripts/launch_fulltext_all_coll.sh
new file mode 100644
index 0000000000000000000000000000000000000000..2883f9dca685af4c87b38a0e4e9124ad1143ec02
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_fulltext_all_coll.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+Mypath='/var/www/html/oem_V2/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/oem_V2/modules/convert/batch/config'
+
+#rm convert_letterbox_coll_config_only_indexes.lck
+#rm convert_letterbox_coll_config_only_indexes_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll letterbox_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll attachments_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll attachments_version_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll calendar_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll folder_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll chrono_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll reprise_coll
diff --git a/modules/convert/batch/scripts/launch_fulltext_attachments.sh b/modules/convert/batch/scripts/launch_fulltext_attachments.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c4fecdce5d966eb9a10308e849148c3f2765eee5
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_fulltext_attachments.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+Mypath='/var/www/html/oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/oem/modules/convert/batch/config'
+
+rm convert_attachments_coll_config_only_indexes.lck
+rm convert_attachments_coll_config_only_indexes_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll attachments_coll
diff --git a/modules/convert/batch/scripts/launch_fulltext_letterbox.sh b/modules/convert/batch/scripts/launch_fulltext_letterbox.sh
new file mode 100644
index 0000000000000000000000000000000000000000..084d583388506987e0f997c9da665bda409e4134
--- /dev/null
+++ b/modules/convert/batch/scripts/launch_fulltext_letterbox.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+Mypath='/var/www/html/oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/oem/modules/convert/batch/config'
+
+rm convert_letterbox_coll_config_only_indexes.lck
+rm convert_letterbox_coll_config_only_indexes_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll letterbox_coll
diff --git a/modules/convert/batch/scripts/lgi.sh b/modules/convert/batch/scripts/lgi.sh
new file mode 100644
index 0000000000000000000000000000000000000000..e724de2f88e1be40475053f6b834dfb2f5924639
--- /dev/null
+++ b/modules/convert/batch/scripts/lgi.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+Mypath='/var/www/html/oem_V2/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/oem_V2/modules/convert/batch/config'
+
+rm convert_letterbox_coll_config_only_indexes.lck
+rm convert_letterbox_coll_config_only_indexes_error.lck
+
+rm convert_attachments_coll_config_only_indexes.lck
+rm convert_attachments_coll_config_only_indexes_error.lck
+
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll letterbox_coll
+php $Mypath/fill_stack.php -c $ConfigPath/config_only_indexes.xml -coll attachments_coll
\ No newline at end of file
diff --git a/modules/convert/batch/scripts/mywkhtmltoimage.sh b/modules/convert/batch/scripts/mywkhtmltoimage.sh
new file mode 100644
index 0000000000000000000000000000000000000000..2be138daf9ce6d8cf3880aa7d331cd19d2309af0
--- /dev/null
+++ b/modules/convert/batch/scripts/mywkhtmltoimage.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+xvfb-run -a --server-args="-screen 0, 1024x768x24" /usr/bin/wkhtmltoimage -q $*
diff --git a/modules/convert/batch/scripts/mywkhtmltopdf.sh b/modules/convert/batch/scripts/mywkhtmltopdf.sh
new file mode 100644
index 0000000000000000000000000000000000000000..76c76e2c5869e7afffb7adcc641769ca06f9ff3e
--- /dev/null
+++ b/modules/convert/batch/scripts/mywkhtmltopdf.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+xvfb-run -a --server-args="-screen 0, 1024x768x24" /usr/bin/wkhtmltopdf -q $*
diff --git a/modules/convert/batch/scripts/parallel/launch_convert_letterbox_0.sh.default b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_0.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..5ea397e8bfc522dfd3f227df398e60e296df6280
--- /dev/null
+++ b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_0.sh.default
@@ -0,0 +1,8 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/parallel/config'
+
+for (( i=0; i < 3; i++ ));
+    do php $Mypath/fill_stack.php -c $ConfigPath/config_0.xml -coll letterbox_coll
+done
diff --git a/modules/convert/batch/scripts/parallel/launch_convert_letterbox_1.sh.default b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_1.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..686b8dd0909cc01c198492ddf4b5ca6de8bd0313
--- /dev/null
+++ b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_1.sh.default
@@ -0,0 +1,8 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/parallel/config'
+
+for (( i=0; i < 3; i++ ));
+    do php $Mypath/fill_stack.php -c $ConfigPath/config_1.xml -coll letterbox_coll
+done
diff --git a/modules/convert/batch/scripts/parallel/launch_convert_letterbox_2.sh.default b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_2.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..2413c94236b6e58009a34fbc61777631b09e9e0f
--- /dev/null
+++ b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_2.sh.default
@@ -0,0 +1,8 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/parallel/config'
+
+for (( i=0; i < 3; i++ ));
+    do php $Mypath/fill_stack.php -c $ConfigPath/config_2.xml -coll letterbox_coll
+done
diff --git a/modules/convert/batch/scripts/parallel/launch_convert_letterbox_3.sh.default b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_3.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..4f1e58d4afa8dff876295a1cbc7fdf887515d1af
--- /dev/null
+++ b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_3.sh.default
@@ -0,0 +1,8 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/parallel/config'
+
+for (( i=0; i < 3; i++ ));
+    do php $Mypath/fill_stack.php -c $ConfigPath/config_3.xml -coll letterbox_coll
+done
diff --git a/modules/convert/batch/scripts/parallel/launch_convert_letterbox_4.sh.default b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_4.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..38999f620871d079e2cf8f5eedddd1bf0876e685
--- /dev/null
+++ b/modules/convert/batch/scripts/parallel/launch_convert_letterbox_4.sh.default
@@ -0,0 +1,8 @@
+#!/bin/bash
+Mypath='/var/www/html/maarch_oem/modules/convert/batch'
+cd $Mypath
+ConfigPath='/var/www/html/maarch_oem/modules/convert/batch/parallel/config'
+
+for (( i=0; i < 3; i++ ));
+    do php $Mypath/fill_stack.php -c $ConfigPath/config_4.xml -coll letterbox_coll
+done
diff --git a/modules/convert/batch/scripts/parallel/param_cron.txt b/modules/convert/batch/scripts/parallel/param_cron.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4a260f65532630bb95396bf58df277e8c4c45c6f
--- /dev/null
+++ b/modules/convert/batch/scripts/parallel/param_cron.txt
@@ -0,0 +1,6 @@
+# tous les jours toutes les 2 heures de 0h a 20h du lundi au samedi lancement des batchs de conversion
+0 0-20/2 * * 1-6 maarch /var/www/maarch/modules/maarch_oem/batch/scripts/parallel/launch_convert_letterbox_0.sh
+1 0-20/2 * * 1-6 maarch /var/www/maarch/modules/maarch_oem/batch/scripts/parallel/launch_convert_letterbox_1.sh
+2 0-20/2 * * 1-6 maarch /var/www/maarch/modules/maarch_oem/batch/scripts/parallel/launch_convert_letterbox_2.sh
+3 0-20/2 * * 1-6 maarch /var/www/maarch/modules/maarch_oem/batch/scripts/parallel/launch_convert_letterbox_3.sh
+4 0-20/2 * * 1-6 maarch /var/www/maarch/modules/maarch_oem/batch/scripts/parallel/launch_convert_letterbox_4.sh
diff --git a/modules/convert/batch/verif_index.php b/modules/convert/batch/verif_index.php
new file mode 100644
index 0000000000000000000000000000000000000000..6333e5a42321017b91ea1e8040d0fe0cae4eb4e0
--- /dev/null
+++ b/modules/convert/batch/verif_index.php
@@ -0,0 +1,16 @@
+<?php
+
+date_default_timezone_set('Europe/Paris');
+
+// load the config and prepare to process
+include('load_fill_stack.php');
+
+
+/******************************************************************************/
+$GLOBALS['zendIndex'] =
+        $GLOBALS['processIndexes']->createZendIndexObject(
+                $GLOBALS['path_to_lucene'], $GLOBALS['ProcessIndexesSize']
+        );
+unlink($GLOBALS['lckFile']);
+exit($GLOBALS['zendIndex']->numDocs());
+
diff --git a/modules/convert/class/class_modules_tools.php b/modules/convert/class/class_modules_tools.php
new file mode 100644
index 0000000000000000000000000000000000000000..949f379d3a9450e65f648faf2eb7862d9b83f67e
--- /dev/null
+++ b/modules/convert/class/class_modules_tools.php
@@ -0,0 +1,101 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @defgroup convert convert Module
+*/
+
+/**
+* @brief   Module convert :  Module Tools Class
+*
+* <ul>
+* <li>Set the session variables needed to run the convert module</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+/**
+* @brief Module convert : Module Tools Class
+*
+* <ul>
+* <li>Loads the tables used by the convert</li>
+* <li>Set the session variables needed to run the convert module</li>
+* </ul>
+*
+* @ingroup convert
+*/
+class convert extends Database
+{
+    function __construct()
+    {
+        parent::__construct();
+        $this->index = array();
+    }
+
+    /**
+    * Loads convert  tables into sessions vars from the
+    * convert/xml/config.xml
+    * Loads convert log setting into sessions vars from the
+    * convert/xml/config.xml
+    */
+    public function build_modules_tables()
+    {
+        if (file_exists($_SESSION['config']['corepath'].'custom'
+                        .DIRECTORY_SEPARATOR.$_SESSION['custom_override_id']
+                        .DIRECTORY_SEPARATOR."modules".DIRECTORY_SEPARATOR
+                        ."convert".DIRECTORY_SEPARATOR
+                        ."xml".DIRECTORY_SEPARATOR."config.xml")
+        ) {
+            $path = $_SESSION['config']['corepath'].'custom'
+                .DIRECTORY_SEPARATOR.$_SESSION['custom_override_id']
+                .DIRECTORY_SEPARATOR."modules".DIRECTORY_SEPARATOR."convert"
+                .DIRECTORY_SEPARATOR."xml".DIRECTORY_SEPARATOR."config.xml";
+        } else {
+            $path = "modules".DIRECTORY_SEPARATOR."convert"
+                .DIRECTORY_SEPARATOR."xml".DIRECTORY_SEPARATOR."config.xml";
+        }
+        $xmlconfig = simplexml_load_file($path);
+        //$CONFIG = $xmlconfig->CONFIG;
+        // Loads the tables of the module convert
+        // into session ($_SESSION['tablename'] array)
+
+        // Loads the log setting of the module convert
+        // into session ($_SESSION['history'] array)
+        $HISTORY = $xmlconfig->HISTORY;
+        $_SESSION['history']['convertadd'] = (string) $HISTORY->convertadd;
+        $_SESSION['history']['convertup'] = (string) $HISTORY->convertup;
+        $_SESSION['history']['convertdel'] = (string) $HISTORY->convertdel;
+    }
+
+    /**
+    * Load into session vars all the convert specific vars :
+    * calls private methods
+    */
+    public function load_module_var_session($userData)
+    {
+        //functions::show_array($_SESSION['convertFeatures']);
+    }
+}
diff --git a/modules/convert/class/ws.php b/modules/convert/class/ws.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9f0494bcda6befe7f8b5bf5eaea63218a537c8d
--- /dev/null
+++ b/modules/convert/class/ws.php
@@ -0,0 +1,5 @@
+<?php 
+global $SOAP_dispatch_map;
+global $XMLRPC_dispatch_map;
+global $SOAP_typedef;
+
diff --git a/modules/convert/convert.sql b/modules/convert/convert.sql
new file mode 100644
index 0000000000000000000000000000000000000000..62438dd3d9f06853f95df3eb5c5e27e01121eaf5
--- /dev/null
+++ b/modules/convert/convert.sql
@@ -0,0 +1,87 @@
+
+
+ALTER TABLE adr_x DROP COLUMN IF EXISTS adr_type;
+ALTER TABLE adr_x ADD COLUMN adr_type character varying(32) NOT NULL DEFAULT 'DOC';
+ALTER TABLE adr_attachments DROP COLUMN IF EXISTS adr_type;
+ALTER TABLE adr_attachments ADD COLUMN adr_type character varying(32) NOT NULL DEFAULT 'DOC';
+
+
+--convert result
+ALTER TABLE res_attachments DROP COLUMN IF EXISTS convert_result;
+ALTER TABLE res_attachments ADD COLUMN convert_result character varying(10) DEFAULT NULL::character varying;
+ALTER TABLE res_letterbox DROP COLUMN IF EXISTS convert_result;
+ALTER TABLE res_letterbox ADD COLUMN convert_result character varying(10) DEFAULT NULL::character varying;
+ALTER TABLE res_x DROP COLUMN IF EXISTS convert_result;
+ALTER TABLE res_x ADD COLUMN convert_result character varying(10) DEFAULT NULL::character varying;
+ALTER TABLE res_version_attachments DROP COLUMN IF EXISTS convert_result;
+ALTER TABLE res_version_attachments ADD COLUMN convert_result character varying(10) DEFAULT NULL::character varying;
+
+
+--thumbnails result
+ALTER TABLE res_attachments DROP COLUMN IF EXISTS tnl_result;
+ALTER TABLE res_attachments ADD COLUMN tnl_result character varying(10) DEFAULT NULL::character varying;
+ALTER TABLE res_letterbox DROP COLUMN IF EXISTS tnl_result;
+ALTER TABLE res_letterbox ADD COLUMN tnl_result character varying(10) DEFAULT NULL::character varying;
+ALTER TABLE res_x DROP COLUMN IF EXISTS tnl_result;
+ALTER TABLE res_x ADD COLUMN tnl_result character varying(10) DEFAULT NULL::character varying;
+ALTER TABLE res_version_attachments DROP COLUMN IF EXISTS tnl_result;
+ALTER TABLE res_version_attachments ADD COLUMN tnl_result character varying(10) DEFAULT NULL::character varying;
+
+
+-- ************************************************************************* --
+--                               DATAS                             --
+-- ************************************************************************* --
+
+-- docservers
+
+DELETE FROM docserver_types where docserver_type_id = 'CONVERT';
+INSERT INTO docserver_types (docserver_type_id, docserver_type_label, enabled, is_container, container_max_number, is_compressed, compression_mode, is_meta, meta_template, is_logged, log_template, is_signed, fingerprint_mode) 
+VALUES ('CONVERT', 'Conversions', 'Y', 'N', 0, 'N', 'NONE', 'N', 'NONE', 'N', 'NONE', 'Y', 'NONE');
+
+DELETE FROM docservers where docserver_id = 'CONVERT_MLB';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('CONVERT_MLB', 'CONVERT', 'Server for mlb documents conversion', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/convert_mlb/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'letterbox_coll', 13, 'NANTERRE', 4);
+
+DELETE FROM docservers where docserver_id = 'FASTHD_ATTACH';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('FASTHD_ATTACH', 'FASTHD', 'Fast internal disc bay for attachments', 'N', 'Y', 50000000000, 1, '/opt/maarch/docservers/manual_attachments/', NULL, NULL, NULL, '2011-01-13 14:47:49.197164', NULL, 'attachments_coll', 2, 'NANTERRE', 3);
+
+DELETE FROM docservers where docserver_id = 'FASTHD_ATTACH_VERSION';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('FASTHD_ATTACH_VERSION', 'FASTHD', 'Fast internal disc bay for attachments version', 'N', 'Y', 50000000000, 1, '/opt/maarch/docservers/manual_attachments_version/', NULL, NULL, NULL, '2011-01-13 14:47:49.197164', NULL, 'attachments_version_coll', 100, 'NANTERRE', 100);
+
+DELETE FROM docservers where docserver_id = 'CONVERT_ATTACH';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('CONVERT_ATTACH', 'CONVERT', 'Server for attachments documents conversion', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/convert_attachments/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'attachments_coll', 14, 'NANTERRE', 5);
+
+DELETE FROM docservers where docserver_id = 'CONVERT_ATTACH_VERSION';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('CONVERT_ATTACH_VERSION', 'CONVERT', 'Server for attachments version documents conversion', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/convert_attachments_version/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'attachments_version_coll', 101, 'NANTERRE', 101);
+
+-- for thumbnails, attachments and fulltext :
+DELETE FROM docservers where docserver_id = 'TNL_ATTACH';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('TNL_ATTACH', 'TNL', 'Server for thumbnails of attachments', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/thumbnails_attachments/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'attachments_coll', 15, 'NANTERRE', 6);
+
+DELETE FROM docservers where docserver_id = 'TNL_ATTACH_VERSION';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('TNL_ATTACH_VERSION', 'TNL', 'Server for thumbnails of attachments version', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/thumbnails_attachments_version/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'attachments_version_coll', 102, 'NANTERRE', 102);
+
+update docservers set docserver_id = 'TNL_MLB', priority_number = 12 where docserver_id = 'TNL';
+
+DELETE FROM docserver_types where docserver_type_id = 'FULLTEXT';
+INSERT INTO docserver_types (docserver_type_id, docserver_type_label, enabled, is_container, container_max_number, is_compressed, compression_mode, is_meta, meta_template, is_logged, log_template, is_signed, fingerprint_mode) 
+VALUES ('FULLTEXT', 'Fulltext', 'Y', 'N', 0, 'N', 'NONE', 'N', 'NONE', 'N', 'NONE', 'Y', 'NONE');
+
+DELETE FROM docservers where docserver_id = 'FULLTEXT_MLB';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('FULLTEXT_MLB', 'FULLTEXT', 'Server for mlb documents fulltext', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/fulltext_mlb/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'letterbox_coll', 16, 'NANTERRE', 7);
+
+DELETE FROM docservers where docserver_id = 'FULLTEXT_ATTACH';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('FULLTEXT_ATTACH', 'FULLTEXT', 'Server for attachments documents fulltext', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/fulltext_attachments/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'attachments_coll', 17, 'NANTERRE', 8);
+
+DELETE FROM docservers where docserver_id = 'FULLTEXT_ATTACH_VERSION';
+INSERT INTO docservers (docserver_id, docserver_type_id, device_label, is_readonly, enabled, size_limit_number, actual_size_number, path_template, ext_docserver_info, chain_before, chain_after, creation_date, closing_date, coll_id, priority_number, docserver_location_id, adr_priority_number) 
+VALUES ('FULLTEXT_ATTACH_VERSION', 'FULLTEXT', 'Server for attachments version documents fulltext', 'N', 'Y', 50000000000, 0, '/opt/maarch/docservers/fulltext_attachments_version/', NULL, NULL, NULL, '2015-03-16 14:47:49.197164', NULL, 'attachments_version_coll', 103, 'NANTERRE', 103);
+
diff --git a/modules/convert/css/module.css b/modules/convert/css/module.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/modules/convert/js/functions.js b/modules/convert/js/functions.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f7c77da42a31858501935467493f7aa968f0a4c
--- /dev/null
+++ b/modules/convert/js/functions.js
@@ -0,0 +1 @@
+//
diff --git a/modules/convert/lang/en.php b/modules/convert/lang/en.php
new file mode 100644
index 0000000000000000000000000000000000000000..533aa85eecca7405c8c34c5f83cf57b2ae158861
--- /dev/null
+++ b/modules/convert/lang/en.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ *
+ *   Copyright 2008-2016 Maarch
+ *
+ *   This file is part of Maarch Framework.
+ *
+ *   Maarch Framework is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Maarch Framework is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
diff --git a/modules/convert/lang/fr.php b/modules/convert/lang/fr.php
new file mode 100644
index 0000000000000000000000000000000000000000..533aa85eecca7405c8c34c5f83cf57b2ae158861
--- /dev/null
+++ b/modules/convert/lang/fr.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ *
+ *   Copyright 2008-2016 Maarch
+ *
+ *   This file is part of Maarch Framework.
+ *
+ *   Maarch Framework is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Maarch Framework is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
diff --git a/modules/convert/optimizeLuceneIndex.php b/modules/convert/optimizeLuceneIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..bb022b92bd69f9c5bf93ff267392e6ba0db9ae9b
--- /dev/null
+++ b/modules/convert/optimizeLuceneIndex.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+*   Copyright 2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process fulltext class
+*
+* <ul>
+* <li>Services to process the fulltext of resources</li>
+* </ul>
+*
+* @file
+* @author <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+	if(strpos($_SERVER['argv'][1], '/indexes/') >= 0){
+
+		$_ENV['maarch_tools_path'] = $_SERVER['argv'][2].'/apps/maarch_entreprise/tools/';
+
+		// Storing text in lucene index
+		set_include_path('../../../apps/maarch_entreprise/tools/' . PATH_SEPARATOR . get_include_path());
+
+		if(!@include('Zend/Search/Lucene.php')) {
+		    set_include_path('apps/maarch_entreprise/tools/'. PATH_SEPARATOR . get_include_path()
+		    );
+		    require_once("Zend/Search/Lucene.php");
+		}
+		require_once 'Zend/Search/Lucene/Storage/File/Filesystem.php';
+		require_once 'Zend/Search/Lucene/Storage/Directory/Filesystem.php';
+
+		$directory = new Zend_Search_Lucene_Storage_Directory_Filesystem((string) $_SERVER['argv'][1]);
+
+		$testDir = Zend_Search_Lucene::getActualGeneration($directory);
+
+		if ($testDir != -1) {
+			$index = Zend_Search_Lucene::open((string) $_SERVER['argv'][1]);
+
+			if (!empty($index)) {
+				$index->setFormatVersion(Zend_Search_Lucene::FORMAT_2_3);
+				Zend_Search_Lucene_Analysis_Analyzer::setDefault(
+					new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
+				);
+				$index->optimize();
+			}
+		}
+
+	}
+
+
+?>
diff --git a/modules/convert/services/ManageConvert.php b/modules/convert/services/ManageConvert.php
new file mode 100644
index 0000000000000000000000000000000000000000..37bde281c5ea3f7934912ec18164f63f9fd110b5
--- /dev/null
+++ b/modules/convert/services/ManageConvert.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief Manage convert class
+*
+* <ul>
+* <li>Services to Manage the convertion of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+
+require_once 'modules/convert/services/ManageConvertAbstract.php';
+
+class Convert_ManageConvert_Service extends Convert_ManageConvertAbstract_Service {
+	
+	
+}
diff --git a/modules/convert/services/ManageConvertAbstract.php b/modules/convert/services/ManageConvertAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc0980e5cdeaf2dac35a65fa659d6b09615612f6
--- /dev/null
+++ b/modules/convert/services/ManageConvertAbstract.php
@@ -0,0 +1,164 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief Manage convert class
+*
+* <ul>
+* <li>Services to Manage the convertion of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+require_once 'core/services/Abstract.php';
+require_once 'core/class/class_functions.php';
+require_once 'core/class/class_db_pdo.php';
+require_once 'core/class/class_db.php';
+require_once 'core/docservers_tools.php';
+require_once 'core/class/docservers_controler.php';
+require_once 'core/services/ManageDocservers.php';
+require_once 'modules/convert/services/ProcessConvert.php';
+require_once 'modules/convert/services/ProcessThumbnails.php';
+require_once 'modules/convert/services/ProcessFulltext.php';
+
+class Convert_ManageConvertAbstract_Service extends Core_Abstract_Service {
+
+    /**
+     * Ask for conversion in all mode
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @throws Exception Check des valeurs d'entrées
+     * @return array $returnArray the result
+     */
+    public function convertAll(array $args=[])
+    {
+        $timestart = microtime(true);
+        // Prés-requis :
+        $this->checkRequired($args, ['collId','resTable','adrTable','resId',]);
+        $this->checkNumeric($args, ['resId',]);
+        $this->checkString($args, ['collId','resTable','adrTable',]);
+
+        // Variabilisation :
+        $returnArray = array();
+        $collId      = $args['collId'];
+        $resTable    = $args['resTable'];
+        $adrTable    = $args['adrTable'];
+        $resId       = $args['resId'];
+        
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        $path_to_lucene = '';
+        if (isset($args['path_to_lucene']) && !empty($args['path_to_lucene'])){
+            $path_to_lucene = $args['path_to_lucene'];
+        }
+
+        $params = array(
+            'collId'         => $collId, 
+            'resTable'       => $resTable, 
+            'adrTable'       => $adrTable, 
+            'resId'          => $resId,
+            'tmpDir'         => $tmpDir,
+            'path_to_lucene' => $path_to_lucene
+        );
+
+        //CONV
+        $ProcessConvertService = new Convert_ProcessConvert_Service();
+        $resultOfConversion = $ProcessConvertService->convert($params);
+        
+        if ($resultOfConversion['status'] <> '0') {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'CONV:' . $resultOfConversion['error'],
+            );
+            return $returnArray;
+        }
+
+        //TNL
+        $ProcessConvertService = new Convert_ProcessThumbnails_Service();
+        $resultOfConversion = $ProcessConvertService->thumbnails($params);
+        if ($resultOfConversion['status'] <> '0') {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'TNL:' . $resultOfConversion['error'],
+            );
+            return $returnArray;
+        }
+
+        //FULLTEXT
+        if (!empty($args['zendIndex'])) {
+            $zendIndex = $args['zendIndex'];
+            $params = array(
+                'collId'         => $collId, 
+                'resTable'       => $resTable, 
+                'adrTable'       => $adrTable, 
+                'resId'          => $resId,
+                'tmpDir'         => $tmpDir,
+                'path_to_lucene' => $path_to_lucene,
+                'zendIndex'      => $zendIndex
+            );
+        } else {
+            $params = array(
+                'collId'         => $collId, 
+                'resTable'       => $resTable, 
+                'adrTable'       => $adrTable, 
+                'resId'          => $resId,
+                'tmpDir'         => $tmpDir,
+                'path_to_lucene' => $path_to_lucene
+            );
+        }
+        $ProcessConvertService = new Convert_ProcessFulltext_Service();
+        $resultOfConversion = $ProcessConvertService->fulltext($params);
+        if ($resultOfConversion['status'] <> '0') {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'TXT:' . $resultOfConversion['error'],
+            );
+            Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ManageConvertAbstract_Service::convertAll aucun contenu a indexer dans fulltext');
+            return $returnArray;
+        }
+        
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ManageConvertAbstract_Service::convertAll');
+        return $returnArray;
+    }
+
+}
diff --git a/modules/convert/services/ProcessConvert.php b/modules/convert/services/ProcessConvert.php
new file mode 100644
index 0000000000000000000000000000000000000000..6cde4c768237ae5e961a88037cad129c4ed0c22b
--- /dev/null
+++ b/modules/convert/services/ProcessConvert.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process convert class
+*
+* <ul>
+* <li>Services to process the convertion of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+
+require_once 'modules/convert/services/ProcessConvertAbstract.php';
+
+class Convert_ProcessConvert_Service extends Convert_ProcessConvertAbstract_Service {
+	
+	
+}
diff --git a/modules/convert/services/ProcessConvertAbstract.php b/modules/convert/services/ProcessConvertAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..d5c079ed4fd800340467063ac26ffb53c95095ed
--- /dev/null
+++ b/modules/convert/services/ProcessConvertAbstract.php
@@ -0,0 +1,592 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process convert class
+*
+* <ul>
+* <li>Services to process the convertion of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+
+require_once 'core/services/Abstract.php';
+require_once 'core/class/class_functions.php';
+require_once 'core/class/class_db_pdo.php';
+require_once 'core/class/class_db.php';
+require_once 'core/docservers_tools.php';
+require_once 'core/class/docservers_controler.php';
+require_once 'core/services/ManageDocservers.php';
+
+class Convert_ProcessConvertAbstract_Service extends Core_Abstract_Service {
+
+    protected $libreOfficeExecutable;
+
+    //public function __construct($libreOfficeExecutable = 'cloudooo')
+    public function __construct($libreOfficeExecutable = 'soffice')
+    //public function __construct($libreOfficeExecutable = 'unoconv')
+    {
+        $this->libreOfficeExecutable = $libreOfficeExecutable;
+    }
+
+    /**
+     * Ask for conversion
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @param array $tgtfmt array of target format
+     * @return array $returnArray the result
+     */
+    public function convert(array $args=[])
+    {
+        $timestart = microtime(true);
+        // Core_Logs_Service::info(['message'=>'debut convert', 'code'=>111, ]);
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        $dbConv = new Database($GLOBALS['configFile']);
+        
+        //retrieve path of the resource
+        $stmtConv = $dbConv->query("select * from " . $resTable 
+            . " where res_id = ?", array($resId)
+        );
+        $line = $stmtConv->fetchObject();
+        $ManageDocservers = new Core_ManageDocservers_Service();
+        if ($line->res_id <> '') {
+            $resourcePath = $ManageDocservers->getSourceResourcePath(
+                $resTable, 
+                $adrTable, 
+                $line->res_id,
+                'DOC'
+            );
+        }
+        if (!file_exists($resourcePath)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'file not exists : ' . $resourcePath,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the resource on tmp directory
+        $fileNameOnTmp = $tmpDir . rand() . rand();
+        if (!copy($resourcePath, $fileNameOnTmp)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'copy on tmp failed',
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //now do the conversion !
+        if (strtoupper($line->format) <> 'PDF') {
+            $resultOfConversion = $this->launchConvert(
+                $fileNameOnTmp, 
+                'pdf', 
+                $tmpDir,
+                pathinfo($resourcePath, PATHINFO_EXTENSION)
+            );
+        } else {
+            //echo $fileNameOnTmp;
+            copy($fileNameOnTmp, $fileNameOnTmp . '.pdf');
+            $resultOfConversion = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        }
+        
+        if ($resultOfConversion['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfConversion;
+        }
+        //find the target docserver
+        $targetDs = $ManageDocservers->findTargetDs($collId);
+        if (empty($targetDs)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'Ds of collection not found:' . $collId,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the result on docserver
+        // Core_Logs_Service::info(['message'=>'avant cp ds', 'code'=>1112, ]);
+        $resultCopyDs = $ManageDocservers->copyResOnDS($fileNameOnTmp . '.pdf', $targetDs);
+        if ($resultCopyDs['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultCopyDs;
+        }
+        // Core_Logs_Service::info(['message'=>'avant update', 'code'=>19, ]);
+        //update the database
+        $resultOfUpDb = $this->updateDatabase(
+            $collId,
+            $resTable, 
+            $adrTable, 
+            $resId,
+            $targetDs,
+            $resultCopyDs['value']['destinationDir'],
+            $resultCopyDs['value']['fileDestinationName']
+        );
+        // Core_Logs_Service::info(['message'=>var_export($resultOfUpDb, true), 'code'=>111111, ]);
+        // Core_Logs_Service::info(['message'=>$collId, 'code'=>2, ]);
+        // Core_Logs_Service::info(['message'=>$resTable, 'code'=>3, ]);
+        // Core_Logs_Service::info(['message'=>$adrTable, 'code'=>4, ]);
+        // Core_Logs_Service::info(['message'=>$resId, 'code'=>5, ]);
+        // Core_Logs_Service::info(['message'=>'apres res_id', 'code'=>6, ]);
+        // Core_Logs_Service::info(['message'=>$targetDs, 'code'=>6, ]);
+        // Core_Logs_Service::info(['message'=>var_export($resultCopyDs, true), 'code'=>7, ]);
+
+        if ($resultOfUpDb['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfUpDb;
+        }
+
+        unlink($fileNameOnTmp);
+        unlink($fileNameOnTmp . '.pdf');
+
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessConvertAbstract_Service::convert');
+        return $returnArray;
+    }
+
+    /**
+     * Launch the conversion
+     *
+     * @param string $srcfile source file
+     * @param string $tgtfmt target format
+     * @param string $tgtdir target dir
+     * @param string $srcfmt source format
+     * @return array $returnArray the result
+     */
+    public function launchConvert(
+        $srcfile, 
+        $tgtfmt, 
+        $tgtdir=false, 
+        $srcfmt=null
+    ) {
+		$timestart=microtime(true);
+
+        $processHtml = false;
+		$executable='';
+		
+        Core_Logs_Service::info(['message'=>'[TIMER] Debut Convert_ProcessConvertAbstract_Service::launchConvert']);
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            $processHtml = true;
+            Core_Logs_Service::info(['message'=>'[TIMER] srcfmt ' . $srcfmt]);
+            copy($srcfile, str_ireplace('.maarch', '.', $srcfile) . '.html');
+            if (file_exists('/usr/bin/mywkhtmltopdf')) {
+                $command = "mywkhtmltopdf " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.pdf');
+            } else {
+                $envVar = "export DISPLAY=FRPAROEMINT:0.0 ; ";
+                $command = $envVar . "wkhtmltopdf " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.pdf');
+            }
+			$executable='wkhtmltopdf';
+        } else {
+			$executable='soffice';
+            Core_Logs_Service::info(['message'=>'[TIMER] let LO do it ' . $this->libreOfficeExecutable]);
+            if ($this->libreOfficeExecutable == "cloudooo") {
+                $serverAddress = "http://192.168.21.40:8011";
+                $tokens = array();
+                require_once 'apps/maarch_entreprise/tools/phpxmlrpc/lib/xmlrpc.inc';
+                require_once 'apps/maarch_entreprise/tools/phpxmlrpc/lib/xmlrpcs.inc';
+                require_once 'apps/maarch_entreprise/tools/phpxmlrpc/lib/xmlrpc_wrappers.inc';
+                $fileContent = file_get_contents($srcfile, FILE_BINARY);
+                $encodedContent = base64_encode($fileContent);
+                $params = array();
+                array_push($params, new PhpXmlRpc\Value($encodedContent));
+                array_push($params, new PhpXmlRpc\Value($srcfmt));
+                array_push($params, new PhpXmlRpc\Value($tgtfmt));
+                array_push($params, new PhpXmlRpc\Value(false));
+                $v = new PhpXmlRpc\Value($params, "array");
+            } elseif ($this->libreOfficeExecutable == "unoconv") {
+                $tokens = array('"' . $this->libreOfficeExecutable . '"');
+                $tokens[] = "-f";
+                $tokens[] = $tgtfmt;
+                $tokens[] = '-o "' . $srcfile . '.' . $tgtfmt . '"';
+                $tokens[] = '"' . $srcfile . '"';
+            } else {
+                $tokens = array('"' . $this->libreOfficeExecutable . '"');
+                $tokens[] = "--headless";
+                $tokens[] = "--convert-to";
+                $tokens[] = $tgtfmt;
+                $tokens[] = '"' . $srcfile . '"';
+                if (!$tgtdir) {
+                    $tgtdir = dirname($srcfile);
+                }
+                $tokens[] = '--outdir "' . $tgtdir . '"';
+            }
+            
+            if (!$srcfmt) {
+                $tokens[] = $srcfmt;
+            }
+
+            $command = implode(' ', $tokens);
+
+            $output = array();
+            $return = null;
+            $this->errors = array();
+        }
+        //echo $command . '<br />';exit;
+        if ($this->libreOfficeExecutable == "cloudooo" && !$processHtml) {
+            Core_Logs_Service::info(['message'=>'[TIMER] commande : cloudooo url ' . $serverAddress]);
+            Core_Logs_Service::info(['message'=>'[TIMER] Debut Convert_ProcessConvertAbstract_Service::launchConvert__exec']);
+            $req = new PhpXmlRpc\Request('convertFile', $v);
+            //Core_Logs_Service::info(['message'=>'[TIMER] commande : cloudooo url ' . $serverAddress]);
+            Core_Logs_Service::info(['message'=>'[TIMER] Fin Convert_ProcessConvertAbstract_Service::launchConvert__exec']);
+            $client = new PhpXmlRpc\Client($serverAddress);
+            $resp = $client->send($req);
+            if (!$resp->faultCode()) {
+                $encoder = new PhpXmlRpc\Encoder();
+                $value = $encoder->decode($resp->value());
+                $theFile = fopen($srcfile . '.' . $tgtfmt, 'w+');
+                fwrite($theFile, base64_decode($value));
+                fclose($theFile);
+                $returnArray = array(
+                    'status' => '0',
+                    'value' => '',
+                    'error' => '',
+                );
+            } else {
+                //print "An error occurred: ";
+                //print "Code: " . htmlspecialchars($resp->faultCode()) 
+                //    . " Reason: '" . htmlspecialchars($resp->faultString()) . "'\n";
+                $returnArray = array(
+                    'status' => '1',
+                    'value' => '',
+                    'error' => "Code: " . htmlspecialchars($resp->faultCode()) 
+                        . " Reason: '" . htmlspecialchars($resp->faultString()),
+                );
+            }
+        } else {
+		    $timestart_command = microtime(true);
+		    exec("timeout -k 5m 3m " . $command, $output, $return);
+		    Core_Logs_Service::debug(['message'=>'[TIMER] commande : ' . $command]);
+		    Core_Logs_Service::executionTimeLog($timestart_command, '', 'info', '[TIMER] ' . $executable . ' - Convert_ProcessConvertAbstract_Service::launchConvert__exec');
+		    if ($return === 0) {
+		        $returnArray = array(
+		            'status' => '0',
+		            'value' => '',
+		            'error' => '',
+		        );
+		    } else {
+		        $returnArray = array(
+		            'status' => '1',
+		            'value' => '',
+		            'error' => $return . $output,
+		        );
+		    }
+        }
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            $returnArray = array();
+            unlink(str_ireplace('.maarch', '.', $srcfile) . '.html');
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        }
+        Core_Logs_Service::executionTimeLog($timestart, '', 'info', '[TIMER] Fin Convert_ProcessConvertAbstract_Service::launchConvert');
+        return $returnArray;
+    }
+
+    /**
+     * Updating the database with the location information of the document on the
+     * new docserver
+     * @param string $collId collection
+     * @param string $resTable res table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process
+     * @param docserver $docserver docserver object
+     * @param string $path location of the resource on the docserver
+     * @param string $fileName file name of the resource on the docserver
+     * @return array $returnArray the result
+     */
+    private function updateDatabase(
+        $collId, 
+        $resTable, 
+        $adrTable, 
+        $resId,
+        $docserver,
+        $path, 
+        $fileName
+    ) {
+        try {
+            $docserver->path_template = str_replace(
+                DIRECTORY_SEPARATOR, 
+                '#', 
+                $docserver->path_template
+            );
+            $path = str_replace($docserver->path_template, '', $path);
+            $dbConv = new Database($GLOBALS['configFile']);
+            $query = "update convert_stack set status = 'P' where "
+               . " coll_id = ? and res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $collId,
+                    $resId
+                )
+            );
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? order by adr_priority";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "select docserver_id, path, filename, offset_doc, fingerprint"
+                       . " from " . $resTable . " where res_id = ?";
+                $stmt = $dbConv->query($query, array($resId));
+                $recordset = $stmt->fetchObject();
+                // Core_Logs_Service::info(['message'=>$recordset, 'code'=>8, ]);
+                $resDocserverId = $recordset->docserver_id;
+                $resPath = $recordset->path;
+                $resFilename = $recordset->filename;
+                $resOffsetDoc = $recordset->offset_doc;
+                $fingerprintInit = $recordset->fingerprint;
+                $query = "select adr_priority_number from docservers "
+                       . " where docserver_id = ?";
+                $stmt = $dbConv->query($query, array($resDocserverId));
+                $recordset = $stmt->fetchObject();
+                $query = "insert into " . $adrTable . " (res_id, "
+                       . "docserver_id, path, filename, offset_doc, fingerprint, "
+                       . "adr_priority) values (?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $resDocserverId,
+                        $resPath,
+                        $resFilename,
+                        $resOffsetDoc,
+                        $fingerprintInit,
+                        $recordset->adr_priority_number
+                    )
+                );
+            }
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? and adr_type = 'CONV'";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "insert into " . $adrTable . " (res_id, docserver_id, "
+                   . "path, filename, offset_doc, fingerprint, adr_priority, adr_type) values (" 
+                   . "?, ?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        'CONV'
+                    )
+                );
+            } else {
+                $query = "update " . $adrTable . " set docserver_id = ?, "
+                   . " path = ?, filename = ?, offset_doc = ?, fingerprint = ?, adr_priority = ?"
+                   . " where res_id = ? and adr_type = ? ";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        $resId,
+                        'CONV'
+                    )
+                );
+            }
+            if ($_SESSION['user']['UserId'] <> '') {
+                $user = $_SESSION['user']['UserId'];
+            } else {
+                $user = 'CONVERT_BOT';
+            }
+            $query = "insert into history (table_name, record_id, "
+                   . "event_type, user_id, event_date, info, id_module) values (" 
+                   . "?, ?, 'ADD', '" . $user . "', " 
+                   . $dbConv->current_datetime() 
+                   . ", ?, 'convert')";
+            $stmt = $dbConv->query( 
+                $query, 
+                array(
+                    $resTable,
+                    $resId,
+                    "process convert done"
+                )
+            );
+
+            $queryCpt = "select coalesce(custom_t9, '0') as custom_t9 from " . $resTable 
+                . " where res_id = ?";
+            $stmtCpt = $dbConv->query($queryCpt, array($resId));
+            $rsCpt = $stmtCpt->fetchObject();
+            $cptConvert = $rsCpt->custom_t9 + 1;
+
+            $query = "update " . $resTable 
+                . " set convert_result = '1', is_multi_docservers = 'Y', custom_t9 = '" . $cptConvert . "' where "
+                . " res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $resId
+                )
+            );
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } catch (Exception $e) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $e->getMessage(),
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+     * Updating the database with the error code
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @param string $result error code
+     * @return nothing
+     */
+    private function manageErrorOnDb(
+        $resTable, 
+        $resId,
+        $result
+    ) {
+        $dbConv = new Database($GLOBALS['configFile']);
+        $query = "update " . $resTable 
+            . " set convert_result = ? where "
+            . " res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $result,
+                $resId
+            )
+        );
+    }
+
+    /**
+     * Test if the record is already processed by convert module
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @return boolean
+     */
+    public function isAlreadyProcessedByConvert(
+        $resTable, 
+        $resId
+    ) {
+        $dbConv = new Database($GLOBALS['configFile']);
+        $query = "select convert_result from " . $resTable 
+            . "  where res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $resId
+            )
+        );
+        $rs = $stmt->fetchObject();
+        if (
+            empty($rs->convert_result) || 
+            $rs->convert_result == '0'
+        ) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
diff --git a/modules/convert/services/ProcessFulltext.php b/modules/convert/services/ProcessFulltext.php
new file mode 100644
index 0000000000000000000000000000000000000000..8911aab6863da64caee87971f19f9e052e3d0f14
--- /dev/null
+++ b/modules/convert/services/ProcessFulltext.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process fulltext class
+*
+* <ul>
+* <li>Services to process the fulltext of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+
+require_once 'modules/convert/services/ProcessFulltextAbstract.php';
+
+class Convert_ProcessFulltext_Service extends Convert_ProcessFulltextAbstract_Service {
+	
+	
+}
diff --git a/modules/convert/services/ProcessFulltextAbstract.php b/modules/convert/services/ProcessFulltextAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..3a7e7f8cfa2817b62766c1cdd3eb146cf16a6188
--- /dev/null
+++ b/modules/convert/services/ProcessFulltextAbstract.php
@@ -0,0 +1,740 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process fulltext class
+*
+* <ul>
+* <li>Services to process the fulltext of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+require_once 'core/services/Abstract.php';
+require_once 'core/class/class_functions.php';
+require_once 'core/class/class_db_pdo.php';
+require_once 'core/class/class_db.php';
+require_once 'core/docservers_tools.php';
+require_once 'core/class/docservers_controler.php';
+require_once 'core/services/ManageDocservers.php';
+
+// Storing text in lucene index
+set_include_path('apps/maarch_entreprise/tools/' 
+    . PATH_SEPARATOR . get_include_path()
+);
+
+if(!@include('Zend/Search/Lucene.php')) {
+    set_include_path($GLOBALS['MaarchDirectory'].'apps/maarch_entreprise/tools/' 
+        . PATH_SEPARATOR . get_include_path()
+    );
+    if(!@include('Zend/Search/Lucene.php')) {
+    set_include_path('/var/www/oem/apps/maarch_entreprise/tools/' 
+        . PATH_SEPARATOR . get_include_path()
+    );
+    }
+    require_once("Zend/Search/Lucene.php");
+}
+
+//include_once('html2text/html2text.php');
+
+class Convert_ProcessFulltextAbstract_Service extends Core_Abstract_Service {
+
+    protected $pdftotext;
+
+    public function __construct($pdftotext = 'pdftotext')
+    {
+        $this->pdftotext = $pdftotext;
+    }
+
+    /**
+     * Ask for fulltext
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @param array $tgtfmt array of target format
+     * @return array $returnArray the result
+     */
+    public function fulltext(array $args=[])
+    {
+        $timestart = microtime(true);
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        // if (empty($args['batchMode'])) {
+        //     $batchMode = false;
+        // } else {
+        //     $batchMode = $args['batchMode'];
+        // }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty for fulltext',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        if(isset($args['path_to_lucene']) && !empty($args['path_to_lucene'])){
+            $indexFileDirectory = $args['path_to_lucene'];
+        } else {
+            $countColl = count($_SESSION['collections']);
+            for ($i=0;$i<$countColl;$i++) {
+                if ($_SESSION['collections'][$i]['id'] == $collId) {
+                    $indexFileDirectory 
+                        = $_SESSION['collections'][$i]['path_to_lucene_index'];
+                }
+            }
+        }
+
+        $dbConv = new Database($GLOBALS['configFile']);
+        
+        //retrieve path of the resource
+        $stmtConv = $dbConv->query("select * from " . $resTable 
+            . " where res_id = ?", array($resId)
+        );
+        $line = $stmtConv->fetchObject();
+        $ManageDocservers = new Core_ManageDocservers_Service();
+        if ($line->res_id <> '')  {
+            $resourcePath = $ManageDocservers->getSourceResourcePath(
+                $resTable, 
+                $adrTable, 
+                $line->res_id, 
+                'CONV'
+            );
+        }
+        if (!file_exists($resourcePath)) {
+            $returnArray = array(
+                'status' => '2',
+                'value' => '',
+                'error' => 'file not already converted in pdf for fulltext. path :' 
+                    . $resourcePath . ", adrType : CONV, adr_table : " . $adrTable,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the resource on tmp directory
+        $fileNameOnTmp = $tmpDir . rand() . rand();
+        if (!copy($resourcePath, $fileNameOnTmp)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'copy on tmp failed for fulltext. Copy ' . $resourcePath . ' to ' . $fileNameOnTmp,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //now do the fulltext !
+        if (!empty($args['zendIndex'])) {
+            $resultOfConversion = $this->launchFulltext(
+                $fileNameOnTmp, 
+                $resId, 
+                $indexFileDirectory, 
+                $tmpDir,
+                $args['zendIndex']
+            );
+        } else {
+            $resultOfConversion = $this->launchFulltext(
+                $fileNameOnTmp, 
+                $resId, 
+                $indexFileDirectory, 
+                $tmpDir
+            );
+        }
+        
+        
+        if ($resultOfConversion['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessFulltextAbstract_Service::fulltext aucunContenuAIndexer');
+            return $resultOfConversion;
+        }
+        //find the target docserver
+        $targetDs = $ManageDocservers->findTargetDs($collId, 'FULLTEXT');
+        if (empty($targetDs)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'Ds of collection and ds type not found for fulltext:' 
+                    . $collId . ' FULLTEXT',
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the result on docserver
+        $resultCopyDs = $ManageDocservers->copyResOnDS($fileNameOnTmp . '.txt', $targetDs);
+        if ($resultCopyDs['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultCopyDs;
+        }
+        //update the database
+        $resultOfUpDb = $this->updateDatabase(
+            $collId,
+            $resTable, 
+            $adrTable, 
+            $resId,
+            $targetDs,
+            $resultCopyDs['value']['destinationDir'],
+            $resultCopyDs['value']['fileDestinationName'],
+            $args['zendIndex']
+        );
+        if ($resultOfUpDb['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfUpDb;
+        }
+
+        unlink($fileNameOnTmp);
+        unlink($fileNameOnTmp . '.txt');
+
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessFulltextAbstract_Service::fulltext');
+        return $returnArray;
+    }
+
+    /**
+     * Launch the fulltext process
+     *
+     * @param string $srcfile source file
+     * @param string $tgtdir target dir
+     * @param string $srcfmt source format
+     * @return array $returnArray the result
+     */
+    private function launchFulltext(
+        $srcfile, 
+        $resId,
+        $indexFileDirectory, 
+        $tgtdir=false,
+        $zendIndex=''
+    ) {
+        if (!empty($zendIndex)) {
+            $return = $this->prepareIndexFullTextPdf(
+                $srcfile, 
+                $tgtdir, 
+                $indexFileDirectory,
+                $resId,
+                $zendIndex
+            );
+        } else {
+            $return = $this->prepareIndexFullTextPdf(
+                $srcfile, 
+                $tgtdir, 
+                $indexFileDirectory,
+                $resId
+            );
+        }
+        
+        if ($return === 0) {
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } else {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $return . $output,
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+    * Read a txt file
+    * @param  $file string path of the file to read
+    * @return string contents of the file
+    */
+    private function readFileF($file)
+    {
+        $result = "";
+        if (is_file($file)) {
+            $fp = fopen($file, "r");
+            $result = fread($fp, filesize($file));
+            fclose($fp);
+        }
+        return $result;
+    }
+
+    private function prepareIndexFullTextPdf($pathToFile, $tmpDir, $indexFileDirectory, $resId, $zendIndex)
+    {
+        $timestart = microtime(true);
+        if (is_file($pathToFile)) {
+            $tmpFile = $tmpDir . basename($pathToFile) . ".txt";
+            // if ($_ENV['osname'] == "WINDOWS") {
+            //     $resultExtraction = exec(escapeshellarg($_ENV['maarch_tools_path'] . "pdftotext"
+            //         . DIRECTORY_SEPARATOR . $_ENV['pdftotext']) . " "
+            //         . escapeshellarg($pathToFile) . " " . escapeshellarg($tmpFile)
+            //     );
+            // } elseif ($_ENV['osname'] == "UNIX") {
+                // $resultExtraction = exec("pdftotext -enc UTF-8 " . escapeshellarg($pathToFile)
+                //     . " " . escapeshellarg($tmpFile) 
+                // );
+            $timestart_fulltext = microtime(true);
+            $resultExtraction = exec("pdftotext " . escapeshellarg($pathToFile)
+                    . " " . escapeshellarg($tmpFile) 
+                );
+            Core_Logs_Service::executionTimeLog($timestart_fulltext, '', 'debug', '[TIMER] Convert_ProcessFulltextAbstract_Service::prepareIndexFullTextPdf__exec');
+            //}
+            // echo "pdftotext " . escapeshellarg($pathToFile)
+            //         . " " . escapeshellarg($tmpFile) . '<br/><br/><br/>';
+            $fileContent = trim($this->readFileF($tmpFile));
+            //echo $fileContent . '<br />';
+            //exit;
+            //echo $tmpFile . '<br />';
+            //echo $indexFileDirectory . '<br />';
+            //echo $resId . '<br />';
+            if (!empty($zendIndex)) {
+                $result = $this->launchIndexFullTextWithZendIndex(
+                        $fileContent, 
+                        $indexFileDirectory, 
+                        $resId, 
+                        $zendIndex
+                );
+            } else {
+                // TODO : will be done only by the batch convert in OnlyIndexes mode
+                //$result = $this->launchIndexFullText($fileContent, $indexFileDirectory, $resId);
+                $result = 0;
+            }
+            
+        } else {
+            $result = 'file not found ' . $pathToFile;
+        }
+        Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessFulltextAbstract_Service::prepareIndexFullTextPdf');
+        return $result;
+    }
+
+    /**
+    * Return zend index object for batch mode
+    * @param  $indexFileDirectory string directory of the lucene index
+    * @return zend index object
+    */
+    public function createZendIndexObject($tempIndexFileDirectory, $numberOfIndexes = 1000) 
+    {
+        //echo 'createZendIndexObject : ' . $numberOfIndexes . PHP_EOL;
+        $func = new functions();
+        $indexFileDirectory = (string) $tempIndexFileDirectory; 
+        // with version 1.12, we need a string, not an XML element
+        
+        if (!is_dir($indexFileDirectory)) {
+            $index = Zend_Search_Lucene::create($indexFileDirectory);
+        } else {
+            if ($func->isDirEmpty($indexFileDirectory)) {
+                $index = Zend_Search_Lucene::create($indexFileDirectory);
+            } else {
+                $index = Zend_Search_Lucene::open($indexFileDirectory);
+            }
+        }
+        $index->setFormatVersion(Zend_Search_Lucene::FORMAT_2_3); 
+        // we set the lucene format to 2.3
+        Zend_Search_Lucene_Analysis_Analyzer::setDefault(
+            new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
+        );
+
+        //$index->MaxBufferedDocs();
+        $index->setMaxBufferedDocs($numberOfIndexes);
+
+        return $index;
+    }
+
+    /**
+    * Commit the zend index at the end of the batch
+    * @return nothing
+    */
+    public function commitZendIndex($index) 
+    {
+        //echo 'the commit' . PHP_EOL;
+        $index->commit();
+    }
+
+    /**
+    * Retrieve the text of a pdftext and launch the lucene engine
+    * @param  $pathToFile string path of the file to index
+    * @param  $indexFileDirectory string directory of the lucene index
+    * @param  $id integer id of the document to index
+    * @return integer user exit code is stored in fulltext_result column of the
+    * document in "res_x"
+    */
+    private function launchIndexFullText($fileContent, $tempIndexFileDirectory, $Id) 
+    {
+        // $IndexFileDirectory is replace by tempIndexFileDirectory
+        $func = new functions();
+        $fileContent = $func->normalize($fileContent);
+        $fileContent = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $fileContent);
+        $indexFileDirectory = (string) $tempIndexFileDirectory; 
+        // with version 1.12, we need a string, not an XML element
+        $result = -1;
+        if (strlen($fileContent) > 2) {
+            if (!is_dir($indexFileDirectory)) {
+                //$_ENV['logger']->write($indexFileDirectory . " not exists !", "ERROR", 2);
+                $index = Zend_Search_Lucene::create($indexFileDirectory);
+            } else {
+                if ($func->isDirEmpty($indexFileDirectory)) {
+                    //$_ENV['logger']->write($indexFileDirectory . " empty !");
+                    $index = Zend_Search_Lucene::create($indexFileDirectory);
+                } else {
+                    $index = Zend_Search_Lucene::open($indexFileDirectory);
+                }
+            }
+            $index->setFormatVersion(Zend_Search_Lucene::FORMAT_2_3); 
+            // we set the lucene format to 2.3
+            Zend_Search_Lucene_Analysis_Analyzer::setDefault(
+                new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
+            );
+            // we need utf8 for accents
+            $term = new Zend_Search_Lucene_Index_Term($Id, 'Id');
+            foreach ($index->termDocs($term) as $id) {
+                $index->delete($id);
+            }
+            //echo $fileContent;
+            $doc = new Zend_Search_Lucene_Document();
+            $doc->addField(Zend_Search_Lucene_Field::UnIndexed('Id', (integer) $Id));
+            $doc->addField(Zend_Search_Lucene_Field::UnStored(
+                'contents', $fileContent)
+            );
+            //$func->show_array($doc);
+            $index->addDocument($doc);
+            $index->commit();
+            //$func->show_array($index);
+            //$index->optimize();
+            $result = 0;
+        } else {
+            $result = 1;
+        }
+        return $result;
+    }
+
+    /**
+    * Retrieve the text of a pdftext and launch the lucene engine
+    * @param  $pathToFile string path of the file to index
+    * @param  $indexFileDirectory string directory of the lucene index
+    * @param  $id integer id of the document to index
+    * @return integer user exit code is stored in fulltext_result column of the
+    * document in "res_x"
+    */
+    private function launchIndexFullTextWithZendIndex($fileContent, $tempIndexFileDirectory, $Id, $index) 
+    {
+        //echo 'launchIndexFullTextWithZendIndex' . PHP_EOL;
+        // $IndexFileDirectory is replace by tempIndexFileDirectory
+        $func = new functions();
+        $fileContent = $func->normalize($fileContent);
+        $fileContent = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $fileContent);
+
+        // with version 1.12, we need a string, not an XML element
+        $result = -1;
+        if (strlen($fileContent) > 2) {
+            try {
+                // we need utf8 for accents
+                $term = new Zend_Search_Lucene_Index_Term($Id, 'Id');
+                foreach ($index->termDocs($term) as $id) {
+                    $index->delete($id);
+                }
+                //echo $fileContent;
+                $doc = new Zend_Search_Lucene_Document();
+                $doc->addField(Zend_Search_Lucene_Field::UnIndexed('Id', (integer) $Id));
+                $doc->addField(Zend_Search_Lucene_Field::UnStored(
+                    'contents', $fileContent)
+                );
+                //$func->show_array($doc);
+                $index->addDocument($doc);
+                //$index->commit();
+                //$func->show_array($index);
+                //$index->optimize();
+                $result = 0;
+            } catch (Exception $e) {
+                $result = $e->getMessage();
+            }
+            
+        } else if (strlen($fileContent) >= 0){
+            $result = 0;
+        }
+        return $result;
+    }
+
+    /**
+     * Updating the database with the location information of the document on the
+     * new docserver
+     * @param string $collId collection
+     * @param string $resTable res table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process
+     * @param docserver $docserver docserver object
+     * @param string $path location of the resource on the docserver
+     * @param string $fileName file name of the resource on the docserver
+     * @return array $returnArray the result
+     */
+    private function updateDatabase(
+        $collId, 
+        $resTable, 
+        $adrTable, 
+        $resId,
+        $docserver,
+        $path, 
+        $fileName,
+        $zendIndex = ''
+    ) {
+        try {
+            $docserver->path_template = str_replace(
+                DIRECTORY_SEPARATOR, 
+                '#', 
+                $docserver->path_template
+            );
+            $path = str_replace($docserver->path_template, '', $path);
+            $dbConv = new Database($GLOBALS['configFile']);
+            $query = "update convert_stack set status = 'P' where "
+               . " coll_id = ? and res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $collId,
+                    $resId
+                )
+            );
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? order by adr_priority";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "select docserver_id, path, filename, offset_doc, fingerprint"
+                       . " from " . $resTable . " where res_id = ?";
+                $stmt = $dbConv->query($query, array($resId));
+                $recordset = $stmt->fetchObject();
+                $resDocserverId = $recordset->docserver_id;
+                $resPath = $recordset->path;
+                $resFilename = $recordset->filename;
+                $resOffsetDoc = $recordset->offset_doc;
+                $fingerprintInit = $recordset->fingerprint;
+                $query = "select adr_priority_number from docservers "
+                       . " where docserver_id = ?";
+                $stmt = $dbConv->query($query, array($resDocserverId));
+                $recordset = $stmt->fetchObject();
+                $query = "insert into " . $adrTable . " (res_id, "
+                       . "docserver_id, path, filename, offset_doc, fingerprint, "
+                       . "adr_priority) values (?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $resDocserverId,
+                        $resPath,
+                        $resFilename,
+                        $resOffsetDoc,
+                        $fingerprintInit,
+                        $recordset->adr_priority_number
+                    )
+                );
+            }
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? and adr_type = 'TXT'";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "insert into " . $adrTable . " (res_id, docserver_id, "
+                   . "path, filename, offset_doc, fingerprint, adr_priority, adr_type) values (" 
+                   . "?, ?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        'TXT'
+                    )
+                );
+            } else {
+                $query = "update " . $adrTable . " set docserver_id = ?, "
+                   . " path = ?, filename = ?, offset_doc = ?, fingerprint = ?, adr_priority = ?"
+                   . " where res_id = ? and adr_type = ? ";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        $resId,
+                        'TXT'
+                    )
+                );
+            }
+            if ($_SESSION['user']['UserId'] <> '') {
+                $user = $_SESSION['user']['UserId'];
+            } else {
+                $user = 'CONVERT_BOT';
+            }
+            $query = "insert into history (table_name, record_id, "
+                   . "event_type, user_id, event_date, info, id_module) values (" 
+                   . "?, ?, 'ADD', '" . $user . "', " 
+                   . $dbConv->current_datetime() 
+                   . ", ?, 'convert')";
+            $stmt = $dbConv->query( 
+                $query, 
+                array(
+                    $resTable,
+                    $resId,
+                    "process fulltext done"
+                )
+            );
+
+            $queryCpt = "select coalesce(custom_t15, '0') as custom_t15 from " . $resTable 
+                . " where res_id = ?";
+            $stmtCpt = $dbConv->query($queryCpt, array($resId));
+            $rsCpt = $stmtCpt->fetchObject();
+            $cptFullText = $rsCpt->custom_t15 + 1;
+
+            if (!empty($zendIndex)) {
+                $query = "update " . $resTable 
+                    . " set fulltext_result = '1', is_multi_docservers = 'Y', custom_t15 = '" . $cptFullText . "' where "
+                    . " res_id = ?";
+            } else {
+                $query = "update " . $resTable 
+                    . " set fulltext_result = '0', is_multi_docservers = 'Y', custom_t15 = '" . $cptFullText . "' where "
+                    . " res_id = ?";
+            }
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $resId
+                )
+            );
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } catch (Exception $e) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $e->getMessage(),
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+     * Updating the database with the error code
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @param string $result error code
+     * @return nothing
+     */
+    private function manageErrorOnDb(
+        $resTable, 
+        $resId,
+        $result
+    ) {
+        $dbConv = new Database($GLOBALS['configFile']);
+
+        $queryCpt = "select coalesce(custom_t15, '0') as custom_t15 from " . $resTable 
+                . " where res_id = ?";
+        $stmtCpt = $dbConv->query($queryCpt, array($resId));
+        $rsCpt = $stmtCpt->fetchObject();
+        $cptFullText = $rsCpt->custom_t15 + 1;
+        
+        $query = "update " . $resTable 
+            . " set fulltext_result = ?, custom_t15 = '" . $cptFullText . "' where "
+            . " res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $result,
+                $resId
+            )
+        );
+    }
+
+    public static function optimizeLuceneIndex(array $args=[]){
+        $timestart = microtime(true);
+        // Prés-requis :
+        self::checkRequired($args, ['collId']);
+        self::checkString($args, ['collId']); 
+        
+        $collId = $args['collId'];
+
+        $countColl = count($_SESSION['collections']);
+        for ($i=0;$i<$countColl;$i++) {
+            if ($_SESSION['collections'][$i]['id'] == $collId) {
+                $path_to_lucene = $_SESSION['collections'][$i]['path_to_lucene_index'];
+            }
+        }
+
+        if(!empty($path_to_lucene)){
+            exec('php '.$_SESSION['config']['corepath'].'modules/convert/optimizeLuceneIndex.php '.$path_to_lucene.' '.$_SESSION['config']['corepath'].' > /dev/null 2>&1 &');
+        }
+        Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessFulltextAbstract_Service::optimizeLuceneIndex');
+        return true;
+    }
+
+}
diff --git a/modules/convert/services/ProcessThumbnails.php b/modules/convert/services/ProcessThumbnails.php
new file mode 100644
index 0000000000000000000000000000000000000000..17f4b754bd76ad1d9e390dfa15da4a2ea76157ae
--- /dev/null
+++ b/modules/convert/services/ProcessThumbnails.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process thumbnails class
+*
+* <ul>
+* <li>Services to process the thumbnails of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+
+require_once 'modules/convert/services/ProcessThumbnailsAbstract.php';
+
+class Convert_ProcessThumbnails_Service extends Convert_ProcessThumbnailsAbstract_Service {
+	
+	
+}
diff --git a/modules/convert/services/ProcessThumbnailsAbstract.php b/modules/convert/services/ProcessThumbnailsAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ac20cf65c48d37365b4ce7ba6c1728fa2831ab8
--- /dev/null
+++ b/modules/convert/services/ProcessThumbnailsAbstract.php
@@ -0,0 +1,501 @@
+<?php
+
+/*
+*   Copyright 2008-2016 Maarch
+*
+*   This file is part of Maarch Framework.
+*
+*   Maarch Framework is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   Maarch Framework is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public License
+*   along with Maarch Framework.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+* @brief process thumbnails class
+*
+* <ul>
+* <li>Services to process the thumbnails of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+
+require_once 'core/services/Abstract.php';
+require_once 'core/class/class_functions.php';
+require_once 'core/class/class_db_pdo.php';
+require_once 'core/class/class_db.php';
+require_once 'core/docservers_tools.php';
+require_once 'core/class/docservers_controler.php';
+require_once 'core/services/ManageDocservers.php';
+
+class Convert_ProcessThumbnailsAbstract_Service extends Core_Abstract_Service {
+
+    protected $tnlExecutable;
+
+    public function __construct($tnlExecutable = 'convert')
+    {
+        $this->tnlExecutable = $tnlExecutable;
+    }
+
+    /**
+     * Ask for thumbnails
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @param array $tgtfmt array of target format
+     * @return array $returnArray the result
+     */
+    public function thumbnails(array $args=[])
+    {
+        $timestart = microtime(true);
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        $dbConv = new Database($GLOBALS['configFile']);
+        
+        //retrieve path of the resource
+        $stmtConv = $dbConv->query("select * from " . $resTable 
+            . " where res_id = ?", array($resId)
+        );
+        $line = $stmtConv->fetchObject();
+        $ManageDocservers = new Core_ManageDocservers_Service();
+        if ($args['fileSource'] <> '' && file_exists($args['fileSource'])) {
+            $resourcePath = $args['fileSource'];
+        } else {
+            if ($line->res_id <> '')  {
+                $adrType = 'CONV';
+                if (
+                    strtoupper($line->format) == 'HTML' ||
+                    strtoupper($line->format) == 'MAARCH'
+                ) {
+                    $adrType = 'DOC';
+                }
+                $resourcePath = $ManageDocservers->getSourceResourcePath(
+                    $resTable, 
+                    $adrTable, 
+                    $line->res_id, 
+                    $adrType
+                );
+            }
+        }
+        
+        if (!file_exists($resourcePath)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'file not already converted in pdf for thumbnails. Path : ' 
+                    . $resourcePath . ", adrType : " . $adrType,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the resource on tmp directory
+        $fileNameOnTmp = $tmpDir . rand() . rand();
+        if (!copy($resourcePath, $fileNameOnTmp)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'copy on tmp failed for thumbnails. Copy ' . $resourcePath . ' to ' . $fileNameOnTmp,
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //now do the thumbnails !
+        $resultOfConversion = $this->launchThumbnails(
+            $fileNameOnTmp, 
+            $tmpDir,
+            pathinfo($resourcePath, PATHINFO_EXTENSION)
+        );
+        if ($resultOfConversion['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfConversion;
+        }
+        //find the target docserver
+        $targetDs = $ManageDocservers->findTargetDs($collId, 'TNL');
+        if (empty($targetDs)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'Ds of collection and ds type not found for thumbnails:' 
+                    . $collId . ' TNL',
+            );
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $returnArray;
+        }
+        //copy the result on docserver
+        $resultCopyDs = $ManageDocservers->copyResOnDS($fileNameOnTmp . '.png', $targetDs);
+        if ($resultCopyDs['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultCopyDs;
+        }
+        //update the database
+        $resultOfUpDb = $this->updateDatabase(
+            $collId,
+            $resTable, 
+            $adrTable, 
+            $resId,
+            $targetDs,
+            $resultCopyDs['value']['destinationDir'],
+            $resultCopyDs['value']['fileDestinationName']
+        );
+        if ($resultOfUpDb['status'] <> '0') {
+            $this->manageErrorOnDb($resTable, $resId, '-1');
+            return $resultOfUpDb;
+        }
+
+        unlink($fileNameOnTmp);
+        unlink($fileNameOnTmp . '.png');
+
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        Core_Logs_Service::executionTimeLog($timestart, '', 'info', '[TIMER] Convert_ProcessThumbnailsAbstract_Service::thumbnails');
+        return $returnArray;
+    }
+
+    /**
+     * Launch the thumbnails process
+     *
+     * @param string $srcfile source file
+     * @param string $tgtdir target dir
+     * @param string $srcfmt source format
+     * @return array $returnArray the result
+     */
+    private function launchThumbnails(
+        $srcfile, 
+        $tgtdir=false, 
+        $srcfmt
+    ) {
+        $timestart = microtime(true);
+        if (!$tgtdir) {
+            $tgtdir = dirname($srcfile);
+        }
+
+        $output = array();
+        $return = null;
+        $this->errors = array();
+
+        //wkhtmltoimage must be installed with compiled sources
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            copy($srcfile, str_ireplace('.maarch', '.', $srcfile) . '.html');
+            if (file_exists('/usr/bin/mywkhtmltoimage')) {
+                $command = "mywkhtmltoimage  --width 164 --height 105 --quality 100 --zoom 0.2 " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.png');
+            } else {
+                $envVar = "export DISPLAY=FRPAROEMINT:0.0 ; ";
+                $command = $envVar . "wkhtmltoimage --width 164 --height 105 --quality 100 --zoom 0.2 " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.png');
+            }
+        } else {
+            $command = "convert -thumbnail 200x300 -background white -alpha remove " 
+                . escapeshellarg($srcfile) . "[0] "
+                . escapeshellarg($tgtdir . basename($srcfile) . '.png');
+        }
+        //echo $command . PHP_EOL;exit;
+        $timestart_command = microtime(true);
+        exec($command, $output, $return);
+        Core_Logs_Service::debug(['message'=>'[TIMER] Commande : ' . $command]);
+        Core_Logs_Service::executionTimeLog($timestart_command, '', 'debug', '[TIMER] Convert_ProcessThumbnailsAbstract_Service::launchThumbnails__exec');
+
+        if ($return === 0) {
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        } else {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $return . $output,
+            );
+        }
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            $returnArray = array();
+            unlink(str_ireplace('.maarch', '.', $srcfile) . '.html');
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        }
+        Core_Logs_Service::executionTimeLog($timestart, '', 'debug', '[TIMER] Convert_ProcessThumbnailsAbstract_Service::launchThumbnails');
+        return $returnArray;
+    }
+
+    /**
+     * Updating the database with the location information of the document on the
+     * new docserver
+     * @param string $collId collection
+     * @param string $resTable res table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process
+     * @param docserver $docserver docserver object
+     * @param string $path location of the resource on the docserver
+     * @param string $fileName file name of the resource on the docserver
+     * @return array $returnArray the result
+     */
+    private function updateDatabase(
+        $collId, 
+        $resTable, 
+        $adrTable, 
+        $resId,
+        $docserver,
+        $path, 
+        $fileName
+    ) {
+        try {
+            $docserver->path_template = str_replace(
+                DIRECTORY_SEPARATOR, 
+                '#', 
+                $docserver->path_template
+            );
+            $path = str_replace($docserver->path_template, '', $path);
+            $dbConv = new Database($GLOBALS['configFile']);
+            $query = "update convert_stack set status = 'P' where "
+               . " coll_id = ? and res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $collId,
+                    $resId
+                )
+            );
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? order by adr_priority";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "select docserver_id, path, filename, offset_doc, fingerprint"
+                       . " from " . $resTable . " where res_id = ?";
+                $stmt = $dbConv->query($query, array($resId));
+                $recordset = $stmt->fetchObject();
+                $resDocserverId = $recordset->docserver_id;
+                $resPath = $recordset->path;
+                $resFilename = $recordset->filename;
+                $resOffsetDoc = $recordset->offset_doc;
+                $fingerprintInit = $recordset->fingerprint;
+                $query = "select adr_priority_number from docservers "
+                       . " where docserver_id = ?";
+                $stmt = $dbConv->query($query, array($resDocserverId));
+                $recordset = $stmt->fetchObject();
+                $query = "insert into " . $adrTable . " (res_id, "
+                       . "docserver_id, path, filename, offset_doc, fingerprint, "
+                       . "adr_priority) values (?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $resDocserverId,
+                        $resPath,
+                        $resFilename,
+                        $resOffsetDoc,
+                        $fingerprintInit,
+                        $recordset->adr_priority_number
+                    )
+                );
+            }
+
+            $query = "select * from " . $adrTable 
+                . " where res_id = ? and adr_type = 'TNL'";
+            $stmt = $dbConv->query($query, array($resId));
+            if ($stmt->rowCount() == 0) {
+                $query = "insert into " . $adrTable . " (res_id, docserver_id, "
+                   . "path, filename, offset_doc, fingerprint, adr_priority, adr_type) values (" 
+                   . "?, ?, ?, ?, ?, ?, ?, ?)";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $resId,
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        'TNL'
+                    )
+                );
+            } else {
+                $query = "update " . $adrTable . " set docserver_id = ?, "
+                   . " path = ?, filename = ?, offset_doc = ?, fingerprint = ?, adr_priority = ?"
+                   . " where res_id = ? and adr_type = ? ";
+                $stmt = $dbConv->query(
+                    $query, 
+                    array(
+                        $docserver->docserver_id,
+                        $path,
+                        $fileName,
+                        $offsetDoc,
+                        $fingerprint,
+                        $docserver->adr_priority_number,
+                        $resId,
+                        'TNL'
+                    )
+                );
+            }
+            if ($_SESSION['user']['UserId'] <> '') {
+                $user = $_SESSION['user']['UserId'];
+            } else {
+                $user = 'CONVERT_BOT';
+            }
+            $query = "insert into history (table_name, record_id, "
+                   . "event_type, user_id, event_date, info, id_module) values (" 
+                   . "?, ?, 'ADD', '" . $user . "', " 
+                   . $dbConv->current_datetime() 
+                   . ", ?, 'convert')";
+            $stmt = $dbConv->query( 
+                $query, 
+                array(
+                    $resTable,
+                    $resId,
+                    "process thumbnails done"
+                )
+            );
+
+            $query = "update " . $resTable 
+                . " set tnl_result = '1', is_multi_docservers = 'Y' where "
+                . " res_id = ?";
+            $stmt = $dbConv->query(
+                $query,
+                array(
+                    $resId
+                )
+            );
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            return $returnArray;
+        } catch (Exception $e) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $e->getMessage(),
+            );
+            return $returnArray;
+        }
+    }
+
+    /**
+     * Updating the database with the error code
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @param string $result error code
+     * @return nothing
+     */
+    private function manageErrorOnDb(
+        $resTable, 
+        $resId,
+        $result
+    ) {
+        $dbConv = new Database($GLOBALS['configFile']);
+        $query = "update " . $resTable 
+            . " set tnl_result = ? where "
+            . " res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $result,
+                $resId
+            )
+        );
+    }
+
+    /**
+     * Test if the record is already processed by convert module
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @return boolean
+     */
+    public function isAlreadyProcessedByhumbnails(
+        $resTable, 
+        $resId
+    ) {
+        $dbConv = new Database($GLOBALS['configFile']);
+        $query = "select tnl_result from " . $resTable 
+            . "  where res_id = ?";
+        $stmt = $dbConv->query(
+            $query,
+            array(
+                $resId
+            )
+        );
+        $rs = $stmt->fetchObject();
+        if (
+            empty($rs->tnl_result) || 
+            $rs->tnl_result == '0'
+        ) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
diff --git a/modules/convert/test_convert.php b/modules/convert/test_convert.php
new file mode 100644
index 0000000000000000000000000000000000000000..25ec308b0e4fa178b9620aec6897b41436e35b2e
--- /dev/null
+++ b/modules/convert/test_convert.php
@@ -0,0 +1,106 @@
+<?php
+
+// sample for letterbox :
+// http:/urltomaarch/apps/maarch_entreprise/index.php?page=test_convert&module=convert&id=1931&collId=letterbox_coll
+
+// sample for attachments :
+// http:/urltomaarch/apps/maarch_entreprise/index.php?page=test_convert&module=convert&id=1&collId=attachments_coll
+
+// sample for thumbnails :
+// http:/urltomaarch//apps/maarch_entreprise/index.php?page=test_convert&module=convert&id=1939&collId=letterbox_coll&convertMode=thumbnails
+
+// sample for fulltext :
+// http:/urltomaarch//apps/maarch_entreprise/index.php?page=test_convert&module=convert&id=1989&collId=letterbox_coll&convertMode=fulltext
+
+// sample for letterbox in allMode :
+// http:/urltomaarch/apps/maarch_entreprise/index.php?page=test_convert&module=convert&id=1931&collId=letterbox_coll&convertMode=allMode
+
+// sample for attachments in allMode :
+// http:/urltomaarch/apps/maarch_entreprise/index.php?page=test_convert&module=convert&id=1&collId=attachments_coll&convertMode=allMode
+
+$func = new functions();
+
+for ($i=0;$i<count($_SESSION['collections']);$i++) {
+    if ($_SESSION['collections'][$i]['id'] == $_REQUEST['collId']) {
+        $resTable = $_SESSION['collections'][$i]['table'];
+        $adrTable = $_SESSION['collections'][$i]['adr'];
+    }
+}
+
+if (empty($_REQUEST['convertMode'])) {
+    $convertMode = 'convert';
+} else {
+    $convertMode = $_REQUEST['convertMode'];
+}
+
+echo $_REQUEST['convertMode'] . '<br />';
+echo $_REQUEST['collId'] . '<br />';
+echo $resTable . PHP_EOL . '<br />';
+echo $adrTable . PHP_EOL . '<br />';
+echo $_REQUEST['id'] . PHP_EOL . '<br />';
+
+$params = array(
+    'collId' => $_REQUEST['collId'], 
+    'resTable' => $resTable, 
+    'adrTable' => $adrTable, 
+    'resId' => $_REQUEST['id'],
+    'tmpDir' => $_SESSION['config']['tmppath']
+);
+
+require_once 'core/services/ManageDocservers.php';
+$ManageDocservers = new Core_ManageDocservers_Service();
+
+if ($convertMode == 'allMode') {
+	require_once 'modules/convert/services/ManageConvert.php';
+    $ManageConvertService = new Convert_ManageConvert_Service();
+    $resultOfConversion = $ManageConvertService->convertAll($params);
+    $adrType = 'CONV';
+} elseif ($convertMode == 'thumbnails') {
+	$adrType = 'TNL';
+    require_once 'modules/convert/services/ProcessThumbnails.php';
+    $ProcessConvertService = new Convert_ProcessThumbnails_Service();
+    $resultOfConversion = $ProcessConvertService->thumbnails($params);
+    $resourcePath = $ManageDocservers->getSourceResourcePath(
+        $resTable, 
+        $adrTable, 
+        $_REQUEST['id'], 
+        $adrType
+    );
+} elseif ($convertMode == 'fulltext') {
+	$adrType = 'TXT';
+    require_once 'modules/convert/services/ProcessFulltext.php';
+    $ProcessConvertService = new Convert_ProcessFulltext_Service();
+    $resultOfConversion = $ProcessConvertService->fulltext($params);
+    $resourcePath = $ManageDocservers->getSourceResourcePath(
+        $resTable, 
+        $adrTable, 
+        $_REQUEST['id'], 
+        $adrType
+    );
+} else {
+	$adrType = 'CONV';
+    require_once 'modules/convert/services/ProcessConvert.php';
+    $ProcessConvertService = new Convert_ProcessConvert_Service();
+    $resultOfConversion = $ProcessConvertService->convert($params);
+    $resourcePath = $ManageDocservers->getSourceResourcePath(
+        $resTable, 
+        $adrTable, 
+        $_REQUEST['id'], 
+        $adrType
+    );
+}
+
+echo $resourcePath . '<br />';
+
+$func->show_array($resultOfConversion);
+
+$link .= $_SESSION['config']['businessappurl']
+    . 'index.php?display=true'
+    . '&dir=indexing_searching'
+    . '&page=ViewRes'
+    . '&collId=' . $_REQUEST['collId']
+    . '&id=' . $_REQUEST['id']
+    . '&adrType=' . $adrType;
+$linkToRes = '<a href="' . $link . '" target="_blank">clic to view the new resource !</a>';
+
+echo '<br />' . $linkToRes;
\ No newline at end of file
diff --git a/modules/convert/xml/IVS/data_types.xml b/modules/convert/xml/IVS/data_types.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d182eb100928695356cb6d78bc710f956cf331f0
--- /dev/null
+++ b/modules/convert/xml/IVS/data_types.xml
@@ -0,0 +1,2 @@
+<dataTypes>
+</dataTypes>
\ No newline at end of file
diff --git a/modules/convert/xml/IVS/requests_definitions.xml b/modules/convert/xml/IVS/requests_definitions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de13c79b15367cb425620879d493ddcb06df6ef1
--- /dev/null
+++ b/modules/convert/xml/IVS/requests_definitions.xml
@@ -0,0 +1,2 @@
+<requestDefinitions>
+</requestDefinitions>
\ No newline at end of file
diff --git a/modules/convert/xml/IVS/validation_rules.xml b/modules/convert/xml/IVS/validation_rules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bfc6f655dba2a9e75d2bb4d8200ede18b3ebfe59
--- /dev/null
+++ b/modules/convert/xml/IVS/validation_rules.xml
@@ -0,0 +1,2 @@
+<validationRules>
+</validationRules>
\ No newline at end of file
diff --git a/modules/convert/xml/config.xml b/modules/convert/xml/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3837913ef90fc5ef9659bb382c4c708ebe7a8733
--- /dev/null
+++ b/modules/convert/xml/config.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+	<CONFIG>
+		<name>convert</name>
+		<comment>_CONVERT_COMMENT</comment>
+		<file_prefix>convert</file_prefix>
+		<loaded>true</loaded>
+	</CONFIG>
+	<TABLENAME/>
+	<HISTORY>
+		<convertadd>true</convertadd>
+		<convertup>true</convertup>
+		<convertdel>true</convertdel>
+	</HISTORY>
+</root>
diff --git a/modules/convert/xml/menu.xml b/modules/convert/xml/menu.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d15cc8033fce6abb48b9de486ec5ffba3204a7d5
--- /dev/null
+++ b/modules/convert/xml/menu.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+</root>
diff --git a/modules/convert/xml/services.xml b/modules/convert/xml/services.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d15cc8033fce6abb48b9de486ec5ffba3204a7d5
--- /dev/null
+++ b/modules/convert/xml/services.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+</root>
diff --git a/phpunit.xml b/phpunit.xml
index 14db58569e28d9afbbf64cb7154b6b6ade9f4e6d..2ae7c3d3054df3b74c4a449a1f3abdf6a2bbf621 100755
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -9,6 +9,7 @@
             <file>core/Test/ResExtControllerTest.php</file-->
             <file>core/Test/StatusControllerTest.php</file>
             <file>core/Test/UserControllerTest.php</file>
+            <file>modules/convert/Test/ProcessFulltextTest.php</file>
         </testsuite>
     </testsuites>
     <filter>
@@ -27,6 +28,8 @@
           <directory suffix=".php">modules/entities/Models</directory>
           <directory suffix=".php">modules/basket/Models</directory>
           <directory suffix=".php">modules/notes/Models</directory>
+          <directory suffix=".php">modules/convert/Controllers</directory>
+          <directory suffix=".php">modules/convert/Models</directory>
       </whitelist>
     </filter>
     <logging>