mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
SVN:trunk[708]
This commit is contained in:
@@ -35,6 +35,7 @@ require_once('../core/cmdbobject.class.inc.php');
|
||||
require_once('../application/utils.inc.php');
|
||||
require_once('../application/applicationcontext.class.inc.php');
|
||||
require_once('../application/ui.linkswidget.class.inc.php');
|
||||
require_once('../application/ui.passwordwidget.class.inc.php');
|
||||
|
||||
abstract class cmdbAbstractObject extends CMDBObject
|
||||
{
|
||||
@@ -220,6 +221,7 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
'target_attr' => $oAttDef->GetExtKeyToRemote(),
|
||||
'view_link' => false,
|
||||
'menu' => false,
|
||||
'display_limit' => true, // By default limit the list to speed up the initial load & display
|
||||
);
|
||||
}
|
||||
$oPage->p(MetaModel::GetClassIcon($sTargetClass)." ".$oAttDef->GetDescription());
|
||||
@@ -1001,6 +1003,12 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
$sHTMLValue = '';
|
||||
break;
|
||||
|
||||
case 'One Way Password':
|
||||
$oWidget = new UIPasswordWidget($sAttCode, $iId, $sNameSuffix);
|
||||
$sHTMLValue = $oWidget->Display($oPage, $aArgs);
|
||||
// Event list & validation is handled directly by the widget
|
||||
break;
|
||||
|
||||
case 'String':
|
||||
default:
|
||||
// #@# todo - add context information (depending on dimensions)
|
||||
@@ -1056,7 +1064,10 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
break;
|
||||
}
|
||||
$sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$';
|
||||
$oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $bMandatory, sFormId) } );"); // Bind to a custom event: validate
|
||||
if (!empty($aEventlist))
|
||||
{
|
||||
$oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $bMandatory, sFormId) } );"); // Bind to a custom event: validate
|
||||
}
|
||||
$aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one
|
||||
if (count($aDependencies) > 0)
|
||||
{
|
||||
|
||||
@@ -131,27 +131,30 @@ class ApplicationMenu
|
||||
{
|
||||
$index = $aMenu['index'];
|
||||
$oMenu = self::GetMenuNode($index);
|
||||
$aChildren = self::GetChildren($index);
|
||||
$sCSSClass = (count($aChildren) > 0) ? ' class="submenu"' : '';
|
||||
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
|
||||
if ($sHyperlink != '')
|
||||
if ($oMenu->IsEnabled())
|
||||
{
|
||||
$oPage->AddToMenu('<li'.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->AddToMenu('<li'.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
|
||||
}
|
||||
$aCurrentMenu = self::$aMenusIndex[$index];
|
||||
if ($iActiveMenu == $index)
|
||||
{
|
||||
$bActive = true;
|
||||
}
|
||||
if (count($aChildren) > 0)
|
||||
{
|
||||
$oPage->AddToMenu('<ul>');
|
||||
$bActive |= self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
|
||||
$oPage->AddToMenu('</ul>');
|
||||
$aChildren = self::GetChildren($index);
|
||||
$sCSSClass = (count($aChildren) > 0) ? ' class="submenu"' : '';
|
||||
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
|
||||
if ($sHyperlink != '')
|
||||
{
|
||||
$oPage->AddToMenu('<li'.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->AddToMenu('<li'.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
|
||||
}
|
||||
$aCurrentMenu = self::$aMenusIndex[$index];
|
||||
if ($iActiveMenu == $index)
|
||||
{
|
||||
$bActive = true;
|
||||
}
|
||||
if (count($aChildren) > 0)
|
||||
{
|
||||
$oPage->AddToMenu('<ul>');
|
||||
$bActive |= self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
|
||||
$oPage->AddToMenu('</ul>');
|
||||
}
|
||||
}
|
||||
}
|
||||
return $bActive;
|
||||
@@ -298,6 +301,15 @@ abstract class MenuNode
|
||||
return $this->AddParams('../pages/UI.php', $aExtraParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the menu is enabled (i.e. displayed) for the current user
|
||||
* @return bool True if enabled, false otherwise
|
||||
*/
|
||||
public function IsEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract function RenderContent(WebPage $oPage, $aExtraParams = array());
|
||||
|
||||
protected function AddParams($sHyperlink, $aExtraParams)
|
||||
@@ -394,20 +406,23 @@ class OQLMenuNode extends MenuNode
|
||||
{
|
||||
protected $sPageTitle;
|
||||
protected $sOQL;
|
||||
protected $bSearch;
|
||||
|
||||
/**
|
||||
* Create a menu item based on an OQL query and inserts it into the application's main menu
|
||||
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
|
||||
* @param string $sPageTitle Title displayed into the page's content (will be looked-up in the dictionnary for translation)
|
||||
* @param string $sOQL OQL query defining the set of objects to be displayed
|
||||
* @param integer $iParentIndex ID of the parent menu
|
||||
* @param float $fRank Number used to order the list, any number will do, but for a given level (i.e same parent) all menus are sorted based on this value
|
||||
* @param bool $bSearch Whether or not to display a (collapsed) search frame at the top of the page
|
||||
* @return MenuNode
|
||||
*/
|
||||
public function __construct($sMenuId, $sOQL, $iParentIndex, $fRank = 0)
|
||||
public function __construct($sMenuId, $sOQL, $iParentIndex, $fRank = 0, $bSearch = false)
|
||||
{
|
||||
parent::__construct($sMenuId, $iParentIndex, $fRank);
|
||||
$this->sPageTitle = "Menu:$sMenuId+";
|
||||
$this->sOQL = $sOQL;
|
||||
$this->bSearch = $bSearch;
|
||||
}
|
||||
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
@@ -422,8 +437,16 @@ class OQLMenuNode extends MenuNode
|
||||
$sIcon = '';
|
||||
}
|
||||
// The standard template used for all such pages: a (closed) search form at the top and a list of results at the bottom
|
||||
$sTemplate = <<<EOF
|
||||
$sTemplate = '';
|
||||
|
||||
if ($this->bSearch)
|
||||
{
|
||||
$sTemplate .= <<<EOF
|
||||
<itopblock BlockClass="DisplayBlock" type="search" asynchronous="false" encoding="text/oql">$this->sOQL</itopblock>
|
||||
EOF;
|
||||
}
|
||||
|
||||
$sTemplate .= <<<EOF
|
||||
<p class="page-header">$sIcon<itopstring>$this->sPageTitle</itopstring></p>
|
||||
<itopblock BlockClass="DisplayBlock" type="list" asynchronous="false" encoding="text/oql">$this->sOQL</itopblock>
|
||||
EOF;
|
||||
@@ -431,6 +454,40 @@ EOF;
|
||||
$oTemplate->Render($oPage, $aExtraParams);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This class defines a menu item that displays a search form for the given class of objects
|
||||
*/
|
||||
class SearchMenuNode extends MenuNode
|
||||
{
|
||||
protected $sPageTitle;
|
||||
protected $sClass;
|
||||
|
||||
/**
|
||||
* Create a menu item based on an OQL query and inserts it into the application's main menu
|
||||
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
|
||||
* @param string $sClass The class of objects to search for
|
||||
* @param string $sPageTitle Title displayed into the page's content (will be looked-up in the dictionnary for translation)
|
||||
* @param integer $iParentIndex ID of the parent menu
|
||||
* @param float $fRank Number used to order the list, any number will do, but for a given level (i.e same parent) all menus are sorted based on this value
|
||||
* @return MenuNode
|
||||
*/
|
||||
public function __construct($sMenuId, $sClass, $iParentIndex, $fRank = 0)
|
||||
{
|
||||
parent::__construct($sMenuId, $iParentIndex, $fRank);
|
||||
$this->sPageTitle = "Menu:$sMenuId+";
|
||||
$this->sClass = $sClass;
|
||||
}
|
||||
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
// The standard template used for all such pages: an open search form at the top
|
||||
$sTemplate = <<<EOF
|
||||
<itopblock BlockClass="DisplayBlock" type="search" asynchronous="false" encoding="text/oql" parameters="open:true">SELECT $this->sClass</itopblock>
|
||||
EOF;
|
||||
$oTemplate = new DisplayTemplate($sTemplate);
|
||||
$oTemplate->Render($oPage, $aExtraParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class defines a menu that points to any web page. It takes only two parameters:
|
||||
@@ -468,4 +525,60 @@ class WebPageMenuNode extends MenuNode
|
||||
assert(false); // Shall never be called, the external web page will handle the display by itself
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class defines a menu that points to the page for creating a new object of the specified class.
|
||||
* It take only one parameter: the name of the class
|
||||
* Note: the parameter menu=xxx (where xxx is the id of the menu itself) will be added to the hyperlink
|
||||
* in order to make it the active one
|
||||
*/
|
||||
class NewObjectMenuNode extends MenuNode
|
||||
{
|
||||
protected $sClass;
|
||||
|
||||
/**
|
||||
* Create a menu item that points to the URL for creating a new object, the menu will be added only if the current user has enough
|
||||
* rights to create such an object (or an object of a child class)
|
||||
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
|
||||
* @param string $sClass URL to the page to load. Use relative URL if you want to keep the application portable !
|
||||
* @param integer $iParentIndex ID of the parent menu
|
||||
* @param float $fRank Number used to order the list, any number will do, but for a given level (i.e same parent) all menus are sorted based on this value
|
||||
* @return MenuNode
|
||||
*/
|
||||
public function __construct($sMenuId, $sClass, $iParentIndex, $fRank = 0)
|
||||
{
|
||||
parent::__construct($sMenuId, $iParentIndex, $fRank);
|
||||
$this->sClass = $sClass;
|
||||
}
|
||||
|
||||
public function GetHyperlink($aExtraParams)
|
||||
{
|
||||
$sHyperlink = '../pages/UI.php?operation=new&class='.$this->sClass;
|
||||
$aExtraParams['menu'] = $this->GetIndex();
|
||||
return $this->AddParams($sHyperlink, $aExtraParams);
|
||||
}
|
||||
|
||||
public function IsEnabled()
|
||||
{
|
||||
// Enable this menu, only if the current user has enough rights to create such an object, or an object of
|
||||
// any child class
|
||||
|
||||
$aSubClasses = MetaModel::EnumChildClasses($this->sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
|
||||
$bActionIsAllowed = false;
|
||||
|
||||
foreach($aSubClasses as $sCandidateClass)
|
||||
{
|
||||
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
|
||||
{
|
||||
$bActionIsAllowed = true;
|
||||
break; // Enough for now
|
||||
}
|
||||
}
|
||||
return $bActionIsAllowed;
|
||||
}
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
assert(false); // Shall never be called, the external web page will handle the display by itself
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -170,7 +170,7 @@ class DisplayTemplate
|
||||
|
||||
case 'itopcheck':
|
||||
$sClassName = $aAttributes['class'];
|
||||
if (MetaModel::IsValidClass($sClassName))
|
||||
if (MetaModel::IsValidClass($sClassName) && UserRights::IsActionAllowed($sClassName, UR_ACTION_READ))
|
||||
{
|
||||
$oTemplate = new DisplayTemplate($sContent);
|
||||
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
|
||||
|
||||
68
application/ui.passwordwidget.class.inc.php
Normal file
68
application/ui.passwordwidget.class.inc.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// 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; version 3 of the License.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Class UIPasswordWidget
|
||||
* UI wdiget for displaying and editing one-way encrypted passwords
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/
|
||||
|
||||
require_once('../application/webpage.class.inc.php');
|
||||
require_once('../application/displayblock.class.inc.php');
|
||||
|
||||
class UIPasswordWidget
|
||||
{
|
||||
protected static $iWidgetIndex = 0;
|
||||
protected $sAttCode;
|
||||
protected $sNameSuffix;
|
||||
protected $iId;
|
||||
|
||||
public function __construct($sAttCode, $iInputId, $sNameSuffix = '')
|
||||
{
|
||||
self::$iWidgetIndex++;
|
||||
$this->sAttCode = $sAttCode;
|
||||
$this->sNameSuffix = $sNameSuffix;
|
||||
$this->iId = $iInputId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML fragment corresponding to the linkset editing widget
|
||||
* @param WebPage $oP The web page used for all the output
|
||||
* @param Hash $aArgs Extra context arguments
|
||||
* @return string The HTML fragment to be inserted into the page
|
||||
*/
|
||||
public function Display(WebPage $oPage, $aArgs = array())
|
||||
{
|
||||
$sCode = $this->sAttCode.$this->sNameSuffix;
|
||||
$iWidgetIndex = self::$iWidgetIndex;
|
||||
$sHtmlValue = '';
|
||||
$sHtmlValue = '<input type="password" name="attr_'.$sCode.'" id="'.$this->iId.'" value="*****"/> <span id="v_'.$this->iId.'"></span><br/>';
|
||||
$sHtmlValue .= '<input type="password" id="'.$this->iId.'_confirm" value="*****"/> '.Dict::S('UI:PasswordConfirm').' <input type="button" value="'.Dict::S('UI:Button:ResetPassword').'" onClick="ResetPwd(\''.$this->iId.'\');">';
|
||||
$sHtmlValue .= '<input type="hidden" id="'.$this->iId.'_changed" name="attr_'.$sCode.'_changed" value="0"/>';
|
||||
|
||||
$oPage->add_ready_script("$('#$this->iId').bind('keyup change', function(evt) { return PasswordFieldChanged('$this->iId') } );"); // Bind to a custom event: validate
|
||||
$oPage->add_ready_script("$('#$this->iId').bind('keyup change', function(evt) { return PasswordFieldChanged('$this->iId') } );"); // Bind to a custom event: validate
|
||||
$oPage->add_ready_script("$('#$this->iId').bind('keyup change validate', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
||||
$oPage->add_ready_script("$('#{$this->iId}_confirm').bind('keyup change', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
|
||||
|
||||
return $sHtmlValue;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
require_once('MyHelpers.class.inc.php');
|
||||
require_once('ormdocument.class.inc.php');
|
||||
require_once('ormpassword.class.inc.php');
|
||||
|
||||
/**
|
||||
* MissingColumnException - sent if an attribute is being created but the column is missing in the row
|
||||
@@ -377,7 +378,7 @@ class AttributeLinkedSetIndirect extends AttributeLinkedSet
|
||||
* @package iTopORM
|
||||
*/
|
||||
class AttributeDBFieldVoid extends AttributeDefinition
|
||||
{
|
||||
{
|
||||
static protected function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array("allowed_values", "depends_on", "sql"));
|
||||
@@ -465,7 +466,7 @@ class AttributeDBFieldVoid extends AttributeDefinition
|
||||
* @package iTopORM
|
||||
*/
|
||||
class AttributeDBField extends AttributeDBFieldVoid
|
||||
{
|
||||
{
|
||||
static protected function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array("default_value", "is_null_allowed"));
|
||||
@@ -861,6 +862,66 @@ class AttributePassword extends AttributeString
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a text column (size < 255) to an attribute that is encrypted in the database
|
||||
* The encryption is based on a key set per iTop instance. Thus if you export your
|
||||
* database (in SQL) to someone else without providing the key at the same time
|
||||
* the encrypted fields will remain encrypted
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
class AttributeEncryptedString extends AttributeString
|
||||
{
|
||||
static $sKey = null; // Encryption key used for all encrypted fields
|
||||
|
||||
public function __construct($sCode, $aParams)
|
||||
{
|
||||
parent::__construct($sCode, $aParams);
|
||||
if (self::$sKey == null)
|
||||
{
|
||||
self::$sKey = MetaModel::GetConfig()->GetEncryptionKey();
|
||||
}
|
||||
}
|
||||
|
||||
protected function GetSQLCol() {return "TINYBLOB";}
|
||||
|
||||
public function GetFilterDefinitions()
|
||||
{
|
||||
// Note: due to this, you will get an error if a an encrypted field is declared as a search criteria (see ZLists)
|
||||
// not allowed to search on encrypted fields !
|
||||
return array();
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue)
|
||||
{
|
||||
if (is_null($proposedValue)) return null;
|
||||
return (string)$proposedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the value when reading from the database
|
||||
*/
|
||||
public function FromSQLToValue($aCols, $sPrefix = '')
|
||||
{
|
||||
$oSimpleCrypt = new SimpleCrypt();
|
||||
$sValue = $oSimpleCrypt->Decrypt(self::$sKey, $aCols[$sPrefix]);
|
||||
return $sValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt the value before storing it in the database
|
||||
*/
|
||||
public function GetSQLValues($value)
|
||||
{
|
||||
$oSimpleCrypt = new SimpleCrypt();
|
||||
$encryptedValue = $oSimpleCrypt->Encrypt(self::$sKey, $value);
|
||||
|
||||
$aValues = array();
|
||||
$aValues[$this->Get("sql")] = $encryptedValue;
|
||||
return $aValues;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a text column (size > ?) to an attribute
|
||||
*
|
||||
@@ -1880,6 +1941,140 @@ class AttributeBlob extends AttributeDefinition
|
||||
return ''; // Not exportable in XML, or as CDATA + some subtags ??
|
||||
}
|
||||
}
|
||||
/**
|
||||
* One way encrypted (hashed) password
|
||||
*/
|
||||
class AttributeOneWayPassword extends AttributeDefinition
|
||||
{
|
||||
static protected function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array("depends_on"));
|
||||
}
|
||||
|
||||
public function GetType() {return "One Way Password";}
|
||||
public function GetTypeDesc() {return "One Way Password";}
|
||||
public function GetEditClass() {return "One Way Password";}
|
||||
|
||||
public function IsDirectField() {return true;}
|
||||
public function IsScalar() {return true;}
|
||||
public function IsWritable() {return true;}
|
||||
public function GetDefaultValue() {return "";}
|
||||
public function IsNullAllowed() {return $this->GetOptional("is_null_allowed", false);}
|
||||
|
||||
// Facilitate things: allow the user to Set the value from a string or from an ormPassword (already encrypted)
|
||||
public function MakeRealValue($proposedValue)
|
||||
{
|
||||
$oPassword = $proposedValue;
|
||||
if (!is_object($oPassword))
|
||||
{
|
||||
$oPassword = new ormPassword('', '');
|
||||
$oPassword->SetPassword($proposedValue);
|
||||
}
|
||||
return $oPassword;
|
||||
}
|
||||
|
||||
public function GetSQLExpressions()
|
||||
{
|
||||
$aColumns = array();
|
||||
// Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix
|
||||
$aColumns[''] = $this->GetCode().'_hash';
|
||||
$aColumns['_salt'] = $this->GetCode().'_salt';
|
||||
return $aColumns;
|
||||
}
|
||||
|
||||
public function FromSQLToValue($aCols, $sPrefix = '')
|
||||
{
|
||||
if (!isset($aCols[$sPrefix]))
|
||||
{
|
||||
$sAvailable = implode(', ', array_keys($aCols));
|
||||
throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}");
|
||||
}
|
||||
$hashed = $aCols[$sPrefix];
|
||||
|
||||
if (!isset($aCols[$sPrefix.'_salt']))
|
||||
{
|
||||
$sAvailable = implode(', ', array_keys($aCols));
|
||||
throw new MissingColumnException("Missing column '".$sPrefix."_salt' from {$sAvailable}");
|
||||
}
|
||||
$sSalt = $aCols[$sPrefix.'_salt'];
|
||||
|
||||
$value = new ormPassword($hashed, $sSalt);
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetSQLValues($value)
|
||||
{
|
||||
// #@# Optimization: do not load blobs anytime
|
||||
// As per mySQL doc, selecting blob columns will prevent mySQL from
|
||||
// using memory in case a temporary table has to be created
|
||||
// (temporary tables created on disk)
|
||||
// We will have to remove the blobs from the list of attributes when doing the select
|
||||
// then the use of Get() should finalize the load
|
||||
if ($value instanceOf ormPassword)
|
||||
{
|
||||
$aValues = array();
|
||||
$aValues[$this->GetCode().'_hash'] = $value->GetHash();
|
||||
$aValues[$this->GetCode().'_salt'] = $value->GetSalt();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aValues = array();
|
||||
$aValues[$this->GetCode().'_hash'] = '';
|
||||
$aValues[$this->GetCode().'_salt'] = '';
|
||||
echo "Writing an empty password !!!";
|
||||
echo "<pre>\n";
|
||||
print_r($value);
|
||||
echo "</pre>\n";
|
||||
}
|
||||
return $aValues;
|
||||
}
|
||||
|
||||
public function GetSQLColumns()
|
||||
{
|
||||
$aColumns = array();
|
||||
$aColumns[$this->GetCode().'_hash'] = 'TINYBLOB';
|
||||
$aColumns[$this->GetCode().'_salt'] = 'TINYBLOB';
|
||||
return $aColumns;
|
||||
}
|
||||
|
||||
public function GetFilterDefinitions()
|
||||
{
|
||||
return array();
|
||||
// still not working... see later...
|
||||
}
|
||||
|
||||
public function GetBasicFilterOperators()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
public function GetBasicFilterLooseOperator()
|
||||
{
|
||||
return '=';
|
||||
}
|
||||
|
||||
public function GetBasicFilterSQLExpr($sOpCode, $value)
|
||||
{
|
||||
return 'true';
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
{
|
||||
if (is_object($value))
|
||||
{
|
||||
return $value->GetAsHTML();
|
||||
}
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
{
|
||||
return ''; // Not exportable in CSV
|
||||
}
|
||||
|
||||
public function GetAsXML($value)
|
||||
{
|
||||
return ''; // Not exportable in XML
|
||||
}
|
||||
}
|
||||
|
||||
// Indexed array having two dimensions
|
||||
class AttributeTable extends AttributeText
|
||||
|
||||
@@ -102,7 +102,7 @@ class CMDBChangeOpCreate extends CMDBChangeOp
|
||||
*/
|
||||
public function GetDescription()
|
||||
{
|
||||
return 'Object created';
|
||||
return Dict::S('Change:ObjectCreated');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ class CMDBChangeOpDelete extends CMDBChangeOp
|
||||
*/
|
||||
public function GetDescription()
|
||||
{
|
||||
return 'Object deleted';
|
||||
return Dict::S('Change:ObjectDeleted');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,16 +228,16 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
|
||||
if (substr($sNewValue,0, strlen($sOldValue)) == $sOldValue) // Text added at the end
|
||||
{
|
||||
$sDelta = substr($sNewValue, strlen($sOldValue));
|
||||
$sResult = "$sDelta appended to $sAttName";
|
||||
$sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sAttName);
|
||||
}
|
||||
else if (substr($sNewValue, -strlen($sOldValue)) == $sOldValue) // Text added at the beginning
|
||||
{
|
||||
$sDelta = substr($sNewValue, 0, strlen($sNewValue) - strlen($sOldValue));
|
||||
$sResult = "$sDelta appended to $sAttName";
|
||||
$sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sAttName);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sResult = "$sAttName set to $sNewValue (previous value: $sOldValue)";
|
||||
$sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sAttName, $sNewValue, $sOldValue);
|
||||
}
|
||||
}
|
||||
elseif($bIsHtml && $oAttDef->IsExternalKey())
|
||||
@@ -253,7 +253,7 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
|
||||
}
|
||||
else
|
||||
{
|
||||
$sResult = "$sAttName set to $sNewValue (previous value: $sOldValue)";
|
||||
$sResult = Dict::Format('Change:Att_SetTo_NewValue_PreviousValue_OldValue', $sAttName, $sNewValue, $sOldValue);
|
||||
}
|
||||
}
|
||||
return $sResult;
|
||||
@@ -313,7 +313,111 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
|
||||
$sDocView .= "<br/>".Dict::Format('UI:OpenDocumentInNewWindow_',$oPrevDoc->GetDisplayLink(get_class($this), $this->GetKey(), 'prevdata')).", \n";
|
||||
$sDocView .= Dict::Format('UI:DownloadDocument_', $oPrevDoc->GetDownloadLink(get_class($this), $this->GetKey(), 'prevdata'))."\n";
|
||||
//$sDocView = $oPrevDoc->GetDisplayInline(get_class($this), $this->GetKey(), 'prevdata');
|
||||
$sResult = "$sAttName changed, previous value: $sDocView";
|
||||
$sResult = Dict::Format('Change:AttName_Changed_PreviousValue_OldValue', $sAttName, $sDocView);
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Safely record the modification of one way encrypted password
|
||||
*/
|
||||
class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "core/cmdb",
|
||||
"key_type" => "",
|
||||
"name_attcode" => "change",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_changeop_setatt_pwd",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeOneWayPassword("prev_pwd", array("sql" => 'data', "default_value" => '', "is_null_allowed"=> true, "allowed_values" => null, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe (as a text string) the modifications corresponding to this change
|
||||
*/
|
||||
public function GetDescription()
|
||||
{
|
||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||
$bIsHtml = true;
|
||||
|
||||
$sResult = '';
|
||||
$oTargetObjectClass = $this->Get('objclass');
|
||||
$oTargetObjectKey = $this->Get('objkey');
|
||||
$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
|
||||
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
|
||||
|
||||
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
|
||||
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
|
||||
$sAttName = $oAttDef->GetLabel();
|
||||
$sResult = Dict::Format('Change:AttName_Changed', $sAttName);
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely record the modification of an encrypted field
|
||||
*/
|
||||
class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "core/cmdb",
|
||||
"key_type" => "",
|
||||
"name_attcode" => "change",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_changeop_setatt_encrypted",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeEncryptedString("prevstring", array("sql" => 'data', "default_value" => '', "is_null_allowed"=> true, "allowed_values" => null, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe (as a text string) the modifications corresponding to this change
|
||||
*/
|
||||
public function GetDescription()
|
||||
{
|
||||
// Temporary, until we change the options of GetDescription() -needs a more global revision
|
||||
$bIsHtml = true;
|
||||
|
||||
$sResult = '';
|
||||
$oTargetObjectClass = $this->Get('objclass');
|
||||
$oTargetObjectKey = $this->Get('objkey');
|
||||
$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
|
||||
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
|
||||
|
||||
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
|
||||
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
|
||||
$sAttName = $oAttDef->GetLabel();
|
||||
$sPrevString = $this->Get('prevstring');
|
||||
$sResult = Dict::Format('Change:AttName_Changed_PreviousValue_OldValue', $sAttName, $sPrevString);
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
@@ -370,7 +474,7 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
|
||||
$sTextView = '<div>'.$this->GetAsHtml('prevdata').'</div>';
|
||||
|
||||
//$sDocView = $oPrevDoc->GetDisplayInline(get_class($this), $this->GetKey(), 'prevdata');
|
||||
$sResult = "$sAttName changed, previous value: $sTextView";
|
||||
$sResult = Dict::Format('Change:AttName_Changed_PreviousValue_OldValue', $sAttName, $sTextView);
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
@@ -187,7 +187,47 @@ abstract class CMDBObject extends DBObject
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
if ($oAttDef->IsLinkSet()) continue; // #@# temporary
|
||||
|
||||
if ($oAttDef instanceOf AttributeBlob)
|
||||
if ($oAttDef instanceOf AttributeOneWayPassword)
|
||||
{
|
||||
// One Way encrypted passwords' history is stored -one way- encrypted
|
||||
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeOneWayPassword");
|
||||
$oMyChangeOp->Set("change", $oChange->GetKey());
|
||||
$oMyChangeOp->Set("objclass", get_class($this));
|
||||
$oMyChangeOp->Set("objkey", $this->GetKey());
|
||||
$oMyChangeOp->Set("attcode", $sAttCode);
|
||||
|
||||
if (array_key_exists($sAttCode, $aOrigValues))
|
||||
{
|
||||
$original = $aOrigValues[$sAttCode];
|
||||
}
|
||||
else
|
||||
{
|
||||
$original = '';
|
||||
}
|
||||
$oMyChangeOp->Set("prev_pwd", $original);
|
||||
$iId = $oMyChangeOp->DBInsertNoReload();
|
||||
}
|
||||
elseif ($oAttDef instanceOf AttributeEncryptedString)
|
||||
{
|
||||
// Encrypted string history is stored encrypted
|
||||
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeEncrypted");
|
||||
$oMyChangeOp->Set("change", $oChange->GetKey());
|
||||
$oMyChangeOp->Set("objclass", get_class($this));
|
||||
$oMyChangeOp->Set("objkey", $this->GetKey());
|
||||
$oMyChangeOp->Set("attcode", $sAttCode);
|
||||
|
||||
if (array_key_exists($sAttCode, $aOrigValues))
|
||||
{
|
||||
$original = $aOrigValues[$sAttCode];
|
||||
}
|
||||
else
|
||||
{
|
||||
$original = '';
|
||||
}
|
||||
$oMyChangeOp->Set("prevdata", $original);
|
||||
$iId = $oMyChangeOp->DBInsertNoReload();
|
||||
}
|
||||
elseif ($oAttDef instanceOf AttributeBlob)
|
||||
{
|
||||
// Data blobs
|
||||
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeBlob");
|
||||
|
||||
@@ -46,6 +46,7 @@ define ('DEFAULT_SECURE_CONNECTION_REQUIRED', false);
|
||||
define ('DEFAULT_HTTPS_HYPERLINKS', false);
|
||||
define ('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|basic|external');
|
||||
define ('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']');
|
||||
define ('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random value, later...
|
||||
|
||||
/**
|
||||
* Config
|
||||
@@ -126,6 +127,13 @@ class Config
|
||||
*/
|
||||
protected $m_sExtAuthVariable;
|
||||
|
||||
/**
|
||||
* @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value
|
||||
* unless you want to import a database from another iTop instance, in which case you must use
|
||||
* the same encryption key in order to properly decode the encrypted fields
|
||||
*/
|
||||
protected $m_sEncryptionKey;
|
||||
|
||||
public function __construct($sConfigFile, $bLoadConfig = true)
|
||||
{
|
||||
$this->m_sFile = $sConfigFile;
|
||||
@@ -177,6 +185,7 @@ class Config
|
||||
$this->m_sDefaultLanguage = 'EN US';
|
||||
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
|
||||
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_sEncryptionKey = DEFAULT_ENCRYPTION_KEY;
|
||||
|
||||
$this->m_aModuleSettings = array();
|
||||
|
||||
@@ -278,6 +287,7 @@ class Config
|
||||
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
|
||||
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
|
||||
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
|
||||
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : DEFAULT_ENCRYPTION_KEY;
|
||||
}
|
||||
|
||||
protected function Verify()
|
||||
@@ -430,6 +440,10 @@ class Config
|
||||
return $this->m_sDefaultLanguage;
|
||||
}
|
||||
|
||||
public function GetEncryptionKey()
|
||||
{
|
||||
return $this->m_sEncryptionKey;
|
||||
}
|
||||
|
||||
public function GetAllowedLoginTypes()
|
||||
{
|
||||
@@ -531,6 +545,11 @@ class Config
|
||||
$this->m_sExtAuthVariable = $sExtAuthVariable;
|
||||
}
|
||||
|
||||
public function SetEncryptionKey($sKey)
|
||||
{
|
||||
$this->m_sEncryptionKey = $sKey;
|
||||
}
|
||||
|
||||
public function FileIsWritable()
|
||||
{
|
||||
return is_writable($this->m_sFile);
|
||||
@@ -580,6 +599,7 @@ class Config
|
||||
fwrite($hFile, "\t'https_hyperlinks' => ".($this->m_bHttpsHyperlinks ? 'true' : 'false').",\n");
|
||||
fwrite($hFile, "\t'default_language' => '{$this->m_sDefaultLanguage}',\n");
|
||||
fwrite($hFile, "\t'allowed_login_types' => '{$this->m_sAllowedLoginTypes}',\n");
|
||||
fwrite($hFile, "\t'encryption_key' => '{$this->m_sEncryptionKey}',\n");
|
||||
fwrite($hFile, ");\n");
|
||||
|
||||
fwrite($hFile, "\n");
|
||||
|
||||
@@ -3216,6 +3216,11 @@ abstract class MetaModel
|
||||
return self::$m_oConfig->GetModuleSetting($sModule, $sProperty, $defaultvalue);
|
||||
}
|
||||
|
||||
public static function GetConfig()
|
||||
{
|
||||
return self::$m_oConfig;
|
||||
}
|
||||
|
||||
protected static $m_aPlugins = array();
|
||||
public static function RegisterPlugin($sType, $sName, $aInitCallSpec = array())
|
||||
{
|
||||
|
||||
119
core/ormpassword.class.inc.php
Normal file
119
core/ormpassword.class.inc.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// 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; version 3 of the License.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
require_once('../core/simplecrypt.class.inc.php');
|
||||
|
||||
/**
|
||||
* ormPassword
|
||||
* encapsulate the behavior of a one way encrypted password stored hashed
|
||||
* with a per password (as random as possible) salt, in order to prevent a "Rainbow table" hack.
|
||||
* If a cryptographic random number generator is available (on Linux or Windows)
|
||||
* it will be used for generating the salt.
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
* @package itopORM
|
||||
*/
|
||||
|
||||
class ormPassword
|
||||
{
|
||||
protected $m_sHashed;
|
||||
protected $m_sSalt;
|
||||
|
||||
/**
|
||||
* Constructor, initializes the password from the encrypted values
|
||||
*/
|
||||
public function __construct($sHash = '', $sSalt = '')
|
||||
{
|
||||
$this->m_sHashed = $sHash;
|
||||
$this->m_sSalt = $sSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the clear text password, with a unique salt
|
||||
*/
|
||||
public function SetPassword($sClearTextPassword)
|
||||
{
|
||||
$this->m_sSalt = SimpleCrypt::GetNewSalt();
|
||||
$this->m_sHashed = $this->ComputeHash($sClearTextPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the password: displays some stars
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return '*****'; // Password can not be read
|
||||
}
|
||||
|
||||
public function IsEmpty()
|
||||
{
|
||||
return ($this->m_hashed == null);
|
||||
}
|
||||
|
||||
public function GetHash()
|
||||
{
|
||||
return $this->m_sHashed;
|
||||
}
|
||||
|
||||
public function GetSalt()
|
||||
{
|
||||
return $this->m_sSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the password: displays some stars
|
||||
* @return string
|
||||
*/
|
||||
public function GetAsHTML()
|
||||
{
|
||||
return '*****'; // Password can not be read
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the supplied clear text password matches the encrypted one
|
||||
* @param string $sClearTextPassword
|
||||
* @return boolean True if it matches, false otherwise
|
||||
*/
|
||||
public function CheckPassword($sClearTextPassword)
|
||||
{
|
||||
$bResult = false;
|
||||
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
|
||||
if ($this->m_sHashed == $sHashedPwd)
|
||||
{
|
||||
$bResult = true;
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the hashed version of a password using a unique salt
|
||||
* for this password. A unique salt is generated if needed
|
||||
* @return string
|
||||
*/
|
||||
protected function ComputeHash($sClearTextPwd)
|
||||
{
|
||||
if ($this->m_sSalt == null)
|
||||
{
|
||||
$this->m_sSalt = SimpleCrypt::GetNewSalt();
|
||||
}
|
||||
return hash('sha256', $this->m_sSalt.$sClearTextPwd);
|
||||
}
|
||||
}
|
||||
?>
|
||||
235
core/simplecrypt.class.inc.php
Normal file
235
core/simplecrypt.class.inc.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// 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; version 3 of the License.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* SimpleCrypt Class - crypto helpers
|
||||
* Simple encryption of strings, uses mcrypt or degrades to a pure PHP
|
||||
* implementation when mcrypt is not present.
|
||||
* Based on Miguel Ros' work found at:
|
||||
* http://rossoft.wordpress.com/2006/05/22/simple-encryption-class/
|
||||
*
|
||||
* Usage:
|
||||
* $oSimpleCrypt = new SimpleCrypt();
|
||||
* $encrypted = $oSimpleCrypt->encrypt('a_key','the_text');
|
||||
* $sClearText = $oSimpleCrypt->decrypt('a_key',$encrypted);
|
||||
*
|
||||
* The result is $plain equals to 'the_text'
|
||||
*
|
||||
* You can use a different engine if you don't have Mcrypt:
|
||||
* $oSimpleCrypt = new SimpleCrypt('Simple');
|
||||
*
|
||||
* A string encrypted with one engine can't be decrypted with
|
||||
* a different one even if the key is the same.
|
||||
*
|
||||
* @author Miguel Ros <rossoft@gmail.com>
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @version 0.3
|
||||
* @license GPL
|
||||
*/
|
||||
|
||||
class SimpleCrypt
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
* @param string $sEngineName Engine for encryption. Values: Simple, Mcrypt
|
||||
*/
|
||||
function __construct($sEngineName = 'Mcrypt')
|
||||
{
|
||||
if (($sEngineName == 'Mcrypt') && (!function_exists('mcrypt_module_open')))
|
||||
{
|
||||
// Defaults to Simple encryption if the mcrypt module is not present
|
||||
$sEngineName = 'Simple';
|
||||
}
|
||||
$sEngineName = 'SimpleCrypt' . $sEngineName . 'Engine';
|
||||
$this->oEngine = new $sEngineName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the string with the given key
|
||||
* @param string $key
|
||||
* @param string $sString Plaintext string
|
||||
* @return string Ciphered string
|
||||
*/
|
||||
function Encrypt($key, $sString)
|
||||
{
|
||||
return $this->oEngine->Encrypt($key,$sString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decrypts the string by the given key
|
||||
* @param string $key
|
||||
* @param string $string Ciphered string
|
||||
* @return string Plaintext string
|
||||
*/
|
||||
function Decrypt($key, $string)
|
||||
{
|
||||
return $this->oEngine->Decrypt($key,$string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random "salt" value, to be used when "hashing" a password
|
||||
* using a one-way encryption algorithm, to prevent an attack using a "rainbow table"
|
||||
* Tryes to use the best available random number generator
|
||||
* @return string The generated random "salt"
|
||||
*/
|
||||
static function GetNewSalt()
|
||||
{
|
||||
// Copied from http://www.php.net/manual/en/function.mt-rand.php#83655
|
||||
// get 128 pseudorandom bits in a string of 16 bytes
|
||||
|
||||
$sRandomBits = null;
|
||||
|
||||
// Unix/Linux platform?
|
||||
$fp = @fopen('/dev/urandom','rb');
|
||||
if ($fp !== FALSE)
|
||||
{
|
||||
//echo "Random bits pulled from /dev/urandom<br/>\n";
|
||||
$sRandomBits .= @fread($fp,16);
|
||||
@fclose($fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MS-Windows platform?
|
||||
if (@class_exists('COM'))
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
|
||||
try
|
||||
{
|
||||
$CAPI_Util = new COM('CAPICOM.Utilities.1');
|
||||
$sBase64RandomBits = ''.$CAPI_Util->GetRandom(16,0);
|
||||
|
||||
// if we ask for binary data PHP munges it, so we
|
||||
// request base64 return value. We squeeze out the
|
||||
// redundancy and useless ==CRLF by hashing...
|
||||
if ($sBase64RandomBits)
|
||||
{
|
||||
//echo "Random bits got from CAPICOM.Utilities.1<br/>\n";
|
||||
$sRandomBits = md5($sBase64RandomBits, TRUE);
|
||||
}
|
||||
}
|
||||
catch (Exception $ex)
|
||||
{
|
||||
// echo 'Exception: ' . $ex->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($sRandomBits == null)
|
||||
{
|
||||
// No "strong" random generator available, use PHP's built-in mechanism
|
||||
//echo "Random bits generated from mt_rand<br/>\n";
|
||||
mt_srand(crc32(microtime()));
|
||||
$sRandomBits = '';
|
||||
for($i = 0; $i < 4; $i++)
|
||||
{
|
||||
$sRandomBits .= sprintf('%04x', mt_rand(0, 65535));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return $sRandomBits;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for encryption engines
|
||||
*/
|
||||
interface CryptEngine
|
||||
{
|
||||
function Encrypt($key, $sString);
|
||||
function Decrypt($key, $encrypted_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple Engine doesn't need any PHP extension.
|
||||
* Every encryption of the same string with the same key
|
||||
* will return the same encrypted string
|
||||
*/
|
||||
class SimpleCryptSimpleEngine implements CryptEngine
|
||||
{
|
||||
public function Encrypt($key, $sString)
|
||||
{
|
||||
$result = '';
|
||||
for($i=1; $i<=strlen($sString); $i++)
|
||||
{
|
||||
$char = substr($sString, $i-1, 1);
|
||||
$keychar = substr($key, ($i % strlen($key))-1, 1);
|
||||
$char = chr(ord($char)+ord($keychar));
|
||||
$result.=$char;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function Decrypt($key, $encrypted_data)
|
||||
{
|
||||
$result = '';
|
||||
for($i=1; $i<=strlen($encrypted_data); $i++)
|
||||
{
|
||||
$char = substr($encrypted_data, $i-1, 1);
|
||||
$keychar = substr($key, ($i % strlen($key))-1, 1);
|
||||
$char = chr(ord($char)-ord($keychar));
|
||||
$result.=$char;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* McryptEngine requires Mcrypt extension
|
||||
* Every encryption of the same string with the same key
|
||||
* will return a different encrypted string.
|
||||
*/
|
||||
class SimpleCryptMcryptEngine implements CryptEngine
|
||||
{
|
||||
var $alg = MCRYPT_BLOWFISH;
|
||||
var $td = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->td = mcrypt_module_open($this->alg,'','cbc','');
|
||||
}
|
||||
|
||||
public function Encrypt($key, $sString)
|
||||
{
|
||||
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($this->td), MCRYPT_RAND); // MCRYPT_RAND is the only choice on Windows prior to PHP 5.3
|
||||
mcrypt_generic_init($this->td, $key, $iv);
|
||||
if (empty($sString))
|
||||
{
|
||||
$sString = str_repeat("\0", 8);
|
||||
}
|
||||
$encrypted_data = mcrypt_generic($this->td, $sString);
|
||||
mcrypt_generic_deinit($this->td);
|
||||
return $iv.$encrypted_data;
|
||||
}
|
||||
|
||||
public function Decrypt($key, $encrypted_data)
|
||||
{
|
||||
$iv = substr($encrypted_data, 0, mcrypt_enc_get_iv_size($this->td));
|
||||
$string = substr($encrypted_data, mcrypt_enc_get_iv_size($this->td));
|
||||
mcrypt_generic_init($this->td, $key, $iv);
|
||||
$decrypted_data = rtrim(mdecrypt_generic($this->td, $string), "\0");
|
||||
mcrypt_generic_deinit($this->td);
|
||||
return $decrypted_data;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
mcrypt_module_close($this->td);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -104,6 +104,15 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue' => 'New value',
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue+' => 'new value of the attribute',
|
||||
));
|
||||
// Used by CMDBChangeOp... & derived classes
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Change:ObjectCreated' => 'Object created',
|
||||
'Change:ObjectDeleted' => 'Object deleted',
|
||||
'Change:AttName_SetTo_NewValue_PreviousValue_OldValue' => '%1$s set to %2$s (previous value: %3$s)',
|
||||
'Change:Text_AppendedTo_AttName' => '%1$s appended to %2$s',
|
||||
'Change:AttName_Changed_PreviousValue_OldValue' => '%1$s modified, previous value: %2$s',
|
||||
'Change:AttName_Changed' => '%1$s modified',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: CMDBChangeOpSetAttributeBlob
|
||||
|
||||
@@ -315,7 +315,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
</ul>
|
||||
</p>',
|
||||
|
||||
'UI:WelcomeMenu:MyCalls' => 'User Requests assigned to me',
|
||||
'UI:WelcomeMenu:MyCalls' => 'My requests',
|
||||
'UI:WelcomeMenu:MyIncidents' => 'Incidents assigned to me',
|
||||
'UI:AllOrganizations' => ' All Organizations ',
|
||||
'UI:YourSearch' => 'Your Search',
|
||||
@@ -345,9 +345,11 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Button:Create' => ' Create ',
|
||||
'UI:Button:Delete' => ' Delete ! ',
|
||||
'UI:Button:ChangePassword' => ' Change Password ',
|
||||
|
||||
'UI:Button:ResetPassword' => ' Reset Password ',
|
||||
|
||||
'UI:SearchToggle' => 'Search',
|
||||
'UI:ClickToCreateNew' => 'Click here to create a new %1$s',
|
||||
'UI:SearchFor_Class' => 'Search for %1$s objects',
|
||||
'UI:NoObjectToDisplay' => 'No object to display.',
|
||||
'UI:Error:MandatoryTemplateParameter_object_id' => 'Parameter object_id is mandatory when link_attr is specified. Check the definition of the display template.',
|
||||
'UI:Error:MandatoryTemplateParameter_target_attr' => 'Parameter target_attr is mandatory when link_attr is specified. Check the definition of the display template.',
|
||||
@@ -383,6 +385,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:GroupBy:Count' => 'Count',
|
||||
'UI:GroupBy:Count+' => 'Number of elements',
|
||||
'UI:CountOfObjects' => '%1$d objects matching the criteria.',
|
||||
'UI_CountOfObjectsShort' => '%1$d objects.',
|
||||
'UI:NoObject_Class_ToDisplay' => 'No %1$s to display',
|
||||
'UI:History:LastModified_On_By' => 'Last modified on %1$s by %2$s.',
|
||||
'UI:HistoryTab' => 'History',
|
||||
@@ -818,6 +821,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:Deadline_Hours_Minutes' => '%1$dh %2$dmin',
|
||||
'UI:Deadline_Days_Hours_Minutes' => '%1$dd %2$dh %3$dmin',
|
||||
'UI:Help' => 'Help',
|
||||
'UI:PasswordConfirm' => '(Confirm)',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -104,6 +104,13 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue' => 'Nuevo valor',
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue+' => 'nuevo valor del atributo',
|
||||
));
|
||||
// Used by CMDBChangeOp... & derived classes
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Change:AttName_SetTo_NewValue_PreviousValue_OldValue' => '%1$s modificado en %2$s (valor anterior: %3$s)',
|
||||
'Change:Text_AppendedTo_AttName' => '%1$s añadido a %2$s',
|
||||
'Change:AttName_Changed_PreviousValue_OldValue' => '%1$s modificado, valor anterior: %2$s',
|
||||
'Change:AttName_Changed' => '%1$s modificado',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: CMDBChangeOpSetAttributeBlob
|
||||
|
||||
@@ -331,7 +331,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
</ul>
|
||||
</p>',
|
||||
|
||||
'UI:WelcomeMenu:MyCalls' => 'User Requests assigned to me',
|
||||
'UI:WelcomeMenu:MyCalls' => 'My requests',
|
||||
'UI:WelcomeMenu:MyIncidents' => 'Incidents assigned to me',
|
||||
'UI:AllOrganizations' => ' All Organizations ',
|
||||
'UI:YourSearch' => 'Your Search',
|
||||
@@ -361,6 +361,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'UI:Button:Create' => ' Create ',
|
||||
'UI:Button:Delete' => ' Delete ! ',
|
||||
'UI:Button:ChangePassword' => ' Change Password ',
|
||||
'UI:Button:ResetPassword' => ' Reset Password ',
|
||||
|
||||
'UI:SearchToggle' => 'Search',
|
||||
'UI:ClickToCreateNew' => 'Click here to create a new %1$s',
|
||||
@@ -399,6 +400,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'UI:GroupBy:Count' => 'Count',
|
||||
'UI:GroupBy:Count+' => 'Number of elements',
|
||||
'UI:CountOfObjects' => '%1$d objects matching the criteria.',
|
||||
'UI_CountOfObjectsShort' => '%1$d objects.',
|
||||
'UI:NoObject_Class_ToDisplay' => 'No %1$s to display',
|
||||
'UI:History:LastModified_On_By' => 'Last modified on %1$s by %2$s.',
|
||||
'UI:HistoryTab' => 'History',
|
||||
@@ -829,6 +831,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:Deadline_Hours_Minutes' => '%1$dh %2$dmin',
|
||||
'UI:Deadline_Days_Hours_Minutes' => '%1$dd %2$dh %3$dmin',
|
||||
'UI:Help' => 'Ayuda',
|
||||
'UI:PasswordConfirm' => '(Confirm)',
|
||||
));
|
||||
|
||||
?>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
// Class: CMDBChange
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChange' => 'change',
|
||||
'Class:CMDBChange+' => 'Changes tracking',
|
||||
'Class:CMDBChange/Attribute:date' => 'date',
|
||||
@@ -46,7 +46,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: CMDBChangeOp
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOp' => 'change operation',
|
||||
'Class:CMDBChangeOp+' => 'Change operations tracking',
|
||||
'Class:CMDBChangeOp/Attribute:change' => 'change',
|
||||
@@ -67,7 +67,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: CMDBChangeOpCreate
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpCreate' => 'object creation',
|
||||
'Class:CMDBChangeOpCreate+' => 'Object creation tracking',
|
||||
));
|
||||
@@ -76,7 +76,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: CMDBChangeOpDelete
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpDelete' => 'object deletion',
|
||||
'Class:CMDBChangeOpDelete+' => 'Object deletion tracking',
|
||||
));
|
||||
@@ -85,7 +85,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: CMDBChangeOpSetAttribute
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpSetAttribute' => 'object change',
|
||||
'Class:CMDBChangeOpSetAttribute+' => 'Object properties change tracking',
|
||||
'Class:CMDBChangeOpSetAttribute/Attribute:attcode' => 'Attribute',
|
||||
@@ -96,7 +96,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: CMDBChangeOpSetAttributeScalar
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpSetAttributeScalar' => 'property change',
|
||||
'Class:CMDBChangeOpSetAttributeScalar+' => 'Object scalar properties change tracking',
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:oldvalue' => 'Previous value',
|
||||
@@ -104,12 +104,21 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue' => 'New value',
|
||||
'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue+' => 'new value of the attribute',
|
||||
));
|
||||
// Used by CMDBChangeOp... & derived classes
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Change:ObjectCreated' => 'Elément créé',
|
||||
'Change:ObjectDeleted' => 'Elément effacé',
|
||||
'Change:AttName_SetTo_NewValue_PreviousValue_OldValue' => '%1$s modifié en %2$s (ancienne valeur: %3$s)',
|
||||
'Change:Text_AppendedTo_AttName' => '%1$s ajouté à %2$s',
|
||||
'Change:AttName_Changed_PreviousValue_OldValue' => '%1$s modifié, ancienne valeur: %2$s',
|
||||
'Change:AttName_Changed' => '%1$s modifié',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: CMDBChangeOpSetAttributeBlob
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpSetAttributeBlob' => 'data change',
|
||||
'Class:CMDBChangeOpSetAttributeBlob+' => 'data change tracking',
|
||||
'Class:CMDBChangeOpSetAttributeBlob/Attribute:prevdata' => 'Previous data',
|
||||
@@ -120,7 +129,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: CMDBChangeOpSetAttributeText
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:CMDBChangeOpSetAttributeText' => 'text change',
|
||||
'Class:CMDBChangeOpSetAttributeText+' => 'text change tracking',
|
||||
'Class:CMDBChangeOpSetAttributeText/Attribute:prevdata' => 'Previous data',
|
||||
@@ -131,7 +140,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: Event
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:Event' => 'Log Event',
|
||||
'Class:Event+' => 'An application internal event',
|
||||
'Class:Event/Attribute:message' => 'message',
|
||||
@@ -148,7 +157,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: EventNotification
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:EventNotification' => 'Notification event',
|
||||
'Class:EventNotification+' => 'Trace of a notification that has been sent',
|
||||
'Class:EventNotification/Attribute:trigger_id' => 'Trigger',
|
||||
@@ -163,7 +172,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: EventNotificationEmail
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:EventNotificationEmail' => 'Email emission event',
|
||||
'Class:EventNotificationEmail+' => 'Trace of an email that has been sent',
|
||||
'Class:EventNotificationEmail/Attribute:to' => 'TO',
|
||||
@@ -184,7 +193,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: EventIssue
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:EventIssue' => 'Issue event',
|
||||
'Class:EventIssue+' => 'Trace of an issue (warning, error, etc.)',
|
||||
'Class:EventIssue/Attribute:issue' => 'Issue',
|
||||
@@ -207,7 +216,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: EventWebService
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:EventWebService' => 'Web service event',
|
||||
'Class:EventWebService+' => 'Trace of an web service call',
|
||||
'Class:EventWebService/Attribute:verb' => 'Verb',
|
||||
@@ -228,7 +237,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: Action
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:Action' => 'action',
|
||||
'Class:Action+' => 'Custom action',
|
||||
'Class:Action/Attribute:name' => 'Name',
|
||||
@@ -253,7 +262,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: ActionNotification
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:ActionNotification' => 'notification',
|
||||
'Class:ActionNotification+' => 'Notification (abstract)',
|
||||
));
|
||||
@@ -262,7 +271,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: ActionEmail
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:ActionEmail' => 'email notification',
|
||||
'Class:ActionEmail+' => 'Action: Email notification',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Test recipient',
|
||||
@@ -295,7 +304,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: Trigger
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:Trigger' => 'trigger',
|
||||
'Class:Trigger+' => 'Custom event handler',
|
||||
'Class:Trigger/Attribute:description' => 'Description',
|
||||
@@ -310,7 +319,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: TriggerOnObject
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:TriggerOnObject' => 'Trigger on a class of objects',
|
||||
'Class:TriggerOnObject+' => 'Trigger on a given class of objects',
|
||||
'Class:TriggerOnObject/Attribute:target_class' => 'Target class',
|
||||
@@ -321,7 +330,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: TriggerOnStateChange
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:TriggerOnStateChange' => 'Trigger on object state change',
|
||||
'Class:TriggerOnStateChange+' => 'Trigger on object state change',
|
||||
'Class:TriggerOnStateChange/Attribute:state' => 'State',
|
||||
@@ -332,7 +341,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: TriggerOnStateEnter
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:TriggerOnStateEnter' => 'Trigger on object entering a state',
|
||||
'Class:TriggerOnStateEnter+' => 'Trigger on object state change - entering',
|
||||
));
|
||||
@@ -341,7 +350,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: TriggerOnStateLeave
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:TriggerOnStateLeave' => 'Trigger on object leaving a state',
|
||||
'Class:TriggerOnStateLeave+' => 'Trigger on object state change - leaving',
|
||||
));
|
||||
@@ -350,7 +359,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: TriggerOnObjectCreate
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:TriggerOnObjectCreate' => 'Trigger on object creation',
|
||||
'Class:TriggerOnObjectCreate+' => 'Trigger on object creation of [a child class of] the given class',
|
||||
));
|
||||
@@ -359,7 +368,7 @@ Dict::Add('EN US', 'French', 'Français', array(
|
||||
// Class: lnkTriggerAction
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'French', 'Français', array(
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:lnkTriggerAction' => 'Actions-Trigger',
|
||||
'Class:lnkTriggerAction+' => 'Link between a trigger and an action',
|
||||
'Class:lnkTriggerAction/Attribute:action_id' => 'Action',
|
||||
|
||||
@@ -346,6 +346,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'UI:Button:Create' => ' Créer ',
|
||||
'UI:Button:Delete' => ' Supprimer ! ',
|
||||
'UI:Button:ChangePassword' => ' Changer ! ',
|
||||
'UI:Button:ResetPassword' => ' Ràz du mot de passe ',
|
||||
|
||||
'UI:SearchToggle' => 'Recherche',
|
||||
|
||||
@@ -384,6 +385,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'UI:GroupBy:Count' => 'Nombre',
|
||||
'UI:GroupBy:Count+' => 'Nombre d\'éléments',
|
||||
'UI:CountOfObjects' => '%1$d objets correspondants aux critères.',
|
||||
'UI_CountOfObjectsShort' => '%1$d objets.',
|
||||
'UI:NoObject_Class_ToDisplay' => 'Aucun objet %1$s à afficher',
|
||||
'UI:History:LastModified_On_By' => 'Dernière modification par %2$s le %1$s.',
|
||||
'UI:HistoryTab' => 'Historique',
|
||||
@@ -829,6 +831,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
'UI:Deadline_Hours_Minutes' => '%1$dh %2$dmin',
|
||||
'UI:Deadline_Days_Hours_Minutes' => '%1$dj %2$dh %3$dmin',
|
||||
'UI:Help' => 'Aide',
|
||||
'UI:PasswordConfirm' => '(Confirmer)',
|
||||
));
|
||||
|
||||
?>
|
||||
|
||||
@@ -207,3 +207,45 @@ function UpdateDependentFields(aFieldNames)
|
||||
}
|
||||
oWizardHelper.AjaxQueryServer();
|
||||
}
|
||||
|
||||
function ResetPwd(id)
|
||||
{
|
||||
// Reset the values of the password fields
|
||||
$('#'+id).val('*****');
|
||||
$('#'+id+'_confirm').val('*****');
|
||||
// And reset the flag, to tell it that the password remains unchanged
|
||||
$('#'+id+'_changed').val(0);
|
||||
// Visual feedback, None when it's Ok
|
||||
$('#v_'+id).html('');
|
||||
}
|
||||
|
||||
// Called whenever the content of a one way encrypted password changes
|
||||
function PasswordFieldChanged(id)
|
||||
{
|
||||
// Set the flag, to tell that the password changed
|
||||
console.log('Password changed');
|
||||
$('#'+id+'_changed').val(1);
|
||||
}
|
||||
|
||||
// Special validation function for one way encrypted password fields
|
||||
function ValidatePasswordField(id, sFormId)
|
||||
{
|
||||
var bChanged = $('#'+id+'_changed').val();
|
||||
if (bChanged)
|
||||
{
|
||||
if ($('#'+id).val() != $('#'+id+'_confirm').val())
|
||||
{
|
||||
oFormErrors['err_'+sFormId]++;
|
||||
if (oFormErrors['input_'+sFormId] == null)
|
||||
{
|
||||
// Let's remember the first input with an error, so that we can put back the focus on it later
|
||||
oFormErrors['input_'+sFormId] = id;
|
||||
}
|
||||
// Visual feedback
|
||||
$('#v_'+id).html('<img src="../images/validation_error.png" />');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$('#v_'+id).html(''); //<img src="../images/validation_ok.png" />');
|
||||
return true;
|
||||
}
|
||||
@@ -44,8 +44,7 @@ class UserLocal extends UserInternal
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributePassword("password", array("allowed_values"=>null, "sql"=>"pwd", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEncryptedString("encrypted_password", array("allowed_values"=>null, "sql"=>"encrypted_pwd", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeOneWayPassword("password", array("allowed_values"=>null, "sql"=>"pwd", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'password', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
|
||||
@@ -57,7 +56,14 @@ class UserLocal extends UserInternal
|
||||
|
||||
public function CheckCredentials($sPassword)
|
||||
{
|
||||
if ($this->Get('password') == $sPassword)
|
||||
// if ($this->Get('password') == $sPassword)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
$oPassword = $this->Get('password'); // ormPassword object
|
||||
// Cannot compare directly the values since they are hashed, so
|
||||
// Let's ask the password to compare the hashed values
|
||||
if ($oPassword->CheckPassword($sPassword))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Menu:ChangeManagement' => 'Change management',
|
||||
'Menu:Change:Overview' => 'Overview',
|
||||
'Menu:Change:Overview+' => '',
|
||||
'Menu:NewChange' => 'New Change',
|
||||
'Menu:NewChange+' => 'Create a new Change ticket',
|
||||
'Menu:SearchChanges' => 'Search for Changes',
|
||||
'Menu:SearchChanges+' => 'Search for Change tickets',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Changes awaiting acceptance',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes awaiting approval',
|
||||
|
||||
@@ -27,6 +27,12 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Menu:ChangeManagement' => 'Gestión del cambio',
|
||||
'Menu:Change:Overview' => 'Visión General',
|
||||
'Menu:Change:Overview+' => '',
|
||||
'Menu:NewChange' => 'New Change',
|
||||
'Menu:NewChange+' => 'Create a new Change ticket',
|
||||
'Menu:SearchChanges' => 'Search for Changes',
|
||||
'Menu:SearchChanges+' => 'Search for Change tickets',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Cambios esperando ser aceptados',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Cambios esperando ser aprovados',
|
||||
|
||||
@@ -27,6 +27,12 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Menu:ChangeManagement' => 'Gestion des changements',
|
||||
'Menu:Change:Overview' => 'Vue d\'ensemble',
|
||||
'Menu:Change:Overview+' => '',
|
||||
'Menu:NewChange' => 'Nouveau changement',
|
||||
'Menu:NewChange+' => 'Créer un nouveau ticket de changement',
|
||||
'Menu:SearchChanges' => 'Rechercher des changements',
|
||||
'Menu:SearchChanges+' => 'Rechercher parmi les tickets de changement',
|
||||
'Menu:Change:Shortcuts' => 'Raccourcis',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Tickets en attente d\'acceptance',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Tickets en attente d\'approbation',
|
||||
|
||||
@@ -483,9 +483,12 @@ class EmergencyChange extends ApprovedChange
|
||||
|
||||
$oMyMenuGroup = new MenuGroup('ChangeManagement', 50 /* fRank */);
|
||||
new TemplateMenuNode('Change:Overview', '../modules/itop-change-mgmt-1.0.0/overview.html', $oMyMenuGroup->GetIndex() /* oParent */, 0 /* fRank */);
|
||||
new OQLMenuNode('MyChanges', 'SELECT Change WHERE agent_id = :current_contact_id', $oMyMenuGroup->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Changes', 'SELECT Change WHERE status != "closed"', $oMyMenuGroup->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('WaitingApproval', 'SELECT ApprovedChange WHERE status IN ("plannedscheduled")', $oMyMenuGroup->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('WaitingAcceptance', 'SELECT NormalChange WHERE status IN ("new")', $oMyMenuGroup->GetIndex(), 4 /* fRank */);
|
||||
new NewObjectMenuNode('NewChange', 'Change', $oMyMenuGroup->GetIndex(), 1 /* fRank */);
|
||||
new SearchMenuNode('SearchChanges', 'Change', $oMyMenuGroup->GetIndex(), 2 /* fRank */);
|
||||
$oShortcutNode = new TemplateMenuNode('Change:Shortcuts', '', $oMyMenuGroup->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('MyChanges', 'SELECT Change WHERE agent_id = :current_contact_id', $oShortcutNode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Changes', 'SELECT Change WHERE status != "closed"', $oShortcutNode->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('WaitingApproval', 'SELECT ApprovedChange WHERE status IN ("plannedscheduled")', $oShortcutNode->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('WaitingAcceptance', 'SELECT NormalChange WHERE status IN ("new")', $oShortcutNode->GetIndex(), 4 /* fRank */);
|
||||
|
||||
?>
|
||||
|
||||
@@ -31,7 +31,10 @@
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Relation:impacts/Description' => 'Eléments impactés par',
|
||||
'Relation:impacts/VerbUp' => 'Impacte...',
|
||||
'Relation:impacts/VerbDown' => 'Eléments impactés par...',
|
||||
'Relation:impacts/VerbDown' => 'Dépend de...',
|
||||
'Relation:depends on/Description' => 'Eléments dont dépend cet élément',
|
||||
'Relation:depends on/VerbUp' => 'Dépend de...',
|
||||
'Relation:depends on/VerbDown' => 'Impacte...',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -1474,7 +1474,7 @@ new WebPageMenuNode('Audit', '../pages/audit.php', $iAdminGroup, 33 /* fRank */)
|
||||
|
||||
$oTypologyNode = new TemplateMenuNode('Catalogs', '', $iAdminGroup, 50 /* fRank */);
|
||||
$iTopology = $oTypologyNode->GetIndex();
|
||||
new OQLMenuNode('Organization', 'SELECT Organization', $iTopology, 10 /* fRank */);
|
||||
new OQLMenuNode('Organization', 'SELECT Organization', $iTopology, 10 /* fRank */, true /* bSearch */);
|
||||
new OQLMenuNode('Application', 'SELECT Application', $iTopology, 20 /* fRank */);
|
||||
new OQLMenuNode('DBServer', 'SELECT DBServer', $iTopology, 40 /* fRank */);
|
||||
|
||||
@@ -1486,24 +1486,28 @@ new TemplateMenuNode('ConfigManagementOverview', '../modules/itop-config-mgmt-1.
|
||||
|
||||
|
||||
$oContactNode = new TemplateMenuNode('Contact', '../modules/itop-config-mgmt-1.0.0/contacts_menu.html', $oConfigManagementGroup->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Person', 'SELECT Person', $oContactNode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Team', 'SELECT Team', $oContactNode->GetIndex(), 2 /* fRank */);
|
||||
new NewObjectMenuNode('NewContact', 'Contact', $oContactNode->GetIndex(), 1 /* fRank */);
|
||||
new SearchMenuNode('SearchContacts', 'Contact', $oContactNode->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('Person', 'SELECT Person', $oContactNode->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('Team', 'SELECT Team', $oContactNode->GetIndex(), 4 /* fRank */);
|
||||
|
||||
new OQLMenuNode('Document', 'SELECT Document', $oConfigManagementGroup->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('Location', 'SELECT Location', $oConfigManagementGroup->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('Document', 'SELECT Document', $oConfigManagementGroup->GetIndex(), 2 /* fRank */, true /* bSearch */);
|
||||
new OQLMenuNode('Location', 'SELECT Location', $oConfigManagementGroup->GetIndex(), 3 /* fRank */, true /* bSearch */);
|
||||
|
||||
|
||||
$oCINode = new TemplateMenuNode('ConfigManagementCI', '../modules/itop-config-mgmt-1.0.0/cis_menu.html', $oConfigManagementGroup->GetIndex(), 4 /* fRank */);
|
||||
new NewObjectMenuNode('NewCI', 'FunctionalCI', $oCINode->GetIndex(), 0 /* fRank */);
|
||||
new SearchMenuNode('SearchCIs', 'FunctionalCI', $oCINode->GetIndex(), 1 /* fRank */);
|
||||
|
||||
new OQLMenuNode('BusinessProcess', 'SELECT BusinessProcess', $oCINode->GetIndex(), 0 /* fRank */);
|
||||
new OQLMenuNode('ApplicationSolution', 'SELECT ApplicationSolution', $oCINode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('BusinessProcess', 'SELECT BusinessProcess', $oCINode->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('ApplicationSolution', 'SELECT ApplicationSolution', $oCINode->GetIndex(), 3 /* fRank */);
|
||||
|
||||
$oSWNode = new TemplateMenuNode('ConfigManagementSoftware', '', $oCINode->GetIndex(), 2 /* fRank */);
|
||||
$oSWNode = new TemplateMenuNode('ConfigManagementSoftware', '', $oCINode->GetIndex(), 4 /* fRank */);
|
||||
new OQLMenuNode('Licence', 'SELECT Licence', $oSWNode->GetIndex(), 0 /* fRank */);
|
||||
new OQLMenuNode('Patch', 'SELECT Patch', $oSWNode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('ApplicationInstance', 'SELECT SoftwareInstance', $oSWNode->GetIndex(), 2 /* fRank */);
|
||||
|
||||
$oHWNode = new TemplateMenuNode('ConfigManagementHardware', '', $oCINode->GetIndex(), 3 /* fRank */);
|
||||
$oHWNode = new TemplateMenuNode('ConfigManagementHardware', '', $oCINode->GetIndex(), 5 /* fRank */);
|
||||
new OQLMenuNode('Subnet', 'SELECT Subnet', $oHWNode->GetIndex(), 0 /* fRank */);
|
||||
new OQLMenuNode('NetworkDevice', 'SELECT NetworkDevice', $oHWNode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Server', 'SELECT Server', $oHWNode->GetIndex(), 2 /* fRank */);
|
||||
|
||||
@@ -28,6 +28,12 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Menu:IncidentManagement+' => 'Incident Management',
|
||||
'Menu:Incident:Overview' => 'Overview',
|
||||
'Menu:Incident:Overview+' => 'Overview',
|
||||
'Menu:NewIncident' => 'New Incident',
|
||||
'Menu:NewIncident+' => 'Create a new Incident ticket',
|
||||
'Menu:SearchIncidents' => 'Search for Incidents',
|
||||
'Menu:SearchIncidents+' => 'Search for Incident tickets',
|
||||
'Menu:Incident:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Incidents assigned to me',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidents assigned to me (as Agent)',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Escalated Incidents',
|
||||
|
||||
@@ -28,6 +28,12 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Menu:IncidentManagement+' => 'Gestión de Incidentes',
|
||||
'Menu:Incident:Overview' => 'Visión General',
|
||||
'Menu:Incident:Overview+' => 'Visión General',
|
||||
'Menu:NewIncident' => 'New Incident',
|
||||
'Menu:NewIncident+' => 'Create a new Incident ticket',
|
||||
'Menu:SearchIncidents' => 'Search for Incidents',
|
||||
'Menu:SearchIncidents+' => 'Search for Incident tickets',
|
||||
'Menu:Incident:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Incidentes asignados a mí',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidentes asignados a mí (como Agente)',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Incidentes Escalados',
|
||||
|
||||
@@ -28,6 +28,12 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Menu:IncidentManagement+' => 'Gestion des incidents',
|
||||
'Menu:Incident:Overview' => 'Vue d\'ensemble',
|
||||
'Menu:Incident:Overview+' => 'Vue d\'ensemble',
|
||||
'Menu:NewIncident' => 'Nouvel Incident',
|
||||
'Menu:NewIncident+' => 'Créer un nouveau ticket d\'incident',
|
||||
'Menu:SearchIncidents' => 'Rechercher des incidents',
|
||||
'Menu:SearchIncidents+' => 'Rechercher parmi les tickets d\'incidents',
|
||||
'Menu:Incident:Shortcuts' => 'Raccourcis',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Mes tickets',
|
||||
'Menu:Incident:MyIncidents+' => 'Tickets d\'incident qui me sont assignés',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Ticket en cours d\'escalade',
|
||||
|
||||
@@ -96,8 +96,11 @@ class Incident extends ResponseTicket
|
||||
|
||||
$oMyMenuGroup = new MenuGroup('IncidentManagement', 40 /* fRank */);
|
||||
new TemplateMenuNode('Incident:Overview', '../modules/itop-incident-mgmt-1.0.0/overview.html', $oMyMenuGroup->GetIndex() /* oParent */, 0 /* fRank */);
|
||||
new OQLMenuNode('Incident:MyIncidents', 'SELECT Incident WHERE agent_id = :current_contact_id', $oMyMenuGroup->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Incident:EscalatedIncidents', 'SELECT Incident WHERE status IN ("escalated_tto", "escalated_ttr")', $oMyMenuGroup->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('Incident:OpenIncidents', 'SELECT Incident WHERE status IN ("new", "assigned", "escalated_tto", "escalated_ttr", "resolved")', $oMyMenuGroup->GetIndex(), 3 /* fRank */);
|
||||
new NewObjectMenuNode('NewIncident', 'Incident', $oMyMenuGroup->GetIndex(), 1 /* fRank */);
|
||||
new SearchMenuNode('SearchIncidents', 'Incident', $oMyMenuGroup->GetIndex(), 2 /* fRank */);
|
||||
$oShortcutNode = new TemplateMenuNode('Incident:Shortcuts', '', $oMyMenuGroup->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('Incident:MyIncidents', 'SELECT Incident WHERE agent_id = :current_contact_id', $oShortcutNode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('Incident:EscalatedIncidents', 'SELECT Incident WHERE status IN ("escalated_tto", "escalated_ttr")', $oShortcutNode->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('Incident:OpenIncidents', 'SELECT Incident WHERE status IN ("new", "assigned", "escalated_tto", "escalated_ttr", "resolved")', $oShortcutNode->GetIndex(), 3 /* fRank */);
|
||||
|
||||
?>
|
||||
|
||||
@@ -28,6 +28,12 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Menu:RequestManagement+' => 'Helpdesk',
|
||||
'Menu:UserRequest:Overview' => 'Overview',
|
||||
'Menu:UserRequest:Overview+' => 'Overview',
|
||||
'Menu:NewUserRequest' => 'New User Request',
|
||||
'Menu:NewUserRequest+' => 'Create a new User Request ticket',
|
||||
'Menu:SearchUserRequests' => 'Search for User Requests',
|
||||
'Menu:SearchUserRequests+' => 'Search for User Request tickets',
|
||||
'Menu:UserRequest:Shortcuts' => 'Shortcuts',
|
||||
'Menu:UserRequest:Shortcuts+' => '',
|
||||
'Menu:UserRequest:MyRequests' => 'Requests assigned to me',
|
||||
'Menu:UserRequest:MyRequests+' => 'Requests assigned to me (as Agent)',
|
||||
'Menu:UserRequest:EscalatedRequests' => 'Escalated Requests',
|
||||
|
||||
@@ -28,6 +28,12 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Menu:RequestManagement+' => 'Servicio de ayuda',
|
||||
'Menu:UserRequest:Overview' => 'Visión General',
|
||||
'Menu:UserRequest:Overview+' => 'Visión General',
|
||||
'Menu:NewUserRequest' => 'New User Request',
|
||||
'Menu:NewUserRequest+' => 'Create a new User Request ticket',
|
||||
'Menu:SearchUserRequests' => 'Search for User Requests',
|
||||
'Menu:SearchUserRequests+' => 'Search for User Request tickets',
|
||||
'Menu:UserRequest:Shortcuts' => 'Shortcuts',
|
||||
'Menu:UserRequest:Shortcuts+' => '',
|
||||
'Menu:UserRequest:MyRequests' => 'Solicitudes asignadas a mí',
|
||||
'Menu:UserRequest:MyRequests+' => 'Solicitudes asignadas a mí (como Agente)',
|
||||
'Menu:UserRequest:EscalatedRequests' => 'Solicitudes Escaladas',
|
||||
|
||||
@@ -28,6 +28,12 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Menu:RequestManagement+' => 'Gestion des demandes utilisateurs',
|
||||
'Menu:UserRequest:Overview' => 'Vue d\'ensemble',
|
||||
'Menu:UserRequest:Overview+' => 'Vue d\'ensemble des demandes utilisateurs',
|
||||
'Menu:NewUserRequest' => 'Nouvelle demande utilisateur',
|
||||
'Menu:NewUserRequest+' => 'Créer un nouveau ticket de demande utilisateur',
|
||||
'Menu:SearchUserRequests' => 'Rechercher des demandes utilisateur',
|
||||
'Menu:SearchUserRequests+' => 'Rechercher parmi les demandes utilisateur',
|
||||
'Menu:UserRequest:Shortcuts' => 'Raccourcis',
|
||||
'Menu:UserRequest:Shortcuts+' => '',
|
||||
'Menu:UserRequest:MyRequests' => 'Mes demandes',
|
||||
'Menu:UserRequest:MyRequests+' => 'Demandes utilisateurs qui me sont assignées',
|
||||
'Menu:UserRequest:EscalatedRequests' => 'Demandes en escalade',
|
||||
|
||||
@@ -86,8 +86,11 @@ class UserRequest extends ResponseTicket
|
||||
$oMyMenuGroup = new MenuGroup('RequestManagement', 30 /* fRank */);
|
||||
|
||||
new TemplateMenuNode('UserRequest:Overview', '../modules/itop-request-mgmt-1.0.0/overview.html', $oMyMenuGroup->GetIndex() /* oParent */, 0 /* fRank */);
|
||||
new OQLMenuNode('UserRequest:MyRequests', 'SELECT UserRequest WHERE agent_id = :current_contact_id', $oMyMenuGroup->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('UserRequest:EscalatedRequests', 'SELECT UserRequest WHERE status IN ("escalated_tto", "escalated_ttr")', $oMyMenuGroup->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('UserRequest:OpenRequests', 'SELECT UserRequest WHERE status IN ("new", "assigned", "escalated_tto", "escalated_ttr", "frozen", "resolved")', $oMyMenuGroup->GetIndex(), 3 /* fRank */);
|
||||
new NewObjectMenuNode('NewUserRequest', 'UserRequest', $oMyMenuGroup->GetIndex(), 1 /* fRank */);
|
||||
new SearchMenuNode('SearchUserRequests', 'UserRequest', $oMyMenuGroup->GetIndex(), 2 /* fRank */);
|
||||
$oShortcutNode = new TemplateMenuNode('UserRequest:Shortcuts', '', $oMyMenuGroup->GetIndex(), 3 /* fRank */);
|
||||
new OQLMenuNode('UserRequest:MyRequests', 'SELECT UserRequest WHERE agent_id = :current_contact_id', $oShortcutNode->GetIndex(), 1 /* fRank */);
|
||||
new OQLMenuNode('UserRequest:EscalatedRequests', 'SELECT UserRequest WHERE status IN ("escalated_tto", "escalated_ttr")', $oShortcutNode->GetIndex(), 2 /* fRank */);
|
||||
new OQLMenuNode('UserRequest:OpenRequests', 'SELECT UserRequest WHERE status IN ("new", "assigned", "escalated_tto", "escalated_ttr", "frozen", "resolved")', $oShortcutNode->GetIndex(), 3 /* fRank */);
|
||||
|
||||
?>
|
||||
|
||||
15
pages/UI.php
15
pages/UI.php
@@ -407,7 +407,7 @@ function UpdateObject(&$oObj)
|
||||
{
|
||||
// Non-visible, or read-only attribute, do nothing
|
||||
}
|
||||
else if ($oAttDef->GetEditClass() == 'Document')
|
||||
elseif ($oAttDef->GetEditClass() == 'Document')
|
||||
{
|
||||
// There should be an uploaded file with the named attr_<attCode>
|
||||
$oDocument = utils::ReadPostedDocument('file_'.$sAttCode);
|
||||
@@ -417,6 +417,17 @@ function UpdateObject(&$oObj)
|
||||
$oObj->Set($sAttCode, $oDocument);
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef->GetEditClass() == 'One Way Password')
|
||||
{
|
||||
// Check if the password was typed/changed
|
||||
$bChanged = utils::ReadPostedParam("attr_{$sAttCode}_changed", false);
|
||||
if ($bChanged)
|
||||
{
|
||||
// The password has been changed or set
|
||||
$rawValue = utils::ReadPostedParam("attr_$sAttCode", null);
|
||||
$oObj->Set($sAttCode, $rawValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$rawValue = utils::ReadPostedParam("attr_$sAttCode", null);
|
||||
@@ -769,7 +780,7 @@ try
|
||||
{
|
||||
foreach($aSubClasses as $sCandidateClass)
|
||||
{
|
||||
if (!MetaModel::IsAbstract($sCandidateClass))
|
||||
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
|
||||
{
|
||||
$aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user