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