FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
admin-license-file.php
1 <?php
2 /***********************************************************
3  Copyright (C) 2008-2014 Hewlett-Packard Development Company, L.P.
4  Copyright (C) 2015-2018, Siemens AG
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License
8  version 2 as published by the Free Software Foundation.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  ***********************************************************/
19 
24 
25 define("TITLE_ADMIN_LICENSE_FILE", _("License Administration"));
26 
28 {
30  private $dbManager;
31 
32  function __construct()
33  {
34  $this->Name = "admin_license";
35  $this->Title = TITLE_ADMIN_LICENSE_FILE;
36  $this->MenuList = "Admin::License Admin";
37  $this->DBaccess = PLUGIN_DB_ADMIN;
38  $this->vars = array();
39  $this->obligationSelectorName = "assocObligations";
40  $this->obligationSelectorId = "assocObligations";
41  parent::__construct();
42 
43  $this->dbManager = $GLOBALS['container']->get('db.manager');
44  }
45 
49  function RegisterMenus()
50  {
51  if ($this->State != PLUGIN_STATE_READY) {
52  return(0);
53  }
54 
55  $URL = $this->Name."&add=y";
56  $text = _("Add new license");
57  menu_insert("Main::".$this->MenuList."::Add License",0, $URL, $text);
58  $URL = $this->Name;
59  $text = _("Select license family");
60  menu_insert("Main::".$this->MenuList."::Select License",0, $URL, $text);
61  }
62 
63  public function Output()
64  {
65  $V = "";
66  $errorstr = "License not added";
67 
68  // update the db
69  if (@$_POST["updateit"]) {
70  $resultstr = $this->Updatedb($_POST);
71  $this->vars['message'] = $resultstr;
72  if (strstr($resultstr, $errorstr)) {
73  return $this->Updatefm(0);
74  } else {
75  return $this->Inputfm();
76  }
77  }
78 
79  if (@$_REQUEST['add'] == 'y') {
80  return $this->Updatefm(0);
81  }
82 
83  // Add new rec to db
84  if (@$_POST["addit"]) {
85  $resultstr = $this->Adddb();
86  $this->vars['message'] = $resultstr;
87  if (strstr($resultstr, $errorstr)) {
88  return $this->Updatefm(0);
89  } else {
90  return $this->Inputfm();
91  }
92  }
93 
94  // bring up the update form
95  $rf_pk = @$_REQUEST['rf_pk'];
96  if ($rf_pk) {
97  return $this->Updatefm($rf_pk);
98  }
99 
100  // return a license text
101  if (@$_GET["getLicenseText"] && @$_GET["licenseID"]) {
102  $licenseText = $this->getLicenseTextForID(@$_GET["licenseID"]);
103  if (! $licenseText) {
104  return new Response("Error in querying license text.",
105  Response::HTTP_BAD_REQUEST, array(
106  'Content-type' => 'text/plain'
107  ));
108  }
109  return new Response($licenseText, Response::HTTP_OK,
110  array(
111  'Content-type' => 'text/plain'
112  ));
113  }
114 
115  if (@$_POST["req_shortname"]) {
116  $this->vars += $this->getLicenseListData($_POST["req_shortname"], $_POST["req_marydone"]);
117  }
118  $this->vars['Inputfm'] = $this->Inputfm();
119  return $this->render('admin_license_file.html.twig');
120  }
121 
127  function Inputfm()
128  {
129  $V = "<FORM name='Inputfm' action='?mod=" . $this->Name . "' method='POST'>";
130  $V.= _("What license family do you wish to view:<br>");
131 
132  // qualify by marydone, short name and long name
133  // all are optional
134  $V.= "<p>";
135  $V.= _("Filter: ");
136  $V.= "<select name='req_marydone'>\n";
137  $Selected = (@$_REQUEST['req_marydone'] == 'all') ? " SELECTED ": "";
138  $text = _("All");
139  $V.= "<option value='all' $Selected> $text </option>";
140  $Selected = (@$_REQUEST['req_marydone'] == 'done') ? " SELECTED ": "";
141  $text = _("Checked");
142  $V.= "<option value='done' $Selected> $text </option>";
143  $Selected = (@$_REQUEST['req_marydone'] == 'notdone') ? " SELECTED ": "";
144  $text = _("Not Checked");
145  $V.= "<option value='notdone' $Selected> $text </option>";
146  $V.= "</select>";
147  $V.= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
148 
149  // by short name -ajax-> fullname
150  $V.= _("License family name: ");
151  $Shortnamearray = $this->FamilyNames();
152  $Shortnamearray = array("All"=>"All") + $Shortnamearray;
153  $Selected = @$_REQUEST['req_shortname'];
154  $Pulldown = Array2SingleSelect($Shortnamearray, "req_shortname", $Selected);
155  $V.= $Pulldown;
156  $V.= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
157  $text = _("Find");
158  $V.= "<INPUT type='submit' value='$text'>\n";
159  $V .= "</FORM>\n";
160  $V.= "<hr>";
161 
162  return $V;
163  }
164 
165 
166  private function getLicenseData($where)
167  {
168  $sql = "SELECT rf_pk, marydone, rf_shortname, rf_spdx_compatible, " .
169  "rf_shortname, rf_fullname, rf_url, rf_text, ".
170  "string_agg(ob_topic, ';') AS ob_topic " .
171  "FROM ONLY license_ref " .
172  "LEFT OUTER JOIN obligation_map ON rf_fk = rf_pk " .
173  "LEFT OUTER JOIN obligation_ref ON ob_fk = ob_pk " .
174  "$where GROUP BY rf_pk ORDER BY rf_shortname";
175 
176  return $this->dbManager->getRows($sql);
177  }
178 
187  function getLicenseListData($namestr, $filter)
188  {
189  // look at all
190  if ($namestr == "All") {
191  $where = "";
192  } else {
193  $where = "where rf_shortname like '" . pg_escape_string($namestr) . "%' ";
194  }
195 
196  // $filter is one of these: "all", "done", "notdone"
197  if ($filter != "all") {
198  if (empty($where)) {
199  $where .= "where ";
200  } else {
201  $where .= " and ";
202  }
203  if ($filter == "done") {
204  $where .= " marydone=true";
205  }
206  if ($filter == "notdone") {
207  $where .= " marydone=false";
208  }
209  }
210 
211  $data = $this->getLicenseData($where);
212  if (! $data) {
213  $dataMessage = _(
214  "No licenses matching the filter and name pattern were found");
215  } else {
216  $dataSize = sizeof($data);
217  $plural = "";
218 
219  if ($dataSize > 1) {
220  $plural = "s";
221  }
222  $dataMessage = $dataSize . _(" License$plural found");
223  }
224 
225  return array(
226  'data' => $data,
227  'dataMessage' => $dataMessage,
228  'message' => "",
229  'tracebackURI' => Traceback_uri());
230  }
231 
232  function Updatefm($rf_pk)
233  {
234  $this->vars += $this->getUpdatefmData($rf_pk);
235  return $this->render('admin_license-upload_form.html.twig', $this->vars);
236  }
237 
243  function getUpdatefmData($rf_pk)
244  {
245  $vars = array();
246 
247  $rf_pk_update = "";
248 
249  if (0 < count($_POST)) {
250  $rf_pk_update = $_POST['rf_pk'];
251  if (! empty($rf_pk)) {
252  $rf_pk_update = $rf_pk;
253  } else if (empty($rf_pk_update)) {
254  $rf_pk_update = $_GET['rf_pk'];
255  }
256  }
257 
258  $vars['obligationSelectorName'] = $this->obligationSelectorName . "[]";
259  $vars['obligationSelectorId'] = $this->obligationSelectorId;
260 
261  $vars['actionUri'] = "?mod=" . $this->Name . "&rf_pk=$rf_pk_update";
262  $vars['req_marydone'] = array_key_exists('req_marydone', $_POST) ? $_POST['req_marydone'] : '';
263  $vars['req_shortname'] = array_key_exists('req_shortname', $_POST) ? $_POST['req_shortname'] : '';
264  $vars['req_marydone'] = array_key_exists('req_marydone', $_POST) ? $_POST['req_marydone'] : '';
265  $vars['rf_shortname'] = array_key_exists('rf_shortname', $_POST) ? $_POST['rf_shortname'] : '';
266  $vars['rf_fullname'] = array_key_exists('rf_fullname', $_POST) ? $_POST['rf_fullname'] : '';
267  $vars['rf_text'] = array_key_exists('rf_text', $_POST) ? $_POST['rf_text'] : '';
268  $selectedObligations = array_key_exists($this->obligationSelectorName,
269  $_POST) ? $_POST[$this->obligationSelectorName] : [];
270 
271  $parentMap = new LicenseMap($this->dbManager, 0, LicenseMap::CONCLUSION);
272  $parentLicenes = $parentMap->getTopLevelLicenseRefs();
273  $vars['parentMap'] = array(0=>'[self]');
274  foreach ($parentLicenes as $licRef) {
275  $vars['parentMap'][$licRef->getId()] = $licRef->getShortName();
276  }
277 
278  $reportMap = new LicenseMap($this->dbManager, 0, LicenseMap::REPORT);
279  $reportLicenes = $reportMap->getTopLevelLicenseRefs();
280  $vars['reportMap'] = array(0=>'[self]');
281  foreach ($reportLicenes as $licRef) {
282  $vars['reportMap'][$licRef->getId()] = $licRef->getShortName();
283  }
284 
285  $obligationMap = new ObligationMap($this->dbManager);
286  $obligations = $obligationMap->getObligations();
287  foreach ($obligations as $obligation) {
288  $vars['obligationTopics'][$obligation['ob_pk']] = $obligation['ob_topic'];
289  }
290  foreach ($selectedObligations as $obligation) {
291  $row['obligationSelected'][$obligation] = $obligationMap->getTopicNameFromId(
292  $obligation);
293  }
294 
295  if ($rf_pk > 0) { // true if this is an update
296  $row = $this->dbManager->getSingleRow(
297  "SELECT * FROM ONLY license_ref WHERE rf_pk=$1", array($rf_pk),
298  __METHOD__ . '.forUpdate');
299  if ($row === false) {
300  $text = _("No licenses matching this key");
301  $text1 = _("was found");
302  return "$text ($rf_pk) $text1.";
303  }
304  $row['rf_parent'] = $parentMap->getProjectedId($rf_pk);
305  $row['rf_report'] = $reportMap->getProjectedId($rf_pk);
306 
307  $obligationsAssigned = $parentMap->getObligationsForLicenseRef($rf_pk);
308  foreach ($obligationsAssigned as $obligation) {
309  $row['obligationSelected'][$obligation] = $obligationMap->getTopicNameFromId(
310  $obligation);
311  }
312  } else {
313  $row = array(
314  'rf_active' => 't',
315  'marydone' => 'f',
316  'rf_text_updatable' => 't',
317  'rf_parent' => 0,
318  'rf_report' => 0,
319  'rf_risk' => 0,
320  'rf_spdx_compatible' => 'f',
321  'rf_url' => '',
322  'rf_detector_type' => 1,
323  'rf_notes' => ''
324  );
325  }
326 
327  foreach (array_keys($row) as $key) {
328  if (array_key_exists($key, $_POST)) {
329  $row[$key] = $_POST[$key];
330  }
331  }
332 
333  $vars['boolYesNoMap'] = array("true"=>"Yes", "false"=>"No");
334  $row['rf_active'] = $this->isTrue($row['rf_active']) ? 'true' : 'false';
335  $row['marydone'] = $this->isTrue($row['marydone']) ? 'true' : 'false';
336  $row['rf_text_updatable'] = $this->isTrue($row['rf_text_updatable']) ? 'true' : 'false';
337  $row['rf_spdx_compatible'] = $this->isTrue($row['rf_spdx_compatible']) ? 'true' : 'false';
338  $vars['risk_level'] = array_key_exists('risk_level', $_POST) ? intval($_POST['risk_level']) : $row['rf_risk'];
339  $vars['isReadOnly'] = !(empty($rf_pk) || $row['rf_text_updatable']=='true');
340  $vars['detectorTypes'] = array("1"=>"Reference License", "2"=>"Nomos", "3"=>"Unconcrete License");
341 
342  $vars['rfId'] = $rf_pk?:$rf_pk_update;
343 
344  return array_merge($vars,$row);
345  }
346 
351  private function isTrue($value)
352  {
353  if (is_bool($value)) {
354  return $value;
355  } else {
356  $value = strtolower($value);
357  return ($value === 't' || $value === 'true');
358  }
359  }
360 
362  private function isShortnameBlocked($rfId, $shortname, $text)
363  {
364  $sql = "SELECT count(*) from license_ref where rf_pk <> $1 and (LOWER(rf_shortname) = LOWER($2) or (rf_text <> ''
365  and rf_text = $3 and LOWER(rf_text) NOT LIKE 'license by nomos.'))";
366  $check_count = $this->dbManager->getSingleRow($sql,
367  array(
368  $rfId,
369  $shortname,
370  $text
371  ), __METHOD__ . '.countLicensesByNomos');
372  return (0 < $check_count['count']);
373  }
374 
376  private function isShortNameExists($rfId, $shortname)
377  {
378  $sql = "SELECT LOWER(rf_shortname) AS rf_shortname FROM license_ref WHERE rf_pk=$1";
379  $row = $this->dbManager->getSingleRow($sql,array($rfId),__METHOD__.'.DoNotChnageShortName');
380  if ($row['rf_shortname'] === strtolower($shortname)) {
381  return 1;
382  } else {
383  return 0;
384  }
385  }
386 
392  function Updatedb()
393  {
394  $rfId = intval($_POST['rf_pk']);
395  $shortname = trim($_POST['rf_shortname']);
396  $fullname = trim($_POST['rf_fullname']);
397  $url = $_POST['rf_url'];
398  $notes = $_POST['rf_notes'];
399  $text = trim($_POST['rf_text']);
400  $parent = $_POST['rf_parent'];
401  $report = $_POST['rf_report'];
402  $riskLvl = intval($_POST['risk_level']);
403  $selectedObligations = array_key_exists($this->obligationSelectorName,
404  $_POST) ? $_POST[$this->obligationSelectorName] : [];
405 
406  if (empty($shortname)) {
407  $text = _("ERROR: The license shortname is empty. License not added.");
408  return "<b>$text</b><p>";
409  }
410 
411  if (!$this->isShortNameExists($rfId,$shortname)) {
412  $text = _("ERROR: The shortname can not be changed. License not added.");
413  return "<b>$text</b><p>";
414  }
415 
416  $md5term = (empty($text) || stristr($text, "License by Nomos")) ? 'null' : 'md5($10)';
417 
418  $sql = "UPDATE license_ref SET
419  rf_active=$2, marydone=$3, rf_shortname=$4, rf_fullname=$5,
420  rf_url=$6, rf_notes=$7, rf_text_updatable=$8, rf_detector_type=$9, rf_text=$10,
421  rf_md5=$md5term, rf_risk=$11, rf_spdx_compatible=$12, rf_flag=$13
422  WHERE rf_pk=$1";
423  $params = array($rfId,
424  $_POST['rf_active'],$_POST['marydone'],$shortname,$fullname,
425  $url,$notes,$_POST['rf_text_updatable'],$_POST['rf_detector_type'],$text,
426  $riskLvl,$_POST['rf_spdx_compatible'],2);
427  $statement = __METHOD__ . ".updateLicense";
428  if ($md5term == "null") {
429  $statement .= ".nullMD5";
430  }
431  $this->dbManager->prepare($statement, $sql);
432  $this->dbManager->freeResult($this->dbManager->execute($statement, $params));
433 
434  $licenseMapDelStatement = __METHOD__ . '.deleteFromMap';
435  $licenseMapDelSql = 'DELETE FROM license_map WHERE rf_fk=$1 AND usage=$2';
436  $this->dbManager->prepare($licenseMapDelStatement, $licenseMapDelSql);
437 
438  $parentMap = new LicenseMap($this->dbManager, 0, LicenseMap::CONCLUSION);
439  if ($parent == 0) {
440  // Update conclusion to self
441  $this->dbManager->execute($licenseMapDelStatement,
442  array($rfId, LicenseMap::CONCLUSION));
443  } else {
444  $parentLicenses = $parentMap->getTopLevelLicenseRefs();
445  if (array_key_exists($parent, $parentLicenses) &&
446  $parent != $parentMap->getProjectedId($rfId)) {
447  $this->dbManager->execute($licenseMapDelStatement,
448  array($rfId, LicenseMap::CONCLUSION));
449  $this->dbManager->insertTableRow('license_map',
450  array('rf_fk'=>$rfId, 'rf_parent'=>$parent, 'usage'=>LicenseMap::CONCLUSION));
451  }
452  }
453 
454  if ($report == 0) {
455  // Update report to self
456  $this->dbManager->execute($licenseMapDelStatement,
457  array($rfId, LicenseMap::REPORT));
458  } else {
459  $reportMap = new LicenseMap($this->dbManager, 0, LicenseMap::REPORT);
460  $reportLicenses = $parentMap->getTopLevelLicenseRefs();
461  if (array_key_exists($report, $reportLicenses) &&
462  $report != $reportMap->getProjectedId($rfId)) {
463  $this->dbManager->execute($licenseMapDelStatement,
464  array($rfId, LicenseMap::REPORT));
465  $this->dbManager->insertTableRow('license_map',
466  array('rf_fk'=>$rfId, 'rf_parent'=>$report, 'usage'=>LicenseMap::REPORT));
467  }
468  }
469 
470  $obligationMap = new ObligationMap($this->dbManager);
471  foreach ($selectedObligations as $obligation) {
472  $obligationMap->associateLicenseWithObligation($obligation, $rfId);
473  }
474 
475  $allObligations = $parentMap->getObligationsForLicenseRef($rfId);
476  $removedObligations = array_diff($allObligations, $selectedObligations);
477  foreach ($removedObligations as $obligation) {
478  $obligationMap->unassociateLicenseFromObligation($obligation, $rfId);
479  }
480 
481  $ob = "License $_POST[rf_shortname] updated.<p>";
482  return $ob;
483  }
484 
485 
491  function Adddb()
492  {
493  $rf_shortname = trim($_POST['rf_shortname']);
494  $rf_fullname = trim($_POST['rf_fullname']);
495  $rf_url = $_POST['rf_url'];
496  $rf_notes = $_POST['rf_notes'];
497  $rf_text = trim($_POST['rf_text']);
498  $parent = $_POST['rf_parent'];
499  $report = $_POST['rf_report'];
500  $riskLvl = intval($_POST['risk_level']);
501  $selectedObligations = $_POST[$this->obligationSelectorName];
502 
503  if (empty($rf_shortname)) {
504  $text = _("ERROR: The license shortname is empty. License not added.");
505  return "<b>$text</b><p>";
506  }
507 
508  if ($this->isShortnameBlocked(0,$rf_shortname,$rf_text)) {
509  $text = _("ERROR: The shortname or license text already exist in the license list. License not added.");
510  return "<b>$text</b><p>";
511  }
512 
513  $md5term = (empty($rf_text) || stristr($rf_text, "License by Nomos")) ? 'null' : 'md5($7)';
514  $stmt = __METHOD__.'.rf';
515  $sql = "INSERT into license_ref (
516  rf_active, marydone, rf_shortname, rf_fullname,
517  rf_url, rf_notes, rf_md5, rf_text, rf_text_updatable,
518  rf_detector_type, rf_risk, rf_spdx_compatible)
519  VALUES (
520  $1, $2, $3, $4, $5, $6, $md5term, $7, $8, $9, $10, $11) RETURNING rf_pk";
521  $this->dbManager->prepare($stmt,$sql);
522  $res = $this->dbManager->execute($stmt,
523  array(
524  $_POST['rf_active'],
525  $_POST['marydone'],
526  $rf_shortname,
527  $rf_fullname,
528  $rf_url,
529  $rf_notes,
530  $rf_text,
531  $_POST['rf_text_updatable'],
532  $_POST['rf_detector_type'],
533  $riskLvl,
534  $_POST['rf_spdx_compatible']
535  ));
536  $row = $this->dbManager->fetchArray($res);
537  $rfId = $row['rf_pk'];
538 
539  $parentMap = new LicenseMap($this->dbManager, 0, LicenseMap::CONCLUSION);
540  $parentLicenses = $parentMap->getTopLevelLicenseRefs();
541  if (array_key_exists($parent, $parentLicenses)) {
542  $this->dbManager->insertTableRow('license_map',
543  array(
544  'rf_fk' => $rfId,
545  'rf_parent' => $parent,
546  'usage' => LicenseMap::CONCLUSION
547  ));
548  }
549 
550  $reportMap = new LicenseMap($this->dbManager, 0, LicenseMap::REPORT);
551  $reportLicenses = $reportMap->getTopLevelLicenseRefs();
552  if (array_key_exists($report, $reportLicenses)) {
553  $this->dbManager->insertTableRow('license_map',
554  array(
555  'rf_fk' => $rfId,
556  'rf_parent' => $report,
557  'usage' => LicenseMap::REPORT
558  ));
559  }
560 
561  $obligationMap = new ObligationMap($this->dbManager);
562  foreach ($selectedObligations as $obligation) {
563  $obligationMap->associateLicenseWithObligation($obligation, $rfId);
564  }
565 
566  return "License $_POST[rf_shortname] (id=$rfId) added.<p>";
567  }
568 
569 
579  function FamilyNames()
580  {
581  $familynamearray = array();
582  $Shortnamearray = DB2KeyValArray("license_ref", "rf_pk", "rf_shortname", " order by rf_shortname");
583 
584  // truncate each name to the family name
585  foreach ($Shortnamearray as $shortname) {
586  // start with exceptions
587  if (($shortname == "No_license_found") || ($shortname == "Unknown license")) {
588  $familynamearray[$shortname] = $shortname;
589  } else {
590  $tok = strtok($shortname, " _-([/");
591  $familynamearray[$tok] = $tok;
592  }
593  }
594 
595  return ($familynamearray);
596  }
597 
598  private function getLicenseTextForID($licenseID)
599  {
600  $sql = "select rf_text from license_ref where rf_pk=$1";
601  $result = $this->dbManager->getSingleRow($sql, array($licenseID));
602 
603  if (! $result) {
604  return false;
605  }
606  return $result['rf_text'];
607  }
608 }
609 
610 $NewPlugin = new admin_license_file();
isShortNameExists($rfId, $shortname)
check if shortname is changed
Traceback_uri()
Get the URI without query to this location.
Updatedb()
Update the database.
#define PLUGIN_DB_ADMIN
Plugin requires admin level permission on DB.
Definition: libfossology.h:51
getUpdatefmData($rf_pk)
Update forms.
getLicenseListData($namestr, $filter)
Build the input form.
isShortnameBlocked($rfId, $shortname, $text)
check if shortname or license text of this license is existing
Wrapper class for license map.
Definition: LicenseMap.php:29
isTrue($value)
Check if a variable is true.
Inputfm()
Build the input form.
Definition: state.hpp:26
DB2KeyValArray($Table, $KeyCol, $ValCol, $Where="")
Create an associative array by using table rows to source the key/value pairs.
Definition: common-db.php:132
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:28
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:67
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...
RegisterMenus()
Customize submenus.
Adddb()
Add a new license_ref to the database.
Wrapper class for obligation map.
Array2SingleSelect($KeyValArray, $SLName="unnamed", $SelectedVal="", $FirstEmpty=false, $SelElt=true, $Options="", $ReturnKey=true)
Build a single choice select pulldown.
Definition: common-ui.php:41
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:695
render($templateName, $vars=null)
Definition: FO_Plugin.php:442