FOSSology  4.7.1
Open Source License Compliance by Open Source Software
UploadDao.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2018 Siemens AG
4  Authors: Andreas Würl, Steffen Weber
5 
6  SPDX-License-Identifier: GPL-2.0-only
7 */
8 
9 namespace Fossology\Lib\Dao;
10 
21 use Monolog\Logger;
22 use DateTime;
23 
24 require_once(dirname(dirname(__FILE__)) . "/common-dir.php");
25 
26 class UploadDao
27 {
28 
29  const REUSE_NONE = 0;
30  const REUSE_ENHANCED = 2;
31  const REUSE_MAIN = 4;
32  const REUSE_CONF = 16;
33  const REUSE_COPYRIGHT = 128;
34  const UNIFIED_REPORT_HEADINGS = array(
35  "assessment" => array("Assessment Summary" => true),
36  "compliancetasks" => array("Required license compliance tasks" => true),
37  "acknowledgements" => array("Acknowledgements" => true),
38  "exportrestrictions" => array("Export Restrictions" => true),
39  "intellectualProperty" => array("Patent Relevant Statements" => true),
40  "notes" => array("Notes" => true),
41  "scanresults" => array("Results of License Scan" => true),
42  "mainlicenses" => array("Main Licenses" => true),
43  "redlicense" => array("Other OSS Licenses (red) - Do not Use Licenses" => true),
44  "yellowlicense" => array("Other OSS Licenses (yellow) - additional obligations to common rules (e.g. copyleft)" => true),
45  "whitelicense" => array("Other OSS Licenses (white) - only common rules" => true),
46  "overviewwithwithoutobligations" => array("Overview of All Licenses with or without Obligations" => true),
47  "copyrights" => array("Copyrights" => true),
48  "copyrightsuf" => array("Copyrights (User Findings)" => true),
49  "bulkfindings" => array("Bulk Findings" => true),
50  "licensenf" => array("Non-Functional Licenses" => true),
51  "irrelevantfiles" => array("Irrelevant Files" => true),
52  "dnufiles" => array("Do not use Files" => true),
53  "changelog" => array("Clearing Protocol Change Log" => true)
54  );
55  const CLIXML_REPORT_HEADINGS = array(
56  "mainlicensesclixml" => array("Main Licenses" => true),
57  "licensepath" => array("License File Path" => true),
58  "licensehash" => array("License File Hash" => true),
59  "copyrightsclixml" => array("Copyrights" => true),
60  "copyrightpath" => array("Copyright File Path" => true),
61  "copyrighthash" => array("Copyright File Hash" => true),
62  "exportrestrictionsclixml" => array("Export Restrictions(ECC)" => true),
63  "eccpath" => array("ECC File Path" => true),
64  "ecchash" => array("ECC File Hash" => true),
65  "intellectualPropertyclixml" => array("Identified Patent Relevant Analysis(IPRA)" => true),
66  "iprapath" => array("IPRA File Path" => true),
67  "iprahash" => array("IPRA File Hash" => true),
68  "allobligations" => array("All Obligations" => true),
69  "acknowledgementsclixml" => array("Acknowledgements" => true),
70  "irrelevantfilesclixml" => array("Irrelevant Files" => true),
71  "dnufilesclixml" => array("Do not use Files" => true),
72  "notesclixml" => array("Additional Notes" => true)
73  );
75  private $dbManager;
77  private $logger;
79  private $permissionDao;
80 
81  public function __construct(DbManager $dbManager, Logger $logger, UploadPermissionDao $uploadPermissionDao)
82  {
83  $this->dbManager = $dbManager;
84  $this->logger = $logger;
85  $this->permissionDao = $uploadPermissionDao;
86  }
87 
88 
94  public function getUploadEntry($uploadTreeId, $uploadTreeTableName = "uploadtree")
95  {
96  $stmt = __METHOD__ . ".$uploadTreeTableName";
97  $uploadEntry = $this->dbManager->getSingleRow("SELECT * FROM $uploadTreeTableName WHERE uploadtree_pk = $1",
98  array($uploadTreeId), $stmt);
99  if ($uploadEntry) {
100  $uploadEntry['tablename'] = $uploadTreeTableName;
101  }
102  return $uploadEntry;
103  }
104 
111  public function getUploadtreeIdFromPfile($uploadFk, $pfileFk)
112  {
113  $uploadTreeTableName = $this->getUploadtreeTableName($uploadFk);
114  $stmt = __METHOD__ . ".$uploadTreeTableName";
115  $uploadEntry = $this->dbManager->getSingleRow("SELECT uploadtree_pk " .
116  "FROM $uploadTreeTableName " .
117  "WHERE upload_fk = $1 AND pfile_fk = $2",
118  array($uploadFk, $pfileFk), $stmt);
119  return intval($uploadEntry['uploadtree_pk']);
120  }
121 
126  public function getUpload($uploadId)
127  {
128  $stmt = __METHOD__;
129  $row = $this->dbManager->getSingleRow("SELECT * FROM upload WHERE upload_pk = $1",
130  array($uploadId), $stmt);
131 
132  return $row ? Upload::createFromTable($row) : null;
133  }
134 
135  public function getActiveUploadsArray()
136  {
137  $stmt = __METHOD__;
138  $queryResult = $this->dbManager->getRows("SELECT * FROM upload where pfile_fk IS NOT NULL",
139  array(), $stmt);
140 
141  $results = array();
142  foreach ($queryResult as $row) {
143  $results[] = Upload::createFromTable($row);
144  }
145 
146  return $results;
147  }
148 
154  public function getAccessibleUploads($groupId)
155  {
156  $stmt = __METHOD__;
157  $permNone = Auth::PERM_NONE;
158  $sql = "SELECT u.* FROM upload u
159  LEFT JOIN perm_upload p ON p.upload_fk = u.upload_pk AND p.group_fk = $1
160  WHERE u.pfile_fk IS NOT NULL
161  AND (p.perm > $permNone OR u.public_perm > $permNone)";
162 
163  $queryResult = $this->dbManager->getRows($sql, array($groupId), $stmt);
164 
165  $results = array();
166  foreach ($queryResult as $row) {
167  $results[] = Upload::createFromTable($row);
168  }
169 
170  return $results;
171  }
172 
178  public function getItemTreeBounds($itemId, $uploadTreeTableName = "uploadtree")
179  {
180  $uploadEntryData = $this->getUploadEntry($itemId, $uploadTreeTableName);
181  return $this->createItemTreeBounds($uploadEntryData, $uploadTreeTableName);
182  }
183 
189  public function getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId)
190  {
191  $uploadTreeTableName = $this->getUploadtreeTableName($uploadId);
192  return $this->getItemTreeBounds($uploadTreeId, $uploadTreeTableName);
193  }
194 
201  public function getParentItemBounds($uploadId, $uploadTreeTableName = null)
202  {
203  if ($uploadTreeTableName === null) {
204  $uploadTreeTableName = $this->getUploadtreeTableName($uploadId);
205  }
206 
207  $stmt = __METHOD__ . ".$uploadTreeTableName";
208  $parameters = array();
209  $uploadCondition = $this->handleUploadIdForTable($uploadTreeTableName, $uploadId, $parameters);
210 
211  $uploadEntryData = $this->dbManager->getSingleRow("SELECT * FROM $uploadTreeTableName
212  WHERE parent IS NULL
213  $uploadCondition
214  ",
215  $parameters, $stmt);
216 
217  return $uploadEntryData ? $this->createItemTreeBounds($uploadEntryData, $uploadTreeTableName) : false;
218  }
219 
224  public function countPlainFiles(ItemTreeBounds $itemTreeBounds)
225  {
226  $uploadTreeTableName = $itemTreeBounds->getUploadTreeTableName();
227 
228  $stmt = __METHOD__ . ".$uploadTreeTableName";
229  $parameters = array($itemTreeBounds->getLeft(), $itemTreeBounds->getRight());
230  $uploadCondition = $this->handleUploadIdForTable($uploadTreeTableName, $itemTreeBounds->getUploadId(), $parameters);
231 
232  $row = $this->dbManager->getSingleRow("SELECT count(*) as count FROM $uploadTreeTableName
233  WHERE lft BETWEEN $1 AND $2
234  $uploadCondition
235  AND ((ufile_mode & (3<<28))=0)
236  AND pfile_fk != 0",
237  $parameters, $stmt);
238  return intval($row["count"]);
239  }
240 
241  private function handleUploadIdForTable($uploadTreeTableName, $uploadId, &$parameters)
242  {
243  if ($uploadTreeTableName === "uploadtree" || $uploadTreeTableName === "uploadtree_a") {
244  $parameters[] = $uploadId;
245  return " AND upload_fk = $" . count($parameters) . " ";
246  } else {
247  return "";
248  }
249  }
250 
254  public function getStatusTypeMap()
255  {
256  global $container;
258  $uploadStatus = $container->get('upload_status.types');
259  return $uploadStatus->getMap();
260  }
261 
269  public function getStatus($uploadId, $groupId)
270  {
271  if ($this->isAccessible($uploadId, $groupId)) {
272  $row = $this->dbManager->getSingleRow("SELECT status_fk " .
273  "FROM upload_clearing WHERE upload_fk=$1 AND group_fk=$2;",
274  array($uploadId, $groupId));
275  if (false === $row) {
276  return 1;
277  }
278  return $row['status_fk'];
279  } else {
280  throw new \Exception("permission denied");
281  }
282  }
283 
284 
292  public function getAssignee($uploadId, $groupId)
293  {
294  if ($this->isAccessible($uploadId, $groupId)) {
295  $row = $this->dbManager->getSingleRow("SELECT assignee FROM upload_clearing WHERE upload_fk=$1 AND group_fk=$2;",
296  array($uploadId, $groupId));
297  if (false === $row) {
298  return 1;
299  }
300  return $row['assignee'];
301  } else {
302  throw new \Exception("permission denied");
303  }
304  }
305 
313  public function getAssigneeDate(int $uploadId): ?string
314  {
315  $sql = "SELECT MIN(event_ts) as event_ts FROM upload_events WHERE upload_fk = $1 " .
316  "AND event_type = " . UploadEvents::ASSIGNEE_EVENT;
317  $row = $this->dbManager->getSingleRow($sql, [$uploadId], __METHOD__);
318  if (empty($row) || empty($row["event_ts"])) {
319  return null;
320  }
321  return $row["event_ts"];
322  }
323 
330  public function getClosedDate(int $uploadId): ?string
331  {
332  $sql = "SELECT MAX(event_ts) as event_ts FROM upload_events WHERE upload_fk = $1 " .
333  "AND event_type = " . UploadEvents::UPLOAD_CLOSED_EVENT;
334  $row = $this->dbManager->getSingleRow($sql, [$uploadId], __METHOD__);
335  if (empty($row) || empty($row["event_ts"])) {
336  return null;
337  }
338  return $row["event_ts"];
339  }
340 
347  public function getClearingDuration(int $uploadId): array
348  {
349  $batch = $this->getClearingDurationsBatch(array($uploadId));
350  return $batch[$uploadId] ?? ['NA', 0];
351  }
352 
358  public function getClearingDurationsBatch(array $uploadIds): array
359  {
360  if (empty($uploadIds)) {
361  return array();
362  }
363 
364  $uploadIds = array_unique(array_filter($uploadIds));
365  if (empty($uploadIds)) {
366  return array();
367  }
368 
369  $results = array();
370  foreach ($uploadIds as $id) {
371  $results[(int)$id] = array("NA", 0);
372  }
373 
374  $uploadIdsStr = '{' . implode(',', array_map('intval', $uploadIds)) . '}';
375 
376  $sql = "SELECT upload_fk, " .
377  "MIN(CASE WHEN event_type = $2 THEN event_ts END) as assignee_ts, " .
378  "MAX(CASE WHEN event_type = $3 THEN event_ts END) as closed_ts " .
379  "FROM upload_events " .
380  "WHERE upload_fk = ANY($1::int[]) AND event_type IN ($2, $3) " .
381  "GROUP BY upload_fk";
382 
383  $rows = $this->dbManager->getRows($sql, array($uploadIdsStr, UploadEvents::ASSIGNEE_EVENT, UploadEvents::UPLOAD_CLOSED_EVENT), __METHOD__);
384 
385  foreach ($rows as $row) {
386  $id = (int)$row['upload_fk'];
387  $duration = "NA";
388  $durationSort = 0;
389 
390  if (!empty($row['assignee_ts']) && !empty($row['closed_ts'])) {
391  try {
392  $assignDate = new DateTime($row['assignee_ts']);
393  $closingDate = new DateTime($row['closed_ts']);
394  if ($assignDate < $closingDate) {
395  $duration = HumanDuration($closingDate->diff($assignDate));
396  $durationSort = $closingDate->getTimestamp() - $assignDate->getTimestamp();
397  }
398  } catch (\Exception $_) {
399  }
400  }
401  $results[$id] = array($duration, $durationSort);
402  }
403 
404  return $results;
405  }
414  public function getUploadtreeTableName($uploadId)
415  {
416  if (!empty($uploadId)) {
417  $statementName = __METHOD__;
418  $row = $this->dbManager->getSingleRow(
419  "SELECT uploadtree_tablename FROM upload WHERE upload_pk=$1",
420  array($uploadId),
421  $statementName
422  );
423  if (!empty($row['uploadtree_tablename'])) {
424  return $row['uploadtree_tablename'];
425  }
426  }
427  return "uploadtree";
428  }
429 
435  public function getNextItem($uploadId, $itemId, $options = null)
436  {
437  return $this->getItemByDirection($uploadId, $itemId, self::DIR_FWD, $options);
438  }
439 
446  public function getPreviousItem($uploadId, $itemId, $options = null)
447  {
448  return $this->getItemByDirection($uploadId, $itemId, self::DIR_BCK, $options);
449  }
450 
451  const DIR_FWD = 1;
452  const DIR_BCK = -1;
453  const NOT_FOUND = null;
454 
455 
463  public function getItemByDirection($uploadId, $itemId, $direction, $options)
464  {
465  $uploadTreeTableName = $this->getUploadtreeTableName($uploadId);
466  $originItem = $this->getUploadEntry($itemId, $uploadTreeTableName);
467  $originLft = $originItem['lft'];
468 
469  $options[UploadTreeProxy::OPT_ITEM_FILTER] = " AND ut.ufile_mode & (3<<28) = 0";
470  $uploadTreeViewName = 'items2care';
471 
472  if ($direction == self::DIR_FWD) {
473  $uploadTreeViewName .= 'fwd';
474  $options[UploadTreeProxy::OPT_ITEM_FILTER] .= " AND lft>$1";
475  $order = 'ASC';
476  } else {
477  $uploadTreeViewName .= 'bwd';
478  $options[UploadTreeProxy::OPT_ITEM_FILTER] .= " AND lft<$1";
479  $order = 'DESC';
480  }
481 
482  $uploadTreeView = new UploadTreeProxy($uploadId, $options, $uploadTreeTableName, $uploadTreeViewName);
483  $statementName = __METHOD__ . ".$uploadTreeViewName.";
484  $query = $uploadTreeView->getDbViewQuery()." ORDER BY lft $order";
485 
486  $newItemRow = $this->dbManager->getSingleRow("$query LIMIT 1", array($originLft), $statementName);
487  if ($newItemRow) {
488  return $this->createItem($newItemRow, $uploadTreeTableName);
489  } else {
490  return self::NOT_FOUND;
491  }
492  }
493 
494 
499  public function getUploadParent($uploadId)
500  {
501  $uploadTreeTableName = $this->getUploadtreeTableName($uploadId);
502  $statementname = __METHOD__ . $uploadTreeTableName;
503 
504  $parent = $this->dbManager->getSingleRow(
505  "SELECT uploadtree_pk
506  FROM $uploadTreeTableName
507  WHERE upload_fk=$1 AND parent IS NULL", array($uploadId), $statementname);
508  if (false === $parent) {
509  throw new \Exception("Missing upload tree parent for upload");
510  }
511  return $parent['uploadtree_pk'];
512  }
513 
514  public function getLeftAndRight($uploadtreeID, $uploadTreeTableName = "uploadtree")
515  {
516  $statementName = __METHOD__ . $uploadTreeTableName;
517  $leftRight = $this->dbManager->getSingleRow(
518  "SELECT lft,rgt FROM $uploadTreeTableName WHERE uploadtree_pk = $1",
519  array($uploadtreeID), $statementName
520  );
521 
522  return array($leftRight['lft'], $leftRight['rgt']);
523  }
524 
530  public function getContainingFileCount(ItemTreeBounds $itemTreeBounds, UploadTreeProxy $uploadTreeView)
531  {
532  $sql = "SELECT count(*) FROM " . $uploadTreeView->getDbViewName() . " WHERE lft BETWEEN $1 AND $2";
533  $result = $this->dbManager->getSingleRow($sql
534  , array($itemTreeBounds->getLeft(), $itemTreeBounds->getRight()), __METHOD__ . $uploadTreeView->asCTE());
535  return $result['count'];
536  }
537 
544  public function getContainedItems(ItemTreeBounds $itemTreeBounds, $addCondition = "", $addParameters = array())
545  {
546  $uploadTreeTableName = $itemTreeBounds->getUploadTreeTableName();
547 
548  $statementName = __METHOD__ . ".$uploadTreeTableName";
549 
550  $view = new UploadTreeViewProxy($itemTreeBounds, array(UploadTreeViewProxy::CONDITION_PLAIN_FILES));
551 
552  $this->dbManager->prepare($statementName,
553  $view->asCTE() . " SELECT * FROM " . $view->getDbViewName() ." ut ".
554  ($addCondition ? " WHERE " . $addCondition : ''));
555  $res = $this->dbManager->execute($statementName, $addParameters);
556  $items = array();
557 
558  while ($row = $this->dbManager->fetchArray($res)) {
559  $items[] = $this->createItem($row, $uploadTreeTableName);
560  }
561  $this->dbManager->freeResult($res);
562  return $items;
563  }
564 
572  public function addReusedUpload($uploadId, $reusedUploadId, $groupId, $reusedGroupId, $reuseMode=0)
573  {
574  $this->dbManager->insertTableRow('upload_reuse',
575  array('upload_fk'=>$uploadId, 'group_fk'=> $groupId, 'reused_upload_fk'=>$reusedUploadId, 'reused_group_fk'=>$reusedGroupId,'reuse_mode'=>$reuseMode));
576  }
577 
584  public function getReusedUpload($uploadId, $groupId)
585  {
586  $statementName = __METHOD__;
587 
588  $this->dbManager->prepare($statementName,
589  "SELECT reused_upload_fk, reused_group_fk, reuse_mode FROM upload_reuse WHERE upload_fk = $1 AND group_fk=$2 ORDER BY date_added DESC");
590  $res = $this->dbManager->execute($statementName, array($uploadId, $groupId));
591  $reusedPairs = $this->dbManager->fetchAll($res);
592  $this->dbManager->freeResult($res);
593  return $reusedPairs;
594  }
595 
601  protected function createItem($uploadEntry, $uploadTreeTableName)
602  {
603  $itemTreeBounds = new ItemTreeBounds(
604  intval($uploadEntry['uploadtree_pk']),
605  $uploadTreeTableName,
606  intval($uploadEntry['upload_fk']),
607  intval($uploadEntry['lft']), intval($uploadEntry['rgt']));
608 
609  $parent = $uploadEntry['parent'];
610  return new Item(
611  $itemTreeBounds, $parent !== null ? intval($parent) : null, intval($uploadEntry['pfile_fk']), intval($uploadEntry['ufile_mode']), $uploadEntry['ufile_name']
612  );
613  }
614 
621  protected function createItemTreeBounds($uploadEntryData, $uploadTreeTableName)
622  {
623  if ($uploadEntryData === false) {
624  throw new Exception("did not find uploadTreeId in $uploadTreeTableName");
625  }
626  return new ItemTreeBounds(intval($uploadEntryData['uploadtree_pk']), $uploadTreeTableName, intval($uploadEntryData['upload_fk']), intval($uploadEntryData['lft']), intval($uploadEntryData['rgt']));
627  }
628 
634  public function countNonArtifactDescendants(ItemTreeBounds $itemTreeBounds, $isFlat=true)
635  {
636  $stmt=__METHOD__;
637  $sql = "SELECT count(*) FROM ".$itemTreeBounds->getUploadTreeTableName()." ut "
638  . "WHERE ut.upload_fk=$1";
639  $params = array($itemTreeBounds->getUploadId());
640  if (!$isFlat) {
641  $stmt = __METHOD__.'.parent';
642  $params[] = $itemTreeBounds->getItemId();
643  $sql .= " AND ut.ufile_mode & (1<<28) = 0 AND ut.realparent = $2";
644  } else {
645  $params[] = $itemTreeBounds->getLeft();
646  $params[] = $itemTreeBounds->getRight();
647  $sql .= " AND ut.ufile_mode & (3<<28) = 0 AND (ut.lft BETWEEN $2 AND $3)";
648  }
649 
650  $descendants = $this->dbManager->getSingleRow($sql,$params);
651  return $descendants['count'];
652  }
653 
654 
655  public function isAccessible($uploadId, $groupId)
656  {
657  return $this->permissionDao->isAccessible($uploadId, $groupId);
658  }
659 
660  public function isEditable($uploadId, $groupId)
661  {
662  return $this->permissionDao->isEditable($uploadId, $groupId);
663  }
664 
665  public function makeAccessibleToGroup($uploadId, $groupId, $perm=null)
666  {
667  $this->permissionDao->makeAccessibleToGroup($uploadId, $groupId, $perm);
668  }
669 
670  public function makeAccessibleToAllGroupsOf($uploadId, $userId, $perm=null)
671  {
672  $this->permissionDao->makeAccessibleToAllGroupsOf($uploadId, $userId, $perm);
673  }
674 
675  public function filterAccessibleUploads(array $uploadIds, $groupId)
676  {
677  return $this->permissionDao->filterAccessibleUploads($uploadIds, $groupId);
678  }
679 
684  public function getUploadHashes($uploadId)
685  {
686  $pfile = $this->dbManager->getSingleRow('SELECT pfile.* FROM upload, pfile WHERE upload_pk=$1 AND pfile_fk=pfile_pk',
687  array($uploadId), __METHOD__);
688  return array('sha1'=>$pfile['pfile_sha1'],'md5'=>$pfile['pfile_md5'],'sha256'=>$pfile['pfile_sha256']);
689  }
690 
697  public function getFatItemArray($itemId,$uploadId,$uploadtreeTablename)
698  {
699  $sqlChildrenOf = "SELECT COUNT(*) FROM $uploadtreeTablename s
700  WHERE ufile_mode&(1<<28)=0 and s.upload_fk=$2 AND s.realparent=";
701  $sql="WITH RECURSIVE item_path (item_id,num_children,depth,ufile_mode,ufile_name) AS (
702  SELECT uploadtree_pk item_id, ($sqlChildrenOf $1) num_children, 0 depth, ufile_mode, ufile_name
703  FROM $uploadtreeTablename WHERE upload_fk=$2 AND uploadtree_pk=$1
704  UNION
705  SELECT uploadtree_pk item_id, ($sqlChildrenOf ut.uploadtree_pk) num_children,
706  item_path.depth+1 depth, ut.ufile_mode, item_path.ufile_name||'/'||ut.ufile_name ufile_name
707  FROM $uploadtreeTablename ut INNER JOIN item_path ON item_id=ut.realparent
708  WHERE upload_fk=$2 AND ut.ufile_mode&(1<<28)=0 AND num_children<2
709  )
710  SELECT * FROM item_path WHERE num_children!=1 OR ufile_mode&(1<<29)=0 ORDER BY depth DESC LIMIT 1";
711  return $this->dbManager->getSingleRow($sql,array($itemId, $uploadId),__METHOD__.$uploadtreeTablename);
712  }
713 
720  public function getFatItemId($itemId,$uploadId,$uploadtreeTablename)
721  {
722  $itemRow = $this->getFatItemArray($itemId,$uploadId,$uploadtreeTablename);
723  return $itemRow['item_id'];
724  }
725 
730  public function getPFileDataPerFileName(ItemTreeBounds $itemTreeBounds)
731  {
732  $uploadTreeTableName = $itemTreeBounds->getUploadTreeTableName();
733  $statementName = __METHOD__ . '.' . $uploadTreeTableName;
734  $param = array();
735 
736  $param[] = $itemTreeBounds->getLeft();
737  $param[] = $itemTreeBounds->getRight();
738  $condition = " lft BETWEEN $1 AND $2";
739  $condition .= " AND (ufile_mode & (1<<28)) = 0";
740 
741  if ('uploadtree_a' == $uploadTreeTableName) {
742  $param[] = $itemTreeBounds->getUploadId();
743  $condition .= " AND upload_fk=$".count($param);
744  }
745 
746  $sql = "
747 SELECT ufile_name, uploadtree_pk, lft, rgt, ufile_mode,
748  pfile_pk, pfile_md5, pfile_sha1, pfile_sha256
749 FROM $uploadTreeTableName
750  LEFT JOIN pfile
751  ON pfile_fk = pfile_pk
752 WHERE $condition
753 ORDER BY lft asc
754 ";
755 
756  $this->dbManager->prepare($statementName, $sql);
757  $result = $this->dbManager->execute($statementName, $param);
758  $pfilePerFileName = array();
759 
760  $row = $this->dbManager->fetchArray($result);
761  $pathStack = array($row['ufile_name']);
762  $rgtStack = array($row['rgt']);
763  $lastLft = $row['lft'];
764  $this->addToPFilePerFileName($pfilePerFileName, $pathStack, $row);
765  while ($row = $this->dbManager->fetchArray($result)) {
766  if ($row['lft'] < $lastLft) {
767  continue;
768  }
769 
770  $this->updateStackState($pathStack, $rgtStack, $lastLft, $row);
771  $this->addToPFilePerFileName($pfilePerFileName, $pathStack, $row);
772  }
773  $this->dbManager->freeResult($result);
774  return $pfilePerFileName;
775  }
776 
777  private function updateStackState(&$pathStack, &$rgtStack, &$lastLft, $row)
778  {
779  if ($row['lft'] >= $lastLft) {
780  while (count($rgtStack) > 0 && $row['lft'] > $rgtStack[count($rgtStack)-1]) {
781  array_pop($pathStack);
782  array_pop($rgtStack);
783  }
784  if ($row['lft'] > $lastLft) {
785  $pathStack[] = $row['ufile_name'];
786  $rgtStack[] = $row['rgt'];
787  $lastLft = $row['lft'];
788  }
789  }
790  }
791 
792  private function addToPFilePerFileName(&$pfilePerFileName, $pathStack, $row)
793  {
794  if (($row['ufile_mode'] & (1 << 29)) == 0) {
795  $path = implode('/', $pathStack);
796  $pfilePerFileName[$path]['pfile_pk'] = $row['pfile_pk'];
797  $pfilePerFileName[$path]['uploadtree_pk'] = $row['uploadtree_pk'];
798  $pfilePerFileName[$path]['md5'] = $row['pfile_md5'];
799  $pfilePerFileName[$path]['sha1'] = $row['pfile_sha1'];
800  $pfilePerFileName[$path]['sha256'] = $row['pfile_sha256'];
801  }
802  }
803 
809  public function getPFilesDataPerHashAlgo(ItemTreeBounds $itemTreeBounds, $hashAlgo="sha1")
810  {
811  $uploadTreeTableName = $itemTreeBounds->getUploadTreeTableName();
812  $statementName = __METHOD__ . '.' . $uploadTreeTableName;
813  $param = array();
814 
815  $param[] = $itemTreeBounds->getLeft();
816  $param[] = $itemTreeBounds->getRight();
817  $condition = " lft BETWEEN $1 AND $2";
818  $condition .= " AND (ufile_mode & (1<<28)) = 0";
819 
820  if ('uploadtree_a' == $uploadTreeTableName) {
821  $param[] = $itemTreeBounds->getUploadId();
822  $condition .= " AND upload_fk=$".count($param);
823  }
824  $condition .= " AND pfile_$hashAlgo IS NOT NULL";
825 
826  $sql = "
827 SELECT pfile_fk, uploadtree_pk, ufile_mode, pfile_$hashAlgo as hash
828 FROM $uploadTreeTableName
829  LEFT JOIN pfile
830  ON pfile_fk = pfile_pk
831 WHERE $condition
832 ORDER BY lft asc
833 ";
834 
835  $this->dbManager->prepare($statementName, $sql);
836  $result = $this->dbManager->execute($statementName, $param);
837 
838  $pfilePerHashAlgo = array();
839  while ($row = $this->dbManager->fetchArray($result)) {
840  if (($row['ufile_mode']&(1<<29)) == 0) {
841  $pfilePerHashAlgo[strtolower($row['hash'])][] = array('pfile_pk' => $row['pfile_fk'],
842  'uploadtree_pk' => $row['uploadtree_pk']);
843  }
844  }
845  $this->dbManager->freeResult($result);
846  return $pfilePerHashAlgo;
847  }
848 
849 
850  /* @param int $uploadId
851  * @return array
852  */
853  public function getReportInfo($uploadId)
854  {
855  $stmt = __METHOD__;
856  $sql = "SELECT * FROM report_info WHERE upload_fk = $1";
857  $row = $this->dbManager->getSingleRow($sql, array($uploadId), $stmt);
858 
859  if (empty($row)) {
860  $this->dbManager->begin();
861  $stmt = __METHOD__.'ifempty';
862  $sql = "INSERT INTO report_info (upload_fk) VALUES ($1) RETURNING *";
863  $row = $this->dbManager->getSingleRow($sql, array($uploadId), $stmt);
864  $this->dbManager->commit();
865  }
866  return $row;
867  }
868 
874  private function getUserSPDXDefaultsForUpload($uploadId)
875  {
876  $stmt = __METHOD__ . '.getOwner';
877  $sql = "SELECT user_fk FROM upload WHERE upload_pk = $1";
878  $uploadOwner = $this->dbManager->getSingleRow($sql, array($uploadId), $stmt);
879 
880  if (empty($uploadOwner)) {
881  return "unchecked,unchecked,unchecked";
882  }
883 
884  $userId = $uploadOwner['user_fk'];
885 
886  $stmt = __METHOD__ . '.getUserDefaults';
887  $sql = "SELECT spdx_settings FROM users WHERE user_pk = $1";
888  $userDefaults = $this->dbManager->getSingleRow($sql, array($userId), $stmt);
889 
890  if (empty($userDefaults) || empty($userDefaults['spdx_settings'])) {
891  return "unchecked,unchecked,unchecked";
892  }
893 
894  $settings = explode(',', $userDefaults['spdx_settings']);
895  if (count($settings) < 3) {
896  $settings = array_pad($settings, 3, 'unchecked');
897  }
898 
899  $osselotExport = $settings[0];
900  $spdxLicenseComment = $settings[1];
901  $ignoreFilesWOInfo = $settings[2];
902 
903  $result = "$spdxLicenseComment,$ignoreFilesWOInfo,$osselotExport";
904 
905  return $result;
906  }
907 
915  public function updateReportInfo($uploadId, $column, $value)
916  {
917  if ($column === "ri_unifiedcolumns") {
918  $value = json_decode($value, true);
919  $oldValues = $this->getReportInfo($uploadId)["ri_unifiedcolumns"];
920  if (!empty($oldValues)) {
921  $oldValues = json_decode($oldValues, true);
922  } else {
923  $oldValues = self::UNIFIED_REPORT_HEADINGS;
924  }
925  foreach ($value as $key => $val) {
926  $newValText = array_keys($val)[0];
927  $newValValue = array_values($val)[0];
928  $newValValue = ($newValValue === true || $newValValue == "true") ? "on" : null;
929  $oldValues[$key] = [$newValText => $newValValue];
930  }
931  $value = json_encode($oldValues);
932  } elseif ($column === "ri_excluded_obligations") {
933  $value = json_decode($value, true);
934  $oldValues = $this->getReportInfo($uploadId)["ri_excluded_obligations"];
935  if (!empty($oldValues)) {
936  $oldValues = json_decode($oldValues, true);
937  } else {
938  $oldValues = [];
939  }
940  foreach ($value as $key => $newValue) {
941  $oldValues[$key] = $newValue;
942  }
943  $value = json_encode($oldValues);
944  } elseif ($column === "ri_globaldecision") {
945  $value = filter_var($value, FILTER_VALIDATE_BOOL);
946  }
947 
948  $sql = "UPDATE report_info SET $column = $2 WHERE upload_fk = $1;";
949  $stmt = __METHOD__ . "updateReportInfo" . $column;
950  $this->dbManager->getSingleRow($sql, [$uploadId, $value], $stmt);
951  return true;
952  }
953 
954  /* @param int $uploadId
955  * @return int
956  */
957  public function getGlobalDecisionSettingsFromInfo($uploadId, $setGlobal=null)
958  {
959  $stmt = __METHOD__ . 'get';
960  $sql = "SELECT ri_globaldecision, ri_spdx_selection FROM report_info WHERE upload_fk = $1";
961  $row = $this->dbManager->getSingleRow($sql, array($uploadId), $stmt);
962  if (empty($row)) {
963  if ($setGlobal === null) {
964  // Old upload, set default value to enable
965  $setGlobal = 1;
966  }
967  $stmt = __METHOD__ . 'ifempty';
968  $userSPDXDefaults = $this->getUserSPDXDefaultsForUpload($uploadId);
969  $sql = "INSERT INTO report_info (upload_fk, ri_globaldecision, ri_spdx_selection) VALUES ($1, $2, $3) RETURNING ri_globaldecision";
970  $row = $this->dbManager->getSingleRow($sql, array($uploadId, $setGlobal, $userSPDXDefaults), $stmt);
971 
972  }
973 
974  if (!empty($setGlobal)) {
975  $stmt = __METHOD__ . 'update';
976  $sql = "UPDATE report_info SET ri_globaldecision = $2 WHERE upload_fk = $1 RETURNING ri_globaldecision";
977  $row = $this->dbManager->getSingleRow($sql, array($uploadId, $setGlobal), $stmt);
978  }
979 
980  return $row['ri_globaldecision'];
981  }
982 
988  public function getUploadHashesFromPfileId($pfilePk)
989  {
990  $stmt = __METHOD__."getUploadHashesFromPfileId";
991  $sql = "SELECT * FROM pfile WHERE pfile_pk = $1";
992  $row = $this->dbManager->getSingleRow($sql, array($pfilePk), $stmt);
993 
994  return ["sha1" => $row["pfile_sha1"], "md5" => $row["pfile_md5"], "sha256" => $row["pfile_sha256"]];
995  }
996 
1002  public function insertReportConfReuse($uploadId, $reusedUploadId)
1003  {
1004  $stmt = __METHOD__ . ".checkReused";
1005  $sql = "SELECT 1 AS exists FROM report_info WHERE upload_fk = $1 LIMIT 1;";
1006  $row = $this->dbManager->getSingleRow($sql, array($reusedUploadId), $stmt);
1007 
1008  if (empty($row['exists'])) {
1009  return false;
1010  }
1011 
1012  $this->dbManager->begin();
1013 
1014  $stmt = __METHOD__ . ".removeExists";
1015  $sql = "DELETE FROM report_info WHERE upload_fk = $1;";
1016  $this->dbManager->getSingleRow($sql, [$uploadId], $stmt);
1017 
1018  $stmt = __METHOD__ . ".getAllColumns";
1019  $sql = "SELECT string_agg(column_name, ',') AS columns
1020  FROM information_schema.columns
1021  WHERE table_name = 'report_info'
1022  AND column_name != 'ri_pk'
1023  AND column_name != 'upload_fk';";
1024  $row = $this->dbManager->getSingleRow($sql, [], $stmt);
1025  $columns = $row['columns'];
1026 
1027  $stmt = __METHOD__."CopyinsertReportConfReuse";
1028  $this->dbManager->prepare($stmt,
1029  "INSERT INTO report_info(upload_fk, $columns)
1030  SELECT $1, $columns
1031  FROM report_info WHERE upload_fk = $2"
1032  );
1033  $this->dbManager->freeResult($this->dbManager->execute(
1034  $stmt, array($uploadId, $reusedUploadId)
1035  ));
1036 
1037  $this->dbManager->commit();
1038  return true;
1039  }
1040 }
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
getUploadtreeIdFromPfile($uploadFk, $pfileFk)
Definition: UploadDao.php:111
getParentItemBounds($uploadId, $uploadTreeTableName=null)
Definition: UploadDao.php:201
getReusedUpload($uploadId, $groupId)
Definition: UploadDao.php:584
createItem($uploadEntry, $uploadTreeTableName)
Definition: UploadDao.php:601
addReusedUpload($uploadId, $reusedUploadId, $groupId, $reusedGroupId, $reuseMode=0)
Definition: UploadDao.php:572
countNonArtifactDescendants(ItemTreeBounds $itemTreeBounds, $isFlat=true)
Definition: UploadDao.php:634
getClearingDuration(int $uploadId)
Definition: UploadDao.php:347
createItemTreeBounds($uploadEntryData, $uploadTreeTableName)
Definition: UploadDao.php:621
getUploadHashesFromPfileId($pfilePk)
Get Pfile hashes from the pfile id.
Definition: UploadDao.php:988
getPFileDataPerFileName(ItemTreeBounds $itemTreeBounds)
Definition: UploadDao.php:730
getContainingFileCount(ItemTreeBounds $itemTreeBounds, UploadTreeProxy $uploadTreeView)
Definition: UploadDao.php:530
getFatItemId($itemId, $uploadId, $uploadtreeTablename)
Definition: UploadDao.php:720
getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId)
Definition: UploadDao.php:189
getAssigneeDate(int $uploadId)
Definition: UploadDao.php:313
getPFilesDataPerHashAlgo(ItemTreeBounds $itemTreeBounds, $hashAlgo="sha1")
Definition: UploadDao.php:809
getItemByDirection($uploadId, $itemId, $direction, $options)
Definition: UploadDao.php:463
getClearingDurationsBatch(array $uploadIds)
Definition: UploadDao.php:358
getFatItemArray($itemId, $uploadId, $uploadtreeTablename)
Definition: UploadDao.php:697
countPlainFiles(ItemTreeBounds $itemTreeBounds)
Definition: UploadDao.php:224
getNextItem($uploadId, $itemId, $options=null)
Definition: UploadDao.php:435
getClosedDate(int $uploadId)
Definition: UploadDao.php:330
updateReportInfo($uploadId, $column, $value)
Update report info for upload.
Definition: UploadDao.php:915
getPreviousItem($uploadId, $itemId, $options=null)
Definition: UploadDao.php:446
getItemTreeBounds($itemId, $uploadTreeTableName="uploadtree")
Definition: UploadDao.php:178
getUploadtreeTableName($uploadId)
Get the uploadtree table name for this upload_pk If upload_pk does not exist, return "uploadtree".
Definition: UploadDao.php:414
getAssignee($uploadId, $groupId)
Get the upload assignee id.
Definition: UploadDao.php:292
getUploadEntry($uploadTreeId, $uploadTreeTableName="uploadtree")
Definition: UploadDao.php:94
insertReportConfReuse($uploadId, $reusedUploadId)
Definition: UploadDao.php:1002
getUserSPDXDefaultsForUpload($uploadId)
Definition: UploadDao.php:874
getStatus($uploadId, $groupId)
Get the upload status.
Definition: UploadDao.php:269
This class contains the events for the upload_events table.
Fossology exception.
Definition: Exception.php:15
asCTE()
Common Table Expressions.
Definition: DbViewProxy.php:69
HumanDuration(DateInterval $duration)
Convert DateInterval to Human readable format.
Definition: common-ui.php:120
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16