예제 #1
0
파일: audit.php 프로젝트: henryavila/itop
function GetRuleResultFilter($iRuleId, $oDefinitionFilter, $oAppContext)
{
    $oRule = MetaModel::GetObject('AuditRule', $iRuleId);
    $sOql = $oRule->Get('query');
    $oRuleFilter = DBObjectSearch::FromOQL($sOql);
    FilterByContext($oRuleFilter, $oAppContext);
    // Not needed since this filter is a subset of the definition filter, but may speedup things
    if ($oRule->Get('valid_flag') == 'false') {
        // The query returns directly the invalid elements
        $oFilter = $oRuleFilter->Intersect($oDefinitionFilter);
    } else {
        // The query returns only the valid elements, all the others are invalid
        $aValidRows = $oRuleFilter->ToDataArray(array('id'));
        $aValidIds = array();
        foreach ($aValidRows as $aRow) {
            $aValidIds[] = $aRow['id'];
        }
        $oFilter = $oDefinitionFilter->DeepClone();
        if (count($aValidIds) > 0) {
            $aInDefSet = array();
            foreach ($oDefinitionFilter->ToDataArray(array('id')) as $aRow) {
                $aInDefSet[] = $aRow['id'];
            }
            $aInvalids = array_diff($aInDefSet, $aValidIds);
            if (count($aInvalids) > 0) {
                $oFilter->AddCondition('id', $aInvalids, 'IN');
            } else {
                $oFilter->AddCondition('id', 0, '=');
            }
        }
    }
    return $oFilter;
}
예제 #2
0
 public function DoActivate($aContextArgs)
 {
     // Find the related actions
     $oLinkedActions = $this->Get('action_list');
     while ($oLink = $oLinkedActions->Fetch()) {
         $iActionId = $oLink->Get('action_id');
         $oAction = MetaModel::GetObject('Action', $iActionId);
         if ($oAction->IsActive()) {
             $oAction->DoExecute($this, $aContextArgs);
         }
     }
 }
예제 #3
0
/**
 * Create a User Request ticket from the basic information retrieved from an email
 * @param string $sSenderEmail eMail address of the sender (From), used to lookup a contact in iTop
 * @param string $sSubject eMail's subject, will be turned into the title of the ticket
 * @param string $sBody Body of the email, will be fitted into the ticket's description
 * @return UserRequest The created ticket, or  null if the creation failed for some reason...
 */
function CreateTicket($sSenderEmail, $sSubject, $sBody)
{
    $oTicket = null;
    try {
        $oContactSearch = new DBObjectSearch('Contact');
        // Can be either a Person or a Team, but must be a valid Contact
        $oContactSearch->AddCondition('email', $sSenderEmail, '=');
        $oSet = new DBObjectSet($oContactSearch);
        if ($oSet->Count() == 1) {
            $oContact = $oSet->Fetch();
            $oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id'));
            $oTicket = new UserRequest();
            $oTicket->Set('title', $sSubject);
            $oTicket->Set('description', $sBody);
            $oTicket->Set('org_id', $oOrganization->GetKey());
            $oTicket->Set('caller_id', $oContact->GetKey());
            $oTicket->Set('impact', DEFAULT_IMPACT);
            $oTicket->Set('urgency', DEFAULT_URGENCY);
            $oTicket->Set('product', DEFAULT_PRODUCT);
            $oTicket->Set('service_id', DEFAULT_SERVICE_ID);
            //  Can be replaced by a search for a valid service for this 'org_id'
            $oTicket->Set('servicesubcategory_id', DEFAULT_SUBSERVICE_ID);
            // Same as above...
            $oTicket->Set('workgroup_id', DEFAULT_WORKGROUP_ID);
            // Same as above...
            // Record the change information about the object
            $oMyChange = MetaModel::NewObject("CMDBChange");
            $oMyChange->Set("date", time());
            $sUserString = $oContact->GetName() . ', submitted by email';
            $oMyChange->Set("userinfo", $sUserString);
            $iChangeId = $oMyChange->DBInsert();
            $oTicket->DBInsertTracked($oMyChange);
        } else {
            echo "No contact found in iTop having the email: {$sSenderEmail}, email message ignored.\n";
        }
    } catch (Exception $e) {
        echo "Error: exception " . $e->getMessage();
        $oTicket = null;
    }
    return $oTicket;
}
예제 #4
0
 /**
  * Handler called after the creation/update of the database schema
  * @param $oConfiguration Config The new configuration of the application
  * @param $sPreviousVersion string PRevious version number of the module (empty string in case of first install)
  * @param $sCurrentVersion string Current version number of the module
  */
 public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
 {
     // For each record having item_org_id unset,
     //    get the org_id from the container object
     //
     // Prerequisite: change null into 0 (workaround to the fact that we cannot use IS NULL in OQL)
     SetupPage::log_info("Initializing attachment/item_org_id - null to zero");
     $sTableName = MetaModel::DBGetTable('Attachment');
     $sRepair = "UPDATE `{$sTableName}` SET `item_org_id` = 0 WHERE `item_org_id` IS NULL";
     CMDBSource::Query($sRepair);
     SetupPage::log_info("Initializing attachment/item_org_id - zero to the container");
     $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_org_id = 0");
     $oSet = new DBObjectSet($oSearch);
     $iUpdated = 0;
     while ($oAttachment = $oSet->Fetch()) {
         $oContainer = MetaModel::GetObject($oAttachment->Get('item_class'), $oAttachment->Get('item_id'), false, true);
         if ($oContainer) {
             $oAttachment->SetItem($oContainer, true);
             $iUpdated++;
         }
     }
     SetupPage::log_info("Initializing attachment/item_org_id - {$iUpdated} records have been adjusted");
 }
 /**
  * Make the most relevant label, given the value of the expression
  * 	 
  * @param DBSearch oFilter The context in which this expression has been used	 	
  * @param string sValue The value returned by the query, for this expression	 	
  * @param string sDefault The default value if no relevant label could be computed	 	
  * @return The label
  */
 public function MakeValueLabel($oFilter, $sValue, $sDefault)
 {
     $sAttCode = $this->GetName();
     $sParentAlias = $this->GetParent();
     $aSelectedClasses = $oFilter->GetSelectedClasses();
     $sClass = $aSelectedClasses[$sParentAlias];
     $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
     // Set a default value for the general case
     $sRes = $oAttDef->GetAsHtml($sValue);
     // Exceptions...
     if ($oAttDef->IsExternalKey()) {
         $sObjClass = $oAttDef->GetTargetClass();
         $iObjKey = (int) $sValue;
         if ($iObjKey > 0) {
             $oObject = MetaModel::GetObject($sObjClass, $iObjKey);
             $sRes = $oObject->GetHyperlink();
         } else {
             // Undefined
             $sRes = DBObject::MakeHyperLink($sObjClass, 0);
         }
     } elseif ($oAttDef->IsExternalField()) {
         if (is_null($sValue)) {
             $sRes = Dict::S('UI:UndefinedObject');
         }
     }
     return $sRes;
 }
예제 #6
0
/**
 * Get The organization of the current user (i.e. the organization of its contact)
 * @param WebPage $oP The current page, for errors output
 * @return Organization The user's org or null in case of problem...
 */
function GetUserOrg()
{
    $oOrg = null;
    $iContactId = UserRights::GetContactId();
    $oContact = MetaModel::GetObject('Contact', $iContactId, false);
    // false => Can fail
    if (is_object($oContact)) {
        $oOrg = MetaModel::GetObject('Organization', $oContact->Get('org_id'), false);
        // false => can fail
    } else {
        throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser'));
    }
    return $oOrg;
}
 public function DoAddObjects(WebPage $oP, $oFullSetFilter, $oCurrentObj)
 {
     $aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
     foreach ($aLinkedObjectIds as $iObjectId) {
         $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId);
         if (is_object($oLinkedObj)) {
             $aRow = $this->GetFormRow($oP, $oLinkedObj, -$iObjectId, array(), $oCurrentObj);
             // Not yet created link get negative Ids
             $oP->add($this->DisplayFormRow($oP, $this->m_aTableConfig, $aRow, -$iObjectId));
         } else {
             $oP->p(Dict::Format('UI:Error:Object_Class_Id_NotFound', $this->m_sLinkedClass, $iObjectId));
         }
     }
 }
 /**
  * Find the object of the specified Class/ID.
  * @param WebPage $oP The current page
  * @return DBObject The found object, or throws an exception in case of failure
  */
 public function FindObjectFromArgs($aAllowedClasses = null)
 {
     $sClass = utils::ReadParam('class', '', true, 'class');
     $iId = utils::ReadParam('id', 0, true, 'integer');
     if (empty($sClass)) {
         throw new Exception("Missing argument 'class'");
     }
     if (!MetaModel::IsValidClass($sClass)) {
         throw new Exception("Wrong value for argument 'class': {$sClass}");
     }
     if ($iId == 0) {
         throw new Exception("Missing argument 'id'");
     }
     if (!is_null($aAllowedClasses)) {
         $bAllowed = false;
         foreach ($aAllowedClasses as $sParentClass) {
             if (MetaModel::IsParentClass($sParentClass, $sClass)) {
                 $bAllowed = true;
             }
         }
         if (!$bAllowed) {
             throw new Exception("Class '{$sClass} not allowed in this implementation'");
         }
     }
     $oObj = MetaModel::GetObject($sClass, $iId, false);
     if (!is_object($oObj)) {
         throw new Exception("Could not find the object {$sClass}/{$iId}");
     }
     return $oObj;
 }
 protected function DBCloneTracked_Internal($newKey = null)
 {
     $newKey = parent::DBClone($newKey);
     $oClone = MetaModel::GetObject(get_class($this), $newKey);
     return $newKey;
 }
