mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-14 16:04:10 +01:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37351d6b3e | ||
|
|
57a085eec1 | ||
|
|
0019595923 | ||
|
|
4d61c14f80 | ||
|
|
cf1b613923 | ||
|
|
1304e2eb2d | ||
|
|
3cf16627c1 | ||
|
|
4aaa237bf9 | ||
|
|
cece15d10c | ||
|
|
aa15e009cb | ||
|
|
b9ca2ac13d | ||
|
|
80e1e0e61a | ||
|
|
ecebe4ecd5 | ||
|
|
8bfcb14d0c | ||
|
|
1cf1473d6b | ||
|
|
aa43425df3 | ||
|
|
35d77ff642 | ||
|
|
539fa43503 | ||
|
|
eb537f45f4 | ||
|
|
a2a4cd4e7a | ||
|
|
35215cf62f | ||
|
|
66273ebd39 | ||
|
|
512b415bd6 | ||
|
|
906c8855b0 |
@@ -41,10 +41,8 @@ class ajax_page extends WebPage implements iTabbedPage
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
$this->m_sReadyScript = "";
|
||||
//$this->add_header("Content-type: text/html; charset=utf-8");
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
$this->m_oTabs = new TabManager();
|
||||
$this->sContentType = 'text/html';
|
||||
$this->sContentDisposition = 'inline';
|
||||
|
||||
@@ -32,10 +32,8 @@ class CSVPage extends WebPage
|
||||
function __construct($s_title) {
|
||||
parent::__construct($s_title);
|
||||
$this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET);
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
//$this->add_header("Content-Transfer-Encoding: binary");
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
// Create a breadcrumb entry for the current page, but get its title as late as possible (page title could be changed later)
|
||||
$this->bBreadCrumbEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
$this->bBreadCrumbEnabled = false;
|
||||
}
|
||||
|
||||
@@ -71,10 +70,8 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->m_aMessages = array();
|
||||
$this->SetRootUrl(utils::GetAbsoluteUrlAppRoot());
|
||||
$this->add_header("Content-type: text/html; charset=".self::PAGES_CHARSET);
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
$this->add_linked_stylesheet("../css/jquery.treeview.css");
|
||||
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
|
||||
$this->add_linked_stylesheet("../css/jquery-ui-timepicker-addon.css");
|
||||
|
||||
@@ -84,10 +84,8 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
parent::__construct($sTitle);
|
||||
$this->SetStyleSheet();
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
}
|
||||
|
||||
public function SetStyleSheet()
|
||||
|
||||
@@ -482,6 +482,23 @@ class WebPage implements Page
|
||||
$this->a_headers[] = $s_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sHeaderValue for example `SAMESITE`. If null will set the header using the config parameter value.
|
||||
*
|
||||
* @since 2.7.2-2 3.0.0 N°3416
|
||||
* @uses security_header_xframe config parameter
|
||||
* @uses \utils::GetConfig()
|
||||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
||||
*/
|
||||
public function add_xframe_options($sHeaderValue = null)
|
||||
{
|
||||
if (is_null($sHeaderValue)) {
|
||||
$sHeaderValue = utils::GetConfig()->Get('security_header_xframe');
|
||||
}
|
||||
|
||||
$this->add_header('X-Frame-Options: '.$sHeaderValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add needed headers to the page so that it will no be cached
|
||||
*/
|
||||
@@ -490,7 +507,6 @@ class WebPage implements Page
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,10 +43,8 @@ class XMLPage extends WebPage
|
||||
$this->m_bPassThrough = $bPassThrough;
|
||||
$this->m_bHeaderSent = false;
|
||||
$this->add_header("Content-type: text/xml; charset=".self::PAGES_CHARSET);
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
$this->add_header("Content-location: export.xml");
|
||||
}
|
||||
|
||||
|
||||
@@ -1249,6 +1249,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'security_header_xframe' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Value of the X-Frame-Options HTTP header sent by iTop. Possible values : DENY, SAMEORIGIN, or empty string.',
|
||||
'default' => 'SAMEORIGIN',
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -4166,11 +4166,7 @@ abstract class MetaModel
|
||||
}
|
||||
if (count($aCurrentUser) > 0)
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT User WHERE id = :id");
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('id' => UserRights::GetUserId()));
|
||||
$oSet->OptimizeColumnLoad($aCurrentUser);
|
||||
$oUser = $oSet->fetch();
|
||||
$oUser = MetaModel::GetObject("User", UserRights::GetUserId(),true,true);
|
||||
$aPlaceholders['current_user->object()'] = $oUser;
|
||||
foreach ($aCurrentUser as $sField)
|
||||
{
|
||||
@@ -4179,10 +4175,7 @@ abstract class MetaModel
|
||||
}
|
||||
if (count($aCurrentContact) > 0)
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Contact WHERE id = :id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('id' => UserRights::GetContactId()));
|
||||
$oSet->OptimizeColumnLoad(['Contact' => $aCurrentContact]);
|
||||
$oUser = $oSet->fetch();
|
||||
$oUser = MetaModel::GetObject("Person", UserRights::GetContactId(),true,true);
|
||||
foreach ($aCurrentContact as $sField)
|
||||
{
|
||||
$aPlaceholders['current_contact->'.$sField] = $oUser->Get($sField);
|
||||
|
||||
@@ -199,8 +199,8 @@ EOF
|
||||
// Integration within MS-Excel web queries + HTTPS + IIS:
|
||||
// MS-IIS set these header values with no-cache... while Excel fails to do the job if using HTTPS
|
||||
// Then the fix is to force the reset of header values Pragma and Cache-control
|
||||
$oPage->add_header("Pragma:", true);
|
||||
$oPage->add_header("Cache-control:", true);
|
||||
$oPage->add_header("Pragma:");
|
||||
$oPage->add_header("Cache-control:");
|
||||
}
|
||||
|
||||
public function GetHeader()
|
||||
|
||||
@@ -17,17 +17,17 @@
|
||||
*/
|
||||
|
||||
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
|
||||
$version: "v2.7.2";
|
||||
$version: "v2.7.3";
|
||||
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
|
||||
|
||||
// Base colors
|
||||
$gray-base: #000 !default;
|
||||
$gray-darker: lighten($gray-base, 13.5%) !default; // #222
|
||||
$gray-dark: #444 !default;
|
||||
$gray: #777 !default;
|
||||
$gray-light: #808080 !default;
|
||||
$gray-lighter: #ddd !default;
|
||||
$gray-extra-light: #F1F1F1 !default;
|
||||
$gray-base: #000 !default;
|
||||
$gray-darker: lighten($gray-base, 13.5%) !default; // #222
|
||||
$gray-dark: #444 !default;
|
||||
$gray: #777 !default;
|
||||
$gray-light: #808080 !default;
|
||||
$gray-lighter: #ddd !default;
|
||||
$gray-extra-light: #F1F1F1 !default;
|
||||
|
||||
$white: #FFFFFF !default;
|
||||
|
||||
|
||||
@@ -212,9 +212,9 @@ function DisplayInconsistenciesReport($aResults)
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: multipart/x-zip');
|
||||
header('Content-Disposition: inline; filename="'.basename($sZipReport).'"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Expires: 0');
|
||||
header('Content-Length: '.filesize($sZipReport));
|
||||
readfile($sZipReport);
|
||||
unlink($sZipReport);
|
||||
|
||||
@@ -61,7 +61,6 @@ try
|
||||
LoginWebPage::DoLoginEx(null /* any portal */, false);
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ function DisplayErrorAndDie($oPage, $sHtmlErrorMessage, $exitCode = null)
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
$oPage = new ajax_page('');
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ class FilesIntegrity
|
||||
$sChecksum = md5($sContent);
|
||||
if (($iSize != $aFileInfo['size']) || ($sChecksum != $aFileInfo['md5']))
|
||||
{
|
||||
throw new FileIntegrityException(Dict::Format('FilesInformation:Error:CorruptedFile', basename($sFile)));
|
||||
throw new FileIntegrityException(Dict::Format('FilesInformation:Error:CorruptedFile', $sFile));
|
||||
}
|
||||
}
|
||||
// Packed with missing files...
|
||||
|
||||
@@ -111,7 +111,6 @@ function DoBackup($sTargetFile)
|
||||
function ReportStatus($sMessage, $bSuccess, $iErrorCode = 0, $aMoreFields = array())
|
||||
{
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('application/json');
|
||||
$aResult = array(
|
||||
'code' => $iErrorCode,
|
||||
|
||||
@@ -4,20 +4,18 @@ class HubConnectorPage extends NiceWebPage
|
||||
{
|
||||
public function __construct($sTitle)
|
||||
{
|
||||
parent::__construct($sTitle);
|
||||
parent::__construct($sTitle);
|
||||
|
||||
$this->add_header('Cache-control: no-cache, no-store, must-revalidate');
|
||||
$this->add_header('Pragma: no-cache');
|
||||
$this->add_header('Expires: 0');
|
||||
$this->add_header('X-Frame-Options: deny');
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
|
||||
$sImagesDir = utils::GetAbsoluteUrlAppRoot().'images';
|
||||
$sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images';
|
||||
|
||||
$sUserPrefs = appUserPreferences::GetAsJSON();
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->add_script(
|
||||
<<<EOF
|
||||
$sImagesDir = utils::GetAbsoluteUrlAppRoot().'images';
|
||||
$sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images';
|
||||
|
||||
$sUserPrefs = appUserPreferences::GetAsJSON();
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->add_script(
|
||||
<<<EOF
|
||||
var oUserPreferences = $sUserPrefs;
|
||||
EOF
|
||||
);
|
||||
|
||||
@@ -106,7 +106,11 @@ var CombodoPortalToolbox = {
|
||||
if (oOptions.base_modal.usage === 'clone')
|
||||
{
|
||||
oModalElem = oSelectorElem.clone();
|
||||
oModalElem.attr('id', oOptions.id)
|
||||
|
||||
// Force modal to have an HTML ID, otherwise it can lead to complications, especially with the portal_leave_handle.js
|
||||
// See N°3469
|
||||
var sModalID = (oOptions.id !== null) ? oOptions.id : 'modal-with-generated-id-'+Date.now();
|
||||
oModalElem.attr('id', sModalID)
|
||||
.appendTo('body');
|
||||
}
|
||||
// - Get an existing modal in the DOM
|
||||
|
||||
@@ -89,7 +89,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:Query/Attribute:description' => 'Description',
|
||||
'Class:Query/Attribute:description+' => 'Long description for the query (purpose, usage, etc.)',
|
||||
'Class:QueryOQL/Attribute:fields' => 'Fields',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Coma separated list of attributes (or alias.attribute) to export',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Comma separated list of attributes (or alias.attribute) to export',
|
||||
'Class:QueryOQL' => 'OQL Query',
|
||||
'Class:QueryOQL+' => 'A query based on the Object Query Language',
|
||||
'Class:QueryOQL/Attribute:oql' => 'Expression',
|
||||
|
||||
@@ -72,7 +72,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
|
||||
'Class:Query/Attribute:description' => 'Description~~',
|
||||
'Class:Query/Attribute:description+' => 'Long description for the query (purpose, usage, etc.)~~',
|
||||
'Class:QueryOQL/Attribute:fields' => 'Fields~~',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Coma separated list of attributes (or alias.attribute) to export~~',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Comma separated list of attributes (or alias.attribute) to export~~',
|
||||
'Class:QueryOQL' => 'OQL Query~~',
|
||||
'Class:QueryOQL+' => 'A query based on the Object Query Language~~',
|
||||
'Class:QueryOQL/Attribute:oql' => 'Expression~~',
|
||||
|
||||
@@ -71,7 +71,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
'Class:Query/Attribute:description' => 'Popis',
|
||||
'Class:Query/Attribute:description+' => '',
|
||||
'Class:QueryOQL/Attribute:fields' => 'Polia',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Coma separated list of attributes (or alias.attribute) to export~~',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Comma separated list of attributes (or alias.attribute) to export~~',
|
||||
'Class:QueryOQL' => 'OQL Dopyt',
|
||||
'Class:QueryOQL+' => '',
|
||||
'Class:QueryOQL/Attribute:oql' => 'Výraz',
|
||||
|
||||
@@ -86,7 +86,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'Class:Query/Attribute:description' => 'Description~~',
|
||||
'Class:Query/Attribute:description+' => 'Long description for the query (purpose, usage, etc.)~~',
|
||||
'Class:QueryOQL/Attribute:fields' => 'Fields~~',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Coma separated list of attributes (or alias.attribute) to export~~',
|
||||
'Class:QueryOQL/Attribute:fields+' => 'Comma separated list of attributes (or alias.attribute) to export~~',
|
||||
'Class:QueryOQL' => 'OQL Query~~',
|
||||
'Class:QueryOQL+' => 'A query based on the Object Query Language~~',
|
||||
'Class:QueryOQL/Attribute:oql' => 'Expression~~',
|
||||
|
||||
@@ -192,7 +192,7 @@ function activateFirstTabWithError(sFormId) {
|
||||
if ($fieldsWithError.length > 0)
|
||||
{
|
||||
$tabsContainer.tabs("option", "active", index);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -242,7 +242,6 @@ try
|
||||
{
|
||||
case 'parser_preview':
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
|
||||
if ($sSeparator == 'tab') $sSeparator = "\t";
|
||||
|
||||
@@ -38,7 +38,6 @@ try
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
|
||||
$operation = utils::ReadParam('operation', '');
|
||||
$sClass = utils::ReadParam('class', 'MissingAjaxParam', false, 'class');
|
||||
@@ -62,9 +61,14 @@ try
|
||||
ormDocument::DownloadDocument($oPage, $sClass, $id, $sField, 'attachment');
|
||||
if ($iCacheSec > 0)
|
||||
{
|
||||
$oPage->add_header("Expires: "); // Reset the value set in ajax_page
|
||||
$oPage->add_header("Cache-Control: no-transform,public,max-age=$iCacheSec,s-maxage=$iCacheSec");
|
||||
$oPage->add_header("Pragma: cache"); // Reset the value set .... where ?
|
||||
$oPage->add_header("Expires: "); // Reset the value set in ajax_page
|
||||
|
||||
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
|
||||
// so we're resetting its value ! (see N°3416)
|
||||
$oPage->add_xframe_options('');
|
||||
|
||||
$oPage->add_header("Last-Modified: Wed, 15 Jun 2015 13:21:15 GMT"); // An arbitrary date in the past is ok
|
||||
}
|
||||
}
|
||||
@@ -76,12 +80,16 @@ try
|
||||
$id = utils::ReadParam('id', '');
|
||||
$sSecret = utils::ReadParam('s', '');
|
||||
$iCacheSec = 31556926; // One year ahead: an inline image cannot change
|
||||
if (!empty($id) && !empty($sSecret))
|
||||
{
|
||||
if (!empty($id) && !empty($sSecret)) {
|
||||
ormDocument::DownloadDocument($oPage, 'InlineImage', $id, 'contents', 'inline', 'secret', $sSecret);
|
||||
$oPage->add_header("Expires: "); // Reset the value set in ajax_page
|
||||
$oPage->add_header("Cache-Control: no-transform,public,max-age=$iCacheSec,s-maxage=$iCacheSec");
|
||||
$oPage->add_header("Pragma: cache"); // Reset the value set .... where ?
|
||||
$oPage->add_header("Expires: "); // Reset the value set in ajax_page
|
||||
|
||||
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
|
||||
// so we're resetting its value ! (see N°3416)
|
||||
$oPage->add_xframe_options('');
|
||||
|
||||
$oPage->add_header("Last-Modified: Wed, 15 Jun 2016 13:21:15 GMT"); // An arbitrary date in the past is ok
|
||||
}
|
||||
break;
|
||||
@@ -92,6 +100,11 @@ try
|
||||
$oPage->SetContentType('text/javascript');
|
||||
$oPage->add_header('Cache-control: public, max-age=86400'); // Cache for 24 hours
|
||||
$oPage->add_header("Pragma: cache"); // Reset the value set .... where ?
|
||||
|
||||
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
|
||||
// so we're resetting its value ! (see N°3416)
|
||||
$oPage->add_xframe_options('');
|
||||
|
||||
$oPage->add(file_get_contents(Utils::GetCachePath().$sSignature.'.js'));
|
||||
break;
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@ try
|
||||
LoginWebPage::DoLoginEx($sRequestedPortalId, false);
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
|
||||
|
||||
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
|
||||
$sEncoding = utils::ReadParam('encoding', 'serialize');
|
||||
@@ -889,13 +887,12 @@ try
|
||||
case 'chart':
|
||||
// Workaround for IE8 + IIS + HTTPS
|
||||
// See TRAC #363, fix described here: http://forums.codecharge.com/posts.php?post_id=97771
|
||||
$oPage->add_header("Expires: Fri, 17 Jul 1970 05:00:00 GMT");
|
||||
$oPage->add_header("Cache-Control: cache, must-revalidate");
|
||||
$oPage->add_header("Pragma: public");
|
||||
$oPage->add_header("Expires: Fri, 17 Jul 1970 05:00:00 GMT");
|
||||
|
||||
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
|
||||
if ($sFilter != '')
|
||||
{
|
||||
if ($sFilter != '') {
|
||||
$oFilter = DBSearch::unserialize($sFilter);
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oDisplayBlock = new DisplayBlock($oFilter, 'chart_ajax', false);
|
||||
@@ -961,6 +958,11 @@ try
|
||||
if (!empty($sClass) && ($sClass != 'InlineImage') && !empty($id) && !empty($sField))
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
|
||||
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
|
||||
// so we're resetting its value ! (see N°3416)
|
||||
$oPage->add_xframe_options('');
|
||||
|
||||
ormDocument::DownloadDocument($oPage, $sClass, $id, $sField, 'inline');
|
||||
$oKPI->ComputeAndReport('Data fetch and format');
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ try
|
||||
}
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
$sListParams = utils::ReadParam('list_params', '{}', false, 'raw_data');
|
||||
|
||||
@@ -33,10 +33,14 @@ LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be
|
||||
$sOperation = Utils::ReadParam('operation', 'step1');
|
||||
$oP = new SetupPage('iTop email test utility');
|
||||
|
||||
// Although this page doesn't expose sensitive info, with it we can send multiple emails
|
||||
// So we're adding this http header to reduce CSRF exposure...
|
||||
$oP->add_xframe_options('DENY');
|
||||
|
||||
|
||||
/**
|
||||
* Helper to check server setting required to send an email
|
||||
*/
|
||||
*/
|
||||
function CheckEmailSetting($oP)
|
||||
{
|
||||
$bRet = true;
|
||||
@@ -255,11 +259,11 @@ try
|
||||
break;
|
||||
|
||||
case 'step2':
|
||||
$oP->no_cache();
|
||||
$sTo = Utils::ReadParam('to', '', false, 'raw_data');
|
||||
$sFrom = Utils::ReadParam('from', '', false, 'raw_data');
|
||||
DisplayStep2($oP, $sFrom, $sTo);
|
||||
break;
|
||||
$oP->no_cache();
|
||||
$sTo = Utils::ReadParam('to', '', false, 'raw_data');
|
||||
$sFrom = Utils::ReadParam('from', '', false, 'raw_data');
|
||||
DisplayStep2($oP, $sFrom, $sTo);
|
||||
break;
|
||||
|
||||
default:
|
||||
$oP->error("Error: unsupported operation '$sOperation'");
|
||||
|
||||
@@ -716,7 +716,7 @@ class WizStepLicense extends WizardStep
|
||||
$aLicenses = SetupUtils::GetLicenses();
|
||||
$oPage->add_style(
|
||||
<<<EOF
|
||||
fieldset {
|
||||
fieldset ul{
|
||||
max-height: 18em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@@ -435,18 +435,16 @@ abstract class Controller
|
||||
$sFileMimeType = utils::GetFileMimeType($sFilePath);
|
||||
header('Content-Type: '.$sFileMimeType);
|
||||
|
||||
if ($bFileTransfer)
|
||||
{
|
||||
if ($bFileTransfer) {
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Disposition: inline; filename="'.$sDownloadArchiveName);
|
||||
}
|
||||
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Expires: 0');
|
||||
|
||||
foreach ($aHeaders as $sKey => $sValue)
|
||||
{
|
||||
foreach ($aHeaders as $sKey => $sValue) {
|
||||
header($sKey.': '.$sValue);
|
||||
}
|
||||
|
||||
@@ -558,7 +556,7 @@ abstract class Controller
|
||||
{
|
||||
case 'html':
|
||||
$this->m_oPage = new iTopWebPage($this->GetOperationTitle());
|
||||
$this->m_oPage->add_header('X-Frame-Options: deny');
|
||||
$this->m_oPage->add_xframe_options();
|
||||
break;
|
||||
|
||||
case 'ajax':
|
||||
|
||||
@@ -73,7 +73,7 @@ class ItopDataTestCase extends ItopTestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
//require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/utils.inc.php');
|
||||
|
||||
@@ -408,8 +408,12 @@ class ItopDataTestCase extends ItopTestCase
|
||||
* @return \DBObject
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function CreateUser($sLogin, $iProfileId)
|
||||
protected function CreateUser($sLogin, $iProfileId, $sPassword=null)
|
||||
{
|
||||
if (empty($sPassword)){
|
||||
$sPassword = $sLogin;
|
||||
}
|
||||
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $iProfileId);
|
||||
$oUserProfile->Set('reason', 'UNIT Tests');
|
||||
@@ -417,7 +421,7 @@ class ItopDataTestCase extends ItopTestCase
|
||||
$oUser = $this->createObject('UserLocal', array(
|
||||
'contactid' => 2,
|
||||
'login' => $sLogin,
|
||||
'password' => $sLogin,
|
||||
'password' => $sPassword,
|
||||
'language' => 'EN US',
|
||||
'profile_list' => $oSet,
|
||||
));
|
||||
@@ -426,6 +430,29 @@ class ItopDataTestCase extends ItopTestCase
|
||||
return $oUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject $oUser
|
||||
* @param int $iProfileId
|
||||
*
|
||||
* @return \DBObject
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function AddProfileToUser($oUser, $iProfileId)
|
||||
{
|
||||
$oUserProfile = new URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $iProfileId);
|
||||
$oUserProfile->Set('reason', 'UNIT Tests');
|
||||
/** @var DBObjectSet $oSet */
|
||||
$oSet = $oUser->Get('profile_list');
|
||||
$oSet->AddObject($oUserProfile);
|
||||
$oUser = $this->updateObject('UserLocal', $oUser->GetKey(), array(
|
||||
'profile_list' => $oSet,
|
||||
));
|
||||
$this->debug("Updated {$oUser->GetName()} ({$oUser->GetKey()})");
|
||||
|
||||
return $oUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Hypervisor in database
|
||||
|
||||
@@ -781,15 +781,16 @@ try
|
||||
break;
|
||||
|
||||
case 'create_structure':
|
||||
$oP->no_cache();
|
||||
$iPlannedContacts = Utils::ReadParam('plannedcontacts');
|
||||
$iPlannedContracts = Utils::ReadParam('plannedcontracts');
|
||||
$oP->no_cache();
|
||||
$oP->add_xframe_options('DENY');
|
||||
$iPlannedContacts = Utils::ReadParam('plannedcontacts');
|
||||
$iPlannedContracts = Utils::ReadParam('plannedcontracts');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanStructure($iPlannedContacts, $iPlannedContracts);
|
||||
$oDataCreation->ShowPlans($oP);
|
||||
$oDataCreation->ShowForm($oP, 'create_structure_go');
|
||||
break;
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanStructure($iPlannedContacts, $iPlannedContracts);
|
||||
$oDataCreation->ShowPlans($oP);
|
||||
$oDataCreation->ShowForm($oP, 'create_structure_go');
|
||||
break;
|
||||
|
||||
case 'create_structure_go':
|
||||
$oP->no_cache();
|
||||
|
||||
@@ -102,10 +102,16 @@ class CMDBSourceTest extends ItopTestCase
|
||||
"enum('1','2','3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '1'",
|
||||
),
|
||||
'ENUM with values containing parenthesis' => array(
|
||||
true,
|
||||
true, // see N°3065 : if having distinct values having parenthesis in enum values will cause comparison to be inexact
|
||||
"ENUM('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
"enum('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
),
|
||||
//FIXME N°3065 before the fix this returns true :(
|
||||
// 'ENUM with different values, containing parenthesis' => array(
|
||||
// false,
|
||||
// "ENUM('value 1 (with parenthesis)','value 2') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
// "enum('value 1 (with parenthesis)','value 3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
// ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
<testsuite name="Core">
|
||||
<directory>core</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Webservices">
|
||||
<directory>webservices</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Tickets">
|
||||
<directory>itop-tickets</directory>
|
||||
</testsuite>
|
||||
|
||||
281
test/webservices/RestTest.php
Normal file
281
test/webservices/RestTest.php
Normal file
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Webservices;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use Exception;
|
||||
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class RestTest extends ItopDataTestCase
|
||||
{
|
||||
const USE_TRANSACTION = false;
|
||||
|
||||
private $sTmpFile = "";
|
||||
private $bPassJsonDataAsFile = false;
|
||||
private $sUrl;
|
||||
private $sLogin;
|
||||
private $sPassword = "Iuytrez9876543ç_è-(";
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
$this->sLogin = "rest-user-" . date('dmYHis');
|
||||
$this->CreateTestOrganization();
|
||||
|
||||
if (!empty($this->sTmpFile)){
|
||||
unlink($this->sTmpFile);
|
||||
}
|
||||
|
||||
$sConfigFile = \utils::GetConfig()->GetLoadedFile();
|
||||
@chmod($sConfigFile, 0770);
|
||||
$this->sUrl = \MetaModel::GetConfig()->Get('app_root_url');
|
||||
@chmod($sConfigFile, 0444); // Read-only
|
||||
|
||||
$oRestProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => 'REST Services User'), true);
|
||||
$oAdminProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => 'Administrator'), true);
|
||||
|
||||
if (is_object($oRestProfile) && is_object($oAdminProfile))
|
||||
{
|
||||
$oUser = $this->CreateUser($this->sLogin, $oRestProfile->GetKey(), $this->sPassword);
|
||||
$this->AddProfileToUser($oUser, $oAdminProfile->GetKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider BasicProvider
|
||||
* @param bool $bPassJsonDataAsFile
|
||||
*/
|
||||
public function testCreateApi($bPassJsonDataAsFile)
|
||||
{
|
||||
$this->bPassJsonDataAsFile = $bPassJsonDataAsFile;
|
||||
|
||||
//create ticket
|
||||
$description = date('dmY H:i:s');
|
||||
$sOuputJson = $this->CreateTicketViaApi($description);
|
||||
$aJson = json_decode($sOuputJson, true);
|
||||
$this->assertContains("0", "".$aJson['code'], $sOuputJson);
|
||||
$sUserRequestKey = $this->array_key_first($aJson['objects']);
|
||||
$this->assertContains('UserRequest::', $sUserRequestKey);
|
||||
$iId = $aJson['objects'][$sUserRequestKey]['key'];
|
||||
$sExpectedJsonOuput=<<<JSON
|
||||
{"objects":{"UserRequest::$iId":{"code":0,"message":"created","class":"UserRequest","key":"$iId","fields":{"id":"$iId"}}},"code":0,"message":null}
|
||||
JSON;
|
||||
$this->assertEquals($sExpectedJsonOuput, $sOuputJson);
|
||||
|
||||
$sExpectedJsonOuput=<<<JSON
|
||||
{"objects":{"UserRequest::$iId":{"code":0,"message":"","class":"UserRequest","key":"$iId","fields":{"id":"$iId","description":"<p>$description<\/p>"}}},"code":0,"message":"Found: 1"}
|
||||
JSON;
|
||||
$this->assertEquals($sExpectedJsonOuput, $this->GetTicketViaRest($iId));
|
||||
|
||||
$aCmdbChangeUserInfo = $this->GetCmdbChangeUserInfo($iId);
|
||||
$this->assertEquals(['CMDBChangeOpCreate' => 'test'], $aCmdbChangeUserInfo);
|
||||
|
||||
//delete ticket
|
||||
$this->DeleteTicketFromApi($iId);
|
||||
}
|
||||
|
||||
/**
|
||||
* array_key_first comes with PHP7.3
|
||||
* itop should also work with previous PHP versions
|
||||
*/
|
||||
private function array_key_first($aTab){
|
||||
if (!is_array($aTab) || empty($aTab)){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($aTab as $sKey => $sVal){
|
||||
return $sKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider BasicProvider
|
||||
* @param bool $bPassJsonDataAsFile
|
||||
*/
|
||||
public function testUpdateApi($bPassJsonDataAsFile)
|
||||
{
|
||||
$this->bPassJsonDataAsFile = $bPassJsonDataAsFile;
|
||||
|
||||
//create ticket
|
||||
$description = date('dmY H:i:s');
|
||||
$sOuputJson = $this->CreateTicketViaApi($description);
|
||||
$aJson = json_decode($sOuputJson, true);
|
||||
$this->assertContains("0", "".$aJson['code'], $sOuputJson);
|
||||
$sUserRequestKey = $this->array_key_first($aJson['objects']);
|
||||
$this->assertContains('UserRequest::', $sUserRequestKey);
|
||||
$iId = $aJson['objects'][$sUserRequestKey]['key'];
|
||||
|
||||
//update ticket
|
||||
$description = date('Ymd H:i:s');
|
||||
$sExpectedJsonOuput=<<<JSON
|
||||
{"objects":{"UserRequest::$iId":{"code":0,"message":"updated","class":"UserRequest","key":"$iId","fields":{"description":"<p>$description<\/p>"}}},"code":0,"message":null}
|
||||
JSON;
|
||||
$this->assertEquals($sExpectedJsonOuput, $this->UpdateTicketViaApi($iId, $description));
|
||||
|
||||
$aCmdbChangeUserInfo = $this->GetCmdbChangeUserInfo($iId);
|
||||
$this->assertEquals(['CMDBChangeOpCreate' => 'test', 'CMDBChangeOpSetAttributeHTML' => 'test'], $aCmdbChangeUserInfo);
|
||||
|
||||
|
||||
//delete ticket
|
||||
$this->DeleteTicketFromApi($iId);
|
||||
}
|
||||
/**
|
||||
* @dataProvider BasicProvider
|
||||
* @param bool $bPassJsonDataAsFile
|
||||
*/
|
||||
public function testDeleteApi($bPassJsonDataAsFile)
|
||||
{
|
||||
$this->bPassJsonDataAsFile = $bPassJsonDataAsFile;
|
||||
|
||||
//create ticket
|
||||
$description = date('dmY H:i:s');
|
||||
|
||||
$sOuputJson = $this->CreateTicketViaApi($description);
|
||||
$aJson = json_decode($sOuputJson, true);
|
||||
$this->assertContains("0", "".$aJson['code'], $sOuputJson);
|
||||
$sUserRequestKey = $this->array_key_first($aJson['objects']);
|
||||
$this->assertContains('UserRequest::', $sUserRequestKey);
|
||||
$iId = $aJson['objects'][$sUserRequestKey]['key'];
|
||||
|
||||
//delete ticket
|
||||
$sExpectedJsonOuput=<<<JSON
|
||||
{"objects":{"UserRequest::$iId"
|
||||
JSON;
|
||||
$this->assertContains($sExpectedJsonOuput, $this->DeleteTicketFromApi($iId));
|
||||
|
||||
$sExpectedJsonOuput=<<<JSON
|
||||
{"objects":null,"code":0,"message":"Found: 0"}
|
||||
JSON;
|
||||
$this->assertEquals($sExpectedJsonOuput, $this->GetTicketViaRest($iId));
|
||||
}
|
||||
|
||||
private function GetTicketViaRest($iId){
|
||||
$sJsonGetContent = <<<JSON
|
||||
{
|
||||
"operation": "core/get",
|
||||
"class": "UserRequest",
|
||||
"key": "SELECT UserRequest WHERE id=$iId",
|
||||
"output_fields": "id, description"
|
||||
}
|
||||
JSON;
|
||||
|
||||
return $this->CallRestApi($sJsonGetContent);
|
||||
}
|
||||
|
||||
public function BasicProvider(){
|
||||
return [
|
||||
'call rest call' => [ 'bCallApiViaFile' => false],
|
||||
//'pass json_data as file' => [ 'bCallApiViaFile' => true]
|
||||
];
|
||||
}
|
||||
|
||||
private function UpdateTicketViaApi($iId, $description){
|
||||
$sJsonUpdateContent = <<<JSON
|
||||
{"operation": "core/update","comment": "test","class": "UserRequest","key":"$iId","output_fields": "description","fields":{"description": "$description"}}
|
||||
JSON;
|
||||
|
||||
return $this->CallRestApi($sJsonUpdateContent);
|
||||
}
|
||||
|
||||
private function CreateTicketViaApi($description){
|
||||
$sJsonCreateContent = <<<JSON
|
||||
{
|
||||
"operation": "core/create",
|
||||
"comment": "test",
|
||||
"class": "UserRequest",
|
||||
"output_fields": "id",
|
||||
"fields":
|
||||
{
|
||||
"org_id": "SELECT Organization WHERE name = \"Demo\"",
|
||||
|
||||
"title": "Houston, got a problem",
|
||||
"description": "$description"
|
||||
}
|
||||
}
|
||||
JSON;
|
||||
|
||||
return $this->CallRestApi($sJsonCreateContent);
|
||||
}
|
||||
|
||||
private function DeleteTicketFromApi($iId){
|
||||
$sJson = <<<JSON
|
||||
{
|
||||
"operation": "core/delete",
|
||||
"comment": "Cleanup",
|
||||
"class": "UserRequest",
|
||||
"key":$iId,
|
||||
"simulate": false
|
||||
}
|
||||
JSON;
|
||||
return $this->CallRestApi($sJson);
|
||||
|
||||
}
|
||||
|
||||
private function CallRestApi($sJsonDataContent){
|
||||
$ch = curl_init();
|
||||
$aPostFields = [
|
||||
'version' => '1.3',
|
||||
'auth_user' => $this->sLogin,
|
||||
'auth_pwd' => $this->sPassword,
|
||||
];
|
||||
|
||||
if ($this->bPassJsonDataAsFile){
|
||||
$this->sTmpFile = tempnam(sys_get_temp_dir(), 'jsondata_');
|
||||
file_put_contents($this->sTmpFile, $sJsonDataContent);
|
||||
|
||||
$oCurlFile = curl_file_create($this->sTmpFile);
|
||||
$aPostFields['json_data'] = $oCurlFile;
|
||||
}else{
|
||||
$aPostFields['json_data'] = $sJsonDataContent;
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, "$this->sUrl/webservices/rest.php");
|
||||
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$sJson = curl_exec($ch);
|
||||
curl_close ($ch);
|
||||
|
||||
return $sJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $iId
|
||||
* Get CMDBChangeOp info to test
|
||||
* @return array
|
||||
*/
|
||||
private function GetCmdbChangeUserInfo($iId){
|
||||
$sJsonGetContent = <<<JSON
|
||||
{
|
||||
"operation": "core/get",
|
||||
"class": "CMDBChangeOp",
|
||||
"key": "SELECT CMDBChangeOp WHERE objclass='UserRequest' AND objkey=$iId",
|
||||
"output_fields": "userinfo"
|
||||
}
|
||||
JSON;
|
||||
|
||||
$aUserInfo = [];
|
||||
$sOutput = $this->CallRestApi($sJsonGetContent);
|
||||
$aJson = json_decode($sOutput, true);
|
||||
if (is_array($aJson) && array_key_exists('objects', $aJson)){
|
||||
$aObjects = $aJson['objects'];
|
||||
if (!empty($aObjects)){
|
||||
foreach ($aObjects as $aObject){
|
||||
$sClass = $aObject['class'];
|
||||
$sUserInfo = $aObject['fields']['userinfo'];
|
||||
$aUserInfo[$sClass] = $sUserInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aUserInfo;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ function ReportErrorAndExit($sErrorMessage)
|
||||
else
|
||||
{
|
||||
$oP = new WebPage("iTop - Export");
|
||||
$oP->add_header('X-Frame-Options: deny');
|
||||
$oP->add_xframe_options();
|
||||
$oP->p('ERROR: '.$sErrorMessage);
|
||||
$oP->output();
|
||||
exit(-1);
|
||||
@@ -61,10 +61,9 @@ function ReportErrorAndUsage($sErrorMessage)
|
||||
$oP->output();
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
$oP = new WebPage("iTop - Export");
|
||||
$oP->add_header('X-Frame-Options: deny');
|
||||
$oP->add_xframe_options();
|
||||
$oP->p('ERROR: '.$sErrorMessage);
|
||||
Usage($oP);
|
||||
$oP->output();
|
||||
@@ -728,19 +727,17 @@ try
|
||||
if ($sMimeType == 'text/html')
|
||||
{
|
||||
// Note: Using NiceWebPage only for HTML export as it includes JS scripts & files, which makes no sense in other export formats. More over, it breaks Excel spreadsheet import.
|
||||
if($oExporter instanceof HTMLBulkExport)
|
||||
{
|
||||
if($oExporter instanceof HTMLBulkExport) {
|
||||
$oP = new NiceWebPage('iTop export');
|
||||
$oP->add_header('X-Frame-Options: deny');
|
||||
$oP->add_xframe_options();
|
||||
$oP->add_ready_script("$('table.listResults').tablesorter({widgets: ['MyZebra']});");
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
$oP = new WebPage('iTop export');
|
||||
$oP->add_header('X-Frame-Options: deny');
|
||||
$oP->add_style("table br { mso-data-placement:same-cell; }"); // Trick for Excel: keep line breaks inside the same cell !
|
||||
$oP->add_xframe_options();
|
||||
$oP->add_style("table br { mso-data-placement:same-cell; }"); // Trick for Excel: keep line breaks inside the same cell !
|
||||
}
|
||||
$oP->add_style("body { overflow: auto; }");
|
||||
}
|
||||
@@ -760,10 +757,9 @@ catch (BulkExportMissingParameterException $e)
|
||||
Usage($oP);
|
||||
$oP->output();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
catch (Exception $e) {
|
||||
$oP = new WebPage('iTop Export');
|
||||
$oP->add_header('X-Frame-Options: deny');
|
||||
$oP->add_xframe_options();
|
||||
$oP->add('Error: '.$e->getMessage());
|
||||
IssueLog::Error($e->getMessage()."\n".$e->getTraceAsString());
|
||||
$oP->output();
|
||||
|
||||
@@ -189,47 +189,55 @@ if (!empty($sExpression))
|
||||
switch($sFormat)
|
||||
{
|
||||
case 'html':
|
||||
$oP = new NiceWebPage("iTop - Export");
|
||||
$oP->add_style('body { overflow: auto; }'); // Show scroll bars if needed
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
|
||||
|
||||
// Integration within MS-Excel web queries + HTTPS + IIS:
|
||||
// MS-IIS set these header values with no-cache... while Excel fails to do the job if using HTTPS
|
||||
// Then the fix is to force the reset of header values Pragma and Cache-control
|
||||
header("Pragma:", true);
|
||||
header("Cache-control:", true);
|
||||
$oP = new NiceWebPage("iTop - Export");
|
||||
$oP->add_style('body { overflow: auto; }'); // Show scroll bars if needed
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
|
||||
|
||||
// The HTML output is made for pages located in the /pages/ folder
|
||||
// since this page is in a different folder, let's adjust the HTML 'base' attribute
|
||||
// to make the relative hyperlinks in the page work
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$oP->set_base($sUrl.'pages/');
|
||||
// Integration within MS-Excel web queries + HTTPS + IIS:
|
||||
// MS-IIS set these header values with no-cache... while Excel fails to do the job if using HTTPS
|
||||
// Then the fix is to force the reset of header values Pragma and Cache-control
|
||||
header("Cache-control:", true);
|
||||
header("Pragma:", true);
|
||||
|
||||
if(count($aFields) > 0)
|
||||
{
|
||||
$iSearch = array_search('id', $aFields);
|
||||
if ($iSearch !== false)
|
||||
{
|
||||
$bViewLink = true;
|
||||
unset($aFields[$iSearch]);
|
||||
// The HTML output is made for pages located in the /pages/ folder
|
||||
// since this page is in a different folder, let's adjust the HTML 'base' attribute
|
||||
// to make the relative hyperlinks in the page work
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$oP->set_base($sUrl.'pages/');
|
||||
|
||||
if (count($aFields) > 0) {
|
||||
$iSearch = array_search('id', $aFields);
|
||||
if ($iSearch !== false) {
|
||||
$bViewLink = true;
|
||||
unset($aFields[$iSearch]);
|
||||
} else {
|
||||
$bViewLink = false;
|
||||
}
|
||||
$sFields = implode(',', $aFields);
|
||||
$aExtraParams = array(
|
||||
'menu' => false,
|
||||
'toolkit_menu' => false,
|
||||
'display_limit' => false,
|
||||
'localize_values' => $bLocalize,
|
||||
'zlist' => false,
|
||||
'extra_fields' => $sFields,
|
||||
'view_link' => $bViewLink,
|
||||
);
|
||||
} else {
|
||||
$aExtraParams = array(
|
||||
'menu' => false,
|
||||
'toolkit_menu' => false,
|
||||
'display_limit' => false,
|
||||
'localize_values' => $bLocalize,
|
||||
'zlist' => 'details',
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$bViewLink = false;
|
||||
}
|
||||
$sFields = implode(',', $aFields);
|
||||
$aExtraParams = array('menu' => false, 'toolkit_menu' => false, 'display_limit' => false, 'localize_values' => $bLocalize, 'zlist' => false, 'extra_fields' => $sFields, 'view_link' => $bViewLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aExtraParams = array('menu' => false, 'toolkit_menu' => false, 'display_limit' => false, 'localize_values' => $bLocalize, 'zlist' => 'details');
|
||||
}
|
||||
|
||||
$oResultBlock = new DisplayBlock($oFilter, 'list', false, $aExtraParams);
|
||||
$oResultBlock->Display($oP, 'expresult');
|
||||
break;
|
||||
|
||||
$oResultBlock = new DisplayBlock($oFilter, 'list', false, $aExtraParams);
|
||||
$oResultBlock->Display($oP, 'expresult');
|
||||
break;
|
||||
|
||||
case 'csv':
|
||||
$oP = new CSVPage("iTop - Export");
|
||||
$sFields = implode(',', $aFields);
|
||||
@@ -336,17 +344,14 @@ if (!$oP)
|
||||
$oP->p("Parameters:");
|
||||
$oP->p(" * expression: an OQL expression (URL encoded if needed)");
|
||||
$oP->p(" * query: (alternative to 'expression') the id of an entry from the query phrasebook");
|
||||
if (Utils::IsModeCLI())
|
||||
{
|
||||
if (Utils::IsModeCLI()) {
|
||||
$oP->p(" * with_archive: (optional, defaults to 0) if set to 1 then the result set will include archived objects");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP->p(" * with_archive: (optional, defaults to the current mode) if set to 1 then the result set will include archived objects");
|
||||
}
|
||||
$oP->p(" * arg_xxx: (needed if the query has parameters) the value of the parameter 'xxx'");
|
||||
$oP->p(" * format: (optional, default is html) the desired output format. Can be one of 'html', 'spreadsheet', 'csv', 'xlsx' or 'xml'");
|
||||
$oP->p(" * fields: (optional, no effect on XML format) list of fields (attribute codes, or alias.attcode) separated by a coma");
|
||||
$oP->p(" * fields: (optional, no effect on XML format) list of fields (attribute codes, or alias.attcode) separated by a comma");
|
||||
$oP->p(" * fields_advanced: (optional, no effect on XML/HTML formats ; ignored is fields is specified) If set to 1, the default list of fields will include the external keys and their reconciliation keys");
|
||||
$oP->p(" * filename: (optional, no effect in CLI mode) if set then the results will be downloaded as a file");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user