14 namespace Fossology\Reuser;
23 use Symfony\Component\HttpFoundation\Request;
25 include_once(dirname(__DIR__) .
"/agent/version.php");
41 public function __construct()
43 $this->Name =
"agent_reuser";
44 $this->Title = _(
"Reuse of License Clearing");
45 $this->AgentName =
"reuser";
47 parent::__construct();
49 $this->uploadDao = $GLOBALS[
'container']->get(
'dao.upload');
60 return $reuserPlugin->renderContent($vars);
71 return $reuserPlugin->renderFoot($vars);
82 return $reuserPlugin->getScriptIncludes($vars);
91 menu_insert(
"ParmAgents::" . $this->Title, 0, $this->Name);
104 if ($request->get(
'reuseSource') ===
'osselot') {
105 return $this->scheduleOsselotImportDirect($jobId, $uploadId, $errorMsg, $request);
109 $getReuseValue = $request->get(self::REUSE_MODE) ?: array();
110 $reuserDependencies = array(
"agent_adj2nest");
112 $reuseMode = UploadDao::REUSE_NONE;
113 foreach ($getReuseValue as $currentReuseValue) {
114 switch ($currentReuseValue) {
116 $reuseMode |= UploadDao::REUSE_MAIN;
118 case 'reuseEnhanced':
119 $reuseMode |= UploadDao::REUSE_ENHANCED;
122 $reuseMode |= UploadDao::REUSE_CONF;
124 case 'reuseCopyright':
125 $reuseMode |= UploadDao::REUSE_COPYRIGHT;
130 $reuseSelections = $request->get(self::UPLOAD_TO_REUSE_SELECTOR_NAME);
131 if (!is_array($reuseSelections)) {
132 $reuseSelections = [$reuseSelections];
135 $reuseSelections = array_filter($reuseSelections, fn($s) => is_string($s) && substr_count($s,
',') >= 1);
137 if (empty($reuseSelections)) {
138 $errorMsg .=
'No valid reuse upload selections found';
142 foreach ($reuseSelections as $reuseSelection) {
143 [$reuseUploadId, $reuseGroupId] = explode(
',', $reuseSelection, 2);
146 intval($reuseUploadId),
148 intval($reuseGroupId),
153 list($agentDeps, $scancodeDeps) = $this->getReuserDependencies($request);
154 $reuserDependencies = array_unique(array_merge($reuserDependencies, $agentDeps));
155 if (!empty($scancodeDeps)) {
156 $reuserDependencies[] = $scancodeDeps;
159 return $this->
doAgentAdd($jobId, $uploadId, $errorMsg,
160 $reuserDependencies, $uploadId,
null, $request);
163 private function scheduleOsselotImportDirect(
int $jobId,
int $uploadId,
string &$errorMsg, Request $request): int
165 $pkg =
trim((
string) $request->get(
'osselotPackage'));
166 $ver =
trim((
string) $request->get(
'osselotVersions'));
167 if (empty($pkg) || empty($ver)) {
168 $errorMsg .=
'Package name and version are required';
172 $helper =
new OsselotLookupHelper();
173 $cachedPath = $helper->fetchSpdxFile($pkg, $ver);
175 if (!$cachedPath || !is_file($cachedPath) || !is_readable($cachedPath)) {
176 throw new \RuntimeException(
"Could not fetch or read SPDX file for {$pkg}:{$ver}");
180 $fileBase = $SysConf[
'FOSSOLOGY'][
'path'] .
"/ReportImport/";
182 if (!is_dir($fileBase) && !mkdir($fileBase, 0755,
true)) {
183 throw new \RuntimeException(
'Failed to create ReportImport directory');
186 $originalName = basename($cachedPath);
187 if (!str_ends_with($originalName,
'.rdf.xml')) {
188 $baseName = pathinfo($originalName, PATHINFO_FILENAME);
189 $originalName = str_ends_with($originalName,
'.rdf') ?
190 $baseName .
'.rdf.xml' : $originalName .
'.rdf.xml';
193 $targetFile = time() .
'_' . random_int(0, getrandmax()) .
'_' . $originalName;
194 $targetPath = $fileBase . $targetFile;
196 if (!copy($cachedPath, $targetPath)) {
197 throw new \RuntimeException(
'Failed to copy SPDX file');
200 $reportImportAgent =
plugin_find(
'agent_reportImport');
201 if (!$reportImportAgent || !method_exists($reportImportAgent,
'addReport') ||
202 !method_exists($reportImportAgent,
'setAdditionalJqCmdArgs') ||
203 !method_exists($reportImportAgent,
'AgentAdd')) {
204 throw new \RuntimeException(
'agent_reportImport plugin not available or missing methods');
207 $importReq =
new Request();
209 $addNewLicensesAs = $request->get(
'osselotAddNewLicensesAs',
'candidate');
210 if (!in_array($addNewLicensesAs, [
'candidate',
'approved',
'rejected'],
true)) {
211 $addNewLicensesAs =
'candidate';
213 $importReq->request->set(
'addNewLicensesAs', $addNewLicensesAs);
216 'addLicenseInfoFromInfoInFile',
'addLicenseInfoFromConcluded',
217 'addConcludedAsDecisions',
'addConcludedAsDecisionsOverwrite',
218 'addConcludedAsDecisionsTBD',
'addCopyrights'
221 foreach ($booleanOptions as $key) {
222 $fullKey =
'osselot' . ucfirst($key);
223 $rawValue = $request->get($fullKey);
224 $finalValue = $rawValue ?
'true' :
'false';
225 $importReq->request->set($key, $finalValue);
228 $licenseMatch = $request->get(
'osselotLicenseMatch',
'spdxid');
229 if (!in_array($licenseMatch, [
'spdxid',
'name',
'text'],
true)) {
230 $licenseMatch =
'spdxid';
232 $importReq->request->set(
'licenseMatch', $licenseMatch);
234 $jqCmdArgs = $reportImportAgent->addReport($targetFile);
235 $additionalArgs = $reportImportAgent->setAdditionalJqCmdArgs($importReq);
236 $jqCmdArgs .= $additionalArgs;
239 $dependencies = array();
240 $jobQueueId = $reportImportAgent->AgentAdd($jobId, $uploadId, $error, $dependencies, $jqCmdArgs);
242 if ($jobQueueId < 0) {
243 throw new \RuntimeException(
"Cannot schedule job: " . $error);
246 return intval($jobQueueId);
248 }
catch (\Throwable $e) {
249 if (isset($targetPath) && file_exists($targetPath)) {
252 $errorMsg .= $e->getMessage();
253 error_log(
"OSSelot import error: " . $e->getMessage());
266 protected function createPackageLink($uploadId, $reuseUploadId, $groupId, $reuseGroupId, $reuseMode=0)
269 $packageDao = $GLOBALS[
'container']->get(
'dao.package');
270 $newUpload = $this->uploadDao->getUpload($uploadId);
271 $uploadForReuse = $this->uploadDao->getUpload($reuseUploadId);
273 $package = $packageDao->findPackageForUpload($reuseUploadId);
275 if ($package ===
null) {
277 $package = $packageDao->createPackage($packageName ?: $uploadForReuse->getFilename());
278 $packageDao->addUploadToPackage($reuseUploadId, $package);
281 $packageDao->addUploadToPackage($uploadId, $package);
283 $this->uploadDao->addReusedUpload($uploadId, $reuseUploadId, $groupId, $reuseGroupId, $reuseMode);
291 private function getReuserDependencies($request)
293 $dependencies = array();
295 if ($request->get(
"Check_agent_nomos",
false)) {
296 $dependencies[] =
"agent_nomos";
298 if ($request->get(
"Check_agent_monk",
false)) {
299 $dependencies[] =
"agent_monk";
301 if ($request->get(
"Check_agent_ojo",
false)) {
302 $dependencies[] =
"agent_ojo";
304 if ($request->get(
"Check_agent_ninka",
false)) {
305 $dependencies[] =
"agent_ninka";
307 if ($request->get(
"Check_agent_copyright",
false)) {
308 $dependencies[] =
"agent_copyright";
310 if (!empty($request->get(
"scancodeFlags", []))) {
315 $flags = $request->get(
'scancodeFlags');
316 $unpackArgs = intval($request->get(
'scm', 0)) == 1 ?
'I' :
'';
318 "name" =>
"agent_scancode",
319 "args" => $agentScanCode->getScanCodeArgs($flags, $unpackArgs)
322 return [$dependencies, $scancodeDeps];
326 register_plugin(
new ReuserAgentPlugin());
Contains the constants and helpers for authentication of user.
static getGroupId()
Get the current user's group id.
doAgentAdd($jobId, $uploadId, &$errorMsg, $dependencies, $jqargs="", $jq_cmd_args=null, $request=null)
static getCommonHead($a, $b)
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.
plugin_find($pluginName)
Given the official name of a plugin, return the $Plugins object.
char * trim(char *ptext)
Trimming whitespace.