예제 #10
0
 public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
 {
     $sHtml = '';
     $bTruncated = false;
     $oSet = new CMDBObjectSet($this->m_oFilter, array('date' => false));
     if ($this->iLimitStart > 0 || $this->iLimitCount > 0) {
         $oSet->SetLimit($this->iLimitCount, $this->iLimitStart);
         if ($this->iLimitCount - $this->iLimitStart < $oSet->Count()) {
             $bTruncated = true;
         }
     }
     $sHtml .= "<!-- filter: " . $this->m_oFilter->ToOQL() . "-->\n";
     switch ($this->m_sStyle) {
         case 'toggle':
             // First the latest change that the user is allowed to see
             do {
                 $oLatestChangeOp = $oSet->Fetch();
             } while (is_object($oLatestChangeOp) && $oLatestChangeOp->GetDescription() == '');
             if (is_object($oLatestChangeOp)) {
                 // There is one change in the list... only when the object has been created !
                 $sDate = $oLatestChangeOp->GetAsHTML('date');
                 $oChange = MetaModel::GetObject('CMDBChange', $oLatestChangeOp->Get('change'));
                 $sUserInfo = $oChange->GetAsHTML('userinfo');
                 $sHtml .= $oPage->GetStartCollapsibleSection(Dict::Format('UI:History:LastModified_On_By', $sDate, $sUserInfo));
                 $sHtml .= $this->GetHistoryTable($oPage, $oSet);
                 $sHtml .= $oPage->GetEndCollapsibleSection();
             }
             break;
         case 'table':
         default:
             if ($bTruncated) {
                 $sFilter = $this->m_oFilter->serialize();
                 $sHtml .= '<div id="history_container"><p>';
                 $sHtml .= Dict::Format('UI:TruncatedResults', $this->iLimitCount, $oSet->Count());
                 $sHtml .= ' ';
                 $sHtml .= '<a href="#" onclick="DisplayHistory(\'#history_container\', \'' . $sFilter . '\', 0, 0); return false;">' . Dict::S('UI:DisplayAll') . '</a>';
                 $sHtml .= $this->GetHistoryTable($oPage, $oSet);
                 $sHtml .= '</p></div>';
                 $oPage->add_ready_script("\$('#{$sId} table.listResults tr:last td').addClass('truncated');");
             } else {
                 $sHtml .= $this->GetHistoryTable($oPage, $oSet);
             }
     }
     return $sHtml;
 }
예제 #11
0
 /**
  * Get the display name of the selected object, to fill back the autocomplete
  */
 public function GetObjectName($iObjId)
 {
     $aModifierProps = array();
     $aModifierProps['UserRightsGetSelectFilter']['bSearchMode'] = $this->bSearchMode;
     $oObj = MetaModel::GetObject($this->sTargetClass, $iObjId, false, false, $aModifierProps);
     if ($oObj) {
         return $oObj->GetName();
     } else {
         return '';
     }
 }
 /**
  * Give a default value for item_org_id (if relevant...)
  * @return void
  */
 public function SetDefaultOrgId()
 {
     // First check that the organization CAN be fetched from the target class
     //
     $sClass = $this->Get('item_class');
     $aCallSpec = array($sClass, 'MapContextParam');
     if (is_callable($aCallSpec)) {
         $sAttCode = call_user_func($aCallSpec, 'org_id');
         // Returns null when there is no mapping for this parameter
         if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
             // Second: check that the organization CAN be fetched from the current user
             //
             if (MetaModel::IsValidClass('Person')) {
                 $aCallSpec = array($sClass, 'MapContextParam');
                 if (is_callable($aCallSpec)) {
                     $sAttCode = call_user_func($aCallSpec, 'org_id');
                     // Returns null when there is no mapping for this parameter
                     if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                         // OK - try it
                         //
                         $oCurrentPerson = MetaModel::GetObject('Person', UserRights::GetContactId(), false);
                         if ($oCurrentPerson) {
                             $this->Set('item_org_id', $oCurrentPerson->Get($sAttCode));
                         }
                     }
                 }
             }
         }
     }
 }
    /**
     * Display the graph inside the given page, with the "filter" drawer above it
     * @param WebPage $oP
     * @param hash $aResults
     * @param string $sRelation
     * @param ApplicationContext $oAppContext
     * @param array $aExcludedObjects
     */
    function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects = array(), $sObjClass = null, $iObjKey = null, $sContextKey, $aContextParams = array())
    {
        $aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams);
        $aExcludedByClass = array();
        foreach ($aExcludedObjects as $oObj) {
            if (!array_key_exists(get_class($oObj), $aExcludedByClass)) {
                $aExcludedByClass[get_class($oObj)] = array();
            }
            $aExcludedByClass[get_class($oObj)][] = $oObj->GetKey();
        }
        $oP->add("<div class=\"not-printable\">\n");
        $oP->add("<div id=\"ds_flash\" class=\"SearchDrawer\" style=\"display:none;\">\n");
        if (!$oP->IsPrintableVersion()) {
            $oP->add_ready_script(<<<EOF
\t\$( "#tabbedContent_0" ).tabs({ heightStyle: "fill" });
EOF
);
        }
        $oP->add_ready_script(<<<EOF
\t\$("#dh_flash").click( function() {
\t\t\$("#ds_flash").slideToggle('normal', function() { \$("#ds_flash").parent().resize(); \$("#dh_flash").trigger('toggle_complete'); } );
\t\t\$("#dh_flash").toggleClass('open');
\t});
    \$('#ReloadMovieBtn').button().button('disable');
EOF
);
        $aSortedElements = array();
        foreach ($aResults as $sClassIdx => $aObjects) {
            foreach ($aObjects as $oCurrObj) {
                $sSubClass = get_class($oCurrObj);
                $aSortedElements[$sSubClass] = MetaModel::GetName($sSubClass);
            }
        }
        asort($aSortedElements);
        $idx = 0;
        foreach ($aSortedElements as $sSubClass => $sClassName) {
            $oP->add("<span style=\"padding-right:2em; white-space:nowrap;\"><input type=\"checkbox\" id=\"exclude_{$idx}\" name=\"excluded[]\" value=\"{$sSubClass}\" checked onChange=\"\$('#ReloadMovieBtn').button('enable')\"><label for=\"exclude_{$idx}\">&nbsp;" . MetaModel::GetClassIcon($sSubClass) . "&nbsp;{$sClassName}</label></span> ");
            $idx++;
        }
        $oP->add("<p style=\"text-align:right\"><button type=\"button\" id=\"ReloadMovieBtn\" onClick=\"DoReload()\">" . Dict::S('UI:Button:Refresh') . "</button></p>");
        $oP->add("</div>\n");
        $oP->add("<div class=\"HRDrawer\"></div>\n");
        $oP->add("<div id=\"dh_flash\" class=\"DrawerHandle\">" . Dict::S('UI:ElementsDisplayed') . "</div>\n");
        $oP->add("</div>\n");
        // class="not-printable"
        $aAdditionalContexts = array();
        foreach ($aContextDefs as $sKey => $aDefinition) {
            $aAdditionalContexts[] = array('key' => $sKey, 'label' => Dict::S($aDefinition['dict']), 'oql' => $aDefinition['oql'], 'default' => array_key_exists('default', $aDefinition) && $aDefinition['default'] == 'yes');
        }
        $sDirection = utils::ReadParam('d', 'horizontal');
        $iGroupingThreshold = utils::ReadParam('g', 5);
        $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/fraphael.js');
        $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot() . 'css/jquery.contextMenu.css');
        $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/jquery.contextMenu.js');
        $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/simple_graph.js');
        try {
            $this->InitFromGraphviz();
            $sExportAsPdfURL = '';
            $sExportAsPdfURL = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=relation_pdf&relation=' . $sRelation . '&direction=' . ($this->bDirectionDown ? 'down' : 'up');
            $oAppcontext = new ApplicationContext();
            $sContext = $oAppContext->GetForLink();
            $sDrillDownURL = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=details&class=%1$s&id=%2$s&' . $sContext;
            $sExportAsDocumentURL = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=relation_attachment&relation=' . $sRelation . '&direction=' . ($this->bDirectionDown ? 'down' : 'up');
            $sLoadFromURL = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=relation_json&relation=' . $sRelation . '&direction=' . ($this->bDirectionDown ? 'down' : 'up');
            $sAttachmentExportTitle = '';
            if ($sObjClass != null && $iObjKey != null) {
                $oTargetObj = MetaModel::GetObject($sObjClass, $iObjKey, false);
                if ($oTargetObj) {
                    $sAttachmentExportTitle = Dict::Format('UI:Relation:AttachmentExportOptions_Name', $oTargetObj->GetName());
                }
            }
            $sId = 'graph';
            $sStyle = '';
            if ($oP->IsPrintableVersion()) {
                // Optimize for printing on A4/Letter vertically
                $sStyle = 'margin-left:auto; margin-right:auto;';
                $oP->add_ready_script("\$('.simple-graph').width(18/2.54*96).resizable({ stop: function() { \$(window).trigger('resized'); }});");
                // Default width about 18 cm, since most browsers assume 96 dpi
            }
            $oP->add('<div id="' . $sId . '" class="simple-graph" style="' . $sStyle . '"></div>');
            $aParams = array('source_url' => $sLoadFromURL, 'sources' => $this->bDirectionDown ? $this->aSourceObjects : $this->aSinkObjects, 'excluded' => $aExcludedByClass, 'grouping_threshold' => $iGroupingThreshold, 'export_as_pdf' => array('url' => $sExportAsPdfURL, 'label' => Dict::S('UI:Relation:ExportAsPDF')), 'export_as_attachment' => array('url' => $sExportAsDocumentURL, 'label' => Dict::S('UI:Relation:ExportAsAttachment'), 'obj_class' => $sObjClass, 'obj_key' => $iObjKey), 'drill_down' => array('url' => $sDrillDownURL, 'label' => Dict::S('UI:Relation:DrillDown')), 'labels' => array('export_pdf_title' => Dict::S('UI:Relation:PDFExportOptions'), 'export_as_attachment_title' => $sAttachmentExportTitle, 'export' => Dict::S('UI:Button:Export'), 'cancel' => Dict::S('UI:Button:Cancel'), 'title' => Dict::S('UI:RelationOption:Title'), 'untitled' => Dict::S('UI:RelationOption:Untitled'), 'include_list' => Dict::S('UI:RelationOption:IncludeList'), 'comments' => Dict::S('UI:RelationOption:Comments'), 'grouping_threshold' => Dict::S('UI:RelationOption:GroupingThreshold'), 'refresh' => Dict::S('UI:Button:Refresh'), 'check_all' => Dict::S('UI:SearchValue:CheckAll'), 'uncheck_all' => Dict::S('UI:SearchValue:UncheckAll'), 'none_selected' => Dict::S('UI:Relation:NoneSelected'), 'nb_selected' => Dict::S('UI:SearchValue:NbSelected'), 'additional_context_info' => Dict::S('UI:Relation:AdditionalContextInfo'), 'zoom' => Dict::S('UI:Relation:Zoom'), 'loading' => Dict::S('UI:Loading')), 'page_format' => array('label' => Dict::S('UI:Relation:PDFExportPageFormat'), 'values' => array('A3' => Dict::S('UI:PageFormat_A3'), 'A4' => Dict::S('UI:PageFormat_A4'), 'Letter' => Dict::S('UI:PageFormat_Letter'))), 'page_orientation' => array('label' => Dict::S('UI:Relation:PDFExportPageOrientation'), 'values' => array('P' => Dict::S('UI:PageOrientation_Portrait'), 'L' => Dict::S('UI:PageOrientation_Landscape'))), 'additional_contexts' => $aAdditionalContexts, 'context_key' => $sContextKey);
            if (!extension_loaded('gd')) {
                // PDF export requires GD
                unset($aParams['export_as_pdf']);
            }
            if (!extension_loaded('gd') || is_null($sObjClass) || is_null($iObjKey)) {
                // Export as Attachment requires GD (for building the PDF) AND a valid objclass/objkey couple
                unset($aParams['export_as_attachment']);
            }
            $oP->add_ready_script("\$('#{$sId}').simple_graph(" . json_encode($aParams) . ");");
        } catch (Exception $e) {
            $oP->add('<div>' . $e->getMessage() . '</div>');
        }
        $oP->add_script(<<<EOF
\t\t
\tfunction DoReload()
\t{
\t\t\$('#ReloadMovieBtn').button('disable');
\t\ttry
\t\t{
\t\t\tvar aExcluded = [];
\t\t\t\$('input[name^=excluded]').each( function() {
\t\t\t\tif (!\$(this).prop('checked'))
\t\t\t\t{
\t\t\t\t\taExcluded.push(\$(this).val());
\t\t\t\t}
\t\t\t} );
\t\t\t\$('#graph').simple_graph('option', {excluded_classes: aExcluded});
\t\t\t\$('#graph').simple_graph('reload');
\t\t}
\t\tcatch(err)
\t\t{
\t\t\talert(err);
\t\t}
\t}
EOF
);
    }
