Browse Source

Implemented security in import.php

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@834 a333f486-631f-4898-b8df-5754b55c2be0
romainq 14 years ago
parent
commit
145d2181db

+ 1 - 0
core/test.class.inc.php

@@ -218,6 +218,7 @@ abstract class TestWebServices extends TestHandler
 	static protected function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
 	static protected function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
 	{
 	{
 		$aDataAndAuth = $aData;
 		$aDataAndAuth = $aData;
+// To be changed to use basic authentication
 		$aDataAndAuth['operation'] = 'login';
 		$aDataAndAuth['operation'] = 'login';
 		$aDataAndAuth['auth_user'] = $sLogin;
 		$aDataAndAuth['auth_user'] = $sLogin;
 		$aDataAndAuth['auth_pwd'] = $sPassword;
 		$aDataAndAuth['auth_pwd'] = $sPassword;

+ 1 - 0
dictionaries/dictionary.itop.ui.php

@@ -383,6 +383,7 @@ Dict::Add('EN US', 'English', 'English', array(
 	'UI:Error:ObjectsAlreadyDeleted' => 'Error: objects have already been deleted!',
 	'UI:Error:ObjectsAlreadyDeleted' => 'Error: objects have already been deleted!',
 	'UI:Error:BulkDeleteNotAllowedOn_Class' => 'You are not allowed to perform a bulk delete of objects of class %1$s',
 	'UI:Error:BulkDeleteNotAllowedOn_Class' => 'You are not allowed to perform a bulk delete of objects of class %1$s',
 	'UI:Error:DeleteNotAllowedOn_Class' => 'You are not allowed to delete objects of class %1$s',
 	'UI:Error:DeleteNotAllowedOn_Class' => 'You are not allowed to delete objects of class %1$s',
+	'UI:Error:BulkModifyNotAllowedOn_Class' => 'You are not allowed to perform a bulk update of objects of class %1$s',
 	'UI:Error:ObjectAlreadyCloned' => 'Error: the object has already been cloned!',
 	'UI:Error:ObjectAlreadyCloned' => 'Error: the object has already been cloned!',
 	'UI:Error:ObjectAlreadyCreated' => 'Error: the object has already been created!',
 	'UI:Error:ObjectAlreadyCreated' => 'Error: the object has already been created!',
 	'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Error: invalid stimulus "%1$s" on object %2$s in state "%3$s".',
 	'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Error: invalid stimulus "%1$s" on object %2$s in state "%3$s".',

+ 1 - 0
dictionaries/es_cr.dictionary.itop.ui.php

@@ -392,6 +392,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
 	'UI:Error:ObjectsAlreadyDeleted' => 'Error: objects have already been deleted!',
 	'UI:Error:ObjectsAlreadyDeleted' => 'Error: objects have already been deleted!',
 	'UI:Error:BulkDeleteNotAllowedOn_Class' => 'You are not allowed to perform a bulk delete of objects of class %1$s',
 	'UI:Error:BulkDeleteNotAllowedOn_Class' => 'You are not allowed to perform a bulk delete of objects of class %1$s',
 	'UI:Error:DeleteNotAllowedOn_Class' => 'You are not allowed to delete objects of class %1$s',
 	'UI:Error:DeleteNotAllowedOn_Class' => 'You are not allowed to delete objects of class %1$s',
+	'UI:Error:BulkModifyNotAllowedOn_Class' => 'You are not allowed to perform a bulk update of objects of class %1$s',
 	'UI:Error:ObjectAlreadyCloned' => 'Error: the object has already been cloned!',
 	'UI:Error:ObjectAlreadyCloned' => 'Error: the object has already been cloned!',
 	'UI:Error:ObjectAlreadyCreated' => 'Error: the object has already been created!',
 	'UI:Error:ObjectAlreadyCreated' => 'Error: the object has already been created!',
 	'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Error: invalid stimulus "%1$s" on object %2$s in state "%3$s".',
 	'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Error: invalid stimulus "%1$s" on object %2$s in state "%3$s".',

+ 1 - 0
dictionaries/fr.dictionary.itop.ui.php

@@ -385,6 +385,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
 	'UI:Error:ObjectsAlreadyDeleted' => 'Erreur: les objets ont déjà été supprimés !',
 	'UI:Error:ObjectsAlreadyDeleted' => 'Erreur: les objets ont déjà été supprimés !',
 	'UI:Error:BulkDeleteNotAllowedOn_Class' => 'Vous n\'êtes pas autorisé à faire une suppression massive sur les objets de type %1$s',
 	'UI:Error:BulkDeleteNotAllowedOn_Class' => 'Vous n\'êtes pas autorisé à faire une suppression massive sur les objets de type %1$s',
 	'UI:Error:DeleteNotAllowedOn_Class' => 'Vous n\'êtes pas autorisé supprimer des objets de type %1$s',
 	'UI:Error:DeleteNotAllowedOn_Class' => 'Vous n\'êtes pas autorisé supprimer des objets de type %1$s',
+	'UI:Error:BulkModifyNotAllowedOn_Class' => 'Vous n\'êtes pas autorisé à faire une modification massive sur les objets de type %1$s',
 	'UI:Error:ObjectAlreadyCloned' => 'Erreur: l\'objet a déjà été dupliqué !',
 	'UI:Error:ObjectAlreadyCloned' => 'Erreur: l\'objet a déjà été dupliqué !',
 	'UI:Error:ObjectAlreadyCreated' => 'Erreur: l\'objet a déjà été créé !',
 	'UI:Error:ObjectAlreadyCreated' => 'Erreur: l\'objet a déjà été créé !',
 	'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Erreur: le stimulus "%1$s" n\'est pas valide pour l\'objet %2$s dans l\'état "%3$s".',
 	'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Erreur: le stimulus "%1$s" n\'est pas valide pour l\'objet %2$s dans l\'état "%3$s".',

+ 2 - 2
pages/UI.php

@@ -993,7 +993,7 @@ try
 			}
 			}
 			if (!UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, DBObjectSet::FromArray($sClass, $aObjects)))
 			if (!UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, DBObjectSet::FromArray($sClass, $aObjects)))
 			{
 			{
-				throw new SecurityException(Dict::S('UI:Error:BulkDeleteNotAllowedOn_Class'), $sClass);
+				throw new SecurityException(Dict::Format('UI:Error:BulkDeleteNotAllowedOn_Class', $sClass));
 			}
 			}
 			$oP->set_title(Dict::S('UI:BulkDeletePageTitle'));
 			$oP->set_title(Dict::S('UI:BulkDeletePageTitle'));
 			DeleteObjects($oP, $sClass, $aObjects, ($operation == 'bulk_delete_confirmed'));
 			DeleteObjects($oP, $sClass, $aObjects, ($operation == 'bulk_delete_confirmed'));
