FOSSology  4.7.1
Open Source License Compliance by Open Source Software
ui-report-conf.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2019 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
19 
21 {
22 
24  private $dbManager;
25 
29  private $uploadDao;
30 
33  private $userDao;
34 
38  private $licenseDao;
39 
43  private $clearingDao;
44 
48  private $mapDBColumns = array(
49  "reviewedBy" => "ri_reviewed",
50  "department" => "ri_department",
51  "reportRel" => "ri_report_rel",
52  "community" => "ri_community",
53  "component" => "ri_component",
54  "version" => "ri_version",
55  "relDate" => "ri_release_date",
56  "sw360Link" => "ri_sw360_link",
57  "componentType" => "ri_component_type",
58  "componentId" => "ri_component_id",
59  "footerNote" => "ri_footer",
60  "generalAssesment" => "ri_general_assesment",
61  "gaAdditional" => "ri_ga_additional",
62  "gaRisk" => "ri_ga_risk",
63  "dependencyBinarySource" => "ri_depnotes",
64  "exportRestrictionText" => "ri_exportnotes",
65  "copyrightRestrictionText" => "ri_copyrightnotes"
66  );
67 
71  private $radioListUR = array(
72  "nonCritical" => "critical",
73  "critical" => "critical",
74  "noDependency" => "dependencySourceBinary",
75  "dependencySource" => "dependencySourceBinary",
76  "dependencyBinary" => "dependencySourceBinary",
77  "noExportRestriction" => "exportRestriction",
78  "exportRestriction" => "exportRestriction",
79  "noRestriction" => "restrictionForUse",
80  "restrictionForUse" => "restrictionForUse"
81  );
82 
86  private $checkBoxListSPDX = array(
87  "spdxLicenseComment" => "spdxLicenseComment",
88  "ignoreFilesWOInfo" => "ignoreFilesWOInfo",
89  "osselotExport" => "osselotExport"
90  );
91 
92 
93  function __construct()
94  {
95  $this->Name = "report_conf";
96  $this->Title = _("Report Configuration");
97  $this->Dependency = array("browse");
98  $this->DBaccess = PLUGIN_DB_READ;
99  $this->LoginFlag = 0;
100  parent::__construct();
101  $this->uploadDao = $GLOBALS['container']->get('dao.upload');
102  $this->dbManager = $GLOBALS['container']->get('db.manager');
103  $this->userDao = $GLOBALS['container']->get('dao.user');
104  $this->clearingDao = $GLOBALS['container']->get('dao.clearing');
105  $this->licenseDao = $GLOBALS['container']->get('dao.license');
106  }
107 
111  function RegisterMenus()
112  {
113  $tooltipText = _("Report Configuration");
114  menu_insert("Browse-Pfile::Conf",5,$this->Name,$tooltipText);
115  // For the Browse menu, permit switching between detail and summary.
116  $Parm = Traceback_parm_keep(array("upload","item","format"));
117  $URI = $this->Name . $Parm;
118 
119  $menuPosition = 60;
120  $menuText = "Conf";
121  if (GetParm("mod", PARM_STRING) == $this->Name) {
122  menu_insert("View::[BREAK]", 61);
123  menu_insert("View::[BREAK]", 50);
124  menu_insert("View::{$menuText}", $menuPosition);
125  menu_insert("View-Meta::[BREAK]", 61);
126  menu_insert("View-Meta::[BREAK]", 50);
127  menu_insert("View-Meta::{$menuText}", $menuPosition);
128 
129  menu_insert("Browse::Conf",-3);
130  } else {
131  $tooltipText = _("Report Configuration");
132  menu_insert("View::[BREAK]", 61);
133  menu_insert("View::[BREAK]", 50);
134  menu_insert("View::{$menuText}", $menuPosition, $URI, $tooltipText);
135  menu_insert("View-Meta::[BREAK]", 61);
136  menu_insert("View-Meta::[BREAK]", 50);
137  menu_insert("View-Meta::{$menuText}", $menuPosition, $URI, $tooltipText);
138 
139  menu_insert("Browse::Conf", -3, $URI, $tooltipText);
140  }
141  } // RegisterMenus()
142 
149  function allReportConfiguration($uploadId, $groupId)
150  {
151  $vars = [];
152  $row = $this->uploadDao->getReportInfo($uploadId);
153  foreach ($this->mapDBColumns as $key => $value) {
154  $vars[$key] = $row[$value];
155  }
156  $textAreaNoneStyle = ' style="display:none;overflow:auto;width:98%;height:80px;"';
157  $textAreaStyle = ' style="overflow:auto;width:98%;height:80px;"';
158  $vars['styleDependencyTA'] = $vars['styleExportTA'] = $vars['styleRestrictionTA'] = $textAreaStyle;
159  if ($row['ri_depnotes'] == 'NA' || empty($row['ri_depnotes'])) {
160  $vars['styleDependencyTA'] = $textAreaNoneStyle;
161  }
162 
163  if ($row['ri_exportnotes'] == 'NA' || empty($row['ri_exportnotes'])) {
164  $vars['styleExportTA'] = $textAreaNoneStyle;
165  }
166 
167  if ($row['ri_copyrightnotes'] == 'NA' || empty($row['ri_copyrightnotes'])) {
168  $vars['styleRestrictionTA'] = $textAreaNoneStyle;
169  }
170 
171  if (!empty($row['ri_ga_checkbox_selection'])) {
172  $listURCheckbox = explode(',', $row['ri_ga_checkbox_selection']);
173  foreach (array_keys($this->radioListUR) as $key => $value) {
174  $vars[$value] = $listURCheckbox[$key];
175  }
176  }
177 
178  if (!empty($row['ri_spdx_selection'])) {
179  $listSPDXCheckbox = explode(',', $row['ri_spdx_selection']);
180  foreach (array_keys($this->checkBoxListSPDX) as $key => $value) {
181  $vars[$value] = $listSPDXCheckbox[$key];
182  }
183  } else {
184  foreach (array_keys($this->checkBoxListSPDX) as $key) {
185  $vars[$key] = 'unchecked';
186  }
187  }
188 
189  $vars['cyclonedx'] = $this->uploadDao->getCyclonedxSettings($uploadId);
190  $vars['cyclonedxSupportedVersions'] = CycloneDxSettings::SUPPORTED_VERSIONS;
191 
192  $uploadTreeTableName = $this->uploadDao->getUploadtreeTableName($uploadId);
193  $itemTreeBounds = $this->uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
194  $allClearingDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBounds, $groupId);
195 
196  $tableRows = "";
197  $excludedObligations = array();
198  $excludedObligations = (array) json_decode($row['ri_excluded_obligations'], true);
199  foreach ($this->getAllObligationsForGivenUploadId($groupId, $allClearingDecisions) as $obTopic => $obData) {
200  $tableRows .= '<tr><td style="width:35%">'.$obTopic.'</td>';
201  $tableRows .= '<td><textarea readonly="readonly" style="overflow:auto;width:98%;height:80px;">'.
202  $obData['text'].'</textarea></td><td>';
203  foreach ($obData['license'] as $value) {
204  if (!empty($excludedObligations[$obTopic]) && in_array($value, $excludedObligations[$obTopic])) {
205  $tableRows .= '<input class="browse-upload-checkbox view-license-rc-size" type="checkbox" name="obLicenses['.urlencode($obTopic).'][]" value="'.$value.'" checked> '.$value.'<br />';
206  } else {
207  $tableRows .= '<input class="browse-upload-checkbox view-license-rc-size" type="checkbox" name="obLicenses['.urlencode($obTopic).'][]" value="'.$value.'"> '.$value.'<br />';
208  }
209  }
210  $tableRows .= '</td></tr>';
211  }
212  $tableRowsUnifiedReport = "";
213  $unifiedColumns = array();
214  if (!empty($row['ri_unifiedcolumns'])) {
215  $unifiedColumns = (array) json_decode($row['ri_unifiedcolumns'], true);
216  } else {
217  $unifiedColumns = UploadDao::UNIFIED_REPORT_HEADINGS;
218  }
219  foreach ($unifiedColumns as $name => $unifiedReportColumns) {
220  foreach ($unifiedReportColumns as $columnName => $isenabled) {
221  $tableRowsUnifiedReport .= '<tr>';
222  $tableRowsUnifiedReport .= '<td><input class="form-control" type="text" style="width:95%" name="'.$name.'[]" value="'.$columnName.'"></td>';
223  $checked = '';
224  if ($isenabled) {
225  $checked = 'checked';
226  }
227  $tableRowsUnifiedReport .= '<td style="vertical-align:middle"><input class="browse-upload-checkbox view-license-rc-size" type="checkbox" style="width:95%" name="'.$name.'[]" '.$checked.'></td>';
228  $tableRowsUnifiedReport .= '</tr>';
229  }
230  }
231 
232  $tableRowsClixmlReport = "";
233  $clixmlColumns = array();
234  if (!empty($row['ri_clixmlcolumns'])) {
235  $clixmlColumns = (array) json_decode($row['ri_clixmlcolumns'], true);
236  } else {
237  $clixmlColumns = UploadDao::CLIXML_REPORT_HEADINGS;
238  }
239  foreach ($clixmlColumns as $name => $clixmlReportColumns) {
240  foreach ($clixmlReportColumns as $columnName => $isenabled) {
241  $tableRowsClixmlReport .= '<tr>';
242  $tableRowsClixmlReport .= '<td><input class="form-control" type="text" style="width:95%" name="'.$name.'[]" value="'.$columnName.'" readonly></td>';
243  $checked = '';
244  if ($isenabled) {
245  $checked = 'checked';
246  }
247  $tableRowsClixmlReport .= '<td style="vertical-align:middle"><input class="browse-upload-checkbox view-license-rc-size" type="checkbox" style="width:95%" name="'.$name.'[]" '.$checked.'></td>';
248  $tableRowsClixmlReport .= '</tr>';
249  }
250  }
251 
252  if (!empty($row['ri_globaldecision'])) {
253  $vars['applyGlobal'] = "checked";
254  }
255  $vars['tableRows'] = $tableRows;
256  $vars['tableRowsUnifiedReport'] = $tableRowsUnifiedReport;
257  $vars['tableRowsClixmlReport'] = $tableRowsClixmlReport;
258  $vars['ackRows'] = $this->buildAcknowledgementRows($uploadId, $allClearingDecisions);
259  $vars['scriptBlock'] = $this->createScriptBlock();
260 
261  return $vars;
262  }
263 
269  function getAllAcknowledgementsForUpload(array $clearingDecisions)
270  {
271  $ackData = array();
272  foreach ($clearingDecisions as $clearingDecision) {
273  if ($clearingDecision->getType() == DecisionTypes::IRRELEVANT) {
274  continue;
275  }
276  $uploadTreeId = $clearingDecision->getUploadTreeId();
277  foreach ($clearingDecision->getClearingLicenses() as $clearingLicense) {
278  if ($clearingLicense->isRemoved()) {
279  continue;
280  }
281  $ack = $clearingLicense->getAcknowledgement();
282  if (empty(trim($ack))) {
283  continue;
284  }
285  if (!isset($ackData[$ack])) {
286  $ackData[$ack] = array('files' => array(), 'licenses' => array());
287  }
288  $ackData[$ack]['files'][$uploadTreeId] = true;
289  $ackData[$ack]['licenses'][$clearingLicense->getShortName()] = true;
290  }
291  }
292  $result = array();
293  foreach ($ackData as $ack => $data) {
294  $result[$ack] = array(
295  'count' => count($data['files']),
296  'licenses' => array_keys($data['licenses'])
297  );
298  }
299  return $result;
300  }
301 
308  function buildAcknowledgementRows($uploadId, array $clearingDecisions)
309  {
310  $acknowledgements = $this->getAllAcknowledgementsForUpload($clearingDecisions);
311  $rows = "";
312  foreach ($acknowledgements as $ackText => $ackData) {
313  $ackHtml = htmlspecialchars($ackText, ENT_QUOTES);
314  $licensesHtml = htmlspecialchars(implode(', ', $ackData['licenses']));
315  $rows .= '<tr>';
316  $rows .= '<td style="width:5%;text-align:center">'
317  . '<a href="#" class="ack-count-link" data-upload="' . $uploadId
318  . '" data-ack="' . $ackHtml . '">' . $ackData['count'] . '</a></td>';
319  $rows .= '<td style="width:60%"><textarea class="ack-text-area" readonly="readonly"'
320  . ' data-original-ack="' . $ackHtml . '"'
321  . ' style="overflow:auto;width:98%;height:60px;">'
322  . $ackHtml . '</textarea></td>';
323  $rows .= '<td style="width:25%">' . $licensesHtml . '</td>';
324  $rows .= '<td style="width:10%;text-align:center">'
325  . '<button type="button" class="btn btn-danger btn-sm delete-ack-btn"'
326  . ' data-upload="' . $uploadId . '" data-ack="' . $ackHtml . '">'
327  . 'Delete</button></td>';
328  $rows .= '</tr>';
329  }
330  return $rows;
331  }
332 
339  function getAllObligationsForGivenUploadId($groupId, array $clearingDecisions)
340  {
341  $allClearedLicenses = array();
342  $licenseMap = new LicenseMap($this->dbManager, $groupId, LicenseMap::REPORT);
343  foreach ($clearingDecisions as $clearingDecision) {
344  if ($clearingDecision->getType() == DecisionTypes::IRRELEVANT) {
345  continue;
346  }
347  foreach ($clearingDecision->getClearingLicenses() as $clearingLicense) {
348  if ($clearingLicense->isRemoved()) {
349  continue;
350  }
351  $allClearedLicenses[$licenseMap->getProjectedId($clearingLicense->getLicenseId())] = true;
352  }
353  }
354  $uniqueLicenseIds = array_keys($allClearedLicenses);
355  $allObligations = array_merge(
356  $this->licenseDao->getLicenseObligations($uniqueLicenseIds) ?: array(),
357  $this->licenseDao->getLicenseObligations($uniqueLicenseIds, true) ?: array()
358  );
359  $groupedObligations = array();
360  foreach ($allObligations as $obligation) {
361  $groupBy = $obligation['ob_topic'];
362  $licenseName = LicenseRef::convertToSpdxId($obligation['rf_shortname'],
363  $obligation['rf_spdx_id']);
364  if (array_key_exists($groupBy, $groupedObligations)) {
365  $groupedObligations[$groupBy]['license'][$licenseName] = true;
366  } else {
367  $groupedObligations[$groupBy] = array(
368  "topic" => $obligation['ob_topic'],
369  "text" => $obligation['ob_text'],
370  "license" => array($licenseName => true)
371  );
372  }
373  }
374  foreach ($groupedObligations as &$ob) {
375  $ob['license'] = array_keys($ob['license']);
376  }
377  return $groupedObligations;
378  }
379 
384  protected function getCheckBoxSelectionList($listParams)
385  {
386  $cbList = [];
387  foreach ($listParams as $listkey => $listValue) {
388  $ret = GetParm($listValue, PARM_STRING);
389  if ($ret != $listkey) {
390  $cbList[] = "unchecked";
391  } else {
392  $cbList[] = "checked";
393  }
394  }
395  $cbSelectionList = implode(",", $cbList);
396 
397  return $cbSelectionList;
398  }
399 
407  private function getCycloneDxSettingsFromRequest($uploadId)
408  {
409  $stored = $this->uploadDao->getCyclonedxSettings($uploadId);
410  $namespaceInput = trim((string) GetParm('cyclonedxCustomTagNamespace', PARM_RAW));
411  $namespace = $namespaceInput === '' ? CycloneDxSettings::DEFAULT_NAMESPACE :
412  CycloneDxSettings::normaliseNamespace($namespaceInput);
413  if ($namespace === null) {
414  $namespace = $stored->getTagNamespace();
415  $this->vars['message'] = sprintf(_("CycloneDX tag namespace not saved: " .
416  "use letters, digits, '.', '_', '-' and ':' (at most %d characters)."),
417  CycloneDxSettings::MAX_NAMESPACE_LENGTH);
418  }
419  $specVersion = CycloneDxSettings::normaliseSpecVersion(
420  GetParm('cyclonedxSpecVersion', PARM_STRING)) ?? $stored->getSpecVersion();
421  return new CycloneDxSettings(
422  GetParm('cyclonedxLicenseComment', PARM_STRING) === 'cyclonedxLicenseComment',
423  GetParm('cyclonedxIgnoreFilesWOInfo', PARM_STRING) === 'cyclonedxIgnoreFilesWOInfo',
424  GetParm('cyclonedxOsselotExport', PARM_STRING) === 'cyclonedxOsselotExport',
425  $namespace, $specVersion);
426  }
427 
428  public function Output()
429  {
430  $uploadId = GetParm("upload", PARM_INTEGER);
431  $groupId = Auth::getGroupId();
432  $userId = Auth::getUserId();
433  if (!$this->uploadDao->isAccessible($uploadId, $groupId)) {
434  return;
435  }
436 
437  $itemId = GetParm("item", PARM_INTEGER);
438  $this->vars['micromenu'] = Dir2Browse("browse", $itemId, null, $showBox = 0, "View-Meta");
439  $this->vars['globalClearingAvailable'] = Auth::isClearingAdmin();
440 
441  $submitReportConf = GetParm("submitReportConf", PARM_STRING);
442 
443  if (isset($submitReportConf)) {
444  $applyGlobal = @$_POST["applyGlobal"];
445  $applyGlobal = !empty($applyGlobal) ? 1 : 0;
446  $parms = array();
447  $obLicensesEncoded = @$_POST["obLicenses"];
448  $obLicensesEncoded = !empty($obLicensesEncoded) ? $obLicensesEncoded : array();
449  $obLicenses = array();
450  array_walk($obLicensesEncoded,
451  function (&$licArray, $obTopic) use (&$obLicenses) {
452  $obLicenses[urldecode($obTopic)] = $licArray;
453  }
454  );
455  $i = 1;
456  $columns = "";
457  foreach ($this->mapDBColumns as $key => $value) {
458  $columns .= $value." = $".$i.", ";
459  $parms[] = GetParm($key, PARM_RAW);
460  $i++;
461  }
462  $parms[] = $this->getCheckBoxSelectionList($this->radioListUR);
463 
464  $unifiedReportColumnsForJson = array();
465  foreach (UploadDao::UNIFIED_REPORT_HEADINGS as $columnName => $columnValue) {
466  $columnResult = @$_POST[$columnName];
467  $unifiedReportColumnsForJson[$columnName] = array($columnResult[0] => isset($columnResult[1]) ? $columnResult[1] : null);
468  }
469  $clixmlColumnsForJson = array();
470  foreach (UploadDao::CLIXML_REPORT_HEADINGS as $columnName => $columnValue) {
471  $columnResult = @$_POST[$columnName];
472  $clixmlColumnsForJson[$columnName] = array($columnResult[0] => isset($columnResult[1]) ? $columnResult[1] : null);
473  }
474  $checkBoxUrPos = count($parms);
475  $parms[] = $this->getCheckBoxSelectionList($this->checkBoxListSPDX);
476  $checkBoxSpdxPos = count($parms);
477  $parms[] = $this->getCycloneDxSettingsFromRequest($uploadId)->toReportInfo();
478  $cyclonedxPos = count($parms);
479  $parms[] = json_encode($obLicenses);
480  $excludeObligationPos = count($parms);
481  $parms[] = json_encode($unifiedReportColumnsForJson);
482  $unifiedColumnsPos = count($parms);
483  $parms[] = json_encode($clixmlColumnsForJson);
484  $clixmlColumnsPos = count($parms);
485  $parms[] = $applyGlobal;
486  $applyGlobalPos = count($parms);
487  $parms[] = $uploadId;
488  $uploadIdPos = count($parms);
489 
490  $SQL = "UPDATE report_info SET $columns" .
491  "ri_ga_checkbox_selection = $$checkBoxUrPos, " .
492  "ri_spdx_selection = $$checkBoxSpdxPos, " .
493  "ri_cyclonedx_selection = $$cyclonedxPos, " .
494  "ri_excluded_obligations = $$excludeObligationPos, " .
495  "ri_unifiedcolumns = $$unifiedColumnsPos, " .
496  "ri_clixmlcolumns = $$clixmlColumnsPos, " .
497  "ri_globaldecision = $$applyGlobalPos " .
498  "WHERE upload_fk = $$uploadIdPos;";
499  $this->dbManager->getSingleRow($SQL, $parms,
500  __METHOD__ . "updateReportInfoData");
501 
502  if (@$_POST['markGlobal']) {
503  $upload = $this->uploadDao->getUpload($uploadId);
504  $uploadName = $upload->getFilename();
505  $jobId = JobAddJob($userId, $groupId, $uploadName, $uploadId);
507  $deciderPlugin = plugin_find("agent_deciderjob");
508  $conflictStrategyId = "global";
509  $errorMsg = "";
510  $deciderPlugin->AgentAdd($jobId, $uploadId, $errorMsg, array(), $conflictStrategyId);
511  $schedulerMsg = empty(GetRunnableJobList()) ? _("Is the scheduler running? ") : '';
512  $url = Traceback_uri() . "?mod=showjobs&upload=$uploadId";
513  $text = _("Your jobs have been added to job queue.");
514  $linkText = _("View Jobs");
515  $this->vars['message'] = "$schedulerMsg" . "$text <a href=\"$url\">$linkText</a>";
516  }
517  }
518  $this->vars += $this->allReportConfiguration($uploadId, $groupId);
519  $this->vars['typemap'] = [];
520  foreach (ComponentType::TYPE_MAP as $key => $name) {
521  if ($key == ComponentType::PACKAGEURL) {
522  continue;
523  }
524  $this->vars['typemap'][] = ['key' => $key, 'name' => $name];
525  }
526  }
527 
528  public function getTemplateName()
529  {
530  return "ui-report-conf.html.twig";
531  }
532 
537  protected function createScriptBlock()
538  {
539  return "
540 
541  var reportTabCookie = 'stickyReportTab';
542 
543  $(document).ready(function() {
544  $(\"#confTabs\").tabs({
545  active: ($.cookie(reportTabCookie) || 0),
546  activate: function(e, ui){
547  // Get active tab index and update cookie
548  var idString = $(e.currentTarget).attr('id');
549  idString = parseInt(idString.slice(-1)) - 1;
550  $.cookie(reportTabCookie, idString);
551  // Hide submit button on acknowledgements tab (AJAX-only tab)
552  if (ui.newPanel.attr('id') === 'acknowledgementsConfTab') {
553  $('#reportConfSubmit').hide();
554  } else {
555  $('#reportConfSubmit').show();
556  }
557  }
558  });
559 
560  var activeIdx = $.cookie(reportTabCookie) || 0;
561  if ($(\"#confTabs .ui-tabs-panel\").eq(activeIdx).attr('id') === 'acknowledgementsConfTab') {
562  $('#reportConfSubmit').hide();
563  }
564  $(\"input[name='dependencySourceBinary']\").change(function(){
565  var val = $(\"input[name='dependencySourceBinary']:checked\").val();
566  if (val == 'noDependency') {
567  $('#dependencyBinarySource').hide();
568  $('#dependencyBinarySource').val('');
569  } else {
570  $('#dependencyBinarySource').css('display', 'block');
571  }
572  });
573  $(\"input[name='exportRestriction']\").change(function(){
574  var val = $(\"input[name='exportRestriction']:checked\").val();
575  if (val == 'noExportRestriction') {
576  $('#exportRestrictionText').hide();
577  $('#exportRestrictionText').val('');
578  } else {
579  $('#exportRestrictionText').css('display', 'block');
580  }
581  });
582  $(\"input[name='restrictionForUse']\").change(function(){
583  var val = $(\"input[name='restrictionForUse']:checked\").val();
584  if (val == 'noRestriction') {
585  $('#copyrightRestrictionText').hide();
586  $('#copyrightRestrictionText').val('');
587  } else {
588  $('#copyrightRestrictionText').css('display', 'block');
589  }
590  });
591 
592  $('#osselotExportCheckbox').change(function() {
593  if ($(this).is(':checked')) {
594  $('#spdxLicenseCommentCheckbox').prop('checked', true);
595  }
596  });
597  $('#spdxLicenseCommentCheckbox').change(function() {
598  if (!this.checked) {
599  $('#osselotExportCheckbox').prop('checked', false);
600  }
601  });
602 
603  $('#cyclonedxOsselotExportCheckbox').change(function() {
604  if ($(this).is(':checked')) {
605  $('#cyclonedxLicenseCommentCheckbox').prop('checked', true);
606  }
607  });
608  $('#cyclonedxLicenseCommentCheckbox').change(function() {
609  if (!this.checked) {
610  $('#cyclonedxOsselotExportCheckbox').prop('checked', false);
611  }
612  });
613 
614  $(\"[data-toggle='tooltip']\").tooltip();
615 
616  var ackAjaxUrl = '?mod=ajax-acknowledgement-conf';
617 
618  $(document).on('click', '.ack-count-link', function(e) {
619  e.preventDefault();
620  var upload = $(this).data('upload');
621  var ack = $(this).data('ack');
622  $('#ackFilesModalBody').html('<p>Loading...</p>');
623  $('#ackFilesModalCount').text('');
624  $('#ackFilesModal').modal('show');
625  $.get(ackAjaxUrl, {action: 'getFiles', upload: upload, ack: ack},
626  function(data) {
627  if (!data || data.length === 0) {
628  $('#ackFilesModalCount').text('');
629  $('#ackFilesModalBody').html('<p>No files found.</p>');
630  return;
631  }
632  $('#ackFilesModalCount').text('(' + data.length + ' files)');
633  var html = '<table class=\"table table-condensed table-hover\" style=\"margin:0;\">'
634  + '<thead><tr><th>#</th><th>File</th></tr></thead><tbody>';
635  $.each(data, function(i, file) {
636  html += '<tr><td>' + (i + 1) + '</td>'
637  + '<td><a href=\"' + file.url + '\" target=\"_blank\">'
638  + $('<span/>').text(file.name).html()
639  + '</a></td></tr>';
640  });
641  html += '</tbody></table>';
642  $('#ackFilesModalBody').html(html);
643  }
644  ).fail(function() {
645  $('#ackFilesModalCount').text('');
646  $('#ackFilesModalBody').html('<p>Error loading files.</p>');
647  });
648  });
649 
650  $(document).on('dblclick', '.ack-text-area', function() {
651  if (!$(this).prop('readonly')) {
652  return;
653  }
654  var ta = $(this);
655  var td = ta.closest('td');
656  ta.prop('readonly', false).css('border', '2px solid #337ab7').focus();
657  td.append('<div class=\"ack-edit-actions\" style=\"margin-top:4px;\">'
658  + '<button type=\"button\" class=\"btn btn-primary btn-xs ack-save-btn\">Save</button> '
659  + '<button type=\"button\" class=\"btn btn-light btn-xs ack-cancel-btn\">Cancel</button>'
660  + '</div>');
661  });
662 
663  $(document).on('click', '.ack-save-btn', function() {
664  var row = $(this).closest('tr');
665  var td = $(this).closest('td');
666  var ta = td.find('.ack-text-area');
667  var newAck = ta.val();
668  var oldAck = ta.data('original-ack');
669  if (newAck === oldAck) {
670  ta.prop('readonly', true).css('border', '');
671  td.find('.ack-edit-actions').remove();
672  return;
673  }
674  var upload = row.find('.ack-count-link').data('upload');
675  $.post(ackAjaxUrl,
676  {action: 'updateAcknowledgement', upload: upload, oldAck: oldAck, newAck: newAck},
677  function(data) {
678  if (data && data.status === 'success') {
679  $('#acknowledgementsConfTab tbody tr').each(function() {
680  if ($(this).find('.ack-text-area').data('original-ack') === newAck
681  && this !== row[0]) {
682  $(this).remove();
683  }
684  });
685  ta.val(newAck)
686  .data('original-ack', newAck)
687  .prop('readonly', true)
688  .css('border', '');
689  row.find('.ack-count-link').text(data.count).data('ack', newAck);
690  row.find('.delete-ack-btn').data('ack', newAck);
691  td.find('.ack-edit-actions').remove();
692  } else {
693  alert('Failed to update acknowledgement.');
694  }
695  }
696  ).fail(function() {
697  alert('Error communicating with server.');
698  });
699  });
700 
701  $(document).on('click', '.ack-cancel-btn', function() {
702  var td = $(this).closest('td');
703  var ta = td.find('.ack-text-area');
704  ta.val(ta.data('original-ack'))
705  .prop('readonly', true)
706  .css('border', '');
707  td.find('.ack-edit-actions').remove();
708  });
709 
710  $(document).on('click', '.delete-ack-btn', function() {
711  var upload = $(this).data('upload');
712  var ack = $(this).data('ack');
713  if (!confirm('Are you sure you want to clear this acknowledgement from all files?')) {
714  return;
715  }
716  var row = $(this).closest('tr');
717  $.post(ackAjaxUrl,
718  {action: 'deleteAcknowledgement', upload: upload, ack: ack},
719  function(data) {
720  if (data && data.status === 'success') {
721  row.fadeOut(400, function() { row.remove(); });
722  } else {
723  alert('Failed to delete acknowledgement.');
724  }
725  }
726  ).fail(function() {
727  alert('Error communicating with server.');
728  });
729  });
730  });
731  ";
732  }
733 }
734 
735 $NewPlugin = new ui_report_conf();
736 $NewPlugin->Initialize();
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:57
Output()
This function is called when user output is requested. This function is responsible for content....
Definition: FO_Plugin.php:399
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
Wrapper class for license map.
Definition: LicenseMap.php:19
CycloneDX export settings of a user (defaults) or of an upload.
getAllObligationsForGivenUploadId($groupId, array $clearingDecisions)
get all the obligations for cleared licenses
createScriptBlock()
Create Script block for conf.
buildAcknowledgementRows($uploadId, array $clearingDecisions)
Build HTML table rows for acknowledgements tab.
getAllAcknowledgementsForUpload(array $clearingDecisions)
Get acknowledgements for cleared licenses grouped by text.
allReportConfiguration($uploadId, $groupId)
list all the options for Report Configuration
RegisterMenus()
Customize submenus.
getCheckBoxSelectionList($listParams)
__construct()
base constructor. Most plugins will just use this
getCycloneDxSettingsFromRequest($uploadId)
CycloneDX settings submitted with the form.
Dir2Browse($Mod, $UploadtreePk, $LinkLast=NULL, $ShowBox=1, $ShowMicro=NULL, $Enumerate=-1, $PreText='', $PostText='', $uploadtree_tablename="uploadtree")
Get an html linked string of a file browse path.
Definition: common-dir.php:263
menu_insert($Path, $LastOrder=0, $URI=NULL, $Title=NULL, $Target=NULL, $HTML=NULL)
Given a Path, order level for the last item, and optional plugin name, insert the menu item.
Traceback_uri()
Get the URI without query to this location.
Definition: common-parm.php:97
const PARM_INTEGER
Definition: common-parm.php:14
const PARM_RAW
Definition: common-parm.php:22
const PARM_STRING
Definition: common-parm.php:18
GetParm($parameterName, $parameterType)
This function will retrieve the variables and check data types.
Definition: common-parm.php:46
Traceback_parm_keep($List)
Create a new URI, keeping only these items.
plugin_find($pluginName)
Given the official name of a plugin, return the $Plugins object.
GetRunnableJobList()
Get runnable job list, the process is below:
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:690
#define PLUGIN_DB_READ
Plugin requires read permission on DB.
Definition: libfossology.h:37
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16