예제 #14
0
    /**
     * Process the CSV data, for real or as a simulation
     * @param WebPage $oPage The page used to display the wizard
     * @param bool $bSimulate Whether or not to simulate the data load
     * @return array The CSV lines in error that were rejected from the load (with the header line - if any) or null
     */
    function ProcessCSVData(WebPage $oPage, $bSimulate = true)
    {
        $aResult = array();
        $sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
        $sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data');
        $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
        $sTextQualifier = utils::ReadParam('text_qualifier', '"', false, 'raw_data');
        $bHeaderLine = utils::ReadParam('header_line', '0') == 1;
        $iSkippedLines = 0;
        if (utils::ReadParam('box_skiplines', '0') == 1) {
            $iSkippedLines = utils::ReadParam('nb_skipped_lines', '0');
        }
        $sClassName = utils::ReadParam('class_name', '', false, 'class');
        $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
        $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
        $iCurrentStep = $bSimulate ? 4 : 5;
        $bAdvanced = utils::ReadParam('advanced', 0);
        $sEncoding = utils::ReadParam('encoding', 'UTF-8');
        $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
        if (!empty($sSynchroScope)) {
            $oSearch = DBObjectSearch::FromOQL($sSynchroScope);
            $sClassName = $oSearch->GetClass();
            // If a synchronization scope is set, then the class is fixed !
            $oSet = new DBObjectSet($oSearch);
            $iCount = $oSet->Count();
            DisplaySynchroBanner($oPage, $sClassName, $iCount);
            $sClassesSelect = "<select id=\"select_class_name\" name=\"class_name\"><option value=\"{$sClassName}\" selected>" . MetaModel::GetName($sClassName) . "</option>";
            $aSynchroUpdate = utils::ReadParam('synchro_update', array());
        } else {
            $sSynchroScope = '';
            $aSynchroUpdate = null;
        }
        // Parse the data set
        $oCSVParser = new CSVParser($sCSVData, $sSeparator, $sTextQualifier);
        $aData = $oCSVParser->ToArray($iSkippedLines);
        $iRealSkippedLines = $iSkippedLines;
        if ($bHeaderLine) {
            $aResult[] = $sTextQualifier . implode($sTextQualifier . $sSeparator . $sTextQualifier, array_shift($aData)) . $sTextQualifier;
            // Remove the first line and store it in case of error
            $iRealSkippedLines++;
        }
        // Format for the line numbers
        $sMaxLen = strlen('' . count($aData)) < 3 ? 3 : strlen('' . count($aData));
        // Pad line numbers to the appropriate number of chars, but at least 3
        // Compute the list of search/reconciliation criteria
        $aSearchKeys = array();
        foreach ($aSearchFields as $index => $sDummy) {
            $sSearchField = $aFieldsMapping[$index];
            $aMatches = array();
            if (preg_match('/(.+)->(.+)/', $sSearchField, $aMatches) > 0) {
                $sSearchField = $aMatches[1];
                $aSearchKeys[$aMatches[1]] = '';
            } else {
                $aSearchKeys[$sSearchField] = '';
            }
            if (!MetaModel::IsValidFilterCode($sClassName, $sSearchField)) {
                // Remove invalid or unmapped search fields
                $aSearchFields[$index] = null;
                unset($aSearchKeys[$sSearchField]);
            }
        }
        // Compute the list of fields and external keys to process
        $aExtKeys = array();
        $aAttributes = array();
        $aExternalKeysByColumn = array();
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            $iIndex = $iNumber - 1;
            if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') {
                if (preg_match('/(.+)->(.+)/', $sAttCode, $aMatches) > 0) {
                    $sAttribute = $aMatches[1];
                    $sField = $aMatches[2];
                    $aExtKeys[$sAttribute][$sField] = $iIndex;
                    $aExternalKeysByColumn[$iIndex] = $sAttribute;
                } else {
                    if ($sAttCode == 'id') {
                        $aAttributes['id'] = $iIndex;
                    } else {
                        $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
                        if ($oAttDef->IsExternalKey()) {
                            $aExtKeys[$sAttCode]['id'] = $iIndex;
                            $aExternalKeysByColumn[$iIndex] = $sAttCode;
                        } else {
                            $aAttributes[$sAttCode] = $iIndex;
                        }
                    }
                }
            }
        }
        $oMyChange = null;
        if (!$bSimulate) {
            // We're doing it for real, let's create a change
            $sUserString = CMDBChange::GetCurrentUserName() . ' (CSV)';
            CMDBObject::SetTrackInfo($sUserString);
            CMDBObject::SetTrackOrigin('csv-interactive');
            $oMyChange = CMDBObject::GetCurrentChange();
        }
        $oBulk = new BulkChange($sClassName, $aData, $aAttributes, $aExtKeys, array_keys($aSearchKeys), empty($sSynchroScope) ? null : $sSynchroScope, $aSynchroUpdate, null, true);
        $oBulk->SetReportHtml();
        $oPage->add('<input type="hidden" name="csvdata_truncated" id="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>');
        $aRes = $oBulk->Process($oMyChange);
        $sHtml = '<table id="bulk_preview" style="border-collapse: collapse;">';
        $sHtml .= '<tr><th style="padding:2px;border-right: 2px #fff solid;">Line</th>';
        $sHtml .= '<th style="padding:2px;border-right: 2px #fff solid;">Status</th>';
        $sHtml .= '<th style="padding:2px;border-right: 2px #fff solid;">Object</th>';
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') {
                $sHtml .= "<th style=\"padding:2px;border-right: 2px #fff solid;\">" . MetaModel::GetLabel($sClassName, $sAttCode) . "</th>";
            }
        }
        $sHtml .= '<th>Message</th>';
        $sHtml .= '</tr>';
        $iErrors = 0;
        $iCreated = 0;
        $iModified = 0;
        $iUnchanged = 0;
        foreach ($aRes as $iLine => $aResRow) {
            $oStatus = $aResRow['__STATUS__'];
            $sUrl = '';
            $sMessage = '';
            $sCSSRowClass = '';
            $sCSSMessageClass = 'cell_ok';
            switch (get_class($oStatus)) {
                case 'RowStatus_NoChange':
                    $iUnchanged++;
                    $sFinalClass = $aResRow['finalclass'];
                    $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                    $sUrl = $oObj->GetHyperlink();
                    $sStatus = '<img src="../images/unchanged.png" title="' . Dict::S('UI:CSVReport-Icon-Unchanged') . '">';
                    $sCSSRowClass = 'row_unchanged';
                    break;
                case 'RowStatus_Modify':
                    $iModified++;
                    $sFinalClass = $aResRow['finalclass'];
                    $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                    $sUrl = $oObj->GetHyperlink();
                    $sStatus = '<img src="../images/modified.png" title="' . Dict::S('UI:CSVReport-Icon-Modified') . '">';
                    $sCSSRowClass = 'row_modified';
                    break;
                case 'RowStatus_Disappeared':
                    $iModified++;
                    $sFinalClass = $aResRow['finalclass'];
                    $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                    $sUrl = $oObj->GetHyperlink();
                    $sStatus = '<img src="../images/delete.png" title="' . Dict::S('UI:CSVReport-Icon-Missing') . '">';
                    $sCSSRowClass = 'row_modified';
                    if ($bSimulate) {
                        $sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate');
                    } else {
                        $sMessage = Dict::S('UI:CSVReport-Object-MissingUpdated');
                    }
                    break;
                case 'RowStatus_NewObj':
                    $iCreated++;
                    $sFinalClass = $aResRow['finalclass'];
                    $sStatus = '<img src="../images/added.png" title="' . Dict::S('UI:CSVReport-Icon-Created') . '">';
                    $sCSSRowClass = 'row_added';
                    if ($bSimulate) {
                        $sMessage = Dict::S('UI:CSVReport-Object-ToCreate');
                    } else {
                        $sFinalClass = $aResRow['finalclass'];
                        $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                        $sUrl = $oObj->GetHyperlink();
                        $sMessage = Dict::S('UI:CSVReport-Object-Created');
                    }
                    break;
                case 'RowStatus_Issue':
                    $iErrors++;
                    $sMessage .= $oPage->GetP($oStatus->GetDescription());
                    $sStatus = '<img src="../images/error.png" title="' . Dict::S('UI:CSVReport-Icon-Error') . '">';
                    //translate
                    $sCSSMessageClass = 'cell_error';
                    $sCSSRowClass = 'row_error';
                    if (array_key_exists($iLine, $aData)) {
                        $aRow = $aData[$iLine];
                        $aResult[] = $sTextQualifier . implode($sTextQualifier . $sSeparator . $sTextQualifier, $aRow) . $sTextQualifier;
                        // Remove the first line and store it in case of error
                    }
                    break;
            }
            $sHtml .= '<tr class="' . $sCSSRowClass . '">';
            $sHtml .= "<td style=\"background-color:#f1f1f1;border-right:2px #fff solid;\">" . sprintf("%0{$sMaxLen}d", 1 + $iLine + $iRealSkippedLines) . "</td>";
            $sHtml .= "<td style=\"text-align:center;background-color:#f1f1f1;border-right:2px #fff solid;\">{$sStatus}</td>";
            $sHtml .= "<td style=\"text-align:center;background-color:#f1f1f1;\">{$sUrl}</td>";
            foreach ($aFieldsMapping as $iNumber => $sAttCode) {
                if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') {
                    $oCellStatus = $aResRow[$iNumber - 1];
                    $sCellMessage = '';
                    if (isset($aExternalKeysByColumn[$iNumber - 1])) {
                        $sExtKeyName = $aExternalKeysByColumn[$iNumber - 1];
                        $oExtKeyCellStatus = $aResRow[$sExtKeyName];
                        switch (get_class($oExtKeyCellStatus)) {
                            case 'CellStatus_Issue':
                            case 'CellStatus_SearchIssue':
                            case 'CellStatus_NullIssue':
                                $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription());
                                break;
                            case 'CellStatus_Ambiguous':
                                $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription());
                                break;
                            default:
                                // Do nothing
                        }
                    }
                    $sHtmlValue = $oCellStatus->GetDisplayableValue();
                    switch (get_class($oCellStatus)) {
                        case 'CellStatus_Issue':
                            $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription());
                            $sHtml .= '<td class="cell_error" style="border-right:1px #eee solid;">' . Dict::Format('UI:CSVReport-Object-Error', $sHtmlValue) . $sCellMessage . '</td>';
                            break;
                        case 'CellStatus_SearchIssue':
                            $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription());
                            $sHtml .= '<td class="cell_error">ERROR: ' . $sHtmlValue . $sCellMessage . '</td>';
                            break;
                        case 'CellStatus_Ambiguous':
                            $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription());
                            $sHtml .= '<td class="cell_error" style="border-right:1px #eee solid;">' . Dict::Format('UI:CSVReport-Object-Ambiguous', $sHtmlValue) . $sCellMessage . '</td>';
                            break;
                        case 'CellStatus_Modify':
                            $sHtml .= '<td class="cell_modified" style="border-right:1px #eee solid;"><b>' . $sHtmlValue . '</b></td>';
                            break;
                        default:
                            $sHtml .= '<td class="cell_ok" style="border-right:1px #eee solid;">' . $sHtmlValue . $sCellMessage . '</td>';
                    }
                }
            }
            $sHtml .= "<td class=\"{$sCSSMessageClass}\" style=\"background-color:#f1f1f1;\">{$sMessage}</td>";
            $sHtml .= '</tr>';
        }
        $iUnchanged = count($aRes) - $iErrors - $iModified - $iCreated;
        $sHtml .= '</table>';
        $oPage->add('<div class="wizContainer" style="width:auto;display:inline-block;">');
        $oPage->add('<form enctype="multipart/form-data" id="wizForm" method="post">');
        $oPage->add('<input type="hidden" name="step" value="' . ($iCurrentStep + 1) . '"/>');
        $oPage->add('<input type="hidden" name="separator" value="' . htmlentities($sSeparator, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="text_qualifier" value="' . htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="header_line" value="' . $bHeaderLine . '"/>');
        $oPage->add('<input type="hidden" name="nb_skipped_lines" value="' . utils::ReadParam('nb_skipped_lines', '0') . '"/>');
        $oPage->add('<input type="hidden" name="box_skiplines" value="' . utils::ReadParam('box_skiplines', '0') . '"/>');
        $oPage->add('<input type="hidden" name="csvdata" value="' . htmlentities($sCSVData, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="class_name" value="' . $sClassName . '"/>');
        $oPage->add('<input type="hidden" name="advanced" value="' . $bAdvanced . '"/>');
        $oPage->add('<input type="hidden" name="encoding" value="' . $sEncoding . '"/>');
        $oPage->add('<input type="hidden" name="synchro_scope" value="' . $sSynchroScope . '"/>');
        if (!empty($sSynchroScope)) {
            foreach ($aSynchroUpdate as $sKey => $value) {
                $oPage->add('<input type="hidden" name="synchro_update[' . $sKey . ']" value="' . $value . '"/>');
            }
        }
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            $oPage->add('<input type="hidden" name="field[' . $iNumber . ']" value="' . $sAttCode . '"/>');
        }
        foreach ($aSearchFields as $index => $sDummy) {
            $oPage->add('<input type="hidden" name="search_field[' . $index . ']" value="1"/>');
        }
        $aDisplayFilters = array();
        if ($bSimulate) {
            $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsWillStayUnchanged');
            $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWillBeModified');
            $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWillBeAdded');
            $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsWillHaveErrors');
        } else {
            $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsRemainedUnchanged');
            $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWereModified');
            $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWereAdded');
            $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsHadErrors');
        }
        $oPage->add('<p><input type="checkbox" checked id="show_unchanged" onClick="ToggleRows(\'row_unchanged\')"/>&nbsp;<img src="../images/unchanged.png">&nbsp;' . sprintf($aDisplayFilters['unchanged'], $iUnchanged) . '&nbsp&nbsp;');
        $oPage->add('<input type="checkbox" checked id="show_modified" onClick="ToggleRows(\'row_modified\')"/>&nbsp;<img src="../images/modified.png">&nbsp;' . sprintf($aDisplayFilters['modified'], $iModified) . '&nbsp&nbsp;');
        $oPage->add('<input type="checkbox" checked id="show_created" onClick="ToggleRows(\'row_added\')"/>&nbsp;<img src="../images/added.png">&nbsp;' . sprintf($aDisplayFilters['added'], $iCreated) . '&nbsp&nbsp;');
        $oPage->add('<input type="checkbox" checked id="show_errors" onClick="ToggleRows(\'row_error\')"/>&nbsp;<img src="../images/error.png">&nbsp;' . sprintf($aDisplayFilters['errors'], $iErrors) . '</p>');
        $oPage->add('<div class="white" style="display:inline-block">');
        $oPage->add($sHtml);
        $oPage->add('</div> <!-- end of preview -->');
        $oPage->add('<p>');
        if ($bSimulate) {
            $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Restart') . '" onClick="CSVRestart()"/>&nbsp;&nbsp;');
        }
        $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Back') . '" onClick="CSVGoBack()"/>&nbsp;&nbsp;');
        $bShouldConfirm = false;
        if ($bSimulate) {
            // if there are *too many* changes, we should ask the user for a confirmation
            if (count($aRes) >= MetaModel::GetConfig()->Get('csv_import_min_object_confirmation')) {
                $fErrorsPercentage = 100.0 * $iErrors / count($aRes);
                if ($fErrorsPercentage >= MetaModel::GetConfig()->Get('csv_import_errors_percentage')) {
                    $sMessage = Dict::Format('UI:CSVReport-Stats-Errors', $fErrorsPercentage);
                    $bShouldConfirm = true;
                }
                $fCreatedPercentage = 100.0 * $iCreated / count($aRes);
                if ($fCreatedPercentage >= MetaModel::GetConfig()->Get('csv_import_creations_percentage')) {
                    $sMessage = Dict::Format('UI:CSVReport-Stats-Created', $fCreatedPercentage);
                    $bShouldConfirm = true;
                }
                $fModifiedPercentage = 100.0 * $iModified / count($aRes);
                if ($fModifiedPercentage >= MetaModel::GetConfig()->Get('csv_import_modifications_percentage')) {
                    $sMessage = Dict::Format('UI:CSVReport-Stats-Modified', $fModifiedPercentage);
                    $bShouldConfirm = true;
                }
            }
            $iCount = count($aRes);
            //$oPage->add('<input type="submit" value="'.Dict::S('UI:Button:DoImport').'" onClick="$(\'#wizForm\').block();"/></p>');
            $sConfirm = $bShouldConfirm ? 'true' : 'false';
            $oPage->add('<input type="button" value="' . Dict::S('UI:Button:DoImport') . "\" onClick=\"return DoSubmit({$sConfirm});\"/></p>");
        } else {
            $oPage->add('<input type="submit" value="' . Dict::S('UI:Button:Done') . '"/></p>');
        }
        $oPage->add('</form>');
        $oPage->add('</div> <!-- end of wizForm -->');
        if ($bShouldConfirm) {
            $sYesButton = Dict::S('UI:Button:Ok');
            $sNoButton = Dict::S('UI:Button:Cancel');
            $oPage->add('<div id="dlg_confirmation" title="' . htmlentities(Dict::S('UI:CSVImportConfirmTitle'), ENT_QUOTES, 'UTF-8') . '">');
            $oPage->add('<p style="text-align:center"><b>' . $sMessage . '</b></p>');
            $oPage->add('<p style="text-align:center">' . htmlentities(Dict::S('UI:CSVImportConfirmMessage'), ENT_QUOTES, 'UTF-8') . '</p>');
            $oPage->add('<div id="confirmation_chart"></div>');
            $oPage->add('</div> <!-- end of dlg_confirmation -->');
            $oPage->add_ready_script(<<<EOF
\t\$('#dlg_confirmation').dialog( 
\t\t{
\t\t\theight: 'auto',
\t\t\twidth: 500,
\t\t\tmodal:true, 
\t\t\tautoOpen: false, 
\t\t\tbuttons:
\t\t\t{
\t\t\t\t'{$sYesButton}': RunImport,
\t\t\t\t'{$sNoButton}': CancelImport 
\t\t\t} 
\t\t});
\t\tswfobject.embedSWF(\t"../images/open-flash-chart.swf", 
\t\t\t\t\t\t\t"confirmation_chart", 
\t\t\t\t\t\t\t"100%", "300","9.0.0",
\t\t\t\t\t\t\t"expressInstall.swf",
\t\t\t\t\t\t\t{}, 
\t\t\t\t\t\t\t{'wmode': 'transparent'}
\t\t\t\t\t\t);
EOF
);
        }
        $sErrors = addslashes(Dict::Format('UI:CSVImportError_items', $iErrors));
        $sCreated = addslashes(Dict::Format('UI:CSVImportCreated_items', $iCreated));
        $sModified = addslashes(Dict::Format('UI:CSVImportModified_items', $iModified));
        $sUnchanged = addslashes(Dict::Format('UI:CSVImportUnchanged_items', $iUnchanged));
        $oPage->add_script(<<<EOF
function CSVGoBack()
{
\t\$('input[name=step]').val({$iCurrentStep}-1);
\t\$('#wizForm').submit();
\t
}

function CSVRestart()
{
\t\$('input[name=step]').val(1);
\t\$('#wizForm').submit();
\t
}

function ToggleRows(sCSSClass)
{
\t\$('.'+sCSSClass).toggle();
}

function DoSubmit(bConfirm)
{
\tif (bConfirm) //Ask for a confirmation
\t{
\t\t\$('#dlg_confirmation').dialog('open');
\t}
\telse
\t{
\t\t// Submit the form
\t\t\$('#wizForm').block();
\t\t\$('#wizForm').submit();
\t}
\treturn false;
}

function CancelImport()
{
\t\$('#dlg_confirmation').dialog('close');
}

function RunImport()
{
\t\$('#dlg_confirmation').dialog('close');
\t// Submit the form
\t\$('#wizForm').block();
\t\$('#wizForm').submit();
}

function open_flash_chart_data()
{
\tvar iErrors = {$iErrors};
\tvar iModified = {$iModified};
\tvar iCreated = {$iCreated};
\tvar iUnchanged = {$iUnchanged};
\tvar fAlpha = 0.9;
\t
\tvar oResult = {
\t\t"elements": [
\t\t\t{
\t\t\t\t"type": "pie",
\t\t\t\t"tip": "#label# (#percent#)",
\t\t\t\t"gradient-fill": true,
\t\t\t\t"font-size": 14,
\t\t\t\t"colours":[],
\t\t\t\t"values": [],
\t\t\t\t"animate":[
\t\t\t        {
\t\t\t          "type": "fade"
\t\t\t        }
\t\t        ]
\t\t\t}
\t\t],
\t\t"x_axis": null,
\t\t"font-size": 14,
\t\t"bg_colour": "#EEEEEE"
\t};

\tif (iErrors > 0)
\t{
\t\tvar oErrors =
\t\t{
\t\t\t"value":  iErrors,
\t\t\t"label": "{$sErrors}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#CC3333",
\t\t};
\t\toResult.elements[0].values.push(oErrors);
\t\toResult.elements[0].colours.push('#FF6666');
\t}
\tif (iModified > 0)
\t{
\t\tvar oModified =
\t\t{
\t\t\t"value":  iModified,
\t\t\t"label": "{$sModified}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#3333CC",
\t\t};
\t\toResult.elements[0].values.push(oModified);
\t\toResult.elements[0].colours.push('#6666FF');
\t}
\tif (iCreated > 0)
\t{
\t\tvar oCreated =
\t\t{
\t\t\t"value":  iCreated,
\t\t\t"label": "{$sCreated}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#33CC33",
\t\t\t
\t\t};
\t\toResult.elements[0].values.push(oCreated);
\t\toResult.elements[0].colours.push('#66FF66');
\t}
\tif (iUnchanged > 0)
\t{
\t\tvar oUnchanged =
\t\t{
\t\t\t"value":  iUnchanged,
\t\t\t"label": "{$sUnchanged}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#333333",
\t\t\t
\t\t};
\t\toResult.elements[0].values.push(oUnchanged);
\t\toResult.elements[0].colours.push('#666666');
\t}

\treturn JSON.stringify(oResult);
}
EOF
);
        if ($iErrors > 0) {
            return $aResult;
        } else {
            return null;
        }
    }
예제 #15
0
 /**
  * Check the user's password against the LDAP server
  * Algorithm:
  * 1) Connect to the LDAP server, using a predefined account (or anonymously)
  * 2) Search for the specified user, based on a specific search query/pattern
  * 3) If exactly one user is found, continue, otherwise return false (wrong user or wrong query configured)
  * 3) Bind again to LDAP using the DN of the found user and the password
  * 4) If the bind is successful return true, otherwise return false (wrong password)
  * @param string $sPassword The user's password to validate against the LDAP server
  * @return boolean True if the password is Ok, false otherwise
  */
 public function CheckCredentials($sPassword)
 {
     $sLDAPHost = MetaModel::GetModuleSetting('authent-ldap', 'host', 'localhost');
     $iLDAPPort = MetaModel::GetModuleSetting('authent-ldap', 'port', 389);
     $sDefaultLDAPUser = MetaModel::GetModuleSetting('authent-ldap', 'default_user', '');
     $sDefaultLDAPPwd = MetaModel::GetModuleSetting('authent-ldap', 'default_pwd', '');
     $hDS = @ldap_connect($sLDAPHost, $iLDAPPort);
     if ($hDS === false) {
         $this->LogMessage("ldap_authentication: can not connect to the LDAP server '{$sLDAPHost}' (port: {$iLDAPPort}). Check the configuration file config-itop.php.");
         return false;
     }
     $aOptions = MetaModel::GetModuleSetting('authent-ldap', 'options', array());
     foreach ($aOptions as $name => $value) {
         ldap_set_option($hDS, $name, $value);
     }
     if ($bind = @ldap_bind($hDS, $sDefaultLDAPUser, $sDefaultLDAPPwd)) {
         // Search for the person, using the specified query expression
         $sLDAPUserQuery = MetaModel::GetModuleSetting('authent-ldap', 'user_query', '');
         $sBaseDN = MetaModel::GetModuleSetting('authent-ldap', 'base_dn', '');
         $sLogin = $this->Get('login');
         $iContactId = $this->Get('contactid');
         $sFirstName = '';
         $sLastName = '';
         $sEMail = '';
         if ($iContactId > 0) {
             $oPerson = MetaModel::GetObject('Person', $iContactId);
             if (is_object($oPerson)) {
                 $sFirstName = $oPerson->Get('first_name');
                 $sLastName = $oPerson->Get('name');
                 $sEMail = $oPerson->Get('email');
             }
         }
         // %1$s => login
         // %2$s => first name
         // %3$s => last name
         // %4$s => email
         $sQuery = sprintf($sLDAPUserQuery, $sLogin, $sFirstName, $sLastName, $sEMail);
         $hSearchResult = @ldap_search($hDS, $sBaseDN, $sQuery);
         $iCountEntries = $hSearchResult !== false ? @ldap_count_entries($hDS, $hSearchResult) : 0;
         switch ($iCountEntries) {
             case 1:
                 // Exactly one entry found, let's check the password by trying to bind with this user
                 $aEntry = ldap_get_entries($hDS, $hSearchResult);
                 $sUserDN = $aEntry[0]['dn'];
                 $bUserBind = @ldap_bind($hDS, $sUserDN, $sPassword);
                 if ($bUserBind !== false && !empty($sPassword)) {
                     ldap_unbind($hDS);
                     return true;
                     // Password Ok
                 }
                 $this->LogMessage("ldap_authentication: wrong password for user: '******'.");
                 return false;
                 // Wrong password
                 break;
             case 0:
                 // User not found...
                 $this->LogMessage("ldap_authentication: no entry found with the query '{$sQuery}', base_dn = '{$sBaseDN}'. User not found in LDAP.");
                 break;
             default:
                 // More than one entry... maybe the query is not specific enough...
                 $this->LogMessage("ldap_authentication: several (" . ldap_count_entries($hDS, $hSearchResult) . ") entries match the query '{$sQuery}', base_dn = '{$sBaseDN}', check that the query defined in config-itop.php is specific enough.");
         }
         return false;
     } else {
         // Trace: invalid default user for LDAP initial binding
         $this->LogMessage("ldap_authentication: can not bind to the LDAP server '{$sLDAPHost}' (port: {$iLDAPPort}), user='******', pwd='{$sDefaultLDAPPwd}'. Error: '" . ldap_error($hDS) . "'. Check the configuration file config-itop.php.");
         return false;
     }
 }
예제 #16
0
             ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity);
         }
     } else {
         $oP->set_title(Dict::S('UI:ErrorPageTitle'));
         $oP->P(Dict::S('UI:ObjectDoesNotExist'));
     }
     break;
     ///////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////
 case 'swf_navigator':
     // Graphical display of the relations "impact" / "depends on"
     $sClass = utils::ReadParam('class', '', false, 'class');
     $id = utils::ReadParam('id', 0);
     $sRelation = utils::ReadParam('relation', 'impact');
     $aResults = array();
     $oObj = MetaModel::GetObject($sClass, $id);
     $oObj->GetRelatedObjects($sRelation, 20, $aResults);
     $oP->AddTabContainer('Navigator');
     $oP->SetCurrentTabContainer('Navigator');
     $sFirstTab = MetaModel::GetConfig()->Get('impact_analysis_first_tab');
     if ($sFirstTab == 'list') {
         DisplayNavigatorListTab($oP, $aResults, $sRelation, $oObj);
         DisplayNavigatorGraphicsTab($oP, $aResults, $sClass, $id, $sRelation, $oAppContext);
     } else {
         DisplayNavigatorGraphicsTab($oP, $aResults, $sClass, $id, $sRelation, $oAppContext);
         DisplayNavigatorListTab($oP, $aResults, $sRelation, $oObj);
     }
     $oP->SetCurrentTab('');
     break;
     ///////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////
 protected function DeleteConnectedNetworkDevice()
 {
     // The device might be already deleted (reentrance in the current procedure when both device are NETWORK devices!)
     $oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'), false);
     if (is_object($oDevice) && get_class($oDevice) == 'NetworkDevice') {
         // Track and delete the counterpart link
         $sOQL = "SELECT  lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
         $oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('network' => $this->Get('connectableci_id'), 'device' => $this->Get('networkdevice_id'), 'devport' => $this->Get('network_port'), 'nwport' => $this->Get('device_port')));
         // There should be one link - do it in a safe manner anyway
         while ($oConnection = $oConnectionSet->Fetch()) {
             $oConnection->DBDelete();
         }
     }
 }