@@ -1008,7 +1008,7 @@ try
 	
 	
 		if (!UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, DBObjectSet::FromObject($oObj)))
 		if (!UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, DBObjectSet::FromObject($oObj)))
 		{
 		{
-			throw new SecurityException(Dict::S('UI:Error:DeleteNotAllowedOn_Class'), $sClass);
+			throw new SecurityException(Dict::Format('UI:Error:DeleteNotAllowedOn_Class', $sClass));
 		}
 		}
 		DeleteObjects($oP, $sClass, array($oObj), ($operation == 'delete_confirmed'));
 		DeleteObjects($oP, $sClass, array($oObj), ($operation == 'delete_confirmed'));
 		break;
 		break;

+ 66 - 9
pages/testlist.inc.php

@@ -1226,7 +1226,10 @@ class TestImportREST extends TestWebServices
 			$aGetParamReport[] = $sArg.'='.$sValue;
 			$aGetParamReport[] = $sArg.'='.$sValue;
 		}
 		}
 		$sGetParams = implode('&', $aGetParams);
 		$sGetParams = implode('&', $aGetParams);
-		$sRes = self::DoPostRequestAuth('../webservices/import.php?'.$sGetParams, $aPostData);
+		$sLogin = isset($aLoadSpec['login']) ? $aLoadSpec['login'] : 'admin';
+		$sPassword = isset($aLoadSpec['password']) ? $aLoadSpec['password'] : 'admin';
+
+		$sRes = self::DoPostRequestAuth('../webservices/import.php?'.$sGetParams, $aPostData, $sLogin, $sPassword);
 
 
 		$sArguments = implode('<br/>', $aGetParamReport);
 		$sArguments = implode('<br/>', $aGetParamReport);
 
 
