FOSSology  4.4.0
Open Source License Compliance by Open Source Software
AdminLicenseCandidate.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2017 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
8 namespace Fossology\UI\Page;
9 
16 use Symfony\Component\HttpFoundation\Request;
17 use Symfony\Component\HttpFoundation\Response;
18 
20 {
21  const NAME = "admin_license_candidate";
22 
24  private $highlightProcessor;
26  private $highlightRenderer;
28  private $textRenderer;
30  private $licenseDao;
32  private $treeDao;
33 
34 
35  function __construct()
36  {
37  parent::__construct(self::NAME, array(
38  self::TITLE => "Admin License Candidates",
39  self::MENU_LIST => "Admin::License Admin::Candidates",
40  self::REQUIRES_LOGIN => true,
41  self::PERMISSION => Auth::PERM_ADMIN
42  ));
43 
44  $this->highlightProcessor = $this->getObject('view.highlight_processor');
45  $this->highlightRenderer = $this->getObject('view.highlight_renderer');
46  $this->textRenderer = $this->getObject('view.text_renderer');
47  $this->licenseDao = $this->getObject('dao.license');
48  $this->treeDao = $this->getObject('dao.tree');
49  }
50 
56  protected function handle(Request $request)
57  {
58 
59  $rf = intval($request->get('rf'));
60  if ($rf<1) {
61  $vars = array(
62  'aaData' => json_encode($this->getArrayArrayData())
63  );
64  return $this->render('admin_license_candidate.html.twig', $this->mergeWithDefault($vars));
65  }
66 
67  $vars = $this->getDataRow($rf);
68  if ($vars === false) {
69  throw new \Exception('invalid license candidate');
70  }
71  $shortname = $request->get('shortname') ?: $vars['rf_shortname'];
72  $vars['shortname'] = $shortname;
73  $rfText = $vars['rf_text'];
74 
75  $suggest = intval($request->get('suggest_rf'));
76  $suggestLicense = false;
77  if ($suggest>0) {
78  $suggestLicense = $this->getDataRow($suggest, 'ONLY license_ref');
79  }
80  if (! $suggestLicense) {
81  list ($suggestIds, $rendered) = $this->suggestLicenseId($rfText);
82  if (! empty($suggestIds)) {
83  $suggest = $suggestIds[0];
84  $suggestLicense = $this->getDataRow($suggest, 'ONLY license_ref');
85  $vars['rf_text'] = $rendered;
86  }
87  }
88  if ($suggestLicense !== false) {
89  $vars['suggest_rf'] = $suggest;
90  $vars['suggest_spdx_id'] = $suggestLicense['rf_spdx_id'];
91  $vars['suggest_shortname'] = $suggestLicense['rf_shortname'];
92  $vars['suggest_fullname'] = $suggestLicense['rf_fullname'];
93  $vars['suggest_text'] = $suggestLicense['rf_text'];
94  $vars['suggest_url'] = $suggestLicense['rf_url'];
95  $vars['suggest_notes'] = $suggestLicense['rf_notes'];
96  $vars['suggest_risk'] = $suggestLicense['rf_risk'];
97  }
98 
99  /* @var $licenseDao LicenseDao */
100  $licenseDao = $this->getObject('dao.license');
101  $vars['licenseArray'] = $licenseDao->getLicenseArray(0);
102  $vars['scripts'] = js_url();
103 
104  $ok = true;
105  switch ($request->get('do')) {
106  case 'verify':
107  case 'variant':
108  $rfParent = ($request->get('do')=='verify') ? $rf : $suggest;
109  try{
110  $ok = $this->verifyCandidate($rf,$shortname,$rfParent);
111  } catch (\Throwable $th) {
112  $vars['message'] = 'The license text already exists.';
113  break;
114  }
115  if ($ok) {
116  $with = $rfParent ? '' : " as variant of <i>$vars[suggest_shortname]</i> ($rfParent)";
117  $vars = array(
118  'aaData' => json_encode($this->getArrayArrayData()),
119  'message' => 'Successfully verified candidate '.$shortname.$with);
120  return $this->render('admin_license_candidate.html.twig', $this->mergeWithDefault($vars));
121  }
122  $vars['message'] = 'Short name must be unique';
123  break;
124  case 'merge':
125  try {
126  $ok = $this->mergeCandidate($rf,$suggest,$vars);
127  } catch (\Throwable $th) {
128  $vars['message'] = 'The license text already exists.';
129  break;
130  }
131  if ($ok) {
132  $vars = array(
133  'aaData' => json_encode($this->getArrayArrayData()),
134  'message' => "Successfully merged candidate <i>$vars[suggest_shortname]</i> ($suggest) into <i>$vars[rf_shortname]</i> ($rf)");
135  return $this->render('admin_license_candidate.html.twig', $this->mergeWithDefault($vars));
136  }
137  $vars['message'] = 'Sorry, this feature is not ready yet.';
138  break;
139  case 'deletecandidate':
140  return $this->doDeleteCandidate($rf);
141  break;
142  }
143 
144  return $this->render('admin_license_candidate-merge.html.twig', $this->mergeWithDefault($vars));
145  }
146 
147  public function getCandidateArrayData()
148  {
149  $sql = "SELECT rf_pk,rf_spdx_id,rf_shortname,rf_fullname,rf_text,group_name,group_pk "
150  . "FROM license_candidate, groups "
151  . "WHERE group_pk=group_fk AND marydone";
152  /* @var $dbManager DbManager */
153  $dbManager = $this->getObject('db.manager');
154  return $dbManager->getRows($sql, [], __METHOD__);
155  }
156 
157  private function getArrayArrayData()
158  {
159  $rows = $this->getCandidateArrayData();
160  $aaData = array();
161  $delete = "";
162  foreach ($rows as $row) {
163  $link = Traceback_uri() . '?mod=' . self::NAME . '&rf=' . $row['rf_pk'];
164  $edit = '<a href="' . $link . '"><img border="0" src="images/button_edit.png"></a>';
165  $delete = '<img border="0" id="deletecandidate'.$row['rf_pk'].'" onClick="deleteCandidate('.$row['rf_pk'].')" src="images/icons/close_16.png">';
166 
167  $aaData[] = array($edit, htmlentities($row['rf_spdx_id']),
168  htmlentities($row['rf_shortname']), htmlentities($row['rf_fullname']),
169  '<div style="overflow-y:scroll;max-height:150px;margin:0;">' . nl2br(htmlentities($row['rf_text'])) . '</div>',
170  htmlentities($row['group_name']),$delete
171  );
172  }
173  return $aaData;
174  }
175 
176 
177  public function getDataRow($licId,$table='license_candidate')
178  {
179  $sql = "SELECT rf_pk,rf_spdx_id,rf_shortname,rf_fullname,rf_text,rf_url,rf_notes,rf_notes,rf_risk";
180  if ($table == 'license_candidate') {
181  $sql .= ',group_name,group_pk FROM license_candidate LEFT JOIN groups ON group_pk=group_fk '
182  . 'WHERE rf_pk=$1 AND marydone';
183  } else {
184  $sql .= " FROM $table WHERE rf_pk=$1";
185  }
186  /* @var $dbManager DbManager */
187  $dbManager = $this->getObject('db.manager');
188  $row = $dbManager->getSingleRow($sql, array($licId), __METHOD__.".$table");
189  return $row;
190  }
191 
192  public function suggestLicenseId($str, $fromRest = false)
193  {
194  /* @var $monkOneShotPlugin \Fossology\Monk\UI\Oneshot */
195  $monkOneShotPlugin = plugin_find("oneshot-monk");
196 
197  if (null !== $monkOneShotPlugin) {
198  return $monkOneShotPlugin->scanMonkRendered($str, $fromRest);
199  } else {
200  return array(array(), $str);
201  }
202  }
203 
210  public function verifyCandidate($rf, $shortname, $rfParent)
211  {
212  /* @var $licenseDao LicenseDao */
213  $licenseDao = $this->getObject('dao.license');
214  if (!$licenseDao->isNewLicense($shortname, 0)) {
215  return false;
216  }
217 
218  /* @var $dbManager DbManager */
219  $dbManager = $this->getObject('db.manager');
220  $dbManager->begin();
221  $dbManager->getSingleRow('INSERT INTO license_ref (rf_pk, rf_spdx_id, rf_shortname, rf_text, rf_url, rf_add_date, rf_copyleft,
222  "rf_OSIapproved", rf_fullname, "rf_FSFfree", "rf_GPLv2compatible", "rf_GPLv3compatible", rf_notes, "rf_Fedora",
223  marydone, rf_active, rf_text_updatable, rf_md5 , rf_detector_type, rf_risk)
224  (SELECT rf_pk, rf_spdx_id, $2 as rf_shortname, rf_text, rf_url, now() as rf_add_date, rf_copyleft,
225  "rf_OSIapproved", rf_fullname, "rf_FSFfree", "rf_GPLv2compatible", "rf_GPLv3compatible", rf_notes, "rf_Fedora",
226  false AS marydone, rf_active, rf_text_updatable, md5(rf_text) rf_md5 , 1 rf_detector_type, rf_risk
227  FROM license_candidate WHERE rf_pk=$1)',array($rf,$shortname),__METHOD__.'.insert');
228  $dbManager->insertTableRow('license_map',array('rf_fk'=>$rf,'rf_parent'=>$rfParent,'usage'=>LicenseMap::CONCLUSION));
229  $dbManager->getSingleRow('DELETE FROM license_candidate WHERE rf_pk=$1',array($rf),__METHOD__.'.delete');
230  $dbManager->commit();
231  return true;
232  }
233 
234  public function mergeCandidate($candidate, $suggest, $vars)
235  {
237  $dbManager = $this->getObject('db.manager');
238  $tableColumnMap = array("license_file"=>"rf_fk",
239  "license_set_bulk"=>"rf_fk",
240  "clearing_event"=>"rf_fk");
241  foreach ($tableColumnMap as $table=>$column) {
242  $dbManager->prepare($stmt=__METHOD__.".$table","UPDATE $table SET $column=$1 WHERE $column=$2");
243  $dbManager->freeResult( $dbManager->execute($stmt,array($suggest,$candidate)) );
244  }
245  $updates = array();
246  if (empty($vars['suggest_url']) && $vars['rf_url']) {
247  $updates[$vars['rf_url']] = 'rf_url=$' . (count($updates)+1);
248  }
249  if (!$vars['rf_notes']) {
250  $updates[$vars['suggest_notes']."\n".$vars['rf_notes']] = 'rf_notes=$' . (count($updates)+1);
251  }
252  if (count($updates)) {
253  $sql = 'UPDATE license_ref SET '.implode(',', $updates).' WHERE rf_pk=$'.(count($updates)+1);
254  $dbManager->prepare($stmt=__METHOD__.'.update',$sql);
255  $params = array_keys($updates);
256  $params[] = $suggest;
257  $dbManager->freeResult( $dbManager->execute($stmt,$params) );
258  }
259  $dbManager->prepare($stmt=__METHOD__.'.delete','DELETE FROM license_candidate WHERE rf_pk=$1');
260  $dbManager->freeResult( $dbManager->execute($stmt,array($candidate)) );
261  return true;
262  }
263 
264  public function doDeleteCandidate($rfPk,$includeHtml=true)
265  {
266  $dbManager = $this->getObject('db.manager');
267  $stmt = __METHOD__.".getUploadtreeFkForUsedCandidates";
268  $dbManager->prepare($stmt, "SELECT uploadtree_fk
269  FROM clearing_event
270  WHERE removed=false
271  AND date_added IN(SELECT max(date_added)
272  FROM clearing_event
273  WHERE rf_fk=$1
274  GROUP BY uploadtree_fk)");
275  $result = $dbManager->execute($stmt, array($rfPk));
276  $dataFetch = $dbManager->fetchAll($result);
277  $dbManager->freeResult($result);
278  if (empty($dataFetch)) {
279  $dbManager->getSingleRow('DELETE FROM license_candidate WHERE rf_pk=$1', array($rfPk), __METHOD__.".delete");
280  return new Response('true', Response::HTTP_OK, array('Content-type'=>'text/plain'));
281  } else {
282  $treeDao = $this->getObject('dao.tree');
283  $message = $includeHtml ? "<div class='candidateFileList'><ol>":"";
284  foreach ($dataFetch as $cnt => $uploadTreeFk) {
285  $path= $treeDao->getFullPath($uploadTreeFk['uploadtree_fk'], 'uploadtree');
286  $message .= $includeHtml ? "<li>".$path."</li>":$path;
287  }
288  $message .= $includeHtml ? "</ol></div>":"";
289  return new Response($message, Response::HTTP_OK, array('Content-type'=>'text/plain'));
290  }
291  }
292 }
293 
294 register_plugin(new AdminLicenseCandidate());
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
Wrapper class for license map.
Definition: LicenseMap.php:19
render($templateName, $vars=null, $headers=null)
js_url()
Load a new url.
Traceback_uri()
Get the URI without query to this location.
Definition: common-parm.php:97
plugin_find($pluginName)
Given the official name of a plugin, return the $Plugins object.
list_t type structure used to keep various lists. (e.g. there are multiple lists).
Definition: nomos.h:308