예제 #18
0
 /**
  * Common to the recording of link set changes (add/remove/modify)	
  */
 private function PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, $sChangeOpClass, $aOriginalValues = null)
 {
     if ($iLinkSetOwnerId <= 0) {
         return null;
     }
     if (!is_subclass_of($oLinkSet->GetHostClass(), 'CMDBObject')) {
         // The link set owner class does not keep track of its history
         return null;
     }
     // Determine the linked item class and id
     //
     if ($oLinkSet->IsIndirect()) {
         // The "item" is on the other end (N-N links)
         $sExtKeyToRemote = $oLinkSet->GetExtKeyToRemote();
         $oExtKeyToRemote = MetaModel::GetAttributeDef(get_class($this), $sExtKeyToRemote);
         $sItemClass = $oExtKeyToRemote->GetTargetClass();
         if ($aOriginalValues) {
             // Get the value from the original values
             $iItemId = $aOriginalValues[$sExtKeyToRemote];
         } else {
             $iItemId = $this->Get($sExtKeyToRemote);
         }
     } else {
         // I am the "item" (1-N links)
         $sItemClass = get_class($this);
         $iItemId = $this->GetKey();
     }
     // Get the remote object, to determine its exact class
     // Possible optimization: implement a tool in MetaModel, to get the final class of an object (not always querying + query reduced to a select on the root table!
     $oOwner = MetaModel::GetObject($oLinkSet->GetHostClass(), $iLinkSetOwnerId, false);
     if ($oOwner) {
         $sLinkSetOwnerClass = get_class($oOwner);
         $oMyChangeOp = MetaModel::NewObject($sChangeOpClass);
         $oMyChangeOp->Set("objclass", $sLinkSetOwnerClass);
         $oMyChangeOp->Set("objkey", $iLinkSetOwnerId);
         $oMyChangeOp->Set("attcode", $oLinkSet->GetCode());
         $oMyChangeOp->Set("item_class", $sItemClass);
         $oMyChangeOp->Set("item_id", $iItemId);
         return $oMyChangeOp;
     } else {
         // Depending on the deletion order, it may happen that the id is already invalid... ignore
         return null;
     }
 }
 function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
 {
     if ($bEditMode) {
         return;
     }
     // Not editable
     $oPage->add('<table style="vertical-align:top"><tr style="vertical-align:top"><td>');
     $aDetails = array();
     $sClass = get_class($this);
     $oPage->add('<fieldset>');
     $oPage->add('<legend>' . Dict::S('Core:SynchroReplica:PrivateDetails') . '</legend>');
     $aZList = MetaModel::FlattenZlist(MetaModel::GetZListItems($sClass, 'details'));
     foreach ($aZList as $sAttCode) {
         $sDisplayValue = $this->GetAsHTML($sAttCode);
         $aDetails[] = array('label' => '<span title="' . MetaModel::GetDescription($sClass, $sAttCode) . '">' . MetaModel::GetLabel($sClass, $sAttCode) . '</span>', 'value' => $sDisplayValue);
     }
     $oPage->Details($aDetails);
     $oPage->add('</fieldset>');
     if (strlen($this->Get('dest_class')) > 0) {
         $oDestObj = MetaModel::GetObject($this->Get('dest_class'), $this->Get('dest_id'), false);
         if (is_object($oDestObj)) {
             $oPage->add('<fieldset>');
             $oPage->add('<legend>' . Dict::Format('Core:SynchroReplica:TargetObject', $oDestObj->GetHyperlink()) . '</legend>');
             $oDestObj->DisplayBareProperties($oPage, false, $sPrefix, $aExtraParams);
             $oPage->add('<fieldset>');
         }
     }
     $oPage->add('</td><td>');
     $oPage->add('<fieldset>');
     $oPage->add('<legend>' . Dict::S('Core:SynchroReplica:PublicData') . '</legend>');
     $oSource = MetaModel::GetObject('SynchroDataSource', $this->Get('sync_source_id'));
     $sSQLTable = $oSource->GetDataTable();
     $aData = $this->LoadExtendedDataFromTable($sSQLTable);
     $aHeaders = array('attcode' => array('label' => 'Attribute Code', 'description' => ''), 'data' => array('label' => 'Value', 'description' => ''));
     $aRows = array();
     foreach ($aData as $sKey => $value) {
         $aRows[] = array('attcode' => $sKey, 'data' => $value);
     }
     $oPage->Table($aHeaders, $aRows);
     $oPage->add('</fieldset>');
     $oPage->add('</td></tr></table>');
 }