@@ -1240,15 +1243,15 @@ class TestImportREST extends TestWebServices
 		}
 		}
 
 
 		echo "<div style=\"\">\n";
 		echo "<div style=\"\">\n";
-		echo "   <div style=\"float:left; width:45%; padding:5; background-color:#eeeeff;\">\n";
+		echo "   <div style=\"float:left; width:20%; padding:5; background-color:#eeeeff;\">\n";
 		echo "      $sArguments\n";
 		echo "      $sArguments\n";
 		echo "   </div>\n";
 		echo "   </div>\n";
-		echo "   <div style=\"float:right; width:45%; padding:5; background-color:#eeeeff\">\n";
+		echo "   <div style=\"float:right; width:75%; padding:5; background-color:#eeeeff\">\n";
 		echo "      <pre class=\"vardump\">$sCsvDataViewable</pre>\n";
 		echo "      <pre class=\"vardump\">$sCsvDataViewable</pre>\n";
 		echo "   </div>\n";
 		echo "   </div>\n";
 		echo "</div>\n";
 		echo "</div>\n";
 
 
-		echo "<pre class=\"vardump\" style=\"clear: both; padding: 5; background-color: black; color: green;\">$sRes</pre>\n";
+		echo "<pre class=\"vardump\" style=\"clear: both; padding: 15; background-color: black; color: green;\">$sRes</pre>\n";
 
 
 		echo "</div>\n";
 		echo "</div>\n";
 	}
 	}
@@ -1259,12 +1262,16 @@ class TestImportREST extends TestWebServices
 		$aLoads = array(
 		$aLoads = array(
 			array(
 			array(
 				'desc' => 'Missing class',
 				'desc' => 'Missing class',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 				),
 				),
 				'csvdata' => "xxx",
 				'csvdata' => "xxx",
 			),
 			),
 			array(
 			array(
 				'desc' => 'Wrong class',
 				'desc' => 'Wrong class',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'toto',
 					'class' => 'toto',
 				),
 				),
@@ -1272,6 +1279,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Wrong output type',
 				'desc' => 'Wrong output type',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'NetworkDevice',
 					'class' => 'NetworkDevice',
 					'output' => 'onthefly',
 					'output' => 'onthefly',
@@ -1280,6 +1289,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Wrong report level',
 				'desc' => 'Wrong report level',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'NetworkDevice',
 					'class' => 'NetworkDevice',
 					'reportlevel' => 'errors|ouarnings|changed',
 					'reportlevel' => 'errors|ouarnings|changed',
@@ -1288,6 +1299,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Weird format, working anyhow...',
 				'desc' => 'Weird format, working anyhow...',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Server',
 					'class' => 'Server',
 					'output' => 'details',
 					'output' => 'details',
@@ -1302,6 +1315,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load an organization',
 				'desc' => 'Load an organization',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Organization',
 					'class' => 'Organization',
 					'output' => 'details',
 					'output' => 'details',
@@ -1311,6 +1326,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load a location',
 				'desc' => 'Load a location',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1320,6 +1337,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load a person',
 				'desc' => 'Load a person',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Person',
 					'class' => 'Person',
 					'output' => 'details',
 					'output' => 'details',
@@ -1329,6 +1348,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load a person - wrong email format',
 				'desc' => 'Load a person - wrong email format',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Person',
 					'class' => 'Person',
 					'output' => 'details',
 					'output' => 'details',
@@ -1338,6 +1359,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load a team',
 				'desc' => 'Load a team',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Team',
 					'class' => 'Team',
 					'output' => 'details',
 					'output' => 'details',
