FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
AjaxExplorer.php
1 <?php
2 /***********************************************************
3  * Copyright (C) 2008-2015 Hewlett-Packard Development Company, L.P.
4  * 2014-2017,2020, Siemens AG
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  ***********************************************************/
19 
20 namespace Fossology\UI\Ajax;
21 
22 use ClearingView;
40 
47 {
48  const NAME = "ajax_explorer";
49 
50  private $uploadtree_tablename = "";
52  private $uploadDao;
54  private $licenseDao;
56  private $clearingDao;
58  private $agentDao;
60  private $clearingFilter;
62  private $licenseProjector;
64  private $filesThatShouldStillBeCleared;
66  private $filesToBeCleared;
74  protected $agentNames = AgentRef::AGENT_LIST;
75 
76  public function __construct()
77  {
78  parent::__construct(self::NAME, array(
79  self::TITLE => _("Ajax: License Browser"),
80  self::DEPENDENCIES => array("license"),
81  self::PERMISSION => Auth::PERM_READ,
82  self::REQUIRES_LOGIN => false
83  ));
84 
85  $this->uploadDao = $this->getObject('dao.upload');
86  $this->licenseDao = $this->getObject('dao.license');
87  $this->clearingDao = $this->getObject('dao.clearing');
88  $this->agentDao = $this->getObject('dao.agent');
89  $this->clearingFilter = $this->getObject('businessrules.clearing_decision_filter');
90  $this->filesThatShouldStillBeCleared = [];
91  $this->filesToBeCleared = [];
92  $this->alreadyClearedUploadTreeView = NULL;
93  $this->noLicenseUploadTreeView = NULL;
94  }
95 
96  public function __destruct()
97  {
98  // Destruct the proxy views before exiting
99  if ($this->alreadyClearedUploadTreeView !== NULL) {
100  $this->alreadyClearedUploadTreeView->unmaterialize();
101  }
102  if ($this->noLicenseUploadTreeView !== NULL) {
103  $this->noLicenseUploadTreeView->unmaterialize();
104  }
105  }
106 
111  protected function handle(Request $request)
112  {
113  $upload = intval($request->get("upload"));
114  $groupId = Auth::getGroupId();
115  if (!$this->uploadDao->isAccessible($upload, $groupId)) {
116  throw new \Exception("Permission Denied");
117  }
118 
119  $item = intval($request->get("item"));
120  $this->uploadtree_tablename = $this->uploadDao->getUploadtreeTableName($upload);
121  $itemTreeBounds = $this->uploadDao->getItemTreeBounds($item, $this->uploadtree_tablename);
122  $left = $itemTreeBounds->getLeft();
123  if (empty($left)) {
124  throw new \Exception("Job unpack/adj2nest hasn't completed.");
125  }
126 
127  $scannerAgents = array_keys($this->agentNames);
128  $scanJobProxy = new ScanJobProxy($this->agentDao, $upload);
129  $scanJobProxy->createAgentStatus($scannerAgents);
130  $selectedAgentId = intval($request->get('agentId'));
131  $tag_pk = intval($request->get('tag'));
132 
133  $UniqueTagArray = array();
134  $this->licenseProjector = new LicenseMap($this->getObject('db.manager'),$groupId,LicenseMap::CONCLUSION,true);
135  $vars = $this->createFileListing($tag_pk, $itemTreeBounds, $UniqueTagArray, $selectedAgentId, $groupId, $scanJobProxy);
136 
137  return new JsonResponse(array(
138  'sEcho' => intval($request->get('sEcho')),
139  'aaData' => $vars['fileData'],
140  'iTotalRecords' => intval($request->get('totalRecords')),
141  'iTotalDisplayRecords' => $vars['iTotalDisplayRecords']
142  ) );
143  }
144 
145 
155  private function createFileListing($tagId, ItemTreeBounds $itemTreeBounds, &$UniqueTagArray, $selectedAgentId, $groupId, $scanJobProxy)
156  {
157  if (!empty($selectedAgentId)) {
158  $agentName = $this->agentDao->getAgentName($selectedAgentId);
159  $selectedScanners = array($agentName=>$selectedAgentId);
160  } else {
161  $selectedScanners = $scanJobProxy->getLatestSuccessfulAgentIds();
162  }
163 
165  $uploadId = $itemTreeBounds->getUploadId();
166  $isFlat = isset($_GET['flatten']);
167 
168  if ($isFlat) {
169  $options = array(UploadTreeProxy::OPT_RANGE => $itemTreeBounds);
170  } else {
171  $options = array(UploadTreeProxy::OPT_REALPARENT => $itemTreeBounds->getItemId());
172  }
173 
174  $searchMap = array();
175  foreach (explode(' ',GetParm('sSearch', PARM_RAW)) as $pair) {
176  $a = explode(':',$pair);
177  if (count($a) == 1) {
178  $searchMap['head'] = $pair;
179  } else {
180  $searchMap[$a[0]] = $a[1];
181  }
182  }
183 
184  if (array_key_exists('ext', $searchMap) && strlen($searchMap['ext'])>=1) {
185  $options[UploadTreeProxy::OPT_EXT] = $searchMap['ext'];
186  }
187  if (array_key_exists('head', $searchMap) && strlen($searchMap['head'])>=1) {
188  $options[UploadTreeProxy::OPT_HEAD] = $searchMap['head'];
189  }
190  if (($rfId=GetParm('scanFilter',PARM_INTEGER))>0) {
191  $options[UploadTreeProxy::OPT_AGENT_SET] = $selectedScanners;
192  $options[UploadTreeProxy::OPT_SCAN_REF] = $rfId;
193  }
194  if (($rfId=GetParm('conFilter',PARM_INTEGER))>0) {
195  $options[UploadTreeProxy::OPT_GROUP_ID] = Auth::getGroupId();
196  $options[UploadTreeProxy::OPT_CONCLUDE_REF] = $rfId;
197  }
198  $openFilter = GetParm('openCBoxFilter',PARM_RAW);
199  if ($openFilter=='true' || $openFilter=='checked') {
200  $options[UploadTreeProxy::OPT_AGENT_SET] = $selectedScanners;
201  $options[UploadTreeProxy::OPT_GROUP_ID] = Auth::getGroupId();
202  $options[UploadTreeProxy::OPT_SKIP_ALREADY_CLEARED] = true;
203  }
204 
205  $descendantView = new UploadTreeProxy($uploadId, $options, $itemTreeBounds->getUploadTreeTableName(), 'uberItems');
206 
207  $vars['iTotalDisplayRecords'] = $descendantView->count();
208 
209  $columnNamesInDatabase = array($isFlat?'ufile_name':'lft');
210  $defaultOrder = array(array(0, "asc"));
211  $orderString = $this->getObject('utils.data_tables_utility')->getSortingString($_GET, $columnNamesInDatabase, $defaultOrder);
212 
213  $offset = GetParm('iDisplayStart', PARM_INTEGER);
214  $limit = GetParm('iDisplayLength', PARM_INTEGER);
215  if ($offset) {
216  $orderString .= " OFFSET $offset";
217  }
218  if ($limit) {
219  $orderString .= " LIMIT $limit";
220  }
221 
222  /* Get ALL the items under this Uploadtree_pk */
223  $sql = $descendantView->getDbViewQuery()." $orderString";
224  $dbManager = $this->getObject('db.manager');
225 
226  $dbManager->prepare($stmt=__METHOD__.$orderString,$sql);
227  $res = $dbManager->execute($stmt,$descendantView->getParams());
228  $descendants = $dbManager->fetchAll($res);
229  $dbManager->freeResult($res);
230 
231  /* Filter out Children that don't have tag */
232  if (!empty($tagId)) {
233  TagFilter($descendants, $tagId, $itemTreeBounds->getUploadTreeTableName());
234  }
235  if (empty($descendants)) {
236  $vars['fileData'] = array();
237  return $vars;
238  }
239 
240  if ($isFlat) {
241  $firstChild = reset($descendants);
242  $lastChild = end($descendants);
243  $nameRange = array($firstChild['ufile_name'],$lastChild['ufile_name']);
244  } else {
245  $nameRange = array();
246  }
247 
248  $allDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBounds, $groupId, $isFlat);
249  $editedMappedLicenses = $this->clearingFilter->filterCurrentClearingDecisions($allDecisions);
250 
251  $pfileLicenses = $this->updateTheFindingsAndDecisions($selectedScanners,
252  $isFlat, $groupId, $editedMappedLicenses, $itemTreeBounds, $nameRange);
253 
254  $baseUri = Traceback_uri().'?mod=license'.Traceback_parm_keep(array('upload','folder','show'));
255 
256  $tableData = array();
257  global $Plugins;
258  $ModLicView = &$Plugins[plugin_find_id("view-license")];
259  $latestSuccessfulAgentIds = $scanJobProxy->getLatestSuccessfulAgentIds();
260  foreach ($descendants as $child) {
261  if (empty($child)) {
262  continue;
263  }
264  $tableData[] = $this->createFileDataRow($child, $uploadId, $selectedAgentId, $pfileLicenses, $groupId, $editedMappedLicenses, $baseUri, $ModLicView, $UniqueTagArray, $isFlat, $latestSuccessfulAgentIds);
265  }
266 
267  $vars['fileData'] = $tableData;
268  return $vars;
269  }
270 
271 
286  private function createFileDataRow($child, $uploadId, $selectedAgentId, $pfileLicenses, $groupId, $editedMappedLicenses, $uri, $ModLicView, &$UniqueTagArray, $isFlat, $latestSuccessfulAgentIds)
287  {
288  $fileId = $child['pfile_fk'];
289  $childUploadTreeId = $child['uploadtree_pk'];
290  $linkUri = '';
291  if (!empty($fileId) && !empty($ModLicView)) {
292  $linkUri = Traceback_uri();
293  $linkUri .= "?mod=view-license&upload=$uploadId&item=$childUploadTreeId";
294  if ($selectedAgentId) {
295  $linkUri .= "&agentId=$selectedAgentId";
296  }
297  }
298 
299  /* Determine link for containers */
300  $isContainer = Iscontainer($child['ufile_mode']);
301  if ($isContainer && !$isFlat) {
302  $fatChild = $this->uploadDao->getFatItemArray($child['uploadtree_pk'], $uploadId, $this->uploadtree_tablename);
303  $uploadtree_pk = $fatChild['item_id'];
304  $childUploadTreeId = $uploadtree_pk;
305  $upload = $this->uploadDao->getUploadEntry($uploadtree_pk, $this->uploadtree_tablename);
306  $fileId = $upload['pfile_fk'];
307  $parent = $upload['realparent'];
308  $parentItemTreeBound = $this->uploadDao->getItemTreeBounds($parent, $this->uploadtree_tablename);
309 
310  $pfileLicenses = array_replace($pfileLicenses,
311  $this->updateTheFindingsAndDecisions($latestSuccessfulAgentIds, $isFlat,
312  $groupId, $editedMappedLicenses, $parentItemTreeBound));
313 
314  $linkUri = "$uri&item=" . $uploadtree_pk;
315  if ($selectedAgentId) {
316  $linkUri .= "&agentId=$selectedAgentId";
317  }
318  $child['ufile_name'] = $fatChild['ufile_name'];
319  if (!Iscontainer($fatChild['ufile_mode'])) {
320  $isContainer = false;
321  }
322  } else if ($isContainer) {
323  $uploadtree_pk = Isartifact($child['ufile_mode']) ? DirGetNonArtifact($childUploadTreeId, $this->uploadtree_tablename) : $childUploadTreeId;
324  $linkUri = "$uri&item=" . $uploadtree_pk;
325  if ($selectedAgentId) {
326  $linkUri .= "&agentId=$selectedAgentId";
327  }
328  }
329 
330  /* Populate the output ($VF) - file list */
331  /* id of each element is its uploadtree_pk */
332  $fileName = $child['ufile_name'];
333  if ($isContainer) {
334  $fileName = "<a href='$linkUri'><span style='color: darkblue'> <b>$fileName</b> </span></a>";
335  } else if (!empty($linkUri)) {
336  $fileName = "<a href='$linkUri'>$fileName</a>";
337  }
338  /* show licenses under file name */
339  $childItemTreeBounds =
340  new ItemTreeBounds($childUploadTreeId, $this->uploadtree_tablename, $child['upload_fk'], $child['lft'], $child['rgt']);
341  if ($isContainer) {
342  $agentFilter = $selectedAgentId ? array($selectedAgentId) : $latestSuccessfulAgentIds;
343  $licenseEntries = $this->licenseDao->getLicenseShortnamesContained($childItemTreeBounds, $agentFilter, array());
344  $editedLicenses = $this->clearingDao->getClearedLicenses($childItemTreeBounds, $groupId);
345  } else {
346  $licenseEntries = array();
347  if (array_key_exists($fileId, $pfileLicenses)) {
348  foreach ($pfileLicenses[$fileId] as $shortName => $rfInfo) {
349  $agentEntries = array();
350  foreach ($rfInfo as $agent => $match) {
351  $agentName = $this->agentNames[$agent];
352  $agentEntry = "<a href='?mod=view-license&upload=$child[upload_fk]&item=$childUploadTreeId&format=text&agentId=$match[agent_id]&licenseId=$match[license_id]#highlight'>" . $agentName . "</a>";
353 
354  if ($match['match_percentage'] > 0) {
355  $agentEntry .= ": $match[match_percentage]%";
356  }
357  $agentEntries[] = $agentEntry;
358  }
359  $licenseEntries[] = $shortName . " [" . implode("][", $agentEntries) . "]";
360  }
361  }
362 
363  /* @var $decision ClearingDecision */
364  if (false !== ($decision = $this->clearingFilter->getDecisionOf($editedMappedLicenses,$childUploadTreeId, $fileId))) {
365  $editedLicenses = $decision->getPositiveLicenses();
366  } else {
367  $editedLicenses = array();
368  }
369  }
370 
371  $concludedLicenses = array();
373  foreach ($editedLicenses as $licenseRef) {
374  $projectedId = $this->licenseProjector->getProjectedId($licenseRef->getId());
375  $projectedName = $this->licenseProjector->getProjectedShortname($licenseRef->getId(),$licenseRef->getShortName());
376  $concludedLicenses[$projectedId] = $projectedName;
377  }
378 
379  $editedLicenseList = implode(', ', $concludedLicenses);
380  $licenseList = implode(', ', $licenseEntries);
381 
382  $fileListLinks = FileListLinks($uploadId, $childUploadTreeId, 0, $fileId, true, $UniqueTagArray, $this->uploadtree_tablename, !$isFlat);
383 
384  $getTextEditUser = _("Edit");
385  $fileListLinks .= "[<a href='#' onclick='openUserModal($childUploadTreeId)' >$getTextEditUser</a>]";
386 
387  if ($isContainer) {
388  $getTextEditBulk = _("Bulk");
389  $fileListLinks .= "[<a href='#' onclick='openBulkModal($childUploadTreeId)' >$getTextEditBulk</a>]";
390  }
391  $fileListLinks .= "<input type='checkbox' id='selectedForIrrelevant' value='".$childUploadTreeId."'>";
392  $filesThatShouldStillBeCleared = array_key_exists($childItemTreeBounds->getItemId()
393  , $this->filesThatShouldStillBeCleared) ? $this->filesThatShouldStillBeCleared[$childItemTreeBounds->getItemId()] : 0;
394 
395  $filesToBeCleared = array_key_exists($childItemTreeBounds->getItemId()
396  , $this->filesToBeCleared) ? $this->filesToBeCleared[$childItemTreeBounds->getItemId()] : 0;
397 
398  $filesCleared = $filesToBeCleared - $filesThatShouldStillBeCleared;
399 
400  $img = ($filesCleared == $filesToBeCleared) ? 'green' : 'red';
401 
402  // override green/red flag with grey flag in case of no_license_found scanner finding
403  if (!empty($licenseList) && empty($editedLicenseList)) {
404  $img = (
405  (strpos($licenseList, LicenseDao::NO_LICENSE_FOUND) !== false)
406  &&
407  (count(explode(",", $licenseList)) == 1)
408  ) ? 'grey' : $img;
409  }
410 
411  // override green/red flag with yellow flag in case of single file with decision type "To Be Discussed"
412  $isDecisionTBD = $this->clearingDao->isDecisionTBD($childUploadTreeId, $groupId);
413  $img = $isDecisionTBD ? 'yellow' : $img;
414 
415  // override green/red flag with greenRed flag in case of single file with decision type "Do Not Use"
416  $isDecisionDNU = $this->clearingDao->isDecisionDNU($childUploadTreeId, $groupId);
417  $img = $isDecisionDNU ? 'redGreen' : $img;
418 
419  return array($fileName, $licenseList, $editedLicenseList, $img, "$filesCleared/$filesToBeCleared", $fileListLinks);
420  }
421 
434  private function updateTheFindingsAndDecisions($agentIds, $isFlat, $groupId,
435  &$editedMappedLicenses, $itemTreeBounds, $nameRange = array())
436  {
440  $pfileLicenses = [];
441  foreach ($agentIds as $agentName => $agentId) {
442  $licensePerPfile = $this->licenseDao->getLicenseIdPerPfileForAgentId(
443  $itemTreeBounds, $agentId, $isFlat, $nameRange);
444  foreach ($licensePerPfile as $pfile => $licenseRow) {
445  foreach ($licenseRow as $licId => $row) {
446  $lic = $this->licenseProjector->getProjectedShortname($licId);
447  $pfileLicenses[$pfile][$lic][$agentName] = $row;
448  }
449  }
450  }
451 
452  if ($this->alreadyClearedUploadTreeView === NULL) {
453  // Initialize the proxy view only once for the complete table
454  $this->alreadyClearedUploadTreeView = new UploadTreeProxy(
455  $itemTreeBounds->getUploadId(),
456  $options = array(
457  UploadTreeProxy::OPT_SKIP_THESE => UploadTreeProxy::OPT_SKIP_ALREADY_CLEARED,
458  UploadTreeProxy::OPT_ITEM_FILTER => "AND (lft BETWEEN " .
459  $itemTreeBounds->getLeft() . " AND " . $itemTreeBounds->getRight() . ")",
460  UploadTreeProxy::OPT_GROUP_ID => $groupId
461  ), $itemTreeBounds->getUploadTreeTableName(),
462  $viewName = 'already_cleared_uploadtree' . $itemTreeBounds->getUploadId());
463 
464  $this->alreadyClearedUploadTreeView->materialize();
465  }
466 
467  if (! $isFlat) {
468  $this->filesThatShouldStillBeCleared = array_replace(
469  $this->filesThatShouldStillBeCleared,
470  $this->alreadyClearedUploadTreeView->countMaskedNonArtifactChildren(
471  $itemTreeBounds->getItemId()));
472  } else {
473  $this->filesThatShouldStillBeCleared = array_replace(
474  $this->filesThatShouldStillBeCleared,
475  $this->alreadyClearedUploadTreeView->getNonArtifactDescendants(
476  $itemTreeBounds));
477  }
478 
479  if ($this->noLicenseUploadTreeView === NULL) {
480  // Initialize the proxy view only once for the complete table
481  $this->noLicenseUploadTreeView = new UploadTreeProxy(
482  $itemTreeBounds->getUploadId(),
483  $options = array(
484  UploadTreeProxy::OPT_SKIP_THESE => "noLicense",
485  UploadTreeProxy::OPT_ITEM_FILTER => "AND (lft BETWEEN " .
486  $itemTreeBounds->getLeft() . " AND " . $itemTreeBounds->getRight() . ")",
487  UploadTreeProxy::OPT_GROUP_ID => $groupId
488  ), $itemTreeBounds->getUploadTreeTableName(),
489  $viewName = 'no_license_uploadtree' . $itemTreeBounds->getUploadId());
490  $this->noLicenseUploadTreeView->materialize();
491  }
492  if (! $isFlat) {
493  $this->filesToBeCleared = array_replace($this->filesToBeCleared,
494  $this->noLicenseUploadTreeView->countMaskedNonArtifactChildren(
495  $itemTreeBounds->getItemId()));
496  } else {
497  $this->filesToBeCleared = array_replace($this->filesToBeCleared,
498  $this->noLicenseUploadTreeView->getNonArtifactDescendants($itemTreeBounds));
499  }
500 
501  $allDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBounds,
502  $groupId, $isFlat);
503  $editedMappedLicenses = array_replace($editedMappedLicenses,
504  $this->clearingFilter->filterCurrentClearingDecisions($allDecisions));
505  return $pfileLicenses;
506  }
507 }
508 
509 register_plugin(new AjaxExplorer());
const PARM_RAW
Definition: common-parm.php:33
Traceback_uri()
Get the URI without query to this location.
updateTheFindingsAndDecisions($agentIds, $isFlat, $groupId, &$editedMappedLicenses, $itemTreeBounds, $nameRange=array())
Fetch the license findings and decisions.
Iscontainer($mode)
Definition: common-dir.php:49
FileListLinks($upload_fk, $uploadtree_pk, $napk, $pfile_pk, $Recurse=True, &$UniqueTagArray=array(), $uploadtree_tablename="uploadtree", $wantTags=true)
Get list of links: [View][Info][Download]
Wrapper class for license map.
Definition: LicenseMap.php:29
DirGetNonArtifact($UploadtreePk, $uploadtree_tablename='uploadtree')
Given an artifact directory (uploadtree_pk), return the first non-artifact directory (uploadtree_pk)...
Definition: common-dir.php:169
GetParm($parameterName, $parameterType)
This function will retrieve the variables and check data types.
Definition: common-parm.php:57
const PARM_INTEGER
Definition: common-parm.php:25
char * uploadtree_tablename
upload.uploadtree_tablename
Definition: adj2nest.c:112
createFileListing($tagId, ItemTreeBounds $itemTreeBounds, &$UniqueTagArray, $selectedAgentId, $groupId, $scanJobProxy)
static getGroupId()
Get the current user&#39;s group id.
Definition: Auth.php:78
TagFilter(&$UploadtreeRows, $tag_pk, $uploadtree_tablename)
Given a list of uploadtree recs, remove recs that do not have $tag_pk.
Traceback_parm_keep($List)
Create a new URI, keeping only these items.
Isartifact($mode)
Definition: common-dir.php:40
materialize()
create temp table
Definition: DbViewProxy.php:51