dolibarr  9.0.0
ajaxdirtree.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2007-2018 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
26 // This script is called with a POST method.
27 // Directory to scan (full path) is inside POST['dir'] and encode by js escape() if ajax is used or encoded by urlencode if mode=noajax
28 
29 if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); // Disables token renewal
30 if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1');
31 if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
32 if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
33 
34 
35 if (! isset($mode) || $mode != 'noajax') // For ajax call
36 {
37  $res=@include '../../main.inc.php';
38  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
39  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
40  include_once DOL_DOCUMENT_ROOT.'/core/lib/treeview.lib.php';
41  include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
42  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php';
43 
44  //if (GETPOST('preopened')) { $_GET['dir'] = $_POST['dir'] = '/bbb/'; }
45 
46  $openeddir = GETPOST('openeddir');
47  $modulepart= GETPOST('modulepart');
48  $selecteddir = jsUnEscape(GETPOST('dir')); // relative path. We must decode using same encoding function used by javascript: escape()
49 
50  $preopened = GETPOST('preopened');
51 
52  if ($selecteddir != '/') $selecteddir = preg_replace('/\/$/','',$selecteddir); // We removed last '/' except if it is '/'
53 }
54 else // For no ajax call
55 {
56  //if (GETPOST('preopened')) { $_GET['dir'] = $_POST['dir'] = GETPOST('preopened'); }
57 
58  $openeddir = GETPOST('openeddir');
59  $modulepart= GETPOST('modulepart');
60  $selecteddir = GETPOST('dir');
61 
62  $preopened = GETPOST('preopened');
63 
64  if ($selecteddir != '/') $selecteddir = preg_replace('/\/$/','',$selecteddir); // We removed last '/' except if it is '/'
65  if (empty($url)) $url=DOL_URL_ROOT.'/ecm/index.php';
66 }
67 
68 // Load translation files required by the page
69 $langs->load("ecm");
70 
71 // Define fullpathselecteddir.
72 $fullpathselecteddir='<none>';
73 if ($modulepart == 'ecm')
74 {
75  $fullpathselecteddir=$conf->ecm->dir_output.'/'.($selecteddir != '/' ? $selecteddir : '');
76  $fullpathpreopened=$conf->ecm->dir_output.'/'.($preopened != '/' ? $preopened : '');
77 }
78 elseif ($modulepart == 'medias')
79 {
80  $fullpathselecteddir=$dolibarr_main_data_root.'/medias/'.($selecteddir != '/' ? $selecteddir : '');
81  $fullpathpreopened=$dolibarr_main_data_root.'/medias/'.($preopened != '/' ? $preopened : '');
82 }
83 
84 
85 // Security:
86 // On interdit les remontees de repertoire ainsi que les pipe dans les noms de fichiers.
87 if (preg_match('/\.\./',$fullpathselecteddir) || preg_match('/[<>|]/',$fullpathselecteddir))
88 {
89  dol_syslog("Refused to deliver file ".$original_file);
90  // Do no show plain path in shown error message
91  dol_print_error(0,$langs->trans("ErrorFileNameInvalid",GETPOST("file")));
92  exit;
93 }
94 
95 // Check permissions
96 if ($modulepart == 'ecm')
97 {
98  if (! $user->rights->ecm->read) accessforbidden();
99 }
100 elseif ($modulepart == 'medias')
101 {
102  // Always allowed
103 }
104 
105 
106 /*
107  * View
108  */
109 
110 if (! isset($mode) || $mode != 'noajax') // if ajax mode
111 {
112  top_httphead();
113 }
114 
115 //print '<!-- selecteddir (relative dir we click on) = '.$selecteddir.', openeddir = '.$openeddir.', modulepart='.$modulepart.', preopened='.$preopened.' -->'."\n";
116 $userstatic=new User($db);
117 $form=new Form($db);
118 $ecmdirstatic = new EcmDirectory($db);
119 
120 // Load full tree of ECM module from database. We will use it to define nbofsubdir and nboffilesinsubdir
121 if (empty($sqltree)) $sqltree=$ecmdirstatic->get_full_arbo(0);
122 
123 // Try to find selected dir id into $sqltree and save it into $current_ecmdir_id
124 $current_ecmdir_id=-1;
125 foreach($sqltree as $keycursor => $val)
126 {
127  //print $val['fullrelativename']." == ".$selecteddir;
128  if ($val['fullrelativename'] == $selecteddir)
129  {
130  $current_ecmdir_id = $keycursor;
131  }
132 }
133 
134 if (! empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_ECM_DISABLE_JS))
135 {
136  treeOutputForAbsoluteDir($sqltree, $selecteddir, $fullpathselecteddir, $modulepart, $websitekey, $pageid, $preopened, $fullpathpreopened);
137 
138  // TODO Find a solution to not output this code for each leaf we open
139  // Enable jquery handlers on new generated HTML objects (same code than into lib_footer.js.php)
140  // Because the content is reloaded by ajax call, we must also reenable some jquery hooks
141  print "\n<!-- JS CODE TO ENABLE Tooltips on all object with class classfortooltip (reload into ajaxdirtree) -->\n";
142  print '<script type="text/javascript">
143  jQuery(document).ready(function () {
144  jQuery(".classfortooltip").tooltip({
145  show: { collision: "flipfit", effect:\'toggle\', delay:50 },
146  hide: { delay: 50 }, /* If I enable effect:\'toggle\' here, a bug appears: the tooltip is shown when collpasing a new dir if it was shown before */
147  tooltipClass: "mytooltip",
148  content: function () {
149  return $(this).prop(\'title\'); /* To force to get title as is */
150  }
151  });
152  });
153  </script>';
154 
155  // This ajax service is called only when a directory $selecteddir is opened but not when closed.
156  //print '<script language="javascript">';
157  //print "loadandshowpreview('".dol_escape_js($selecteddir)."');";
158  //print '</script>';
159 }
160 
161 
162 if (empty($conf->use_javascript_ajax) || ! empty($conf->global->MAIN_ECM_DISABLE_JS))
163 {
164  print '<ul class="ecmjqft">';
165 
166  // Load full tree from database. We will use it to define nbofsubdir and nboffilesinsubdir
167  if (empty($sqltree)) $sqltree=$ecmdirstatic->get_full_arbo(0); // Slow
168 
169  // ----- This section will show a tree from a fulltree array -----
170  // $section must also be defined
171  // ----------------------------------------------------------------
172 
173  // Define fullpathselected ( _x_y_z ) of $section parameter (!! not into ajaxdirtree)
174  $fullpathselected='';
175  foreach($sqltree as $key => $val)
176  {
177  //print $val['id']."-".$section."<br>";
178  if ($val['id'] == $section)
179  {
180  $fullpathselected=$val['fullpath'];
181  break;
182  }
183  }
184  //print "fullpathselected=".$fullpathselected."<br>";
185 
186  // Update expandedsectionarray in session
187  $expandedsectionarray=array();
188  if (isset($_SESSION['dol_ecmexpandedsectionarray'])) $expandedsectionarray=explode(',',$_SESSION['dol_ecmexpandedsectionarray']);
189 
190  if ($section && GETPOST('sectionexpand') == 'true')
191  {
192  // We add all sections that are parent of opened section
193  $pathtosection=explode('_',$fullpathselected);
194  foreach($pathtosection as $idcursor)
195  {
196  if ($idcursor && ! in_array($idcursor,$expandedsectionarray)) // Not already in array
197  {
198  $expandedsectionarray[]=$idcursor;
199  }
200  }
201  $_SESSION['dol_ecmexpandedsectionarray']=join(',',$expandedsectionarray);
202  }
203  if ($section && GETPOST('sectionexpand') == 'false')
204  {
205  // We removed all expanded sections that are child of the closed section
206  $oldexpandedsectionarray=$expandedsectionarray;
207  $expandedsectionarray=array(); // Reset
208  foreach($oldexpandedsectionarray as $sectioncursor)
209  {
210  // TODO is_in_subtree(fulltree,sectionparent,sectionchild) does nox exists. Enable or remove this...
211  //if ($sectioncursor && ! is_in_subtree($sqltree,$section,$sectioncursor)) $expandedsectionarray[]=$sectioncursor;
212  }
213  $_SESSION['dol_ecmexpandedsectionarray']=join(',',$expandedsectionarray);
214  }
215  //print $_SESSION['dol_ecmexpandedsectionarray'].'<br>';
216 
217  $nbofentries=0;
218  $oldvallevel=0;
219  foreach($sqltree as $key => $val)
220  {
221 
222  $ecmdirstatic->id=$val['id'];
223  $ecmdirstatic->ref=$val['label'];
224 
225  // Refresh cache
226  if (preg_match('/refresh/i',$action))
227  {
228  $result=$ecmdirstatic->fetch($val['id']);
229  $ecmdirstatic->ref=$ecmdirstatic->label;
230 
231  $result=$ecmdirstatic->refreshcachenboffile(0);
232  $val['cachenbofdoc']=$result;
233  }
234 
235  //$fullpathparent=preg_replace('/(_[^_]+)$/i','',$val['fullpath']);
236 
237  // Define showline
238  $showline=0;
239 
240  // If directory is son of expanded directory, we show line
241  if (in_array($val['id_mere'],$expandedsectionarray)) $showline=4;
242  // If directory is brother of selected directory, we show line
243  elseif ($val['id'] != $section && $val['id_mere'] == $ecmdirstatic->motherof[$section]) $showline=3;
244  // If directory is parent of selected directory or is selected directory, we show line
245  elseif (preg_match('/'.$val['fullpath'].'_/i',$fullpathselected.'_')) $showline=2;
246  // If we are level one we show line
247  elseif ($val['level'] < 2) $showline=1;
248 
249  if ($showline)
250  {
251  if (in_array($val['id'],$expandedsectionarray)) $option='indexexpanded';
252  else $option='indexnotexpanded';
253  //print $option;
254 
255  print '<li class="directory collapsed">';
256 
257  // Show tree graph pictos
258  $cpt=1;
259  while ($cpt < $sqltree[$key]['level'])
260  {
261  print ' &nbsp; &nbsp;';
262  $cpt++;
263  }
264  $resarray=tree_showpad($sqltree,$key,1);
265  $a=$resarray[0];
266  $nbofsubdir=$resarray[1];
267  $nboffilesinsubdir=$resarray[2];
268 
269  // Show link
270  print $ecmdirstatic->getNomUrl(0,$option,32,'class="fmdirlia jqft ecmjqft"');
271 
272  print '<div class="ecmjqft">';
273 
274  // Nb of docs
275  print '<table class="nobordernopadding"><tr><td>';
276  print $val['cachenbofdoc'];
277  print '</td>';
278  print '<td align="left">';
279  if ($nbofsubdir && $nboffilesinsubdir) print '<font color="#AAAAAA">+'.$nboffilesinsubdir.'</font> ';
280  print '</td>';
281 
282  // Info
283  print '<td align="center">';
284  $userstatic->id=$val['fk_user_c'];
285  $userstatic->lastname=$val['login_c'];
286  $htmltooltip='<b>'.$langs->trans("ECMSection").'</b>: '.$val['label'].'<br>';
287  $htmltooltip='<b>'.$langs->trans("Type").'</b>: '.$langs->trans("ECMSectionManual").'<br>';
288  $htmltooltip.='<b>'.$langs->trans("ECMCreationUser").'</b>: '.$userstatic->getNomUrl(1, '', false, 1).'<br>';
289  $htmltooltip.='<b>'.$langs->trans("ECMCreationDate").'</b>: '.dol_print_date($val['date_c'],"dayhour").'<br>';
290  $htmltooltip.='<b>'.$langs->trans("Description").'</b>: '.$val['description'].'<br>';
291  $htmltooltip.='<b>'.$langs->trans("ECMNbOfFilesInDir").'</b>: '.$val['cachenbofdoc'].'<br>';
292  if ($nbofsubdir) $htmltooltip.='<b>'.$langs->trans("ECMNbOfFilesInSubDir").'</b>: '.$nboffilesinsubdir;
293  else $htmltooltip.='<b>'.$langs->trans("ECMNbOfSubDir").'</b>: '.$nbofsubdir.'<br>';
294  print $form->textwithpicto('', $htmltooltip, 1, 'info');
295  print "</td>";
296 
297  print '</tr></table>';
298 
299  print '</div>';
300 
301  print "</li>\n";
302  }
303 
304  $oldvallevel=$val['level'];
305  $nbofentries++;
306  }
307 
308  // If nothing to show
309  if ($nbofentries == 0)
310  {
311  print '<li class="directory collapsed">';
312  print '<div class="ecmjqft">';
313  print $langs->trans("ECMNoDirectoryYet");
314  print '</div>';
315  print "</li>\n";
316  }
317 
318  print '</ul>';
319 }
320 
321 
322 // Close db if mode is not noajax
323 if ((! isset($mode) || $mode != 'noajax') && is_object($db)) $db->close();
324 
325 
326 
341 function treeOutputForAbsoluteDir($sqltree, $selecteddir, $fullpathselecteddir, $modulepart, $websitekey, $pageid, $preopened, $fullpathpreopened, $depth=0)
342 {
343  global $conf, $db, $langs, $form;
344  global $dolibarr_main_data_root;
345 
346  $ecmdirstatic = new EcmDirectory($db);
347  $userstatic = new User($db);
348 
349  if (file_exists($fullpathselecteddir))
350  {
351  $files = @scandir($fullpathselecteddir);
352 
353  if (! empty($files))
354  {
355  natcasesort($files);
356  if (count($files) > 2) /* The 2 accounts for . and .. */
357  {
358  echo '<ul class="ecmjqft" style="display: none;">'."\n";
359 
360  // All dirs
361  foreach ($files as $file) // $file can be '.', '..', or 'My dir' or 'My file'
362  {
363  if ($file == 'temp') continue;
364 
365  $nbofsubdir=0;
366  $nboffilesinsubdir=0;
367 
368  $val=array();
369 
370  // Loop on all database entries (sqltree) to find the one matching the subdir found into dir to scan
371  foreach($sqltree as $key => $tmpval)
372  {
373  //print "-- key=".$key." - ".$tmpval['fullrelativename']." vs ".(($selecteddir != '/'?$selecteddir.'/':'').$file)."<br>\n";
374  if ($tmpval['fullrelativename'] == (($selecteddir != '/'?$selecteddir.'/':'').$file)) // We found equivalent record into database
375  {
376  $val=$tmpval;
377  $resarray=tree_showpad($sqltree,$key,1);
378 
379  // Refresh cache for this subdir
380  if (isset($val['cachenbofdoc']) && $val['cachenbofdoc'] < 0) // Cache is not up to date, so we update it for this directory t
381  {
382  $result=$ecmdirstatic->fetch($val['id']);
383  $ecmdirstatic->ref=$ecmdirstatic->label;
384 
385  $result=$ecmdirstatic->refreshcachenboffile(0);
386  $val['cachenbofdoc']=$result;
387  }
388 
389  $a=$resarray[0];
390  $nbofsubdir=$resarray[1];
391  $nboffilesinsubdir=$resarray[2];
392  break;
393  }
394  }
395 
396  //print 'modulepart='.$modulepart.' fullpathselecteddir='.$fullpathselecteddir.' - val[fullrelativename] (in database)='.$val['fullrelativename'].' - val[id]='.$val['id'].' - is_dir='.dol_is_dir($fullpathselecteddir . $file).' - file='.$file."\n";
397  if ($file != '.' && $file != '..' && ((! empty($val['fullrelativename']) && $val['id'] >= 0) || dol_is_dir($fullpathselecteddir . (preg_match('/\/$/',$fullpathselecteddir)?'':'/') . $file)))
398  {
399  if (empty($val['fullrelativename'])) // If we did not find entry into database, but found a directory (dol_is_dir was ok at previous test)
400  {
401  $val['fullrelativename']=(($selecteddir && $selecteddir != '/')?$selecteddir.'/':'').$file;
402  $val['id']=0;
403  $val['label']=$file;
404  $val['description']='';
405  $nboffilesinsubdir=$langs->trans("Unknown");
406  }
407 
408  $collapsedorexpanded='collapsed';
409  if (preg_match('/^'.preg_quote($val['fullrelativename'].'/', '/').'/', $preopened)) $collapsedorexpanded='expanded';
410  print '<li class="directory '.$collapsedorexpanded.'">'; // collapsed is opposite if expanded
411 
412  print "<a class=\"fmdirlia jqft ecmjqft\" href=\"";
413  print "#";
414  print "\" rel=\"" . dol_escape_htmltag($val['fullrelativename'].'/') . "\" id=\"fmdirlia_id_".$val['id']."\"";
415  print " onClick=\"loadandshowpreview('".dol_escape_js($val['fullrelativename'])."',".$val['id'].")";
416  print "\">";
417  print dol_escape_htmltag($file);
418  print "</a>";
419 
420  print '<div class="ecmjqft">';
421 
422  print '<table class="nobordernopadding"><tr>';
423 
424  /*print '<td align="left">';
425  print dol_escape_htmltag($file);
426  print '</td>';*/
427 
428  // Nb of docs
429  print '<td align="right">';
430  print (isset($val['cachenbofdoc']) && $val['cachenbofdoc'] >= 0)?$val['cachenbofdoc']:'&nbsp;';
431  print '</td>';
432  print '<td align="left">';
433  if ($nbofsubdir > 0 && $nboffilesinsubdir > 0) print '<font color="#AAAAAA">+'.$nboffilesinsubdir.'</font> ';
434  print '</td>';
435 
436  // Edit link
437  print '<td align="right" width="18"><a href="';
438  print DOL_URL_ROOT.'/ecm/dir_card.php?module='.urlencode($modulepart).'&section='.$val['id'].'&relativedir='.urlencode($val['fullrelativename']);
439  print '&backtopage='.urlencode($_SERVER["PHP_SELF"].'?file_manager=1&website='.$websitekey.'&pageid='.$pageid);
440  print '">'.img_edit($langs->trans("Edit").' - '.$langs->trans("View"), 0, 'class="valignmiddle opacitymedium"').'</a></td>';
441 
442  // Add link
443  //print '<td align="right"><a href="'.DOL_URL_ROOT.'/ecm/dir_add_card.php?action=create&amp;catParent='.$val['id'].'">'.img_edit_add().'</a></td>';
444  //print '<td align="right" width="14">&nbsp;</td>';
445 
446  // Info
447  if ($modulepart == 'ecm')
448  {
449  print '<td align="right" width="18">';
450  $userstatic->id=isset($val['fk_user_c'])?$val['fk_user_c']:0;
451  $userstatic->lastname=isset($val['login_c'])?$val['login_c']:0;
452  $htmltooltip='<b>'.$langs->trans("ECMSection").'</b>: '.$val['label'].'<br>';
453  $htmltooltip='<b>'.$langs->trans("Type").'</b>: '.$langs->trans("ECMSectionManual").'<br>';
454  $htmltooltip.='<b>'.$langs->trans("ECMCreationUser").'</b>: '.$userstatic->getNomUrl(1, '', false, 1).'<br>';
455  $htmltooltip.='<b>'.$langs->trans("ECMCreationDate").'</b>: '.(isset($val['date_c'])?dol_print_date($val['date_c'],"dayhour"):$langs->trans("NeedRefresh")).'<br>';
456  $htmltooltip.='<b>'.$langs->trans("Description").'</b>: '.$val['description'].'<br>';
457  $htmltooltip.='<b>'.$langs->trans("ECMNbOfFilesInDir").'</b>: '.((isset($val['cachenbofdoc']) && $val['cachenbofdoc'] >= 0)?$val['cachenbofdoc']:$langs->trans("NeedRefresh")).'<br>';
458  if ($nboffilesinsubdir > 0) $htmltooltip.='<b>'.$langs->trans("ECMNbOfFilesInSubDir").'</b>: '.$nboffilesinsubdir;
459  else $htmltooltip.='<b>'.$langs->trans("ECMNbOfSubDir").'</b>: '.($nbofsubdir >= 0 ? $nbofsubdir : $langs->trans("NeedRefresh")).'<br>';
460  print $form->textwithpicto('',$htmltooltip,1,"info");
461  print "</td>";
462  }
463 
464  print "</tr></table>\n";
465  print '</div>';
466 
467  //print 'selecteddir='.$selecteddir.' preopened='.$preopened.' $val[\'fullrelativename\']='.$val['fullrelativename']."<br>\n";
468  if (preg_match('/^'.preg_quote($val['fullrelativename'].'/', '/').'/', $preopened))
469  {
470  //print 'modulepart='.$modulepart.' fullpathselecteddir='.$fullpathselecteddir.' - val[fullrelativename] (in database)='.$val['fullrelativename'].' - val[id]='.$val['id'].' - is_dir='.dol_is_dir($fullpathselecteddir . $file).' - file='.$file."\n";
471  $newselecteddir = $val['fullrelativename'];
472  $newfullpathselecteddir='';
473  if ($modulepart == 'ecm')
474  {
475  $newfullpathselecteddir=$conf->ecm->dir_output.'/'.($val['fullrelativename'] != '/' ? $val['fullrelativename'] : '');
476  }
477  elseif ($modulepart == 'medias')
478  {
479  $newfullpathselecteddir=$dolibarr_main_data_root.'/medias/'.($val['fullrelativename'] != '/' ? $val['fullrelativename'] : '');
480  }
481 
482  if ($newfullpathselecteddir) treeOutputForAbsoluteDir($sqltree, $newselecteddir, $newfullpathselecteddir, $modulepart, $websitekey, $pageid, $preopened, $fullpathpreopened, $depth+1);
483  }
484 
485  print "</li>\n";
486  }
487  }
488 
489  echo "</ul>\n";
490  }
491  }
492  else print "PermissionDenied";
493  }
494 }
495 
GETPOST($paramname, $check='none', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
print
Draft customers invoices.
Definition: index.php:91
tree_showpad(&$fulltree, $key, $silent=0)
Show indent and picto of a tree line.
if(! defined('NOREQUIREMENU')) if(! function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
Definition: main.inc.php:1107
Class to manage Dolibarr users.
Definition: user.class.php:41
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:438
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Class to manage generation of HTML components Only common components must be here.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
jsUnEscape($source)
Same function than javascript unescape() function but in PHP.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
treeOutputForAbsoluteDir($sqltree, $selecteddir, $fullpathselecteddir, $modulepart, $websitekey, $pageid, $preopened, $fullpathpreopened, $depth=0)
treeOutputForAbsoluteDir
Class to manage ECM directories.