@@ -1347,15 +1370,19 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load server',
 				'desc' => 'Load server',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Server',
 					'class' => 'Server',
 					'output' => 'details',
 					'output' => 'details',
 					'reconciliationkeys' => '',
 					'reconciliationkeys' => '',
 				),
 				),
-				'csvdata' => "name;status;owner_name;location_name;os_family;os_version;management_ip;cpu;ram;brand;model;serial_number\nlocalhost.;production;Demo;Grenoble;Ubuntu 9.10;2.6.31-19-generic-#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010;16.16.230.232;Intel(R) Core(TM)2 Duo CPU     T7100  @ 1.80GHz;2005;Hewlett-Packard;HP Compaq 6510b (GM108UC#ABF);CNU7370BNP",
+				'csvdata' => "name;status;owner_name;location_name;location_id->org_name;os_family;os_version;management_ip;cpu;ram;brand;model;serial_number\nlocalhost.;production;Demo;Grenoble;Demo;Ubuntu 9.10;2.6.31-19-generic-#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010;16.16.230.232;Intel(R) Core(TM)2 Duo CPU     T7100  @ 1.80GHz;2005;Hewlett-Packard;HP Compaq 6510b (GM108UC#ABF);CNU7370BNP",
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load NW if',
 				'desc' => 'Load NW if',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'NetworkInterface',
 					'class' => 'NetworkInterface',
 					'output' => 'details',
 					'output' => 'details',
@@ -1366,6 +1393,8 @@ class TestImportREST extends TestWebServices
 			// Data Bruno
 			// Data Bruno
 			array(
 			array(
 				'desc' => 'Load NW devices from real life',
 				'desc' => 'Load NW devices from real life',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'NetworkDevice',
 					'class' => 'NetworkDevice',
 					'output' => 'details',
 					'output' => 'details',
@@ -1377,6 +1406,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Load NW ifs',
 				'desc' => 'Load NW ifs',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'NetworkInterface',
 					'class' => 'NetworkInterface',
 					'output' => 'details',
 					'output' => 'details',
@@ -1389,6 +1420,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'The simplest data load',
 				'desc' => 'The simplest data load',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1397,6 +1430,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'The simplest data load + org',
 				'desc' => 'The simplest data load + org',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1405,6 +1440,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'The simplest data load + org (name)',
 				'desc' => 'The simplest data load + org (name)',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1413,6 +1450,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'The simplest data load + org (code)',
 				'desc' => 'The simplest data load + org (code)',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1421,6 +1460,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Ouput: summary',
 				'desc' => 'Ouput: summary',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'summary',
 					'output' => 'summary',
@@ -1429,6 +1470,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Ouput: retcode',
 				'desc' => 'Ouput: retcode',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'retcode',
 					'output' => 'retcode',
@@ -1437,23 +1480,29 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Error in reconciliation list',
 				'desc' => 'Error in reconciliation list',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
 					'reconciliationkeys' => 'org_id',
 					'reconciliationkeys' => 'org_id',
 				),
 				),
-				'csvdata' => "name\nParis",
+				'csvdata' => "org_name;name\nDemo;Paris",
 			),
 			),
 			array(
 			array(
 				'desc' => 'Error in attribute list that does not allow to compute reconciliation scheme',
 				'desc' => 'Error in attribute list that does not allow to compute reconciliation scheme',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
 				),
 				),
-				'csvdata' => "country\nFrance",
+				'csvdata' => "org_name;country\nDemo;France",
 			),
 			),
 			array(
 			array(
 				'desc' => 'Error in attribute list - case A',
 				'desc' => 'Error in attribute list - case A',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1462,6 +1511,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Error in attribute list - case B1 (key->attcode)',
 				'desc' => 'Error in attribute list - case B1 (key->attcode)',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1470,6 +1521,8 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Error in attribute list - case B2 (key->attcode)',
 				'desc' => 'Error in attribute list - case B2 (key->attcode)',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
@@ -1478,22 +1531,26 @@ class TestImportREST extends TestWebServices
 			),
 			),
 			array(
 			array(
 				'desc' => 'Always changing... special comment in change tracking',
 				'desc' => 'Always changing... special comment in change tracking',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
 					'comment' => 'automated testing'
 					'comment' => 'automated testing'
 				),
 				),
