FOSSology  4.7.1
Open Source License Compliance by Open Source Software
change-license-bulk.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2015, 2018 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
14 use Symfony\Component\HttpFoundation\JsonResponse;
15 use Symfony\Component\HttpFoundation\Request;
16 
18 {
19  const NAME = "change-license-bulk";
21  private $licenseDao;
23  private $dbManager;
25  private $uploadDao;
26 
27  function __construct()
28  {
29  parent::__construct(self::NAME, array(
30  self::TITLE => _("Private: schedule a bulk scan from post"),
31  self::PERMISSION => Auth::PERM_WRITE
32  ));
33 
34  $this->dbManager = $this->getObject('db.manager');
35  $this->licenseDao = $this->getObject('dao.license');
36  $this->uploadDao = $this->getObject('dao.upload');
37  }
38 
43  public function handle(Request $request)
44  {
45  $uploadTreeId = $request->get('uploadTreeId');
46  $uploadTreeId = strpos($uploadTreeId, ',') !== false
47  ? explode(',', $uploadTreeId)
48  : intval($uploadTreeId);
49 
50  if (empty($uploadTreeId)) {
51  return new JsonResponse(array("error" => 'bad request'), JsonResponse::HTTP_BAD_REQUEST);
52  }
53 
54  try {
55  $jobQueueId = $this->scheduleBulkScan($uploadTreeId, $request);
56  } catch (Exception $ex) {
57  $errorMsg = $ex->getMessage();
58  return new JsonResponse(array("error" => $errorMsg), JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
59  }
61 
62  return new JsonResponse(array("jqid" => $jobQueueId));
63  }
64 
71  private function scheduleBulkScan($uploadTreeId, Request $request)
72  {
73  if (is_array($uploadTreeId)) {
74  $jqId = array();
75  foreach ($uploadTreeId as $uploadTreePk) {
76  $jqId[] = $this->getJobQueueId($uploadTreePk, $request);
77  }
78  return $jqId;
79  } else {
80  return $this->getJobQueueId($uploadTreeId, $request);
81  }
82  }
89  private function getJobQueueId($uploadTreeId, Request $request)
90  {
91  $uploadEntry = $this->uploadDao->getUploadEntry($uploadTreeId);
92  $uploadId = intval($uploadEntry['upload_fk']);
93  $userId = Auth::getUserId();
94  $groupId = Auth::getGroupId();
95 
96  if ($uploadId <= 0 || !$this->uploadDao->isAccessible($uploadId, $groupId)) {
97  throw new Exception('permission denied');
98  }
99 
100  $bulkScope = $request->get('bulkScope');
101  switch ($bulkScope) {
102  case 'u':
103  $uploadTreeTable = $this->uploadDao->getUploadtreeTableName($uploadId);
104  $topBounds = $this->uploadDao->getParentItemBounds($uploadId, $uploadTreeTable);
105  $uploadTreeId = $topBounds->getItemId();
106  break;
107 
108  case 'f':
109  if (!Isdir($uploadEntry['ufile_mode']) &&
110  !Iscontainer($uploadEntry['ufile_mode']) &&
111  !Isartifact($uploadEntry['ufile_mode'])) {
112  $uploadTreeId = $uploadEntry['parent'] ?: $uploadTreeId;
113  }
114  break;
115 
116  default:
117  throw new InvalidArgumentException('bad scope request');
118  }
119 
120  $refText = $request->get('refText');
121  $actions = $request->get('bulkAction');
122  $ignoreIrrelevantFiles = (intval($request->get('ignoreIrre')) == 1);
123  $scanFindingsOnly = boolval(intval($request->get('scanOnlyFindings')));
124  $delimiters = $request->get('delimiters');
125 
126  $licenseRemovals = array();
127  foreach ($actions as $licenseAction) {
128  $licenseRemovals[$licenseAction['licenseId']] = array(($licenseAction['action']=='Remove'), $licenseAction['comment'], $licenseAction['reportinfo'], $licenseAction['acknowledgement']);
129  }
130  $bulkId = $this->licenseDao->insertBulkLicense($userId, $groupId,
131  $uploadTreeId, $licenseRemovals, $refText, $ignoreIrrelevantFiles,
132  $delimiters, $scanFindingsOnly);
133 
134  if ($bulkId <= 0) {
135  throw new Exception('cannot insert bulk reference');
136  }
137 
138  // Handle adding text phrase to custom_phrase table if checkbox is checked
139  $addToCustomPhrase = intval($request->get('addToCustomPhrase'));
140  if ($addToCustomPhrase == 1) {
141  $this->importBulkDataToCustomPhrase($bulkId, $userId, $groupId);
142  }
143  $upload = $this->uploadDao->getUpload($uploadId);
144  $uploadName = $upload->getFilename();
145  $job_pk = JobAddJob($userId, $groupId, $uploadName, $uploadId);
147  $deciderPlugin = plugin_find("agent_deciderjob");
148 
149  $dependecies = array(array('name' => 'agent_monk_bulk', 'args' => $bulkId));
150 
151  $conflictStrategyId = intval($request->get('forceDecision'));
152  $errorMsg = '';
153  $jqId = $deciderPlugin->AgentAdd($job_pk, $uploadId, $errorMsg, $dependecies, $conflictStrategyId);
154 
155  if (!empty($errorMsg)) {
156  throw new Exception(str_replace('<br>', "\n", $errorMsg));
157  }
158  return $jqId;
159  }
160 
170  private function importBulkDataToCustomPhrase($bulkId, $userId, $groupId)
171  {
172  // Fetch the bulk reference text from license_ref_bulk
173  $bulkDataSql = "SELECT rf_text FROM license_ref_bulk WHERE lrb_pk = $1";
174  $this->dbManager->prepare($bulkStmt = __METHOD__ . ".getBulkData", $bulkDataSql);
175  $bulkResult = $this->dbManager->execute($bulkStmt, array($bulkId));
176  $bulkRow = $this->dbManager->fetchArray($bulkResult);
177  $this->dbManager->freeResult($bulkResult);
178 
179  if ($bulkRow === false) {
180  error_log("Failed to fetch bulk data for lrb_pk: $bulkId");
181  return;
182  }
183 
184  $refText = $bulkRow['rf_text'];
185  $textMd5 = md5($refText);
186 
187  // Check if duplicate exists
188  $checkSql = "SELECT cp_pk FROM custom_phrase WHERE text_md5 = $1";
189  $this->dbManager->prepare($checkStmt = __METHOD__ . ".checkDuplicate", $checkSql);
190  $checkResult = $this->dbManager->execute($checkStmt, array($textMd5));
191  $existingPhrase = $this->dbManager->fetchArray($checkResult);
192  $this->dbManager->freeResult($checkResult);
193 
194  if ($existingPhrase !== false) {
195  // Duplicate exists, skip insertion
196  error_log("Custom phrase with MD5 hash $textMd5 already exists. Skipping insertion.");
197  return;
198  }
199 
200  // Fetch associated licenses from license_set_bulk (both adding and removing licenses)
201  $licensesSql = "SELECT rf_fk, COALESCE(removing, false) as removing FROM license_set_bulk
202  WHERE lrb_fk = $1";
203  $this->dbManager->prepare($licenseStmt = __METHOD__ . ".getLicenses", $licensesSql);
204  $licensesResult = $this->dbManager->execute($licenseStmt, array($bulkId));
205 
206  $licenses = array();
207  while ($licenseRow = $this->dbManager->fetchArray($licensesResult)) {
208  $licenses[] = array(
209  'rf_fk' => intval($licenseRow['rf_fk']),
210  'removing' => $licenseRow['removing'] === 't' || $licenseRow['removing'] === true
211  );
212  }
213  $this->dbManager->freeResult($licensesResult);
214 
215  // Start transaction to insert into custom_phrase
216  $this->dbManager->begin();
217  try {
218  // Insert into custom_phrase table
219  $insertSql = "INSERT INTO custom_phrase
220  (text, text_md5, acknowledgement, comments, user_fk, group_fk, is_active, created_date)
221  VALUES ($1, $2, $3, $4, $5, $6, $7, CURRENT_TIMESTAMP) RETURNING cp_pk";
222  $params = array($refText, $textMd5, '', '', $userId, $groupId, 'true');
223  $this->dbManager->prepare($insertStmt = __METHOD__ . ".insertPhrase", $insertSql);
224  $result = $this->dbManager->execute($insertStmt, $params);
225  $row = $this->dbManager->fetchArray($result);
226 
227  if ($row === false) {
228  $this->dbManager->freeResult($result);
229  throw new Exception('Failed to insert custom phrase');
230  }
231 
232  $cpPk = $row['cp_pk'];
233  $this->dbManager->freeResult($result);
234 
235  // Insert license associations into custom_phrase_license_map
236  if (!empty($licenses)) {
237  $mapSql = "INSERT INTO custom_phrase_license_map (cp_fk, rf_fk, removing) VALUES ($1, $2, $3)";
238  $this->dbManager->prepare($mapStmt = __METHOD__ . ".insertLicenseMap", $mapSql);
239 
240  foreach ($licenses as $license) {
241  $mapResult = $this->dbManager->execute($mapStmt, array($cpPk, $license['rf_fk'], $license['removing'] ? 'true' : 'false'));
242  $this->dbManager->freeResult($mapResult);
243  }
244  }
245 
246  $this->dbManager->commit();
247  error_log("Custom phrase imported successfully from bulk data. cp_pk: $cpPk, lrb_pk: $bulkId");
248  } catch (Exception $e) {
249  $this->dbManager->rollback();
250  error_log("Error importing bulk data to custom phrase: " . $e->getMessage());
251  // Don't throw exception to avoid breaking the bulk scan
252  // Just log the error and continue
253  }
254  }
255 }
256 
257 register_plugin(new ChangeLicenseBulk());
scheduleBulkScan($uploadTreeId, Request $request)
importBulkDataToCustomPhrase($bulkId, $userId, $groupId)
handle(Request $request)
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
ReportCachePurgeAll()
Purge all records from the report cache.
Isdir($mode)
Definition: common-dir.php:20
Isartifact($mode)
Definition: common-dir.php:29
Iscontainer($mode)
Definition: common-dir.php:38
plugin_find($pluginName)
Given the official name of a plugin, return the $Plugins object.
#define PERM_WRITE
Read-Write permission.
Definition: libfossology.h:33
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16