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 . Traceback_parm_keep(array( "page", "upload", "folic")) . "&detail=0";
63  } else {
64  $text = _("ACME Low Level Review");
65  $URI = $this->Name . Traceback_parm_keep(array( "page", "upload", "folic")) . "&detail=1";
66  }
67 
68  // micro menu when in acme_review
69  menu_insert("acme::$text", 1, $URI, $text);
70  } else {
71  // micro menu item when not in acme_review
72  $text2 = _("ACME Review");
73  $URI = $this->Name . Traceback_parm_keep(array( "page", "upload")) . "&detail=0";
74  menu_insert("Browse::$text2", 1, $URI, $text2);
75  }
76  } // RegisterMenus()
77 
78 
85  function FindACMEProjects($uploadtreeRow, &$acme_project_array)
86  {
87  global $PG_CONN;
88 
89  /* See if there is already an acme project for this pfile */
90  $sql = "select acme_project_fk from acme_pfile where pfile_fk='$uploadtreeRow[pfile_fk]' limit 1";
91  $result = pg_query($PG_CONN, $sql);
92  DBCheckResult($result, $sql, __FILE__, __LINE__);
93  if (pg_num_rows($result) > 0) {
94  /* found a project */
95  $acme_pfileRow = pg_fetch_assoc($result);
96 
97  // retrieve the acme_project record to go with the found acme_project_fk
98  $sql = "select * from acme_project where acme_project_pk='$acme_pfileRow[acme_project_fk]'";
99  $projresult = pg_query($PG_CONN, $sql);
100  DBCheckResult($projresult, $sql, __FILE__, __LINE__);
101  if (pg_num_rows($projresult) > 0) {
102  $acme_project_array[$acme_pfileRow['acme_project_fk']] = pg_fetch_assoc($projresult);
103  $acme_project_array[$acme_pfileRow['acme_project_fk']]['count'] = ($uploadtreeRow['rgt'] - $uploadtreeRow['lft']);
104  }
105  return;
106  } else {
107  /* check each child */
108  $sql = "select uploadtree_pk, pfile_fk, lft, rgt from uploadtree where parent= $uploadtreeRow[uploadtree_pk]";
109  $childrenResult = pg_query($PG_CONN, $sql);
110  DBCheckResult($childrenResult, $sql, __FILE__, __LINE__);
111  while ($child = pg_fetch_assoc($childrenResult)) {
112  $this->FindACMEProjects($child, $acme_project_array);
113  }
114  pg_free_result($childrenResult);
115  }
116  pg_free_result($result);
117 
118  return;
119  } // FindACMEProjects()
120 
121 
128  function GetProjectArray0($upload_pk, $nomosAgentpk, $MinCount=1)
129  {
130  global $PG_CONN;
131  $acme_project_array = array(); // acme project array to return
132 
133  $sql = "select uploadtree_pk, pfile_fk, lft, rgt from uploadtree where upload_fk='$upload_pk' and parent is null";
134  $result = pg_query($PG_CONN, $sql);
135  DBCheckResult($result, $sql, __FILE__, __LINE__);
136  $row = pg_fetch_assoc($result);
137  $this->FindACMEProjects($row, $acme_project_array);
138  pg_free_result($result);
139 
140  return $acme_project_array;
141  }
142 
143 
150  function GetProjectArray1($upload_pk, $nomosAgentpk, $MinCount=1)
151  {
152  global $PG_CONN;
153  $acme_project_array = array(); // acme project array to return
154  $idx = 0;
155 
156  $sql = "select distinct(acme_project_fk) as acme_project_fk, count(acme_project_fk) as filecount from acme_pfile
157  right join uploadtree on uploadtree.pfile_fk=acme_pfile.pfile_fk where upload_fk=$upload_pk
158  group by acme_project_fk order by filecount desc";
159  $result = pg_query($PG_CONN, $sql);
160  DBCheckResult($result, $sql, __FILE__, __LINE__);
161  while ($row = pg_fetch_assoc($result)) {
162  if ($row['filecount'] < $MinCount) {
163  break;
164  }
165 
166  // retrieve the acme_project record to go with the found acme_project_fk
167  $sql = "select * from acme_project where acme_project_pk='$row[acme_project_fk]'";
168  $projresult = pg_query($PG_CONN, $sql);
169  DBCheckResult($projresult, $sql, __FILE__, __LINE__);
170  if (pg_num_rows($projresult) > 0) {
171  $acme_project_array[$idx] = pg_fetch_assoc($projresult);
172  $acme_project_array[$idx]['count'] = $row['filecount'];
173  $idx++;
174  }
175  }
176 
177  return($acme_project_array);
178  } // GetProjectArray1()
179 
180 
187  function HTMLForm($acme_project_array, $upload_pk)
188  {
189  $Outbuf = "";
190  $uploadtreeRec = GetSingleRec("uploadtree", "where upload_fk=$upload_pk and parent is null");
191  $Outbuf .= Dir2Browse($this->Name,$uploadtreeRec['uploadtree_pk'], NULL, 1, "acme");
192  $Outbuf .= "<p>";
193 
194  $URI = "?mod=" . $this->Name . Traceback_parm_keep(array( "page", "upload", "folic", "detail"));
195  $Outbuf .= "<form action='" . $URI . "' method='POST'>\n";
196 
197  $Outbuf .= "<table border=1>";
198  $Outbuf .= "<tr>";
199  $text = _('Include');
200  $Outbuf .= "<th>$text</th>";
201  $text = _('Project');
202  $Outbuf .= "<th>$text</th>";
203  $text = _('Files');
204  $Outbuf .= "<th>$text</th>";
205  $text = _('URL');
206  $Outbuf .= "<th>$text</th>";
207  $text = _('Description');
208  $Outbuf .= "<th>$text</th>";
209  $text = _('License');
210  $Outbuf .= "<th>$text</th>";
211  $text = _('Version');
212  $Outbuf .= "<th>$text</th>";
213  $Outbuf .= "</tr>";
214 
215  /* For alternating row background colors */
216  $RowStyle1 = "style='background-color:lavender'";
217  $RowStyle2 = "style='background-color:lightyellow'";
218  $ColorSpanRows = 1; // Alternate background color every $ColorSpanRows
219  $RowNum = 0;
220 
221  if (empty($acme_project_array)) {
222  $acme_project_array = array();
223  }
224  foreach ($acme_project_array as $project) {
225  /* Set alternating row background color - repeats every $ColorSpanRows rows */
226  $RowStyle = (($RowNum++ % (2*$ColorSpanRows))<$ColorSpanRows) ? $RowStyle1 : $RowStyle2;
227 
228  $Outbuf .= "<tr $RowStyle>";
229  $Checked = $project['include'] == 't' ? "checked=\"checked\"" : '' ;
230  $Outbuf .= "<td><input type='checkbox' name='includeproj[$project[acme_project_pk]]' $Checked></td>\n";
231  $Outbuf .= "<td>$project[project_name]</td>";
232  $ProjectListURL = Traceback_uri() . "?mod=" . $this->Name . "&acme_project=$project[acme_project_pk]&upload=$upload_pk";
233  $Outbuf .= "<td><a href='$ProjectListURL'>$project[count]</a></td>";
234  $Outbuf .= "<td><a href='$project[url]'>$project[url]</a></td>";
235  $Outbuf .= "<td>" . htmlentities($project['description']) . "</td>";
236  $Outbuf .= "<td>$project[licenses]</td>";
237  $Outbuf .= "<td>$project[version]</td>";
238  $Outbuf .= "</tr>";
239  }
240  $Outbuf .= "</table>";
241 
242  $Outbuf .= "$RowNum rows found<br>";
243 
244  $text = _("Save and Generate SPDX file");
245  $Outbuf .= "<p><input type='submit' value='$text' name='spdxbtn'>\n";
246  $text = _("Save");
247  $Outbuf .= "&nbsp;&nbsp;&nbsp;<input type='submit' value='$text' name='savebtn'>\n";
248  $Outbuf .= "</form>\n";
249  /******* END Input form *******/
250 
251  return $Outbuf;
252  }
253 
254 
262  function Populate_acme_upload($acme_project_array, $upload_pk, $detail)
263  {
264  global $PG_CONN;
265 
266  foreach ($acme_project_array as $project) {
267  $sql = "insert into acme_upload (upload_fk, acme_project_fk, include, detail, count) values ($upload_pk, $project[acme_project_pk], true, $detail, $project[count])";
268  $result = pg_query($PG_CONN, $sql);
269  DBCheckResult($result, $sql, __FILE__, __LINE__);
270  pg_free_result($result);
271  }
272  }
273 
274 
280  function GenerateSPDX($acme_project_array)
281  {
282  global $SysConf;
283 
284  $spdx = '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
285  $spdx .='<rdf:RDF' . "\n";
286  $spdx .= ' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"' . "\n";
287  $spdx .= ' xmlns="http://spdx.org/rdf/terms#"' . "\n";
288  $spdx .= ' xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">' . "\n";
289  $spdx .= ' <SpdxDocument rdf:about="http://www.spdx.org/tools#SPDXANALYSIS">' . "\n";
290  $spdx .= ' <specVersion>SPDX-1.1</specVersion>' . "\n";
291  $spdx .= ' <dataLicense rdf:about="http://spdx.org/licenses/PDDL-1.0" />' . "\n";
292  $spdx .= ' <CreationInfo>' . "\n";
293  $spdx .= " <creator>Tool: FOSSology v " . $SysConf['BUILD']['VERSION'] . " svn " . $SysConf['BUILD']['COMMIT_HASH'] . "</creator>\n";
294  $spdx .= "<created>" . date('c') . "</created>\n"; // date-time in ISO 8601 format
295  $spdx .= '</CreationInfo>' . "\n";
296 
297  $in_encoding = iconv_get_encoding("input_encoding");
298  foreach ($acme_project_array as $project) {
299  //debugprint($project, "Project");
300  $spdx .= "<Package>\n";
301  $spdx .= '<name>' . str_replace("&", " and ", strip_tags($project['project_name'])) . '</name>' . "\n";
302  $spdx .= "<versionInfo>$project[version]</versionInfo>\n";
303  $spdx .= "<licenseDeclared>$project[licenses]</licenseDeclared>\n";
304  $spdx .= "<sourceInfo>ProjectURL: $project[url]</sourceInfo>\n";
305  $spdx .= '<description>' . str_replace("&", " and ", strip_tags($project['description'])) . '</description>' . "\n";
306  $spdx .= "</Package>\n";
307  }
308  /*
309  <packageSupplier>Organization: FSF (info@fsf.com)</packageSupplier>
310  <packageOriginator>Organization: FSF (info@fsf.com)</packageOriginator>
311  <packageDdownloadLocation>http://ftp.gnu.org/gnu/coreutils/</packageDdownloadLocation>
312  <packageFileName>coreutils-8.12.tar.gz</packageFileName>
313  <sourceInfo>
314  mechanism: git
315  repository: git://git.sv.gnu.org/coreutils
316  branch: master
317  tag: v8.12
318  </sourceInfo>
319  </Package>
320  */
321 
322  $spdx .= " </SpdxDocument> </rdf:RDF>\n";
323  return $spdx;
324  }
325 
326 
330  function Output()
331  {
332  global $Plugins;
333  global $PG_CONN;
334 
335  //phpinfo();
336  $CriteriaCount = 0;
337  $V="";
338  $GETvars="";
339  $upload_pk = GetParm("upload",PARM_INTEGER);
340  $detail = GetParm("detail",PARM_INTEGER);
341  $detail = empty($detail) ? 0 : 1;
342  $folic = GetParm("folic",PARM_INTEGER);
343  $savebtn = GetParm("savebtn",PARM_RAW);
344  $spdxbtn = GetParm("spdxbtn",PARM_RAW);
345 
346  $agent_pk = LatestAgentpk($upload_pk, "nomos_ars");
347  if (empty($agent_pk)) {
348  echo "Missing fossology license data. Run a license scan on this upload.<br>";
349  exit;
350  }
351  $uploadtree_tablename = GetUploadtreeTableName($upload_pk);
352 
353  // Check if we have data in the acme_upload table, if not then load it
354  $acme_uploadRec = GetSingleRec("acme_upload", "where upload_fk=$upload_pk and detail=$detail");
355  if (empty($acme_uploadRec)) {
356  // populate acme_upload
357  $MinCount = 1;
358  $nomosAgentpk = LatestAgentpk($upload_pk, "nomos_ars");
359  $acme_project_array = $this->GetProjectArray1($upload_pk, $nomosAgentpk, $MinCount); // low level
360  $this->Populate_acme_upload($acme_project_array, $upload_pk, 1);
361  $acme_project_array = $this->GetProjectArray0($upload_pk, $nomosAgentpk, $MinCount); // high level
362  $this->Populate_acme_upload($acme_project_array, $upload_pk, 0);
363  }
364 
365  $sql = "select * from acme_upload, acme_project where acme_project_pk=acme_project_fk and detail=$detail and upload_fk=$upload_pk";
366  $result = pg_query($PG_CONN, $sql);
367  DBCheckResult($result, $sql, __FILE__, __LINE__);
368  $acme_project_array = pg_fetch_all($result);
369  $acme_project_array_orig = $acme_project_array; // save the original state so we know which records to update
370 
371  /* If the save or spdx buttons were clicked, update $acme_project_array and save the data in the acme_upload table */
372  if (! empty($savebtn) or ! empty($spdxbtn)) {
373  /* First set all projects include to false */
374  foreach ($acme_project_array as &$project) {
375  $project['include'] = 'f';
376  }
377  /* Now turn on projects include to match form */
378  if (array_key_exists('includeproj', $_POST)) {
379  $includeArray = $_POST['includeproj'];
380  foreach ($acme_project_array as &$project) {
381  if (array_key_exists($project['acme_project_fk'], $includeArray)) {
382  $project['include'] = "t";
383  }
384  }
385  }
386 
387  /* Finally, update the db with any changed include states */
388  $NumRecs = count($acme_project_array);
389  for ($i = 0; $i < $NumRecs; $i ++) {
390  $project = $acme_project_array[$i];
391  $project_orig = $acme_project_array_orig[$i];
392  if ($project['include'] != $project_orig['include']) {
393  $include = $project['include'] ? "true" : "false";
394  $sql = "update acme_upload set include='$include' where acme_upload_pk='$project[acme_upload_pk]'";
395  $result = pg_query($PG_CONN, $sql);
396  DBCheckResult($result, $sql, __FILE__, __LINE__);
397  pg_free_result($result);
398  }
399  }
400  }
401 
402  /* aggregate the fossology licenses for each pfile and each acme_project */
403  if ($folic) {
404  foreach ($acme_project_array as &$project) {
405  $sql = "select uploadtree_pk from acme_pfile, uploadtree where acme_project_fk=$project[acme_project_fk]
406  and acme_pfile.pfile_fk=uploadtree.pfile_fk and uploadtree.upload_fk=$upload_pk";
407  $result = pg_query($PG_CONN, $sql);
408  DBCheckResult($result, $sql, __FILE__, __LINE__);
409  $LicArray = array();
410  $ItemLicArray = array();
411  while ($acme_pfileRow = pg_fetch_assoc($result)) {
412  $LicArray = GetFileLicenses($agent_pk, '', $acme_pfileRow['uploadtree_pk'], $uploadtree_tablename);
413  foreach ($LicArray as $key => $license) {
414  $ItemLicArray[$key] = $license;
415  }
416  }
417  $project['licenses'] = '';
418  foreach ($ItemLicArray as $license) {
419  if ($license == "No_license_found") {
420  continue;
421  }
422  if (! empty($project['licenses'])) {
423  $project['licenses'] .= ", ";
424  }
425  $project['licenses'] .= $license;
426  }
427  }
428  }
429 
430  /* sort $acme_project_array by count desc */
431  if (! empty($acme_project_array)) {
432  usort($acme_project_array, 'proj_cmp');
433  }
434 
435  /* generate and download spdx file */
436  if (! empty($spdxbtn)) {
437  $spdxfile = $this->GenerateSPDX($acme_project_array);
438  $rv = DownloadString2File($spdxfile, "SPDX.rdf file", "xml");
439  if ($rv !== true) {
440  echo $rv;
441  }
442  }
443 
444  switch ($this->OutputType) {
445  case "XML":
446  break;
447  case "HTML":
448  $this->NoHeader = 0;
449  $this->OutputOpen("HTML", 1);
450  $V .= $this->HTMLForm($acme_project_array, $upload_pk);
451  break;
452  case "Text":
453  break;
454  default:
455  break;
456  }
457  if (! $this->OutputToStdout) {
458  return ($V);
459  }
460  print($V);
461  return;
462  } // Output()
463 }
464 //return; // prevent anyone from seeing this plugin
465 $NewPlugin = new acme_review();
466 $NewPlugin->Initialize();
467 
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:85
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