-				'csvdata' => "name;address\nLe pantheon;Addresse bidon:".((string)microtime(true)),
+				'csvdata' => "org_name;name;address\nDemo;Le pantheon;Addresse bidon:".((string)microtime(true)),
 			),
 			),
 			array(
 			array(
 				'desc' => 'Always changing... but "simulate"',
 				'desc' => 'Always changing... but "simulate"',
+				'login' => 'admin',
+				'password' => 'admin',
 				'args' => array(
 				'args' => array(
 					'class' => 'Location',
 					'class' => 'Location',
 					'output' => 'details',
 					'output' => 'details',
 					'simulate' => '1',
 					'simulate' => '1',
 					'comment' => 'SHOULD NEVER APPEAR IN THE HISTORY'
 					'comment' => 'SHOULD NEVER APPEAR IN THE HISTORY'
 				),
 				),
-				'csvdata' => "name;address\nLe pantheon;restore address?",
+				'csvdata' => "org_name;name;address\nDemo;Le pantheon;restore address?",
 			),
 			),
 		); 
 		); 
 
 

+ 15 - 7
webservices/import.php

@@ -179,6 +179,7 @@ if (false && utils::IsModeCLI())
 }
 }
 else
 else
 {
 {
+	$_SESSION['login_mode'] = 'basic';
 	require_once('../application/loginwebpage.class.inc.php');
 	require_once('../application/loginwebpage.class.inc.php');
 	LoginWebPage::DoLogin(); // Check user rights and prompt if needed
 	LoginWebPage::DoLogin(); // Check user rights and prompt if needed
 
 
@@ -249,6 +250,15 @@ try
 
 
 	//////////////////////////////////////////////////
 	//////////////////////////////////////////////////
 	//
 	//
+	// Security
+	//
+	if (!UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY))
+	{
+		throw new SecurityException(Dict::Format('UI:Error:BulkModifyNotAllowedOn_Class', $sClass));
+	}
+
+	//////////////////////////////////////////////////
+	//
 	// Parse first line, check attributes, analyse the request
 	// Parse first line, check attributes, analyse the request
 	//
 	//
 	if ($sCharSet == 'UTF-8')
 	if ($sCharSet == 'UTF-8')
@@ -339,12 +349,6 @@ try
 		$sReconcKeys = implode(',', $aReconcSpec);
 		$sReconcKeys = implode(',', $aReconcSpec);
 	}
 	}
 
 
-if (false)
-{
-echo "Reconciliation keys<pre class=\"vardump\">";
-print_r($sReconcKeys);
-throw new BulkLoadException("testing");
-}
 	// Interpret the list of reconciliation keys
 	// Interpret the list of reconciliation keys
 	//
 	//
 	$aFinalReconcilKeys = array();
 	$aFinalReconcilKeys = array();
@@ -438,7 +442,7 @@ throw new BulkLoadException("testing");
 		{
 		{
 			$sMoreInfo = 'Web Service (CSV)';
 			$sMoreInfo = 'Web Service (CSV)';
 		}
 		}
-		$oMyChange->Set("userinfo", $sUserString.' '.$sMoreInfo);
+		$oMyChange->Set("userinfo", $sUserString.', '.$sMoreInfo);
 		$iChangeId = $oMyChange->DBInsert();
 		$iChangeId = $oMyChange->DBInsert();
 	}
 	}
 
 
@@ -614,6 +618,10 @@ catch(BulkLoadException $e)
 {
 {
 	$oP->add_comment($e->getMessage());		
 	$oP->add_comment($e->getMessage());		
 }
 }
+catch(SecurityException $e)
+{
+	$oP->add_comment($e->getMessage());		
+}
 catch(Exception $e)
 catch(Exception $e)
 {
 {
 	$oP->add_comment((string)$e);		
 	$oP->add_comment((string)$e);