14 namespace Fossology\Reuser;
20 use Symfony\Component\HttpFoundation\Request;
21 use Symfony\Component\HttpFoundation\Response;
22 use Symfony\Component\HttpFoundation\RedirectResponse;
31 const NAME =
"reusediffview";
39 function __construct()
41 parent::__construct(self::NAME, [
42 self::TITLE => _(
"File Diff View"),
44 self::DEPENDENCIES => [
"browse"],
47 $this->uploadDao = $this->
getObject(
'dao.upload');
54 protected function handle(Request $request)
56 $uploadId = intval($request->get(
'upload'));
57 $item = intval($request->get(
'item'));
58 $currentPfile = intval($request->get(
'currentPfile'));
59 $reusedPfile = intval($request->get(
'reusedPfile'));
60 $reuseId = intval($request->get(
'reuse', 0));
64 '<div class="alert alert-danger">' . _(
"Invalid parameters for diff view") .
'</div>',
65 Response::HTTP_BAD_REQUEST
69 if ($currentPfile <= 0 || $reusedPfile <= 0) {
70 $reuseParam = $reuseId > 0 ?
'&reuse=' . $reuseId :
'';
71 return new RedirectResponse(
72 Traceback_uri() .
"?mod=reusecompare&upload=$uploadId&item=$item$reuseParam"
77 if (!$this->uploadDao->isAccessible($uploadId, $groupId)) {
79 '<div class="alert alert-danger">' . _(
"Permission Denied") .
'</div>',
80 Response::HTTP_FORBIDDEN
88 if (!$currentFile || !$reusedFile) {
90 '<div class="alert alert-danger">' . _(
"File not found") .
'</div>',
91 Response::HTTP_NOT_FOUND
96 $diffData = $this->
generateDiff($currentPfile, $reusedPfile);
104 $curScannerF = array_flip($curScanner);
105 $reScannerF = array_flip($reScanner);
106 $curAddedF = array_flip($curAdded);
107 $reAddedF = array_flip($reAdded);
108 $curRemovedF = array_flip($curRemoved);
109 $reRemovedF = array_flip($reRemoved);
112 $allNames = array_unique(array_merge(
113 $curScanner, $reScanner, $curAdded, $reAdded, $curRemoved, $reRemoved
120 foreach ($allNames as $name) {
121 $inCurScanner = isset($curScannerF[$name]);
122 $inReScanner = isset($reScannerF[$name]);
123 $inCurAdded = isset($curAddedF[$name]);
124 $inReAdded = isset($reAddedF[$name]);
125 $inCurRemoved = isset($curRemovedF[$name]);
126 $inReRemoved = isset($reRemovedF[$name]);
128 $inReEffective = $inReScanner || $inReAdded;
131 $status =
'removed-in-reuse';
132 } elseif ($inCurRemoved) {
133 $status =
'removed-in-current';
134 } elseif ($inCurScanner && $inReScanner) {
136 } elseif ($inReEffective && !$inCurScanner) {
137 $status =
'added-in-reuse';
138 } elseif ($inCurAdded && !$inReEffective) {
139 $status =
'added-in-current';
143 $allLicenses[$name] = [
'status' => $status];
147 $tableName = $this->uploadDao->getUploadtreeTableName($uploadId);
150 $fileItem = $this->uploadDao->getUploadtreeIdFromPfile($uploadId, $currentPfile);
151 if (empty($fileItem)) {
155 $micromenu =
Dir2Browse(
"license", $fileItem,
null, 0,
"View",
156 -1,
'',
'', $tableName);
159 "uploadId" => $uploadId,
162 "currentFile" => $currentFile,
163 "reusedFile" => $reusedFile,
164 "diffData" => $diffData,
165 "allLicenses" => $allLicenses,
166 "pageMenu" => $micromenu,
167 "micromenu" => $micromenu,
170 $defaultVars = $this->mergeWithDefault([]);
171 $defaultVars[
'styles'] .=
"<link rel='stylesheet' href='css/highlights.css'>\n";
172 $vars = array_merge($defaultVars, $vars);
174 return $this->
render(
"reusediffview.html.twig", $vars);
184 $pathReused =
RepPath($pfileB);
185 $pathCurrent =
RepPath($pfileA);
187 if (!$pathReused || !file_exists($pathReused) ||
188 !$pathCurrent || !file_exists($pathCurrent)) {
189 return [[
'type' =>
'unchanged',
'line_number' => 1,
190 'content' => _(
'Unable to load files for diff.')]];
193 $tmpReused = tempnam(sys_get_temp_dir(),
'fosdiff_');
194 $tmpCurrent = tempnam(sys_get_temp_dir(),
'fosdiff_');
195 if ($tmpReused ===
false || $tmpCurrent ===
false) {
196 return [[
'type' =>
'unchanged',
'line_number' => 1,
197 'content' => _(
'Unable to create temp files for diff.')]];
199 if (!copy($pathReused, $tmpReused) || !copy($pathCurrent, $tmpCurrent)) {
201 @unlink($tmpCurrent);
202 return [[
'type' =>
'unchanged',
'line_number' => 1,
203 'content' => _(
'Unable to copy files for diff.')]];
208 $cmd =
"diff -u " . escapeshellarg($tmpReused) .
" " . escapeshellarg($tmpCurrent);
209 exec($cmd, $diffOutput, $exitCode);
211 $contentCurrent = file_get_contents($pathCurrent);
212 $linesCurrent = explode(
"\n", $contentCurrent);
217 if ($exitCode === 0) {
219 foreach ($linesCurrent as $i => $line) {
220 $diff[] = [
'type' =>
'unchanged',
'line_number' => $i + 1,
'content' => $line];
225 if ($exitCode === 2 || empty($diffOutput)) {
226 return [[
'type' =>
'unchanged',
'line_number' => 1,
227 'content' => _(
'Unable to compute diff for this file.')]];
241 foreach ($diffLines as $raw) {
242 if (preg_match(
'/^@@ -(\d+),?\d* \+(\d+),?\d* @@/', $raw, $m)) {
243 $hunks[] = [
'old_start' => (int)$m[1],
'new_start' => (
int)$m[2]];
256 foreach ($diffLines as $raw) {
257 if (preg_match(
'/^@@ -(\d+),?\d* \+(\d+),?\d* @@/', $raw)) {
259 $hunkData[$hunkIdx] = [
'changes' => []];
263 if (!$inHunk || strlen($raw) === 0) {
267 if ($prefix ===
' ' || $prefix ===
'-' || $prefix ===
'+') {
268 $hunkData[$hunkIdx][
'changes'][] = $raw;
276 foreach ($hunkData as $hIdx => $hunk) {
277 $newStart = $hunks[$hIdx][
'new_start'];
280 while ($currentLineIdx < $newStart) {
281 $diff[] = [
'type' =>
'unchanged',
'line_number' => $currentLineIdx,
282 'content' => $linesCurrent[$currentLineIdx - 1]];
287 foreach ($hunk[
'changes'] as $raw) {
289 $content = substr($raw, 1);
290 if ($prefix ===
' ') {
291 $diff[] = [
'type' =>
'unchanged',
'line_number' => $currentLineIdx,
292 'content' => $content];
294 } elseif ($prefix ===
'-') {
295 $diff[] = [
'type' =>
'deleted',
'line_number' => $currentLineIdx,
296 'content' => $content];
298 $diff[] = [
'type' =>
'added',
'line_number' => $currentLineIdx,
299 'content' => $content];
306 while ($currentLineIdx <= count($linesCurrent)) {
307 $diff[] = [
'type' =>
'unchanged',
'line_number' => $currentLineIdx,
308 'content' => $linesCurrent[$currentLineIdx - 1]];
320 $sql =
"SELECT pfile_pk, pfile_size, pfile_sha1, pfile_md5, pfile_sha256, pfile_mimetypefk
321 FROM pfile WHERE pfile_pk = $1";
322 $this->
dbManager->prepare($stmt = __METHOD__ .
'_pfile', $sql);
323 $row = $this->
dbManager->getSingleRow($sql, [$pfileId], $stmt);
335 if (empty($pfileId)) {
339 $sql =
"SELECT DISTINCT lr.rf_shortname
341 JOIN license_ref lr ON lr.rf_pk = lf.rf_fk
342 WHERE lf.pfile_fk = $1
343 AND lr.rf_shortname IS NOT NULL
344 AND lr.rf_shortname != 'Void'";
345 $this->
dbManager->prepare($stmt = __METHOD__ .
'_scan', $sql);
346 $res = $this->
dbManager->execute($stmt, [$pfileId]);
348 while ($row = $this->
dbManager->fetchArray($res)) {
349 $findings[$row[
'rf_shortname']] =
true;
352 return array_keys($findings);
369 if (empty($pfileId) || empty($uploadId)) {
370 return [$added, $removed];
373 $uploadtreePk = $this->uploadDao->getUploadtreeIdFromPfile($uploadId, $pfileId);
374 if (empty($uploadtreePk)) {
375 return [$added, $removed];
379 $sql =
"SELECT DISTINCT lr.rf_shortname
380 FROM clearing_decision cd
381 JOIN clearing_decision_event cde ON cde.clearing_decision_fk = cd.clearing_decision_pk
382 JOIN clearing_event ce ON ce.clearing_event_pk = cde.clearing_event_fk
383 JOIN license_ref lr ON lr.rf_pk = ce.rf_fk
384 WHERE cd.uploadtree_fk = $1
385 AND (ce.removed IS NULL OR ce.removed = false)
387 AND lr.rf_shortname IS NOT NULL
388 AND lr.rf_shortname != 'Void'";
389 $this->
dbManager->prepare($stmt = __METHOD__ .
'_add', $sql);
390 $res = $this->
dbManager->execute($stmt, [$uploadtreePk]);
391 while ($row = $this->
dbManager->fetchArray($res)) {
392 $added[$row[
'rf_shortname']] =
true;
397 $sql =
"SELECT DISTINCT lr.rf_shortname
398 FROM clearing_decision cd
399 JOIN clearing_decision_event cde ON cde.clearing_decision_fk = cd.clearing_decision_pk
400 JOIN clearing_event ce ON ce.clearing_event_pk = cde.clearing_event_fk
401 JOIN license_ref lr ON lr.rf_pk = ce.rf_fk
402 WHERE cd.uploadtree_fk = $1
403 AND ce.removed = true
404 AND lr.rf_shortname IS NOT NULL
405 AND lr.rf_shortname != 'Void'";
406 $this->
dbManager->prepare($stmt = __METHOD__ .
'_rem', $sql);
407 $res = $this->
dbManager->execute($stmt, [$uploadtreePk]);
408 while ($row = $this->
dbManager->fetchArray($res)) {
409 $removed[$row[
'rf_shortname']] =
true;
413 return [array_keys($added), array_keys($removed)];
417 register_plugin(
new ReuseFileDiffViewPlugin());
Contains the constants and helpers for authentication of user.
static getGroupId()
Get the current user's group id.
render($templateName, $vars=null, $headers=null)
Display a two-column file diff view for reuse comparison, matching the EnhancedReuser diff view struc...
generateDiff($pfileA, $pfileB)
parseUnifiedDiff(array $diffLines, array $linesCurrent)
getScannerFindings($pfileId)
getClearingDecisionSets($pfileId, $uploadId)
Dir2Browse($Mod, $UploadtreePk, $LinkLast=NULL, $ShowBox=1, $ShowMicro=NULL, $Enumerate=-1, $PreText='', $PostText='', $uploadtree_tablename="uploadtree")
Get an html linked string of a file browse path.
Traceback_uri()
Get the URI without query to this location.
RepPath($PfilePk, $Repo="files")
Given a pfile id, retrieve the pfile path.
fo_dbManager * dbManager
fo_dbManager object
list_t type structure used to keep various lists. (e.g. there are multiple lists).