diff --git a/htdocs/core/ajax/ajaxdirtree.php b/htdocs/core/ajax/ajaxdirtree.php
index 9e823ec2116..d50b8217984 100644
--- a/htdocs/core/ajax/ajaxdirtree.php
+++ b/htdocs/core/ajax/ajaxdirtree.php
@@ -33,13 +33,14 @@ if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
$res=@include("../../main.inc.php");
include_once(DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php');
+include_once(DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php');
include_once(DOL_DOCUMENT_ROOT.'/core/lib/treeview.lib.php');
include_once(DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php');
include_once(DOL_DOCUMENT_ROOT."/ecm/class/ecmdirectory.class.php");
$openeddir = GETPOST('openeddir');
$modulepart= GETPOST('modulepart');
-$selecteddir = urldecode(GETPOST('dir')); // relative patch. We must keep the urldecode here because para comes from jqueyrFileTree that url encode it.
+$selecteddir = jsUnEscape(GETPOST('dir')); // relative path. We must decode using same encoding function used by javascript: escape()
if ($selecteddir != '/') $selecteddir = preg_replace('/\/$/','',$selecteddir); // We removed last '/' except if it is '/'
$langs->load("ecm");
@@ -89,7 +90,6 @@ foreach($sqltree as $keycursor => $val)
}
}
-//var_dump($sqltree);
if( file_exists($fullpathselecteddir) )
{
@@ -111,6 +111,7 @@ if( file_exists($fullpathselecteddir) )
// Try to find key into $sqltree
$val=array();
+
foreach($sqltree as $key => $tmpval)
{
//print "-- ".$val['fullrelativename']." vs ".(($selecteddir != '/'?$selecteddir.'/':'').$file).'
';
diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php
index 494070575db..9e5a404ec10 100644
--- a/htdocs/core/lib/files.lib.php
+++ b/htdocs/core/lib/files.lib.php
@@ -23,6 +23,17 @@
* \brief Library for file managing functions
*/
+/**
+ * Make a basename working with all page code (default PHP basenamed fails with cyrillic).
+ * We supose dir separator for input is '/'.
+ *
+ * @param string $pathfile String to find basename.
+ * @return string Basename of input
+ */
+function dol_basename($pathfile)
+{
+ return preg_replace('/^.*\/([^\/]+)$/','$1',rtrim($pathfile,'/'));
+}
/**
* Scan a directory and return a list of files/directories.
diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php
index d938d41e974..a0305ef3ed8 100644
--- a/htdocs/core/lib/functions2.lib.php
+++ b/htdocs/core/lib/functions2.lib.php
@@ -24,6 +24,45 @@
* This file contains all rare functions.
*/
+/**
+ * Same function than javascript unescape() function but in PHP.
+ *
+ * @param string $sourcetodecode String to decode
+ * @return
+ */
+function jsUnEscape($source)
+{
+ $decodedStr = "";
+ $pos = 0;
+ $len = strlen ($source);
+ while ($pos < $len) {
+ $charAt = substr ($source, $pos, 1);
+ if ($charAt == '%') {
+ $pos++;
+ $charAt = substr ($source, $pos, 1);
+ if ($charAt == 'u') {
+ // we got a unicode character
+ $pos++;
+ $unicodeHexVal = substr ($source, $pos, 4);
+ $unicode = hexdec ($unicodeHexVal);
+ $entity = "". $unicode . ';';
+ $decodedStr .= utf8_encode ($entity);
+ $pos += 4;
+ }
+ else {
+ // we have an escaped ascii character
+ $hexVal = substr ($source, $pos, 2);
+ $decodedStr .= chr (hexdec ($hexVal));
+ $pos += 2;
+ }
+ } else {
+ $decodedStr .= $charAt;
+ $pos++;
+ }
+ }
+ return dol_html_entity_decode($decodedStr, ENT_COMPAT);
+}
+
/**
* Return list of modules directories
diff --git a/htdocs/ecm/class/ecmdirectory.class.php b/htdocs/ecm/class/ecmdirectory.class.php
index b41e49f3032..a4cd7a79e64 100644
--- a/htdocs/ecm/class/ecmdirectory.class.php
+++ b/htdocs/ecm/class/ecmdirectory.class.php
@@ -607,8 +607,8 @@ class EcmDirectory // extends CommonObject
}
/**
- * Calcule les proprietes fullpath, fullrelativename, fulllabel d'un repertoire
- * du tableau this->cats et de toutes ces enfants.
+ * Define properties fullpath, fullrelativename, fulllabel of a directory of array this->cats and all its childs.
+ * Separator between directories is always '/', whatever is OS.
*
* @param int $id_categ id_categ entry to update
* @param int $protection Deep counter to avoid infinite loop
diff --git a/htdocs/ecm/index.php b/htdocs/ecm/index.php
index 94d6ffcc543..bdbb630bb7f 100644
--- a/htdocs/ecm/index.php
+++ b/htdocs/ecm/index.php
@@ -257,7 +257,8 @@ if ($action == 'refreshmanual')
}
}
else
- {
+ {
+ dol_syslog("Parent is root");
$fk_parent=0; // Parent is root
}
@@ -265,7 +266,7 @@ if ($action == 'refreshmanual')
{
$ecmdirtmp=new EcmDirectory($db);
$ecmdirtmp->ref = 'NOTUSEDYET';
- $ecmdirtmp->label = basename($dirdesc['fullname']);
+ $ecmdirtmp->label = dol_basename($dirdesc['fullname']);
$ecmdirtmp->description = '';
$ecmdirtmp->fk_parent = $fk_parent;
@@ -284,6 +285,10 @@ if ($action == 'refreshmanual')
//var_dump($sqltree);
$adirwascreated=1;
}
+ else
+ {
+ dol_syslog("Failed to create directory ".$ecmdirtmp->label, LOG_ERR);
+ }
}
else {
$txt="Parent of ".$dirdesc['fullname']." not found";
@@ -559,7 +564,7 @@ if (empty($action) || $action == 'file_manager' || preg_match('/refresh/i',$acti
function loadandshowpreview(filedirname,section)
{
- //alert('filename='+filename);
+ alert('filename='+filename);
jQuery('#ecmfileview').empty();
url='?action=preview&module=ecm§ion='+section+'&file='+urlencode(filedirname);
@@ -584,10 +589,12 @@ if (empty($action) || $action == 'file_manager' || preg_match('/refresh/i',$acti
jQuery(document).ready( function() {
jQuery('#filetree').fileTree({ root: '',
+ // Called if we click on a file (not a dir)
script: '',
folderEvent: 'click',
multiFolder: false },
- function(file) {
+ // Called if we click on a file (not a dir)
+ function(file) {
jQuery("#mesg").hide();
loadandshowpreview(file,0);
}
diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php
index 60ce9eaac39..99d54901b41 100644
--- a/test/phpunit/AllTests.php
+++ b/test/phpunit/AllTests.php
@@ -72,6 +72,8 @@ class AllTests
$suite->addTestSuite('ImagesLibTest');
require_once dirname(__FILE__).'/FunctionsTest.php';
$suite->addTestSuite('FunctionsTest');
+ require_once dirname(__FILE__).'/Functions2Test.php';
+ $suite->addTestSuite('Functions2Test');
require_once dirname(__FILE__).'/SecurityTest.php';
$suite->addTestSuite('SecurityTest');
diff --git a/test/phpunit/FilesLibTest.php b/test/phpunit/FilesLibTest.php
index fb919ab56b9..76e19726e26 100644
--- a/test/phpunit/FilesLibTest.php
+++ b/test/phpunit/FilesLibTest.php
@@ -114,6 +114,38 @@ class FilesLibTest extends PHPUnit_Framework_TestCase
print __METHOD__."\n";
}
+
+ /**
+ * testDolBasename
+ *
+ * @return int
+ */
+ public function testDolBasename()
+ {
+ global $conf,$user,$langs,$db;
+ $conf=$this->savconf;
+ $user=$this->savuser;
+ $langs=$this->savlangs;
+ $db=$this->savdb;
+
+ $result=dol_basename('adir/afile');
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals('afile',$result);
+
+ $result=dol_basename('adir/afile/');
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals('afile',$result);
+
+ $result=dol_basename('adir/νεο'); // With cyrillic data. Here basename fails to return correct value
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals('νεο',$result);
+
+ $result=dol_basename('adir/νεο/'); // With cyrillic data. Here basename fails to return correct value
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals('νεο',$result);
+ }
+
+
/**
* testDolCountNbOfLine
*
diff --git a/test/phpunit/Functions2Test.php b/test/phpunit/Functions2Test.php
new file mode 100755
index 00000000000..9a6cc1163f2
--- /dev/null
+++ b/test/phpunit/Functions2Test.php
@@ -0,0 +1,134 @@
+
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see .
+ * or see http://www.gnu.org/
+ */
+
+/**
+ * \file test/phpunit/FunctionsTest.php
+ * \ingroup test
+ * \brief PHPUnit test
+ * \remarks To run this script as CLI: phpunit filename.php
+ */
+
+global $conf,$user,$langs,$db;
+//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver
+require_once 'PHPUnit/Autoload.php';
+require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
+require_once dirname(__FILE__).'/../../htdocs/core/lib/functions2.lib.php';
+
+if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1');
+if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1');
+if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1');
+if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1');
+if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1');
+if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1');
+if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no menu to show
+if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php
+if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
+if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session)
+
+
+/**
+ * Class for PHPUnit tests
+ *
+ * @backupGlobals disabled
+ * @backupStaticAttributes enabled
+ * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased.
+ */
+class Functions2Test extends PHPUnit_Framework_TestCase
+{
+ protected $savconf;
+ protected $savuser;
+ protected $savlangs;
+ protected $savdb;
+
+ /**
+ * Constructor
+ * We save global variables into local variables
+ *
+ * @return CoreTest
+ */
+ function Functions2Test()
+ {
+ //$this->sharedFixture
+ global $conf,$user,$langs,$db;
+ $this->savconf=$conf;
+ $this->savuser=$user;
+ $this->savlangs=$langs;
+ $this->savdb=$db;
+
+ print __METHOD__." db->type=".$db->type." user->id=".$user->id;
+ //print " - db ".$db->db;
+ print "\n";
+ }
+
+ // Static methods
+ public static function setUpBeforeClass()
+ {
+ global $conf,$user,$langs,$db;
+ //$db->begin(); // This is to have all actions inside a transaction even if test launched without suite.
+
+ print __METHOD__."\n";
+ }
+ public static function tearDownAfterClass()
+ {
+ global $conf,$user,$langs,$db;
+ //$db->rollback();
+
+ print __METHOD__."\n";
+ }
+
+ /**
+ * Init phpunit tests
+ *
+ * @return void
+ */
+ protected function setUp()
+ {
+ global $conf,$user,$langs,$db;
+ $conf=$this->savconf;
+ $user=$this->savuser;
+ $langs=$this->savlangs;
+ $db=$this->savdb;
+
+ print __METHOD__."\n";
+ }
+ /**
+ * End phpunit tests
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ print __METHOD__."\n";
+ }
+
+
+ /**
+ * testJsUnEscape
+ *
+ * @return void
+ */
+ public function testJsUnEscape()
+ {
+ $result=jsUnEscape('%u03BD%u03B5%u03BF');
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals('νεο',$result);
+
+ return;
+ }
+}
+?>
\ No newline at end of file