예제 #20
0
/**
 * Downloads a document to the browser, either as 'inline' or 'attachment'
 *  
 * @param WebPage $oPage The web page for the output
 * @param string $sClass Class name of the object
 * @param mixed $id Identifier of the object
 * @param string $sAttCode Name of the attribute containing the document to download
 * @param string $sContentDisposition Either 'inline' or 'attachment'
 * @return none
 */
function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment')
{
    try {
        $oObj = MetaModel::GetObject($sClass, $id, false, false);
        if (!is_object($oObj)) {
            throw new Exception("Invalid id ({$id}) for class '{$sClass}' - the object does not exist or you are not allowed to view it");
        }
        $oDocument = $oObj->Get($sAttCode);
        if (is_object($oDocument)) {
            $oPage->TrashUnexpectedOutput();
            $oPage->SetContentType($oDocument->GetMimeType());
            $oPage->SetContentDisposition($sContentDisposition, $oDocument->GetFileName());
            $oPage->add($oDocument->GetData());
        }
    } catch (Exception $e) {
        $oPage->p($e->getMessage());
    }
}
예제 #21
0
     foreach ($aResults as $sClass => $aObjects) {
         $oSet = CMDBObjectSet::FromArray($sClass, $aObjects);
         $oPage->add("<h1>" . MetaModel::GetRelationDescription($sRelation) . ' ' . $oObj->GetName() . "</h1>\n");
         $oPage->add("<div class=\"page_header\">\n");
         $oPage->add("<h2>" . MetaModel::GetClassIcon($sClass) . "&nbsp;<span class=\"hilite\">" . Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aObjects), Metamodel::GetName($sClass)) . "</h2>\n");
         $oPage->add("</div>\n");
         $oBlock = DisplayBlock::FromObjectSet($oSet, 'list');
         $oBlock->Display($oPage, $iBlock++);
         $oPage->P('&nbsp;');
         // Some space ?
     }
     break;
 case 'xml':
 default:
     $oPage->SetContentType('text/xml');
     $oObj = MetaModel::GetObject($sClass, $id, true);
     // Build the root XML part
     $oXmlDoc = new DOMDocument('1.0', 'UTF-8');
     $oXmlRoot = $oXmlDoc->CreateElement('root');
     $oXmlNode = $oXmlDoc->CreateElement('node');
     $oXmlNode->SetAttribute('id', $oObj->GetKey());
     $oXmlNode->SetAttribute('obj_class', get_class($oObj));
     $oXmlNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oObj))));
     $oXmlNode->SetAttribute('name', htmlspecialchars($oObj->GetRawName()));
     $oXmlNode->SetAttribute('icon', BuildIconPath($oObj->GetIcon(false)));
     // Hard coded for the moment
     AddNodeDetails($oXmlNode, $oObj);
     $oLinks = $oXmlDoc->CreateElement("links");
     $oXmlRoot->SetAttribute('position', 'left');
     $oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation) . ' ' . htmlspecialchars($oObj->GetRawName()));
     IssueLog::Info(__FUNCTION__ . " Rel: {$sRelation}");
 /**
  * Process the reply made from a form built with DisplayBulkModifyForm
  */
 public static function DoBulkModify($oP, $sClass, $aSelectedObj, $sCustomOperation, $bPreview, $sCancelUrl, $aContextData = array())
 {
     $aHeaders = array('form::select' => array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList:not(:disabled)', this.checked);\"></input>", 'description' => Dict::S('UI:SelectAllToggle+')), 'object' => array('label' => MetaModel::GetName($sClass), 'description' => Dict::S('UI:ModifiedObject')), 'status' => array('label' => Dict::S('UI:BulkModifyStatus'), 'description' => Dict::S('UI:BulkModifyStatus+')), 'errors' => array('label' => Dict::S('UI:BulkModifyErrors'), 'description' => Dict::S('UI:BulkModifyErrors+')));
     $aRows = array();
     $oP->add("<div class=\"page_header\">\n");
     $oP->add("<h1>" . MetaModel::GetClassIcon($sClass) . "&nbsp;" . Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), MetaModel::GetName($sClass)) . "</h1>\n");
     $oP->add("</div>\n");
     $oP->set_title(Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass));
     if (!$bPreview) {
         // Not in preview mode, do the update for real
         $sTransactionId = utils::ReadPostedParam('transaction_id', '');
         if (!utils::IsTransactionValid($sTransactionId, false)) {
             throw new Exception(Dict::S('UI:Error:ObjectAlreadyUpdated'));
         }
         utils::RemoveTransaction($sTransactionId);
     }
     $iPreviousTimeLimit = ini_get('max_execution_time');
     $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
     foreach ($aSelectedObj as $iId) {
         set_time_limit($iLoopTimeLimit);
         $oObj = MetaModel::GetObject($sClass, $iId);
         $aErrors = $oObj->UpdateObjectFromPostedForm('');
         $bResult = count($aErrors) == 0;
         if ($bResult) {
             list($bResult, $aErrors) = $oObj->CheckToWrite(true);
         }
         if ($bPreview) {
             $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusOk') : Dict::S('UI:BulkModifyStatusError');
         } else {
             $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped');
         }
         $sCSSClass = $bResult ? HILIGHT_CLASS_NONE : HILIGHT_CLASS_CRITICAL;
         $sChecked = $bResult ? 'checked' : '';
         $sDisabled = $bResult ? '' : 'disabled';
         $aRows[] = array('form::select' => "<input type=\"checkbox\" class=\"selectList\" {$sChecked} {$sDisabled}\"></input>", 'object' => $oObj->GetHyperlink(), 'status' => $sStatus, 'errors' => '<p>' . ($bResult ? '' : implode('</p><p>', $aErrors)) . '</p>', '@class' => $sCSSClass);
         if ($bResult && !$bPreview) {
             $oObj->DBUpdate();
         }
     }
     set_time_limit($iPreviousTimeLimit);
     $oP->Table($aHeaders, $aRows);
     if ($bPreview) {
         $sFormAction = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php';
         // No parameter in the URL, the only parameter will be the ones passed through the form
         // Form to submit:
         $oP->add("<form method=\"post\" action=\"{$sFormAction}\" enctype=\"multipart/form-data\">\n");
         $aDefaults = utils::ReadParam('default', array());
         $oAppContext = new ApplicationContext();
         $oP->add($oAppContext->GetForForm());
         foreach ($aContextData as $sKey => $value) {
             $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"{$value}\">\n");
         }
         $oP->add("<input type=\"hidden\" name=\"operation\" value=\"{$sCustomOperation}\">\n");
         $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n");
         $oP->add("<input type=\"hidden\" name=\"preview_mode\" value=\"0\">\n");
         $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n");
         $oP->add("<button type=\"button\" class=\"action cancel\" onClick=\"window.location.href='{$sCancelUrl}'\">" . Dict::S('UI:Button:Cancel') . "</button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
         $oP->add("<button type=\"submit\" class=\"action\"><span>" . Dict::S('UI:Button:ModifyAll') . "</span></button>\n");
         foreach ($_POST as $sKey => $value) {
             if (preg_match('/attr_(.+)/', $sKey, $aMatches)) {
                 // Beware: some values (like durations) are passed as arrays
                 if (is_array($value)) {
                     foreach ($value as $vKey => $vValue) {
                         $oP->add("<input type=\"hidden\" name=\"{$sKey}[{$vKey}]\" value=\"" . htmlentities($vValue, ENT_QUOTES, 'UTF-8') . "\">\n");
                     }
                 } else {
                     $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"" . htmlentities($value, ENT_QUOTES, 'UTF-8') . "\">\n");
                 }
             }
         }
         $oP->add("</form>\n");
     } else {
         $oP->add("<button type=\"button\" onClick=\"window.location.href='{$sCancelUrl}'\" class=\"action\"><span>" . Dict::S('UI:Button:Done') . "</span></button>\n");
     }
 }
