FOSSology  4.7.0
Open Source License Compliance by Open Source Software
ajax-copyright-hist.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2019, 2022, Siemens AG
4  Author: Daniele Fognini, Johannes Najjar, Steffen Weber, Shaheem Azmal M MD
5 
6  SPDX-License-Identifier: GPL-2.0-only
7 */
8 
16 use Symfony\Component\HttpFoundation\JsonResponse;
17 use Symfony\Component\HttpFoundation\Response;
18 
19 define("TITLE_COPYRIGHTHISTOGRAMPROCESSPOST", _("Private: Browse post"));
20 
26 {
30  protected $listPage;
34  private $uploadtree_tablename;
38  private $dbManager;
42  private $uploadDao;
46  private $copyrightDao;
47 
51  private $dataTablesUtility;
52 
56  private $textFindingTypes = ["copyFindings"];
57 
58  function __construct()
59  {
60  $this->Name = "ajax-copyright-hist";
61  $this->Title = TITLE_COPYRIGHTHISTOGRAMPROCESSPOST;
62  $this->DBaccess = PLUGIN_DB_READ;
63  $this->OutputType = 'JSON';
64  $this->LoginFlag = 0;
65  $this->NoMenu = 0;
66 
67  parent::__construct();
68  global $container;
69  $this->dataTablesUtility = $container->get('utils.data_tables_utility');
70  $this->uploadDao = $container->get('dao.upload');
71  $this->dbManager = $container->get('db.manager');
72  $this->copyrightDao = $container->get('dao.copyright');
73  }
74 
75 
80  function Output()
81  {
82  $returnValue = 0;
83  if ($this->State != PLUGIN_STATE_READY) {
84  return 0;
85  }
86 
87  $action = GetParm("action", PARM_STRING);
88  $upload = GetParm("upload", PARM_INTEGER);
89  $type = GetParm("type", PARM_STRING);
90 
91  if ($action=="deletedecision" || $action=="undodecision") {
92  $decision = GetParm("decision", PARM_INTEGER);
93  $pfile = GetParm("pfile", PARM_INTEGER);
94  } elseif ($action=="deleteHashDecision" || $action=="undoHashDecision") {
95  $hash = GetParm("hash", PARM_STRING);
96  } elseif ($action=="update" || $action=="delete" || $action=="undo" || $action=="revertToOriginal") {
97  $id = GetParm("id", PARM_STRING);
98  $getEachID = array_filter(explode(",", trim($id, ',')), function($var) {
99  return $var !== "";
100  });
101  if (count($getEachID) == 4) {
102  list($upload, $item, $hash, $type) = $getEachID;
103  } else {
104  return new Response('bad request while '.$action,
105  Response::HTTP_BAD_REQUEST,
106  array('Content-type'=>'text/plain')
107  );
108  }
109  }
110 
111  /* check upload permissions */
112  if (!(($action == "getData" || $action == "getDeactivatedData") &&
113  ($this->uploadDao->isAccessible($upload, Auth::getGroupId())) ||
114  ($this->uploadDao->isEditable($upload, Auth::getGroupId())))) {
115  $permDeniedText = _("Permission Denied");
116  $returnValue = "<h2>$permDeniedText</h2>";
117  }
118  $this->uploadtree_tablename = $this->uploadDao->getUploadtreeTableName(
119  $upload);
120 
121  if (in_array($type, $this->textFindingTypes) &&
122  ($action == "getData" || $action == "getDeactivatedData")) {
123  $textFindingsHandler = new TextFindingsAjax($this->uploadtree_tablename);
124  if ($action == "getData") {
125  $returnValue = $textFindingsHandler->doGetData($type, $upload);
126  } elseif ($action == "getDeactivatedData") {
127  $returnValue = $textFindingsHandler->doGetData($type, $upload, false);
128  }
129  } else {
130  switch ($action) {
131  case "getData":
132  $returnValue = $this->doGetData($upload);
133  break;
134  case "getDeactivatedData":
135  $returnValue = $this->doGetData($upload, false);
136  break;
137  case "update":
138  $returnValue = $this->doUpdate($item, $hash, $type);
139  break;
140  case "delete":
141  $returnValue = $this->doDelete($item, $hash, $type);
142  break;
143  case "undo":
144  $returnValue = $this->doUndo($item, $hash, $type);
145  break;
146  case "revertToOriginal":
147  $returnValue = $this->doRevertToOriginal($item, $type);
148  break;
149  case "deletedecision":
150  $returnValue = $this->doDeleteDecision($decision, $pfile, $type);
151  break;
152  case "undodecision":
153  $returnValue = $this->doUndoDecision($decision, $pfile, $type);
154  break;
155  case "deleteHashDecision":
156  $returnValue = $this->doDeleteHashDecision($hash, $upload, $type);
157  break;
158  case "undoHashDecision":
159  $returnValue = $this->doUndoHashDecision($hash, $upload, $type);
160  break;
161  default:
162  $returnValue = "<h2>" . _("Unknown action") . "</h2>";
163  }
164  }
165  return $returnValue;
166  }
167 
177  protected function doGetData($upload, $activated = true)
178  {
179  $item = GetParm("item", PARM_INTEGER);
180  $agent_pk = GetParm("agent", PARM_STRING);
181  $type = GetParm("type", PARM_STRING);
182  $filter = GetParm("filter", PARM_STRING);
183  $listPage = "copyright-list";
184 
185  header('Content-type: text/json');
186  list($aaData, $iTotalRecords, $iTotalDisplayRecords) = $this->getTableData($upload, $item, $agent_pk, $type,$listPage, $filter, $activated);
187  return new JsonResponse(array(
188  'sEcho' => intval($_GET['sEcho']),
189  'aaData' => $aaData,
190  'iTotalRecords' => $iTotalRecords,
191  'iTotalDisplayRecords' => $iTotalDisplayRecords
192  )
193  );
194  }
195 
207  private function getTableData($upload, $item, $agent_pk, $type, $listPage, $filter, $activated = true)
208  {
209  $offset = GetParm('iDisplayStart', PARM_INTEGER);
210  $limit = GetParm('iDisplayLength', PARM_INTEGER);
211  list ($rows, $iTotalDisplayRecords, $iTotalRecords) = $this->getCopyrights($upload, $item, $this->uploadtree_tablename, $agent_pk, $type, $filter, $activated, $offset, $limit);
212  $aaData = array();
213  if (!empty($rows)) {
214  $rw = $this->uploadDao->isEditable($upload, Auth::getGroupId());
215  foreach ($rows as $row) {
216  $aaData [] = $this->fillTableRow($row, $item, $upload, $agent_pk, $type,$listPage, $filter, $activated, $rw);
217  }
218  }
219 
220  return array($aaData, $iTotalRecords, $iTotalDisplayRecords);
221 
222  }
223 
235  public function getCopyrights($upload_pk, $item, $uploadTreeTableName, $agentId, $type, $filter, $activated = true, $offset = null , $limit = null)
236  {
237  $tableName = $this->getTableName($type);
238  $tableNameEvent = $tableName.'_event';
239  $orderString = $this->getOrderString();
240 
241  list($left, $right) = $this->uploadDao->getLeftAndRight($item, $uploadTreeTableName);
242 
243  if ($filter == "") {
244  $filter = "none";
245  }
246 
247  $sql_upload = "";
248  if ('uploadtree_a' == $uploadTreeTableName) {
249  $sql_upload = " AND UT.upload_fk=$5 ";
250  }
251 
252  $join = "";
253  $filterQuery = "";
254  if (($type == 'statement' || $type == 'scancode_statement') && $filter == "nolic") {
255  $noLicStr = "No_license_found";
256  $voidLicStr = "Void";
257  $join = " INNER JOIN license_file AS LF on cp.pfile_fk=LF.pfile_fk ";
258  $filterQuery = " AND LF.rf_fk IN (SELECT rf_pk FROM license_ref WHERE rf_shortname IN ('$noLicStr','$voidLicStr')) ";
259  } else {
260  // No filter, nothing to do
261  }
262  $params = array($left, $right, $type, "{" . $agentId . "}", $upload_pk);
263 
264  $filterParms = $params;
265  $searchFilter = $this->addSearchFilter($filterParms);
266 
267  $activatedClause = "ce.is_enabled = 'false'";
268  if ($activated) {
269  $activatedClause = "ce.is_enabled IS NULL OR ce.is_enabled = 'true'";
270  }
271  $unorderedQuery = "FROM $tableName AS cp " .
272  "INNER JOIN $uploadTreeTableName AS UT ON cp.pfile_fk = UT.pfile_fk " .
273  "LEFT JOIN $tableNameEvent AS ce ON ce.".$tableName."_fk = cp.".$tableName."_pk " .
274  "AND ce.upload_fk = $5 AND ce.uploadtree_fk = UT.uploadtree_pk " .
275  $join .
276  "WHERE cp.content!='' " .
277  "AND ( UT.lft BETWEEN $1 AND $2 ) " .
278  "AND cp.type = $3 " .
279  "AND cp.agent_fk = ANY($4::int[]) " .
280  "AND ($activatedClause)" .
281  $sql_upload;
282  $grouping = " GROUP BY mcontent ";
283 
284  $countQuery = "SELECT count(*) FROM (
285  SELECT mcontent AS content FROM (SELECT
286  (CASE WHEN (ce.content IS NULL OR ce.content = '') THEN cp.content ELSE ce.content END) AS mcontent
287  $unorderedQuery $filterQuery $grouping) AS k $searchFilter) AS cx";
288  $iTotalDisplayRecordsRow = $this->dbManager->getSingleRow($countQuery,
289  $filterParms, __METHOD__.$tableName . ".count" . ($activated ? '' : '_deactivated'));
290  $iTotalDisplayRecords = $iTotalDisplayRecordsRow['count'];
291 
292  $countAllQuery = "SELECT count(*) FROM (SELECT
293 (CASE WHEN (ce.content IS NULL OR ce.content = '') THEN cp.content ELSE ce.content END) AS mcontent
294 $unorderedQuery$grouping) as K";
295  $iTotalRecordsRow = $this->dbManager->getSingleRow($countAllQuery, $params, __METHOD__,$tableName . "count.all" . ($activated ? '' : '_deactivated'));
296  $iTotalRecords = $iTotalRecordsRow['count'];
297 
298  $range = "";
299  $filterParms[] = $offset;
300  $range .= ' OFFSET $' . count($filterParms);
301  $filterParms[] = $limit;
302  $range .= ' LIMIT $' . count($filterParms);
303 
304  $sql = "SELECT mcontent AS content, mhash AS hash, copyright_count FROM (SELECT
305 (CASE WHEN (ce.content IS NULL OR ce.content = '') THEN cp.content ELSE ce.content END) AS mcontent,
306 (CASE WHEN (ce.hash IS NULL OR ce.hash = '') THEN cp.hash ELSE ce.hash END) AS mhash,
307 count(*) AS copyright_count " .
308  "$unorderedQuery $filterQuery GROUP BY mcontent, mhash) AS k $searchFilter $orderString $range";
309  $statement = __METHOD__ . $filter.$tableName . $uploadTreeTableName . ($activated ? '' : '_deactivated');
310  $rows = $this->dbManager->getRows($sql, $filterParms, $statement);
311 
312  return array($rows, $iTotalDisplayRecords, $iTotalRecords);
313  }
314 
328  public function getTableName($type)
329  {
330  switch ($type) {
331  case "ipra" :
332  $tableName = "ipra";
333  break;
334  case "ecc" :
335  $tableName = "ecc";
336  break;
337  case "keyword" :
338  $tableName = "keyword";
339  $filter="none";
340  break;
341  case "statement" :
342  $tableName = "copyright";
343  break;
344  case "scancode_statement":
345  $tableName = "scancode_copyright";
346  break;
347  case "user_statement":
348  $tableName = "copyright_decision";
349  break;
350  case "scancode_email":
351  case "scancode_author":
352  case "scancode_url":
353  $tableName = "scancode_author";
354  break;
355  default:
356  $tableName = "author";
357  }
358  return $tableName;
359  }
360 
365  private function getOrderString()
366  {
367  $columnNamesInDatabase = array('copyright_count', 'content');
368 
369  $defaultOrder = HistogramBase::returnSortOrder();
370 
371  return $this->dataTablesUtility->getSortingString($_GET, $columnNamesInDatabase, $defaultOrder);
372  }
373 
380  public function getAgentId($upload_pk,$copyrightType)
381  {
382  return (LatestAgentpk($upload_pk, $copyrightType));
383  }
384 
390  private function addSearchFilter(&$filterParams)
391  {
392  $searchPattern = GetParm('sSearch', PARM_STRING);
393  $isInverseSearch = GetParm('isInverse', PARM_STRING);
394  if (empty($searchPattern)) {
395  return '';
396  }
397  $filterParams[] = "%$searchPattern%";
398  if ($isInverseSearch == 'true') {
399  return 'WHERE mcontent not ilike $'.count($filterParams).' ';
400  }
401  return 'WHERE mcontent ilike $'.count($filterParams).' ';
402  }
403 
414  private function getTableRowAction($hash, $uploadTreeId, $upload, $type, $activated = true, $rw = true)
415  {
416  if ($rw) {
417  $act = "<img";
418  if (!$activated) {
419  $act .= " hidden='true'";
420  }
421  $act .= " id='delete$type$hash' onClick='delete$type($upload,$uploadTreeId,\"$hash\",\"$type\");' class=\"delete\" src=\"images/space_16.png\">";
422  $act .= "<span";
423  if ($activated) {
424  $act .= " hidden='true'";
425  }
426  $act .= " id='update$type$hash'>deactivated [<a href=\"#\" id='undo$type$hash' onClick='undo$type($upload,$uploadTreeId,\"$hash\",\"$type\");return false;'>Undo</a>]</span>";
427  return $act;
428  }
429  if (!$activated) {
430  return "deactivated";
431  }
432  return "";
433  }
434 
448  private function fillTableRow($row, $uploadTreeId, $upload, $agentId, $type,$listPage, $filter = "", $activated = true, $rw = true)
449  {
450  $hash = $row['hash'];
451  $output = array('DT_RowId' => "$upload,$uploadTreeId,$hash,$type", "DT_RowClass" => "row$hash");
452 
453  $link = "<a href='";
454  $link .= Traceback_uri();
455  $urlArgs = "?mod=".$listPage."&agent=$agentId&item=$uploadTreeId&hash=$hash&type=$type";
456  if ((empty($filter) || $filter == "all")) {
457  if ($activated) {
458  $filter = "active";
459  } else {
460  $filter = "inactive";
461  }
462  }
463  if (!empty($filter)) {
464  $urlArgs .= "&filter=$filter";
465  }
466  $link .= $urlArgs . "'>" . $row['copyright_count'] . "</a>";
467  $output['0'] = $link;
468  $output['1'] = convertToUTF8($row['content']);
469  $output['2'] = $this->getTableRowAction($hash, $uploadTreeId, $upload, $type, $activated, $rw);
470  if ($rw && $activated) {
471  $output['3'] = "<input type='checkbox' class='deleteBySelect$type' id='deleteBySelect$type$hash' value='".$upload.",".$uploadTreeId.",".$hash.",".$type."'>";
472  } else {
473  $output['3'] = "<input type='checkbox' class='undoBySelect$type' id='undoBySelect$type$hash' value='".$upload.",".$uploadTreeId.",".$hash.",".$type."'>";
474  }
475  return $output;
476  }
477 
485  protected function doUpdate($itemId, $hash, $type)
486  {
487  $content = GetParm("value", PARM_RAW);
488  if (empty($content)) {
489  return new Response('empty content not allowed',
490  Response::HTTP_BAD_REQUEST ,array('Content-type'=>'text/plain'));
491  }
492 
493  $item = $this->uploadDao->getItemTreeBounds($itemId, $this->uploadtree_tablename);
494  $cpTable = $this->getTableName($type);
495  $this->copyrightDao->updateTable($item, $hash, $content, Auth::getUserId(), $cpTable);
496 
497  return new Response('success', Response::HTTP_OK,array('Content-type'=>'text/plain'));
498  }
499 
507  protected function doDelete($itemId, $hash, $type)
508  {
509  $item = $this->uploadDao->getItemTreeBounds($itemId, $this->uploadtree_tablename);
510  $cpTable = $this->getTableName($type);
511  $this->copyrightDao->updateTable($item, $hash, '', Auth::getUserId(), $cpTable, 'delete');
512  return new Response('Successfully deleted', Response::HTTP_OK, array('Content-type'=>'text/plain'));
513  }
514 
522  protected function doUndo($itemId, $hash, $type)
523  {
524  $item = $this->uploadDao->getItemTreeBounds($itemId, $this->uploadtree_tablename);
525  $cpTable = $this->getTableName($type);
526  $this->copyrightDao->updateTable($item, $hash, '', Auth::getUserId(), $cpTable, 'rollback');
527  return new Response('Successfully restored', Response::HTTP_OK, array('Content-type'=>'text/plain'));
528  }
529 
536  protected function doRevertToOriginal($itemId, $type)
537  {
538  $newContent = GetParm("newContent", PARM_RAW);
539  if (empty($newContent)) {
540  return new Response('empty content',
541  Response::HTTP_BAD_REQUEST, array('Content-type'=>'text/plain'));
542  }
543  $newHash = md5(StringOperation::replaceUnicodeControlChar($newContent));
544  $item = $this->uploadDao->getItemTreeBounds($itemId, $this->uploadtree_tablename);
545  $cpTable = $this->getTableName($type);
546  $this->copyrightDao->updateTable($item, $newHash, '', Auth::getUserId(), $cpTable, 'revertToOriginal');
547  return new Response('Successfully reverted', Response::HTTP_OK, array('Content-type'=>'text/plain'));
548  }
549 
557  protected function doDeleteDecision($decisionId, $pfileId, $type)
558  {
559  $this->copyrightDao->removeDecision($type."_decision", $pfileId, $decisionId);
560  return new JsonResponse(array("msg" => $decisionId . " .. " . $pfileId . " .. " . $type));
561  }
562 
570  protected function doUndoDecision($decisionId, $pfileId, $type)
571  {
572  $this->copyrightDao->undoDecision($type."_decision", $pfileId, $decisionId);
573  return new JsonResponse(array("msg" => $decisionId . " .. " . $pfileId . " .. " . $type));
574  }
575 
583  protected function doDeleteHashDecision($hash, $upload, $type)
584  {
585  $tableName = $type."_decision";
586  $decisions = $this->copyrightDao->getDecisionsFromHash($tableName, $hash,
587  $upload, $this->uploadtree_tablename);
588  foreach ($decisions as $decision) {
589  $this->copyrightDao->removeDecision($tableName, $decision['pfile_fk'],
590  $decision[$tableName . '_pk']);
591  }
592  return new JsonResponse(array("msg" => "$hash .. $upload .. $type"));
593  }
594 
602  protected function doUndoHashDecision($hash, $upload, $type)
603  {
604  $tableName = $type."_decision";
605  $decisions = $this->copyrightDao->getDecisionsFromHash($tableName, $hash,
606  $upload, $this->uploadtree_tablename);
607  foreach ($decisions as $decision) {
608  $this->copyrightDao->undoDecision($tableName, $decision['pfile_fk'],
609  $decision[$tableName . '_pk']);
610  }
611  return new JsonResponse(array("msg" => "$hash .. $upload .. $type"));
612  }
613 }
614 
615 $NewPlugin = new CopyrightHistogramProcessPost();
616 $NewPlugin->Initialize();
char * uploadtree_tablename
upload.uploadtree_tablename
Definition: adj2nest.c:100
Handles Ajax requests for copyright.
doUpdate($itemId, $hash, $type)
Update result.
getTableRowAction($hash, $uploadTreeId, $upload, $type, $activated=true, $rw=true)
Helper to create action column for results.
getTableName($type)
Get table name based on statement type.
doDeleteDecision($decisionId, $pfileId, $type)
Disable a decision.
getCopyrights($upload_pk, $item, $uploadTreeTableName, $agentId, $type, $filter, $activated=true, $offset=null, $limit=null)
Get results from database and format for JSON.
doGetData($upload, $activated=true)
Handles GET request and create a JSON response.
doRevertToOriginal($itemId, $type)
Revert an edited result back to its original scanner text.
doUndoDecision($decisionId, $pfileId, $type)
Rollback a decision.
doDelete($itemId, $hash, $type)
Disable a result.
getTableData($upload, $item, $agent_pk, $type, $listPage, $filter, $activated=true)
Get the copyright data and fill in expected format.
getAgentId($upload_pk, $copyrightType)
Get Agent ID for an upload.
__construct()
base constructor. Most plugins will just use this
fillTableRow($row, $uploadTreeId, $upload, $agentId, $type, $listPage, $filter="", $activated=true, $rw=true)
Fill table content for JSON response.
addSearchFilter(&$filterParams)
Add filter on content.
Output()
Display the loaded menu and plugins.
doUndo($itemId, $hash, $type)
Rollback a result.
doDeleteHashDecision($hash, $upload, $type)
Disable decisions for an upload which matches a hash.
doUndoHashDecision($hash, $upload, $type)
Rollback decisions for an upload which matches a hash.
getOrderString()
Create sorting string for database query.
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:57
Handles Ajax requests for text findings.
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
static returnSortOrder()
Get sorting orders.
Definition: state.hpp:16
LatestAgentpk($upload_pk, $arsTableName, $arsSuccess=false)
Given an upload_pk, find the latest enabled agent_pk with results.
Traceback_uri()
Get the URI without query to this location.
Definition: common-parm.php:97
const PARM_INTEGER
Definition: common-parm.php:14
const PARM_RAW
Definition: common-parm.php:22
const PARM_STRING
Definition: common-parm.php:18
GetParm($parameterName, $parameterType)
This function will retrieve the variables and check data types.
Definition: common-parm.php:46
if(! defined('ENT_SUBSTITUTE')) convertToUTF8($content, $toHTML=true)
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:690
#define PLUGIN_DB_READ
Plugin requires read permission on DB.
Definition: libfossology.h:37
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16