FOSSology  4.5.1
Open Source License Compliance by Open Source Software
agent-reuser.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2018 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
14 namespace Fossology\Reuser;
15 
23 use Symfony\Component\HttpFoundation\Request;
24 
25 include_once(dirname(__DIR__) . "/agent/version.php");
26 
32 {
33  const UPLOAD_TO_REUSE_SELECTOR_NAME = 'uploadToReuse';
34  const REUSE_MODE = 'reuseMode';
35 
39  private $uploadDao;
40 
41  public function __construct()
42  {
43  $this->Name = "agent_reuser";
44  $this->Title = _("Reuse of License Clearing");
45  $this->AgentName = "reuser";
46 
47  parent::__construct();
48 
49  $this->uploadDao = $GLOBALS['container']->get('dao.upload');
50  }
51 
57  public function renderContent(&$vars)
58  {
59  $reuserPlugin = plugin_find('plugin_reuser');
60  return $reuserPlugin->renderContent($vars);
61  }
62 
68  public function renderFoot(&$vars)
69  {
70  $reuserPlugin = plugin_find('plugin_reuser');
71  return $reuserPlugin->renderFoot($vars);
72  }
73 
79  public function getScriptIncludes(&$vars)
80  {
81  $reuserPlugin = plugin_find('plugin_reuser');
82  return $reuserPlugin->getScriptIncludes($vars);
83  }
84 
89  public function preInstall()
90  {
91  menu_insert("ParmAgents::" . $this->Title, 0, $this->Name);
92  }
93 
102  public function scheduleAgent($jobId, $uploadId, &$errorMsg, $request)
103  {
104  if ($request->get('reuseSource') === 'osselot') {
105  return $this->scheduleOsselotImportDirect($jobId, $uploadId, $errorMsg, $request);
106  }
107 
108  $reuseUploadPair = explode(',', $request->get(self::UPLOAD_TO_REUSE_SELECTOR_NAME), 2);
109  if (count($reuseUploadPair) == 2) {
110  list($reuseUploadId, $reuseGroupId) = $reuseUploadPair;
111  } else {
112  $errorMsg .= 'no reuse upload id given';
113  return -1;
114  }
115  $groupId = $request->get('groupId', Auth::getGroupId());
116  $getReuseValue = $request->get(self::REUSE_MODE) ?: array();
117  $reuserDependencies = array("agent_adj2nest");
118 
119  $reuseMode = UploadDao::REUSE_NONE;
120  foreach ($getReuseValue as $currentReuseValue) {
121  switch ($currentReuseValue) {
122  case 'reuseMain':
123  $reuseMode |= UploadDao::REUSE_MAIN;
124  break;
125  case 'reuseEnhanced':
126  $reuseMode |= UploadDao::REUSE_ENHANCED;
127  break;
128  case 'reuseConf':
129  $reuseMode |= UploadDao::REUSE_CONF;
130  break;
131  case 'reuseCopyright':
132  $reuseMode |= UploadDao::REUSE_COPYRIGHT;
133  break;
134  }
135  }
136 
137  list($agentDeps, $scancodeDeps) = $this->getReuserDependencies($request);
138  $reuserDependencies = array_unique(array_merge($reuserDependencies, $agentDeps));
139  if (!empty($scancodeDeps)) {
140  $reuserDependencies[] = $scancodeDeps;
141  }
142 
143  $this->createPackageLink($uploadId, $reuseUploadId, $groupId, $reuseGroupId,
144  $reuseMode);
145 
146  return $this->doAgentAdd($jobId, $uploadId, $errorMsg,
147  $reuserDependencies, $uploadId, null, $request);
148  }
149 
150  private function scheduleOsselotImportDirect(int $jobId, int $uploadId, string &$errorMsg, Request $request): int
151  {
152  $pkg = trim((string) $request->get('osselotPackage'));
153  $ver = trim((string) $request->get('osselotVersions'));
154  if (empty($pkg) || empty($ver)) {
155  $errorMsg .= 'Package name and version are required';
156  return -1;
157  }
158  try {
159  $helper = new OsselotLookupHelper();
160  $cachedPath = $helper->fetchSpdxFile($pkg, $ver);
161 
162  if (!$cachedPath || !is_file($cachedPath) || !is_readable($cachedPath)) {
163  throw new \RuntimeException("Could not fetch or read SPDX file for {$pkg}:{$ver}");
164  }
165 
166  global $SysConf;
167  $fileBase = $SysConf['FOSSOLOGY']['path'] . "/ReportImport/";
168 
169  if (!is_dir($fileBase) && !mkdir($fileBase, 0755, true)) {
170  throw new \RuntimeException('Failed to create ReportImport directory');
171  }
172 
173  $originalName = basename($cachedPath);
174  if (!str_ends_with($originalName, '.rdf.xml')) {
175  $baseName = pathinfo($originalName, PATHINFO_FILENAME);
176  $originalName = str_ends_with($originalName, '.rdf') ?
177  $baseName . '.rdf.xml' : $originalName . '.rdf.xml';
178  }
179 
180  $targetFile = time() . '_' . random_int(0, getrandmax()) . '_' . $originalName;
181  $targetPath = $fileBase . $targetFile;
182 
183  if (!copy($cachedPath, $targetPath)) {
184  throw new \RuntimeException('Failed to copy SPDX file');
185  }
186 
187  $reportImportAgent = plugin_find('agent_reportImport');
188  if (!$reportImportAgent || !method_exists($reportImportAgent, 'addReport') ||
189  !method_exists($reportImportAgent, 'setAdditionalJqCmdArgs') ||
190  !method_exists($reportImportAgent, 'AgentAdd')) {
191  throw new \RuntimeException('agent_reportImport plugin not available or missing methods');
192  }
193 
194  $importReq = new Request();
195 
196  $addNewLicensesAs = $request->get('osselotAddNewLicensesAs', 'candidate');
197  if (!in_array($addNewLicensesAs, ['candidate', 'approved', 'rejected'], true)) {
198  $addNewLicensesAs = 'candidate';
199  }
200  $importReq->request->set('addNewLicensesAs', $addNewLicensesAs);
201 
202  $booleanOptions = [
203  'addLicenseInfoFromInfoInFile', 'addLicenseInfoFromConcluded',
204  'addConcludedAsDecisions', 'addConcludedAsDecisionsOverwrite',
205  'addConcludedAsDecisionsTBD', 'addCopyrights'
206  ];
207 
208  foreach ($booleanOptions as $key) {
209  $fullKey = 'osselot' . ucfirst($key);
210  $rawValue = $request->get($fullKey);
211  $finalValue = $rawValue ? 'true' : 'false';
212  $importReq->request->set($key, $finalValue);
213  }
214 
215  $licenseMatch = $request->get('osselotLicenseMatch', 'spdxid');
216  if (!in_array($licenseMatch, ['spdxid', 'name', 'text'], true)) {
217  $licenseMatch = 'spdxid';
218  }
219  $importReq->request->set('licenseMatch', $licenseMatch);
220 
221  $jqCmdArgs = $reportImportAgent->addReport($targetFile);
222  $additionalArgs = $reportImportAgent->setAdditionalJqCmdArgs($importReq);
223  $jqCmdArgs .= $additionalArgs;
224 
225  $error = "";
226  $dependencies = array();
227  $jobQueueId = $reportImportAgent->AgentAdd($jobId, $uploadId, $error, $dependencies, $jqCmdArgs);
228 
229  if ($jobQueueId < 0) {
230  throw new \RuntimeException("Cannot schedule job: " . $error);
231  }
232 
233  return intval($jobQueueId);
234 
235  } catch (\Throwable $e) {
236  if (isset($targetPath) && file_exists($targetPath)) {
237  unlink($targetPath);
238  }
239  $errorMsg .= $e->getMessage();
240  error_log("OSSelot import error: " . $e->getMessage());
241  return -1;
242  }
243  }
244 
253  protected function createPackageLink($uploadId, $reuseUploadId, $groupId, $reuseGroupId, $reuseMode=0)
254  {
255  /* @var $packageDao PackageDao */
256  $packageDao = $GLOBALS['container']->get('dao.package');
257  $newUpload = $this->uploadDao->getUpload($uploadId);
258  $uploadForReuse = $this->uploadDao->getUpload($reuseUploadId);
259 
260  $package = $packageDao->findPackageForUpload($reuseUploadId);
261 
262  if ($package === null) {
263  $packageName = StringOperation::getCommonHead($uploadForReuse->getFilename(), $newUpload->getFilename());
264  $package = $packageDao->createPackage($packageName ?: $uploadForReuse->getFilename());
265  $packageDao->addUploadToPackage($reuseUploadId, $package);
266  }
267 
268  $packageDao->addUploadToPackage($uploadId, $package);
269 
270  $this->uploadDao->addReusedUpload($uploadId, $reuseUploadId, $groupId, $reuseGroupId, $reuseMode);
271  }
272 
278  private function getReuserDependencies($request)
279  {
280  $dependencies = array();
281  $scancodeDeps = [];
282  if ($request->get("Check_agent_nomos", false)) {
283  $dependencies[] = "agent_nomos";
284  }
285  if ($request->get("Check_agent_monk", false)) {
286  $dependencies[] = "agent_monk";
287  }
288  if ($request->get("Check_agent_ojo", false)) {
289  $dependencies[] = "agent_ojo";
290  }
291  if ($request->get("Check_agent_ninka", false)) {
292  $dependencies[] = "agent_ninka";
293  }
294  if ($request->get("Check_agent_copyright", false)) {
295  $dependencies[] = "agent_copyright";
296  }
297  if (!empty($request->get("scancodeFlags", []))) {
301  $agentScanCode = plugin_find('agent_scancode');
302  $flags = $request->get('scancodeFlags');
303  $unpackArgs = intval($request->get('scm', 0)) == 1 ? 'I' : '';
304  $scancodeDeps = [
305  "name" => "agent_scancode",
306  "args" => $agentScanCode->getScanCodeArgs($flags, $unpackArgs)
307  ];
308  }
309  return [$dependencies, $scancodeDeps];
310  }
311 }
312 
313 register_plugin(new ReuserAgentPlugin());
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
static getGroupId()
Get the current user's group id.
Definition: Auth.php:80
doAgentAdd($jobId, $uploadId, &$errorMsg, $dependencies, $jqargs="", $jq_cmd_args=null, $request=null)
UI element for reuser during Uploading new package.
scheduleAgent($jobId, $uploadId, &$errorMsg, $request)
Get parameters from request and add to job queue.
renderContent(&$vars)
Render twig templates for plugin_reuser.
const REUSE_MODE
Form element name for main license to reuse.
const UPLOAD_TO_REUSE_SELECTOR_NAME
Form element name for main license to reuse.
createPackageLink($uploadId, $reuseUploadId, $groupId, $reuseGroupId, $reuseMode=0)
Create links between old and new upload.
getScriptIncludes(&$vars)
Get script tags to include before rendering foot.
renderFoot(&$vars)
Render footer twig templates for plugin_reuser.
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.
plugin_find($pluginName)
Given the official name of a plugin, return the $Plugins object.
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:690