FOSSology  4.4.0
Open Source License Compliance by Open Source Software
acme_review.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2012 Hewlett-Packard Development Company, L.P.
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
8 define("TITLE_ACME_REVIEW", _("ACME Review"));
9 
19 function proj_cmp($rowa, $rowb)
20 {
21  $key1 = $rowb['count'] - $rowa['count'];
22  if ($key1) {
23  return $key1;
24  }
25 
26  // secondary key - project_name ascending
27  return (strnatcasecmp($rowa['project_name'], $rowb['project_name']));
28 }
29 
30 class acme_review extends FO_Plugin
31 {
32  var $Name = "acme_review";
33  var $Title = TITLE_ACME_REVIEW;
34  var $Version = "1.0";
35  var $MenuList = "";
36  var $MenuOrder = 110;
37  var $Dependency = array("browse", "view");
38  var $DBaccess = PLUGIN_DB_READ;
39  var $LoginFlag = 0;
40  var $NoHTML = 1; // prevent the http header from being written in case we have to download a file
41 
45  function RegisterMenus()
46  {
47  if (GetParm("mod", PARM_STRING) == $this->Name) {
48  $detail = GetParm("detail",PARM_INTEGER);
49  if ($detail) {
50  $text = _("ACME High Level Review");
51  $URI = $this->Name . Traceback_parm_keep(array( "page", "upload", "folic")) . "&detail=0";
52  } else {
53  $text = _("ACME Low Level Review");
54  $URI = $this->Name . Traceback_parm_keep(array( "page", "upload", "folic")) . "&detail=1";
55  }
56 
57  // micro menu when in acme_review
58  menu_insert("acme::$text", 1, $URI, $text);
59  } else {
60  // micro menu item when not in acme_review
61  $text2 = _("ACME Review");
62  $URI = $this->Name . Traceback_parm_keep(array( "page", "upload")) . "&detail=0";
63  menu_insert("Browse::$text2", 1, $URI, $text2);
64  }
65  } // RegisterMenus()
66 
67 
74  function FindACMEProjects($uploadtreeRow, &$acme_project_array)
75  {
76  global $PG_CONN;
77 
78  /* See if there is already an acme project for this pfile */
79  $sql = "select acme_project_fk from acme_pfile where pfile_fk='$uploadtreeRow[pfile_fk]' limit 1";
80  $result = pg_query($PG_CONN, $sql);
81  DBCheckResult($result, $sql, __FILE__, __LINE__);
82  if (pg_num_rows($result) > 0) {
83  /* found a project */
84  $acme_pfileRow = pg_fetch_assoc($result);
85 
86  // retrieve the acme_project record to go with the found acme_project_fk
87  $sql = "select * from acme_project where acme_project_pk='$acme_pfileRow[acme_project_fk]'";
88  $projresult = pg_query($PG_CONN, $sql);
89  DBCheckResult($projresult, $sql, __FILE__, __LINE__);
90  if (pg_num_rows($projresult) > 0) {
91  $acme_project_array[$acme_pfileRow['acme_project_fk']] = pg_fetch_assoc($projresult);
92  $acme_project_array[$acme_pfileRow['acme_project_fk']]['count'] = ($uploadtreeRow['rgt'] - $uploadtreeRow['lft']);
93  }
94  return;
95  } else {
96  /* check each child */
97  $sql = "select uploadtree_pk, pfile_fk, lft, rgt from uploadtree where parent= $uploadtreeRow[uploadtree_pk]";
98  $childrenResult = pg_query($PG_CONN, $sql);
99  DBCheckResult($childrenResult, $sql, __FILE__, __LINE__);
100  while ($child = pg_fetch_assoc($childrenResult)) {
101  $this->FindACMEProjects($child, $acme_project_array);
102  }
103  pg_free_result($childrenResult);
104  }
105  pg_free_result($result);
106 
107  return;
108  } // FindACMEProjects()
109 
110 
117  function GetProjectArray0($upload_pk, $nomosAgentpk, $MinCount=1)
118  {
119  global $PG_CONN;
120  $acme_project_array = array(); // acme project array to return
121 
122  $sql = "select uploadtree_pk, pfile_fk, lft, rgt from uploadtree where upload_fk='$upload_pk' and parent is null";
123  $result = pg_query($PG_CONN, $sql);
124  DBCheckResult($result, $sql, __FILE__, __LINE__);
125  $row = pg_fetch_assoc($result);
126  $this->FindACMEProjects($row, $acme_project_array);
127  pg_free_result($result);
128 
129  return $acme_project_array;
130  }
131 
132 
139  function GetProjectArray1($upload_pk, $nomosAgentpk, $MinCount=1)
140  {
141  global $PG_CONN;
142  $acme_project_array = array(); // acme project array to return
143  $idx = 0;
144 
145  $sql = "select distinct(acme_project_fk) as acme_project_fk, count(acme_project_fk) as filecount from acme_pfile
146  right join uploadtree on uploadtree.pfile_fk=acme_pfile.pfile_fk where upload_fk=$upload_pk
147  group by acme_project_fk order by filecount desc";
148  $result = pg_query($PG_CONN, $sql);
149  DBCheckResult($result, $sql, __FILE__, __LINE__);
150  while ($row = pg_fetch_assoc($result)) {
151  if ($row['filecount'] < $MinCount) {
152  break;
153  }
154 
155  // retrieve the acme_project record to go with the found acme_project_fk
156  $sql = "select * from acme_project where acme_project_pk='$row[acme_project_fk]'";
157  $projresult = pg_query($PG_CONN, $sql);
158  DBCheckResult($projresult, $sql, __FILE__, __LINE__);
159  if (pg_num_rows($projresult) > 0) {
160  $acme_project_array[$idx] = pg_fetch_assoc($projresult);
161  $acme_project_array[$idx]['count'] = $row['filecount'];
162  $idx++;
163  }
164  }
165 
166  return($acme_project_array);
167  } // GetProjectArray1()
168 
169 
176  function HTMLForm($acme_project_array, $upload_pk)
177  {
178  $Outbuf = "";
179  $uploadtreeRec = GetSingleRec("uploadtree", "where upload_fk=$upload_pk and parent is null");
180  $Outbuf .= Dir2Browse($this->Name,$uploadtreeRec['uploadtree_pk'], NULL, 1, "acme");
181  $Outbuf .= "<p>";
182 
183  $URI = "?mod=" . $this->Name . Traceback_parm_keep(array( "page", "upload", "folic", "detail"));
184  $Outbuf .= "<form action='" . $URI . "' method='POST'>\n";
185 
186  $Outbuf .= "<table border=1>";
187  $Outbuf .= "<tr>";
188  $text = _('Include');
189  $Outbuf .= "<th>$text</th>";
190  $text = _('Project');
191  $Outbuf .= "<th>$text</th>";
192  $text = _('Files');
193  $Outbuf .= "<th>$text</th>";
194  $text = _('URL');
195  $Outbuf .= "<th>$text</th>";
196  $text = _('Description');
197  $Outbuf .= "<th>$text</th>";
198  $text = _('License');
199  $Outbuf .= "<th>$text</th>";
200  $text = _('Version');
201  $Outbuf .= "<th>$text</th>";
202  $Outbuf .= "</tr>";
203 
204  /* For alternating row background colors */
205  $RowStyle1 = "style='background-color:lavender'";
206  $RowStyle2 = "style='background-color:lightyellow'";
207  $ColorSpanRows = 1; // Alternate background color every $ColorSpanRows
208  $RowNum = 0;
209 
210  if (empty($acme_project_array)) {
211  $acme_project_array = array();
212  }
213  foreach ($acme_project_array as $project) {
214  /* Set alternating row background color - repeats every $ColorSpanRows rows */
215  $RowStyle = (($RowNum++ % (2*$ColorSpanRows))<$ColorSpanRows) ? $RowStyle1 : $RowStyle2;
216 
217  $Outbuf .= "<tr $RowStyle>";
218  $Checked = $project['include'] == 't' ? "checked=\"checked\"" : '' ;
219  $Outbuf .= "<td><input type='checkbox' name='includeproj[$project[acme_project_pk]]' $Checked></td>\n";
220  $Outbuf .= "<td>$project[project_name]</td>";
221  $ProjectListURL = Traceback_uri() . "?mod=" . $this->Name . "&acme_project=$project[acme_project_pk]&upload=$upload_pk";
222  $Outbuf .= "<td><a href='$ProjectListURL'>$project[count]</a></td>";
223  $Outbuf .= "<td><a href='$project[url]'>$project[url]</a></td>";
224  $Outbuf .= "<td>" . htmlentities($project['description'], ENT_HTML5 | ENT_QUOTES) . "</td>";
225  $Outbuf .= "<td>$project[licenses]</td>";
226  $Outbuf .= "<td>$project[version]</td>";
227  $Outbuf .= "</tr>";
228  }
229  $Outbuf .= "</table>";
230 
231  $Outbuf .= "$RowNum rows found<br>";
232 
233  $text = _("Save and Generate SPDX file");
234  $Outbuf .= "<p><input type='submit' value='$text' name='spdxbtn'>\n";
235  $text = _("Save");
236  $Outbuf .= "&nbsp;&nbsp;&nbsp;<input type='submit' value='$text' name='savebtn'>\n";
237  $Outbuf .= "</form>\n";
238  /******* END Input form *******/
239 
240  return $Outbuf;
241  }
242 
243 
251  function Populate_acme_upload($acme_project_array, $upload_pk, $detail)
252  {
253  global $PG_CONN;
254 
255  foreach ($acme_project_array as $project) {
256  $sql = "insert into acme_upload (upload_fk, acme_project_fk, include, detail, count) values ($upload_pk, $project[acme_project_pk], true, $detail, $project[count])";
257  $result = pg_query($PG_CONN, $sql);
258  DBCheckResult($result, $sql, __FILE__, __LINE__);
259  pg_free_result($result);
260  }
261  }
262 
263 
269  function GenerateSPDX($acme_project_array)
270  {
271  global $SysConf;
272 
273  $spdx = '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
274  $spdx .='<rdf:RDF' . "\n";
275  $spdx .= ' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"' . "\n";
276  $spdx .= ' xmlns="http://spdx.org/rdf/terms#"' . "\n";
277  $spdx .= ' xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">' . "\n";
278  $spdx .= ' <SpdxDocument rdf:about="http://www.spdx.org/tools#SPDXANALYSIS">' . "\n";
279  $spdx .= ' <specVersion>SPDX-1.1</specVersion>' . "\n";
280  $spdx .= ' <dataLicense rdf:about="http://spdx.org/licenses/PDDL-1.0" />' . "\n";
281  $spdx .= ' <CreationInfo>' . "\n";
282  $spdx .= " <creator>Tool: FOSSology v " . $SysConf['BUILD']['VERSION'] . " svn " . $SysConf['BUILD']['COMMIT_HASH'] . "</creator>\n";
283  $spdx .= "<created>" . date('c') . "</created>\n"; // date-time in ISO 8601 format
284  $spdx .= '</CreationInfo>' . "\n";
285 
286  $in_encoding = iconv_get_encoding("input_encoding");
287  foreach ($acme_project_array as $project) {
288  //debugprint($project, "Project");
289  $spdx .= "<Package>\n";
290  $spdx .= '<name>' . str_replace("&", " and ", strip_tags($project['project_name'])) . '</name>' . "\n";
291  $spdx .= "<versionInfo>$project[version]</versionInfo>\n";
292  $spdx .= "<licenseDeclared>$project[licenses]</licenseDeclared>\n";
293  $spdx .= "<sourceInfo>ProjectURL: $project[url]</sourceInfo>\n";
294  $spdx .= '<description>' . str_replace("&", " and ", strip_tags($project['description'])) . '</description>' . "\n";
295  $spdx .= "</Package>\n";
296  }
297  /*
298  <packageSupplier>Organization: FSF (info@fsf.com)</packageSupplier>
299  <packageOriginator>Organization: FSF (info@fsf.com)</packageOriginator>
300  <packageDdownloadLocation>http://ftp.gnu.org/gnu/coreutils/</packageDdownloadLocation>
301  <packageFileName>coreutils-8.12.tar.gz</packageFileName>
302  <sourceInfo>
303  mechanism: git
304  repository: git://git.sv.gnu.org/coreutils
305  branch: master
306  tag: v8.12
307  </sourceInfo>
308  </Package>
309  */
310 
311  $spdx .= " </SpdxDocument> </rdf:RDF>\n";
312  return $spdx;
313  }
314 
315 
319  function Output()
320  {
321  global $Plugins;
322  global $PG_CONN;
323 
324  //phpinfo();
325  $CriteriaCount = 0;
326  $V="";
327  $GETvars="";
328  $upload_pk = GetParm("upload",PARM_INTEGER);
329  $detail = GetParm("detail",PARM_INTEGER);
330  $detail = empty($detail) ? 0 : 1;
331  $folic = GetParm("folic",PARM_INTEGER);
332  $savebtn = GetParm("savebtn",PARM_RAW);
333  $spdxbtn = GetParm("spdxbtn",PARM_RAW);
334 
335  $agent_pk = LatestAgentpk($upload_pk, "nomos_ars");
336  if (empty($agent_pk)) {
337  echo "Missing fossology license data. Run a license scan on this upload.<br>";
338  exit;
339  }
340  $uploadtree_tablename = GetUploadtreeTableName($upload_pk);
341 
342  // Check if we have data in the acme_upload table, if not then load it
343  $acme_uploadRec = GetSingleRec("acme_upload", "where upload_fk=$upload_pk and detail=$detail");
344  if (empty($acme_uploadRec)) {
345  // populate acme_upload
346  $MinCount = 1;
347  $nomosAgentpk = LatestAgentpk($upload_pk, "nomos_ars");
348  $acme_project_array = $this->GetProjectArray1($upload_pk, $nomosAgentpk, $MinCount); // low level
349  $this->Populate_acme_upload($acme_project_array, $upload_pk, 1);
350  $acme_project_array = $this->GetProjectArray0($upload_pk, $nomosAgentpk, $MinCount); // high level
351  $this->Populate_acme_upload($acme_project_array, $upload_pk, 0);
352  }
353 
354  $sql = "select * from acme_upload, acme_project where acme_project_pk=acme_project_fk and detail=$detail and upload_fk=$upload_pk";
355  $result = pg_query($PG_CONN, $sql);
356  DBCheckResult($result, $sql, __FILE__, __LINE__);
357  $acme_project_array = pg_fetch_all($result);
358  $acme_project_array_orig = $acme_project_array; // save the original state so we know which records to update
359 
360  /* If the save or spdx buttons were clicked, update $acme_project_array and save the data in the acme_upload table */
361  if (! empty($savebtn) or ! empty($spdxbtn)) {
362  /* First set all projects include to false */
363  foreach ($acme_project_array as &$project) {
364  $project['include'] = 'f';
365  }
366  /* Now turn on projects include to match form */
367  if (array_key_exists('includeproj', $_POST)) {
368  $includeArray = $_POST['includeproj'];
369  foreach ($acme_project_array as &$project) {
370  if (array_key_exists($project['acme_project_fk'], $includeArray)) {
371  $project['include'] = "t";
372  }
373  }
374  }
375 
376  /* Finally, update the db with any changed include states */
377  $NumRecs = count($acme_project_array);
378  for ($i = 0; $i < $NumRecs; $i ++) {
379  $project = $acme_project_array[$i];
380  $project_orig = $acme_project_array_orig[$i];
381  if ($project['include'] != $project_orig['include']) {
382  $include = $project['include'] ? "true" : "false";
383  $sql = "update acme_upload set include='$include' where acme_upload_pk='$project[acme_upload_pk]'";
384  $result = pg_query($PG_CONN, $sql);
385  DBCheckResult($result, $sql, __FILE__, __LINE__);
386  pg_free_result($result);
387  }
388  }
389  }
390 
391  /* aggregate the fossology licenses for each pfile and each acme_project */
392  if ($folic) {
393  foreach ($acme_project_array as &$project) {
394  $sql = "select uploadtree_pk from acme_pfile, uploadtree where acme_project_fk=$project[acme_project_fk]
395  and acme_pfile.pfile_fk=uploadtree.pfile_fk and uploadtree.upload_fk=$upload_pk";
396  $result = pg_query($PG_CONN, $sql);
397  DBCheckResult($result, $sql, __FILE__, __LINE__);
398  $LicArray = array();
399  $ItemLicArray = array();
400  while ($acme_pfileRow = pg_fetch_assoc($result)) {
401  $LicArray = GetFileLicenses($agent_pk, '', $acme_pfileRow['uploadtree_pk'], $uploadtree_tablename);
402  foreach ($LicArray as $key => $license) {
403  $ItemLicArray[$key] = $license;
404  }
405  }
406  $project['licenses'] = '';
407  foreach ($ItemLicArray as $license) {
408  if ($license == "No_license_found") {
409  continue;
410  }
411  if (! empty($project['licenses'])) {
412  $project['licenses'] .= ", ";
413  }
414  $project['licenses'] .= $license;
415  }
416  }
417  }
418 
419  /* sort $acme_project_array by count desc */
420  if (! empty($acme_project_array)) {
421  usort($acme_project_array, 'proj_cmp');
422  }
423 
424  /* generate and download spdx file */
425  if (! empty($spdxbtn)) {
426  $spdxfile = $this->GenerateSPDX($acme_project_array);
427  $rv = DownloadString2File($spdxfile, "SPDX.rdf file", "xml");
428  if ($rv !== true) {
429  echo $rv;
430  }
431  }
432 
433  switch ($this->OutputType) {
434  case "HTML":
435  $this->NoHeader = 0;
436  $this->OutputOpen("HTML", 1);
437  $V .= $this->HTMLForm($acme_project_array, $upload_pk);
438  break;
439  default:
440  break;
441  }
442  if (! $this->OutputToStdout) {
443  return ($V);
444  }
445  print($V);
446  return;
447  } // Output()
448 }
449 //return; // prevent anyone from seeing this plugin
450 $NewPlugin = new acme_review();
451 $NewPlugin->Initialize();
452 
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:57
OutputOpen()
This function is called when user output is requested. This function is responsible for assigning hea...
Definition: FO_Plugin.php:305
HTMLForm($acme_project_array, $upload_pk)
create the HTML to display the form showing the found projects
RegisterMenus()
Customize submenus.
Definition: acme_review.php:45
FindACMEProjects($uploadtreeRow, &$acme_project_array)
Find all the acme projects in a hierarchy, starting with $uploadtree_pk. Once you get an acme hit,...
Definition: acme_review.php:74
GetProjectArray1($upload_pk, $nomosAgentpk, $MinCount=1)
Given an upload , return all the unique projects found.
GenerateSPDX($acme_project_array)
Write and return the SPDX file as a string.
Populate_acme_upload($acme_project_array, $upload_pk, $detail)
Populate the acme_upload table for this upload.
Output()
Display the loaded menu and plugins.
GetProjectArray0($upload_pk, $nomosAgentpk, $MinCount=1)
Given an upload , return all the unique projects found.
LatestAgentpk($upload_pk, $arsTableName, $arsSuccess=false)
Given an upload_pk, find the latest enabled agent_pk with results.
DBCheckResult($result, $sql, $filenm, $lineno)
Check the postgres result for unexpected errors. If found, treat them as fatal.
Definition: common-db.php:187
GetSingleRec($Table, $Where="")
Retrieve a single database record.
Definition: common-db.php:91
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.
Definition: common-dir.php:263
GetFileLicenses($agent, $pfile_pk, $uploadtree_pk, $uploadtree_tablename='uploadtree', $duplicate="")
get all the licenses for a single file or uploadtree
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.
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
Traceback_parm_keep($List)
Create a new URI, keeping only these items.
DownloadString2File($text, $name, $contentType)
Send a string to a user as a download file.
Definition: common-ui.php:198
FUNCTION char * GetUploadtreeTableName(PGconn *pgConn, int upload_pk)
Get the uploadtree table name for this upload_pk If upload_pk does not exist, return "uploadtree".
Definition: libfossagent.c:414
#define PLUGIN_DB_READ
Plugin requires read permission on DB.
Definition: libfossology.h:37
foreach($Options as $Option=> $OptVal) if(0==$reference_flag &&0==$nomos_flag) $PG_CONN