예제 #23
0
 /**
  * @return boolean True if the task record can be deleted
  */
 public function Process()
 {
     // By default: consider that the task is not completed
     $bRet = false;
     // Attempt to take the ownership
     $iStatus = $this->MarkAsRunning();
     if ($iStatus == self::OK) {
         try {
             $sStatus = $this->DoProcess();
             if ($this->Get('event_id') != 0) {
                 $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
                 $oEventLog->Set('message', $sStatus);
                 $oEventLog->DBUpdate();
             }
             $bRet = true;
         } catch (Exception $e) {
             $iRemaining = $this->Get('remaining_retries');
             if ($iRemaining > 0) {
                 $iRetryDelay = $this->GetRetryDelay();
                 IssueLog::Info('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $e->getMessage() . ' - remaining retries: ' . $iRemaining . ' - next retry in ' . $iRetryDelay . 's');
                 $this->Set('remaining_retries', $iRemaining - 1);
                 $this->Set('status', 'planned');
                 $this->Set('started', null);
                 $this->Set('planned', time() + $iRetryDelay);
                 $this->DBUpdate();
             } else {
                 IssueLog::Error('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $e->getMessage());
             }
         }
     } else {
         // Already done or being handled by another process... skip...
         $bRet = false;
     }
     return $bRet;
 }
 /**
  * Helper function to load the objects from a standard XML file into the database
  * @param $sFilePath string The full path to the XML file to load
  * @param $bUpdateKeyCacheOnly bool Set to true to *just* update the keys cache but not reload the objects
  */
 function LoadFile($sFilePath, $bUpdateKeyCacheOnly = false)
 {
     global $aKeys;
     $oXml = simplexml_load_file($sFilePath);
     $aReplicas = array();
     foreach ($oXml as $sClass => $oXmlObj) {
         if (!MetaModel::IsValidClass($sClass)) {
             SetupPage::log_error("Unknown class - {$sClass}");
             throw new Exception("Unknown class - {$sClass}");
         }
         $iSrcId = (int) $oXmlObj['id'];
         // Mandatory to cast
         // Import algorithm
         // Here enumerate all the attributes of the object
         // for all attribute that is neither an external field
         // not an external key, assign it
         // Store all external keys for further reference
         // Create the object an store the correspondance between its newly created Id
         // and its original Id
         // Once all the objects have been created re-assign all the external keys to
         // their actual Ids
         $iExistingId = $this->GetObjectKey($sClass, $iSrcId);
         if ($iExistingId != 0) {
             $oTargetObj = MetaModel::GetObject($sClass, $iExistingId);
         } else {
             $oTargetObj = MetaModel::NewObject($sClass);
         }
         foreach ($oXmlObj as $sAttCode => $oSubNode) {
             if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                 $sMsg = "Unknown attribute code - {$sClass}/{$sAttCode}";
                 continue;
                 // ignore silently...
                 //SetupPage::log_error($sMsg);
                 //throw(new Exception($sMsg));
             }
             $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
             if ($oAttDef->IsWritable() && $oAttDef->IsScalar()) {
                 if ($oAttDef->IsExternalKey()) {
                     if (substr(trim($oSubNode), 0, 6) == 'SELECT') {
                         $sQuery = trim($oSubNode);
                         $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sQuery));
                         $iMatches = $oSet->Count();
                         if ($iMatches == 1) {
                             $oFoundObject = $oSet->Fetch();
                             $iExtKey = $oFoundObject->GetKey();
                         } else {
                             $sMsg = "Ext key not reconcilied - {$sClass}/{$iSrcId} - {$sAttCode}: '" . $sQuery . "' - found {$iMatches} matche(s)";
                             SetupPage::log_error($sMsg);
                             $this->m_aErrors[] = $sMsg;
                             $iExtKey = 0;
                         }
                     } else {
                         $iDstObj = (int) $oSubNode;
                         // Attempt to find the object in the list of loaded objects
                         $iExtKey = $this->GetObjectKey($oAttDef->GetTargetClass(), $iDstObj);
                         if ($iExtKey == 0) {
                             $iExtKey = -$iDstObj;
                             // Convention: Unresolved keys are stored as negative !
                             $oTargetObj->RegisterAsDirty();
                         }
                         // here we allow external keys to be invalid because we will resolve them later on...
                     }
                     //$oTargetObj->CheckValue($sAttCode, $iExtKey);
                     $oTargetObj->Set($sAttCode, $iExtKey);
                 } elseif ($oAttDef instanceof AttributeBlob) {
                     $sMimeType = (string) $oSubNode->mimetype;
                     $sFileName = (string) $oSubNode->filename;
                     $data = base64_decode((string) $oSubNode->data);
                     $oDoc = new ormDocument($data, $sMimeType, $sFileName);
                     $oTargetObj->Set($sAttCode, $oDoc);
                 } else {
                     $value = (string) $oSubNode;
                     if ($value == '') {
                         $value = $oAttDef->GetNullValue();
                     }
                     $res = $oTargetObj->CheckValue($sAttCode, $value);
                     if ($res !== true) {
                         // $res contains the error description
                         $sMsg = "Value not allowed - {$sClass}/{$iSrcId} - {$sAttCode}: '" . $oSubNode . "' ; {$res}";
                         SetupPage::log_error($sMsg);
                         $this->m_aErrors[] = $sMsg;
                     }
                     $oTargetObj->Set($sAttCode, $value);
                 }
             }
         }
         $this->StoreObject($sClass, $oTargetObj, $iSrcId, $bUpdateKeyCacheOnly, $bUpdateKeyCacheOnly);
     }
     return true;
 }
예제 #25
0
function DisplayForm(WebPage $oP, $sAction = '', $sExpression = '', $sQueryId = '', $sFormat = null)
{
    $oExportSearch = null;
    $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/tabularfieldsselector.js');
    $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/jquery.dragtable.js');
    $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot() . 'css/dragtable.css');
    $oP->add('<form id="export-form" action="' . $sAction . '" method="post" data-state="not-yet-started">');
    $bExpressionIsValid = true;
    $sExpressionError = '';
    if ($sExpression === null && $sQueryId === null) {
        $bExpressionIsValid = false;
    } else {
        if ($sExpression !== '') {
            try {
                $oExportSearch = DBObjectSearch::FromOQL($sExpression);
            } catch (OQLException $e) {
                $bExpressionIsValid = false;
                $sExpressionError = $e->getMessage();
            }
        }
    }
    if (!$bExpressionIsValid) {
        DisplayExpressionForm($oP, $sAction, $sExpression, $sExpressionError);
        return;
    }
    if ($sExpression !== '') {
        $oP->add('<input type="hidden" name="expression" value="' . htmlentities($sExpression, ENT_QUOTES, 'UTF-8') . '">');
        $oExportSearch = DBObjectSearch::FromOQL($sExpression);
    } else {
        $oQuery = MetaModel::GetObject('QueryOQL', $sQueryId);
        $oExportSearch = DBObjectSearch::FromOQL($oQuery->Get('oql'));
        $oP->add('<input type="hidden" name="query" value="' . htmlentities($sQueryId, ENT_QUOTES, 'UTF-8') . '">');
    }
    $aFormPartsByFormat = array();
    $aAllFormParts = array();
    if ($sFormat == null) {
        // No specific format chosen
        $sDefaultFormat = utils::ReadParam('format', 'xlsx');
        $oP->add('<p>' . Dict::S('Core:BulkExport:ExportFormatPrompt') . ' <select name="format" id="format_selector">');
        $aSupportedFormats = BulkExport::FindSupportedFormats();
        asort($aSupportedFormats);
        foreach ($aSupportedFormats as $sFormatCode => $sLabel) {
            $sSelected = $sFormatCode == $sDefaultFormat ? 'selected' : '';
            $oP->add('<option value="' . $sFormatCode . '" ' . $sSelected . '>' . htmlentities($sLabel, ENT_QUOTES, 'UTF-8') . '</option>');
            $oExporter = BulkExport::FindExporter($sFormatCode);
            $oExporter->SetObjectList($oExportSearch);
            $aParts = $oExporter->EnumFormParts();
            foreach ($aParts as $sPartId => $void) {
                $aAllFormParts[$sPartId] = $oExporter;
            }
            $aFormPartsByFormat[$sFormatCode] = array_keys($aParts);
        }
        $oP->add('</select></p>');
    } else {
        // One specific format was chosen
        $oP->add('<input type="hidden" name="format" value="' . htmlentities($sFormat, ENT_QUOTES, 'UTF-8') . '">');
        $oExporter = BulkExport::FindExporter($sFormat, $oExportSearch);
        $aParts = $oExporter->EnumFormParts();
        foreach ($aParts as $sPartId => $void) {
            $aAllFormParts[$sPartId] = $oExporter;
        }
        $aFormPartsByFormat[$sFormat] = array_keys($aAllFormParts);
    }
    foreach ($aAllFormParts as $sPartId => $oExport) {
        $oP->add('<div class="form_part" id="form_part_' . $sPartId . '">');
        $oExport->DisplayFormPart($oP, $sPartId);
        $oP->add('</div>');
    }
    $oP->add('</form>');
    $oP->add('<div id="export-feedback" style="display:none;"><p class="export-message" style="text-align:center;">' . Dict::S('ExcelExport:PreparingExport') . '</p><div class="export-progress-bar" style="max-width:30em; margin-left:auto;margin-right:auto;"><div class="export-progress-message" style="text-align:center;"></div></div></div>');
    $oP->add('<button type="button" id="export-btn">' . Dict::S('UI:Button:Export') . '</button>');
    $oP->add('<div id="export_text_result" style="display:none;">');
    $oP->add('<div>' . Dict::S('Core:BulkExport:ExportResult') . '</div>');
    $oP->add('<textarea id="export_content" style="width:100%;min-height:15em;"></textarea>');
    $oP->add('</div>');
    $sJSParts = json_encode($aFormPartsByFormat);
    $sJSCancel = json_encode(Dict::S('UI:Button:Cancel'));
    $sJSClose = json_encode(Dict::S('UI:Button:Done'));
    $oP->add_ready_script(<<<EOF
window.aFormParts = {$sJSParts};
\$('#format_selector').on('change init', function() {
\tExportToggleFormat(\$(this).val());
}).trigger('init');
\t\t
\$('.export-progress-bar').progressbar({
\t value: 0,
\t change: function() {
\t\t\$('.export-progress-message').text( \$(this).progressbar( "value" ) + "%" );
\t },
\t complete: function() {
\t\t \$('.export-progress-message').text( '100 %' );
\t }
});

ExportInitButton('#export-btn');

EOF
);
}
예제 #26
0
 // Therefore, we have to allow users to transform the format according to a given specification: date_format
 //////////////////////////////////////////////////
 //
 // Statistics
 //
 $iCountErrors = 0;
 $iCountCreations = 0;
 $iCountUpdates = 0;
 //////////////////////////////////////////////////
 //
 // Check parameters format/consistency
 //
 if (strlen($sCSVData) == 0) {
     throw new ExchangeException("Missing data - at least one line is expected");
 }
 $oDataSource = MetaModel::GetObject('SynchroDataSource', $iDataSourceId, false);
 if (is_null($oDataSource)) {
     throw new ExchangeException("Unknown data source id: '{$iDataSourceId}'");
 }
 $sClass = $oDataSource->GetTargetClass();
 if (strlen($sSep) > 1) {
     throw new ExchangeException("Separator is limited to one character, found '{$sSep}'");
 }
 if (strlen($sQualifier) > 1) {
     throw new ExchangeException("Text qualifier is limited to one character, found '{$sQualifier}'");
 }
 if (!in_array($sOutput, array('retcode', 'summary', 'details'))) {
     throw new ExchangeException("Unknown output format: '{$sOutput}'");
 }
 /*
 	$aReportLevels = explode('|', $sReportLevel);
예제 #27
0
    exit - 1;
}
$iStepCount = ReadMandatoryParam($oP, 'step_count');
$oP->p('Executing a partial synchro - step ' . $iStepCount);
$iSource = ReadMandatoryParam($oP, 'source');
$iStatLog = ReadMandatoryParam($oP, 'log');
$iChange = ReadMandatoryParam($oP, 'change');
$sLastFullLoad = ReadMandatoryParam($oP, 'last_full_load', 'raw_data');
$iChunkSize = ReadMandatoryParam($oP, 'chunk');
$oP->p('Last full load: ' . $sLastFullLoad);
$oP->p('Chunk size: ' . $iChunkSize);
$oP->p('Source: ' . $iSource);
try {
    $oSynchroDataSource = MetaModel::GetObject('SynchroDataSource', $iSource);
    $oLog = MetaModel::GetObject('SynchroLog', $iStatLog);
    $oChange = MetaModel::GetObject('CMDBChange', $iChange);
    if (strlen($sLastFullLoad) > 0) {
        $oLastFullLoad = new DateTime($sLastFullLoad);
        $oSynchroExec = new SynchroExecution($oSynchroDataSource, $oLastFullLoad);
    } else {
        $oSynchroExec = new SynchroExecution($oSynchroDataSource);
    }
    if ($oSynchroExec->DoSynchronizeChunk($oLog, $oChange, $iChunkSize)) {
        // The last line MUST follow this convention
        $oP->p("continue");
    } else {
        // The last line MUST follow this convention
        $oP->p("finished");
    }
    $oP->output();
} catch (Exception $e) {
예제 #28
0
 /**
  * Helpr to clone (in memory) an object and to apply to it the values taken from a second object
  * @param DBObject $oObjToClone
  * @param DBObject $oObjWithValues
  * @return DBObject The modified clone
  */
 protected function CopyFrom($oObjToClone, $oObjWithValues)
 {
     $oObj = MetaModel::GetObject(get_class($oObjToClone), $oObjToClone->GetKey());
     foreach (MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode => $oAttDef) {
         if (!in_array($sAttCode, $this->aExcludedColumns) && $oAttDef->IsWritable()) {
             $oObj->Set($sAttCode, $oObjWithValues->Get($sAttCode));
         }
     }
     return $oObj;
 }
예제 #29
0
 static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
 {
     $aSet = json_decode($sJsonSet, true);
     // true means hash array instead of object
     $oSet = CMDBObjectSet::FromScratch($sLinkClass);
     foreach ($aSet as $aLinkObj) {
         $oLink = MetaModel::NewObject($sLinkClass);
         foreach ($aLinkObj as $sAttCode => $value) {
             $oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
             if ($oAttDef->IsExternalKey() && $value != '' && $value > 0) {
                 // For external keys: load the target object so that external fields
                 // get filled too
                 $oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value);
                 $oLink->Set($sAttCode, $oTargetObj);
             }
             $oLink->Set($sAttCode, $value);
         }
         $oLink->Set($sExtKeyToMe, $oMe->GetKey());
         $oSet->AddObject($oLink);
     }
     return $oSet;
 }
 /**
  * Find an object from a polymorph search specification (Rest/Json)
  * 	 
  * @param string $sClass Name of the class
  * @param mixed $key Either search criteria (substructure), or an object or an OQL string.
  * @param bool $bAllowNullValue Allow the cases such as key = 0 or key = {null} and return null then
  * @return DBObject The object found
  * @throws Exception If the input structure is not valid or it could not find exactly one object
  * @api
  */
 public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
 {
     if (is_object($key)) {
         $res = static::FindObjectFromCriteria($sClass, $key);
     } elseif (is_numeric($key)) {
         if ($bAllowNullValue && $key == 0) {
             $res = null;
         } else {
             $res = MetaModel::GetObject($sClass, $key, false);
             if (is_null($res)) {
                 throw new Exception("Invalid object {$sClass}::{$key}");
             }
         }
     } elseif (is_string($key)) {
         // OQL
         $oSearch = DBObjectSearch::FromOQL($key);
         $oSet = new DBObjectSet($oSearch);
         $iCount = $oSet->Count();
         if ($iCount == 0) {
             throw new Exception("No item found for query: {$key}");
         } elseif ($iCount > 1) {
             throw new Exception("Several items found ({$iCount}) for query: {$key}");
         }
         $res = $oSet->Fetch();
     } else {
         throw new Exception("Wrong format for key");
     }
     return $res;
 }