1<?php
2/***********************************************************
3 Copyright (C) 2010-2013 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 * \file nomos-diff.php
20 * \brief Compare License Browser, list license histogram
21 */
22
23define("TITLE_ui_nomos_diff", _("Compare License Browser"));
24
25class ui_nomos_diff extends FO_Plugin
26{
27  var $Name       = "nomosdiff";
28  var $Title      = TITLE_ui_nomos_diff;
29  var $Version    = "1.0";
30  // var $MenuList= "Jobs::License";
31  var $Dependency = array("browse","view");
32  var $DBaccess   = PLUGIN_DB_READ;
33  var $LoginFlag  = 0;
34  var $ColumnSeparatorStyleL = "style='border:solid 0 #006600; border-left-width:2px;padding-left:1em'";
35
36
37  /**
38   * \brief Create and configure database tables
39   */
40  function Install()
41  {
42    global $PG_CONN;
43    if (empty($PG_CONN)) {
44      return(1);
45    } /* No DB */
46
47    return(0);
48  } // Install()
49
50  /**
51   * \brief Customize submenus.
52   */
53  function RegisterMenus()
54  {
55    /* at this stage you have to call this plugin with a direct URL
56     that displays both trees to compare.
57    */
58    return 0;
59  } // RegisterMenus()
60
61
62  /**
63   * \brief This is called before the plugin is used.
64   * It should assume that Install() was already run one time
65   * (possibly years ago and not during this object's creation).
66   *
67   * \return true on success, false on failure.
68   * A failed initialize is not used by the system.
69   * \note This function must NOT assume that other plugins are installed.
70   */
71  function Initialize()
72  {
73    global $_GET;
74
75    if ($this->State != PLUGIN_STATE_INVALID) {
76      return(1);
77    } // don't re-run
78    if ($this->Name !== "") // Name must be defined
79    {
80      global $Plugins;
81      $this->State=PLUGIN_STATE_VALID;
82      array_push($Plugins,$this);
83    }
84    return($this->State == PLUGIN_STATE_VALID);
85  } // Initialize()
86
87  /**
88   * \brief get an array with uploadtree record and agent_pk
89   */
90  function GetTreeInfo($Uploadtree_pk)
91  {
92    $TreeInfo = GetSingleRec("uploadtree", "WHERE uploadtree_pk = $Uploadtree_pk");
93    $TreeInfo['agent_pk'] = LatestAgentpk($TreeInfo['upload_fk'], "nomos_ars");
94
95    // Get the uploadtree table
96    $UploadRec = GetSingleRec("upload", "where upload_pk=$TreeInfo[upload_fk]");
97    $TreeInfo['uploadtree_tablename'] = $UploadRec['uploadtree_tablename'];
98    return $TreeInfo;
99  }
100
101
102  /**
103   * \brief get history info for the directory BY LICENSE.
104   * \param $Uploadtree_pk - Uploadtree_pk
105   * \return a string with the histogram for the directory BY LICENSE.
106   */
107  function UploadHist($Uploadtree_pk, $TreeInfo)
108  {
109    global $PG_CONN;
110
111    $VLic = '';
112    $lft = $TreeInfo['lft'];
113    $rgt = $TreeInfo['rgt'];
114    $upload_pk = $TreeInfo['upload_fk'];
115    $agent_pk = $TreeInfo['agent_pk'];
116
117    /*  Get the counts for each license under this UploadtreePk*/
118    $sql = "SELECT distinct(rf_shortname) as licname,
119                   count(rf_shortname) as liccount, rf_shortname
120              from license_ref,license_file,
121                  (SELECT distinct(pfile_fk) as PF from $TreeInfo[uploadtree_tablename]
122                     where upload_fk=$upload_pk
123                       and {$TreeInfo['uploadtree_tablename']}.lft BETWEEN $lft and $rgt) as SS
124              where PF=pfile_fk and agent_fk=$agent_pk and rf_fk=rf_pk
125              group by rf_shortname
126              order by liccount desc";
127    $result = pg_query($PG_CONN, $sql);
128    DBCheckResult($result, $sql, __FILE__, __LINE__);
129
130    /* Write license histogram to $VLic  */
131    $LicCount = 0;
132    $UniqueLicCount = 0;
133    $NoLicFound = 0;
134    $VLic .= "<table border=1 id='lichistogram'>\n";
135
136    $text = _("Count");
137    $VLic .= "<tr><th >$text</th>";
138
139    $text = _("Files");
140    $VLic .= "<th >$text</th>";
141
142    $text = _("License Name");
143    $VLic .= "<th align=left>$text</th></tr>\n";
144
145    while ($row = pg_fetch_assoc($result))
146    {
147      $UniqueLicCount++;
148      $LicCount += $row['liccount'];
149
150      /*  Count  */
151      $VLic .= "<tr><td align='right'>$row[liccount]</td>";
152
153      /*  Show  */
154      $ShowTitle = _("Click Show to list files with this license.");
155      $VLic .= "<td align='center'><a href='";
156      $VLic .= Traceback_uri();
157
158      $text = _("Show");
159      $VLic .= "?mod=license_list_files&napk=$agent_pk&item=$Uploadtree_pk&lic=" . urlencode($row['rf_shortname']) . "' title='$ShowTitle'>$text</a></td>";
160
161      /*  License name  */
162      $VLic .= "<td align='left'>";
163      $rf_shortname = rawurlencode($row['rf_shortname']);
164      $VLic .= "<a id='$rf_shortname' onclick='FileColor_Get(\"" . Traceback_uri() . "?mod=ajax_filelic&napk=$agent_pk&item=$Uploadtree_pk&lic=$rf_shortname\")'";
165      $VLic .= ">$row[licname] </a>";
166      $VLic .= "</td>";
167      $VLic .= "</tr>\n";
168      if ($row['licname'] == "No_license_found") $NoLicFound =  $row['liccount'];
169    }
170    pg_free_result($result);
171    $VLic .= "</table>\n";
172    $VLic .= "<p>\n";
173
174    return($VLic);
175  } // UploadHist()
176
177
178  /**
179   * \brief get the entire <td> ... </td> for $Child file listing table
180   * License differences are highlighted.
181   */
182  function ChildElt($Child, $agent_pk, $OtherChild)
183  {
184    $UniqueTagArray = array();
185    $licstr = $Child['licstr'];
186
187    /* If both $Child and $OtherChild are specified,
188     * reassemble licstr and highlight the differences
189     */
190    if ($OtherChild and $OtherChild)
191    {
192      $licstr = "";
193      $DiffLicStyle = "style='background-color:#ffa8a8'";  // mid red pastel
194      foreach ($Child['licarray'] as $rf_pk => $rf_shortname)
195      {
196        if (!empty($licstr)) $licstr .= ", ";
197        if (@$OtherChild['licarray'][$rf_pk])
198        {
199          /* license is in both $Child and $OtherChild */
200          $licstr .= $rf_shortname;
201        }
202        else
203        {
204          /* license is missing from $OtherChild */
205          $licstr .= "<span $DiffLicStyle>$rf_shortname</span>";
206        }
207      }
208    }
209
210    $ColStr = "<td id='$Child[uploadtree_pk]' align='left'>";
211    $ColStr .= "$Child[linkurl]";
212    /* show licenses under file name */
213    $ColStr .= "<br>";
214    $ColStr .= "<span style='position:relative;left:1em'>";
215    $ColStr .= $licstr;
216    $ColStr .= "</span>";
217    $ColStr .= "</td>";
218
219    /* display item links */
220    $ColStr .= "<td valign='top'>";
221    $uploadtree_tablename = GetUploadtreeTableName($Child['upload_fk']);
222    $ColStr .= FileListLinks($Child['upload_fk'], $Child['uploadtree_pk'], $agent_pk, $Child['pfile_fk'], True, $UniqueTagArray, $uploadtree_tablename);
223    $ColStr .= "</td>";
224    return $ColStr;
225  }  /* ChildElt() */
226
227
228  /**
229   * \brief get a string with the html table rows comparing the two file lists. \n
230   * Each row contains 5 table fields.
231   * The third field is just for a column separator.
232   * If files match their fuzzyname then put on the same row.
233   * Highlight license differences.
234   * Unmatched fuzzynames go on a row of their own.
235   */
236  function ItemComparisonRows($Master, $agent_pk1, $agent_pk2)
237  {
238    $TableStr = "";
239    $RowStyle1 = "style='background-color:#ecfaff'";  // pale blue
240    $RowStyle2 = "style='background-color:#ffffe3'";  // pale yellow
241    $RowNum = 0;
242
243    foreach ($Master as $key => $Pair)
244    {
245      $RowStyle = (++$RowNum % 2) ? $RowStyle1 : $RowStyle2;
246      $TableStr .= "<tr $RowStyle>";
247
248      $Child1 = GetArrayVal("1", $Pair);
249      $Child2 = GetArrayVal("2", $Pair);
250      if (empty($Child1))
251      {
252        $TableStr .= "<td></td><td></td>";
253        $TableStr .= "<td $this->ColumnSeparatorStyleL>&nbsp;</td>";
254        $TableStr .= $this->ChildElt($Child2, $agent_pk2, $Child1);
255      }
256      else if (empty($Child2))
257      {
258        $TableStr .= $this->ChildElt($Child1, $agent_pk1, $Child2);
259        $TableStr .= "<td $this->ColumnSeparatorStyleL>&nbsp;</td>";
260        $TableStr .= "<td></td><td></td>";
261      }
262      else if (!empty($Child1) and !empty($Child2))
263      {
264        $TableStr .= $this->ChildElt($Child1, $agent_pk1, $Child2);
265        $TableStr .= "<td $this->ColumnSeparatorStyleL>&nbsp;</td>";
266        $TableStr .= $this->ChildElt($Child2, $agent_pk2, $Child1);
267      }
268
269      $TableStr .= "</tr>";
270    }
271
272    return($TableStr);
273  } // ItemComparisonRows()
274
275
276
277  /**
278   * \brief Add license array to Children array.
279   */
280  function AddLicStr($TreeInfo, &$Children)
281  {
282    if (!is_array($Children)) return;
283    $agent_pk = $TreeInfo['agent_pk'];
284    foreach($Children as &$Child)
285    {
286      /** do not get duplicated licenses */
287      $Child['licarray'] = GetFileLicenses($agent_pk, 0, $Child['uploadtree_pk']);
288      $Child['licstr'] = implode(", ", $Child['licarray']);
289    }
290  }
291
292
293  /**
294   * \brief removes identical files
295   * If a child pair are identical remove the master record
296   */
297  function filter_samehash(&$Master)
298  {
299    if (!is_array($Master)) return;
300
301    foreach($Master as $Key =>&$Pair)
302    {
303      if (empty($Pair[1]) or empty($Pair[2])) continue;
304      if (empty($Pair[1]['pfile_fk'])) continue;
305      if (empty($Pair[2]['pfile_fk'])) continue;
306
307      if ($Pair[1]['pfile_fk'] == $Pair[2]['pfile_fk'])
308      unset($Master[$Key]);
309    }
310    return;
311  }  /* End of samehash */
312
313
314  /**
315   * \brief removes files that have the same name and license list.
316   */
317  function filter_samelic(&$Master)
318  {
319    foreach($Master as $Key =>&$Pair)
320    {
321      if (empty($Pair[1]) or empty($Pair[2])) continue;
322      if (($Pair[1]['ufile_name'] == $Pair[2]['ufile_name'])
323      && ($Pair[1]['licstr'] == $Pair[2]['licstr']))
324      unset($Master[$Key]);
325    }
326    return;
327  }  /* End of samelic */
328
329
330  /**
331   * \brief removes files that have the same fuzzyname, and same license list.
332   */
333  function filter_samelicfuzzy(&$Master)
334  {
335    foreach($Master as $Key =>&$Pair)
336    {
337      if (empty($Pair[1]) or empty($Pair[2])) continue;
338      if (($Pair[1]['fuzzyname'] == $Pair[2]['fuzzyname'])
339      && ($Pair[1]['licstr'] == $Pair[2]['licstr']))
340      unset($Master[$Key]);
341    }
342    return;
343  }  /* End of samelic */
344
345
346  /**
347   * \brief removes pairs of "No_license_found"
348   * Or pairs that only have one file and "No_license_found"
349   * Uses fuzzyname.
350   */
351  function filter_nolics(&$Master)
352  {
353    $NoLicStr = "No_license_found";
354
355    foreach($Master as $Key =>&$Pair)
356    {
357      $Pair1 = GetArrayVal("1", $Pair);
358      $Pair2 = GetArrayVal("2", $Pair);
359
360      if (empty($Pair1))
361      {
362        if ($Pair2['licstr'] == $NoLicStr)
363        unset($Master[$Key]);
364        else
365        continue;
366      }
367      else if (empty($Pair2))
368      {
369        if ($Pair1['licstr'] == $NoLicStr)
370        unset($Master[$Key]);
371        else
372        continue;
373      }
374      else if (($Pair1['licstr'] == $NoLicStr)
375      and ($Pair2['licstr'] == $NoLicStr))
376      unset($Master[$Key]);
377    }
378    return;
379  }  /* End of nolics */
380
381  /**
382   * \brief filter children through same license, same hash, no license, same fuzzy license
383   *
384   * \param $filter - none, samelic, samehash
385   * An empty or unknown filter is the same as "none"
386   */
387  function FilterChildren($filter, &$Master)
388  {
389    switch($filter)
390    {
391      case 'samehash':
392        $this->filter_samehash($Master);
393        break;
394      case 'samelic':
395        $this->filter_samehash($Master);
396        $this->filter_samelic($Master);
397        break;
398      case 'samelicfuzzy':
399        $this->filter_samehash($Master);
400        $this->filter_samelicfuzzy($Master);
401        break;
402      case 'nolics':
403        $this->filter_samehash($Master);
404        $this->filter_nolics($Master);
405        $this->filter_samelicfuzzy($Master);
406        break;
407      default:
408        break;
409    }
410  }
411
412
413  /**
414   * \brief HTML output, returns HTML as string.
415   */
416  function HTMLout($Master, $uploadtree_pk1, $uploadtree_pk2, $in_uploadtree_pk1, $in_uploadtree_pk2, $filter, $TreeInfo1, $TreeInfo2)
417  {
418    /* Initialize */
419    $FreezeText = _("Freeze Path");
420    $unFreezeText = _("Frozen, Click to unfreeze");
421    $OutBuf = '';
422
423    /******* javascript functions ********/
424    $OutBuf .= "\n<script language='javascript'>\n";
425    /* function to replace this page specifying a new filter parameter */
426    $OutBuf .= "function ChangeFilter(selectObj, utpk1, utpk2){";
427    $OutBuf .= "  var selectidx = selectObj.selectedIndex;";
428    $OutBuf .= "  var filter = selectObj.options[selectidx].value;";
429    $OutBuf .= '  window.location.assign("?mod=' . $this->Name .'&item1="+utpk1+"&item2="+utpk2+"&filter=" + filter); ';
430    $OutBuf .= "}";
431
432    /* Freeze function (path list in banner)
433     FreezeColNo is the ID of the column to freeze: 1 or 2
434    Toggle Freeze button label: Freeze Path <-> Unfreeze Path
435    Toggle Freeze button background color: white to light blue
436    Toggle which paths are frozen: if path1 freezes, then unfreeze path2.
437    Rewrite urls: eg &item1 ->  &Fitem1
438    */
439    $OutBuf .= "function Freeze(FreezeColNo) {";
440    $OutBuf .=  "var FreezeElt1 = document.getElementById('Freeze1');";
441    $OutBuf .=  "var FreezeElt2 = document.getElementById('Freeze2');";
442
443    /* change the freeze labels to denote their new status */
444    $OutBuf .=  "if (FreezeColNo == '1')";
445    $OutBuf .=  "{";
446    $OutBuf .=    "if (FreezeElt1.innerHTML == '$unFreezeText') ";
447    $OutBuf .=    "{";
448    $OutBuf .=      "FreezeElt1.innerHTML = '$FreezeText';";
449    $OutBuf .=      "FreezeElt1.style.backgroundColor = 'white';";
450    $OutBuf .=    "}";
451    $OutBuf .=    "else {";
452    $OutBuf .=      "FreezeElt1.innerHTML = '$unFreezeText';";
453    $OutBuf .=      "FreezeElt1.style.backgroundColor = '#EAF7FB';";
454    $OutBuf .=      "FreezeElt2.innerHTML = '$FreezeText';";
455    $OutBuf .=      "FreezeElt2.style.backgroundColor = 'white';";
456    $OutBuf .=    "}";
457    $OutBuf .=  "}";
458    $OutBuf .=  "else {";
459    $OutBuf .=    "if (FreezeElt2.innerHTML == '$unFreezeText') ";
460    $OutBuf .=    "{";
461    $OutBuf .=      "FreezeElt2.innerHTML = '$FreezeText';";
462    $OutBuf .=      "FreezeElt2.style.backgroundColor = 'white';";
463    $OutBuf .=    "}";
464    $OutBuf .=    "else {";
465    $OutBuf .=      "FreezeElt1.innerHTML = '$FreezeText';";
466    $OutBuf .=      "FreezeElt1.style.backgroundColor = 'white';";
467    $OutBuf .=      "FreezeElt2.innerHTML = '$unFreezeText';";
468    $OutBuf .=      "FreezeElt2.style.backgroundColor = '#EAF7FB';";
469    $OutBuf .=    "}";
470    $OutBuf .=  "}";
471
472    /* Alter the url to add freeze={column number}  */
473    $OutBuf .=  "var i=0;";
474    $OutBuf .=  "var linkid;";
475    $OutBuf .=  "var linkelt;";
476    $OutBuf .=  "var UpdateCol;";
477    $OutBuf .=  "if (FreezeColNo == 1) UpdateCol=2;else UpdateCol=1;";
478    $OutBuf .=  "var numlinks = document.links.length;";
479    $OutBuf .=  "for (i=0; i < numlinks; i++)";
480    $OutBuf .=  "{";
481    $OutBuf .=    "linkelt = document.links[i];";
482    $OutBuf .=    "if (linkelt.href.indexOf('col='+UpdateCol) >= 0)";
483    $OutBuf .=    "{";
484    $OutBuf .=      "linkelt.href = linkelt.href + '&freeze=' + FreezeColNo;";
485    $OutBuf .=    "}";
486    $OutBuf .=  "}";
487    $OutBuf .= "}";
488    $OutBuf .= "</script>\n";
489    /******* END javascript functions  ********/
490
491
492    /* Select list for filters */
493    $SelectFilter = "<select name='diff_filter' id='diff_filter' onchange='ChangeFilter(this,$uploadtree_pk1, $uploadtree_pk2)'>";
494    $Selected = ($filter == 'none') ? "selected" : "";
495    $SelectFilter .= "<option $Selected value='none'>0. Remove nothing";
496    $Selected = ($filter == 'samehash') ? "selected" : "";
497    $SelectFilter .= "<option $Selected value='samehash'>1. Remove duplicate (same hash) files";
498    $Selected = ($filter == 'samelic') ? "selected" : "";
499    $SelectFilter .= "<option $Selected value='samelic'>2. Remove duplicate files (different hash) with unchanged licenses";
500    $Selected = ($filter == 'samelicfuzzy') ? "selected" : "";
501    $SelectFilter .= "<option $Selected value='samelicfuzzy'>2b. Same as 2 but fuzzy match file names";
502    $Selected = ($filter == 'nolics') ? "selected" : "";
503    $SelectFilter .= "<option $Selected value='nolics'>3. Same as 2b. but also remove files with no license";
504    $SelectFilter .= "</select>";
505
506
507    $StyleRt = "style='float:right'";
508    $OutBuf .= "<a name='flist' href='#histo' $StyleRt > Jump to histogram </a><br>";
509
510    /* Switch to bucket diff view */
511    $text = _("Switch to bucket view");
512    $BucketURL = Traceback_uri();
513    $BucketURL .= "?mod=bucketsdiff&item1=$uploadtree_pk1&item2=$uploadtree_pk2";
514    $OutBuf .= "<a href='$BucketURL' $StyleRt > $text </a> ";
515
516
517    //    $TableStyle = "style='border-style:collapse;border:1px solid black'";
518    $TableStyle = "";
519    $OutBuf .= "<table border=0 id='dirlist' $TableStyle>";
520
521    /* Select filter pulldown */
522    $OutBuf .= "<tr><td colspan=5 align='center'>Filter: $SelectFilter<br>&nbsp;</td></tr>";
523
524    /* File path */
525    $OutBuf .= "<tr>";
526    $Path1 = Dir2Path($uploadtree_pk1, $TreeInfo1['uploadtree_tablename']);
527    $Path2 = Dir2Path($uploadtree_pk2, $TreeInfo2['uploadtree_tablename']);
528    $OutBuf .= "<td colspan=2>";
529    $OutBuf .= Dir2BrowseDiff($Path1, $Path2, $filter, 1, $this);
530    $OutBuf .= "</td>";
531    $OutBuf .= "<td $this->ColumnSeparatorStyleL colspan=3>";
532    $OutBuf .= Dir2BrowseDiff($Path1, $Path2, $filter, 2, $this);
533    $OutBuf .= "</td></tr>";
534
535    /* File comparison table */
536    $OutBuf .= $this->ItemComparisonRows($Master, $TreeInfo1['agent_pk'], $TreeInfo2['agent_pk']);
537
538    /*  Separator row */
539    $ColumnSeparatorStyleTop = "style='border:solid 0 #006600; border-top-width:2px; border-bottom-width:2px;'";
540    $OutBuf .= "<tr>";
541    $OutBuf .= "<td colspan=5 $ColumnSeparatorStyleTop>";
542    $OutBuf .= "<a name='histo' href='#flist' style='float:right'> Jump to top </a>";
543    $OutBuf .= "</a>";
544    $OutBuf .= "</tr>";
545
546    /* License histogram */
547    $OutBuf .= "<tr>";
548    $Tree1Hist = $this->UploadHist($uploadtree_pk1, $TreeInfo1);
549    $OutBuf .= "<td colspan=2 valign='top' align='center'>$Tree1Hist</td>";
550    $OutBuf .= "<td $this->ColumnSeparatorStyleL>&nbsp;</td>";
551    $Tree2Hist = $this->UploadHist($uploadtree_pk2, $TreeInfo2);
552    $OutBuf .= "<td colspan=2 valign='top' align='center'>$Tree2Hist</td>";
553    $OutBuf .= "</tr></table>\n";
554
555    $OutBuf .= "<a href='#flist' style='float:right'> Jump to top </a><p>";
556
557    return $OutBuf;
558  }
559
560
561  /**
562   * \brief generate output information \n
563   * filter: optional filter to apply \n
564   * item1:  uploadtree_pk of the column 1 tree \n
565   * item2:  uploadtree_pk of the column 2 tree \n
566   * newitem1:  uploadtree_pk of the new column 1 tree \n
567   * newitem2:  uploadtree_pk of the new column 2 tree \n
568   * freeze: column number (1 or 2) to freeze
569   */
570  function Output()
571  {
572    if ($this->State != PLUGIN_STATE_READY) {
573      return(0);
574    }
575    $V="";
576
577    $uTime = microtime(true);
578    /* */
579    $updcache = GetParm("updcache",PARM_INTEGER);
580
581    /* Remove "updcache" from the GET args.
582     * This way all the url's based on the input args won't be
583     * polluted with updcache
584     * Use Traceback_parm_keep to ensure that all parameters are in order */
585    $CacheKey = "?mod=" . $this->Name . Traceback_parm_keep(array("item1","item2", "filter"));
586    if ($updcache)
587    {
588      $_SERVER['REQUEST_URI'] = preg_replace("/&updcache=[0-9]*/","",$_SERVER['REQUEST_URI']);
589      unset($_GET['updcache']);
590      $V = ReportCachePurgeByKey($CacheKey);
591    }
592    else
593    {
594      $V = ReportCacheGet($CacheKey);
595    }
596
597    if (empty($V) )  // no cache exists
598    {
599      $filter = GetParm("filter",PARM_STRING);
600      if (empty($filter)) $filter = "samehash";
601      $FreezeCol = GetParm("freeze",PARM_INTEGER);
602      $in_uploadtree_pk1 = GetParm("item1",PARM_INTEGER);
603      $in_uploadtree_pk2 = GetParm("item2",PARM_INTEGER);
604
605      if (empty($in_uploadtree_pk1) && empty($in_uploadtree_pk2))
606        Fatal("Bad input parameters.  Both item1 and item2 must be specified.", __FILE__, __LINE__);
607
608      /* Check item1 and item2 upload permissions */
609      $Item1Row = GetSingleRec("uploadtree", "WHERE uploadtree_pk = $in_uploadtree_pk1");
610      $UploadPerm = GetUploadPerm($Item1Row['upload_fk']);
611      if ($UploadPerm < Auth::PERM_READ)
612      {
613        $text = _("Permission Denied");
614        echo "<h2>$text item 1<h2>";
615        return;
616      }
617
618      $Item2Row = GetSingleRec("uploadtree", "WHERE uploadtree_pk = $in_uploadtree_pk2");
619      $UploadPerm = GetUploadPerm($Item2Row['upload_fk']);
620      if ($UploadPerm < Auth::PERM_READ)
621      {
622        $text = _("Permission Denied");
623        echo "<h2>$text item 2<h2>";
624        return;
625      }
626
627      $in_newuploadtree_pk1 = GetParm("newitem1",PARM_INTEGER);
628      $in_newuploadtree_pk2 = GetParm("newitem2",PARM_INTEGER);
629      $uploadtree_pk1  = $in_uploadtree_pk1;
630      $uploadtree_pk2 = $in_uploadtree_pk2;
631
632      if (!empty($in_newuploadtree_pk1))
633      {
634        if ($FreezeCol != 2)
635        $uploadtree_pk2  = NextUploadtree_pk($in_newuploadtree_pk1, $in_uploadtree_pk2);
636        $uploadtree_pk1  = $in_newuploadtree_pk1;
637      }
638      else
639      if (!empty($in_newuploadtree_pk2))
640      {
641        if ($FreezeCol != 1)
642        $uploadtree_pk1 = NextUploadtree_pk($in_newuploadtree_pk2, $in_uploadtree_pk1);
643        $uploadtree_pk2 = $in_newuploadtree_pk2;
644      }
645
646      $newURL = Traceback_dir() . "?mod=" . $this->Name . "&item1=$uploadtree_pk1&item2=$uploadtree_pk2";
647      if (!empty($filter)) $newURL .= "&filter=$filter";
648
649      // rewrite page with new uploadtree_pks */
650      if (($uploadtree_pk1 != $in_uploadtree_pk1)
651      || ($uploadtree_pk2 != $in_uploadtree_pk2))
652      {
653        print <<< JSOUT
654<script type="text/javascript">
655  window.location.assign('$newURL');
656</script>
657JSOUT;
658      }
659
660      $TreeInfo1 = $this->GetTreeInfo($uploadtree_pk1);
661      $TreeInfo2 = $this->GetTreeInfo($uploadtree_pk2);
662      $ErrText = _("No license data for");
663      $ErrText2 = _("Use Jobs > Agents to schedule a license scan.");
664      $ErrMsg= '';
665      if ($TreeInfo1['agent_pk'] == 0)
666      {
667        $ErrMsg = "$ErrText $TreeInfo1[ufile_name].<br>$ErrText2<p>";
668      }
669      else
670      if ($TreeInfo2['agent_pk'] == 0)
671      {
672        $ErrMsg = "$ErrText $TreeInfo2[ufile_name].<br>$ErrText2<p>";
673      }
674      else
675      {
676        /* Get list of children */
677        $Children1 = GetNonArtifactChildren($uploadtree_pk1);
678        $Children2 = GetNonArtifactChildren($uploadtree_pk2);
679
680        /* Add fuzzyname to children */
681        FuzzyName($Children1);  // add fuzzyname to children
682        FuzzyName($Children2);  // add fuzzyname to children
683
684        /* add element licstr to children */
685        $this->AddLicStr($TreeInfo1, $Children1);
686        $this->AddLicStr($TreeInfo2, $Children2);
687
688        /* Master array of children, aligned.   */
689        $Master = MakeMaster($Children1, $Children2);
690
691        /* add linkurl to children */
692        FileList($Master, $TreeInfo1['agent_pk'], $TreeInfo2['agent_pk'], $filter, $this,
693        $uploadtree_pk1, $uploadtree_pk2);
694
695        /* Apply filter */
696        $this->FilterChildren($filter, $Master);
697      }
698
699      switch($this->OutputType)
700      {
701        case "XML":
702          break;
703        case "HTML":
704          if ($ErrMsg)
705          $V .= $ErrMsg;
706          else
707          $V .= $this->HTMLout($Master, $uploadtree_pk1, $uploadtree_pk2, $in_uploadtree_pk1, $in_uploadtree_pk2, $filter, $TreeInfo1, $TreeInfo2);
708          break;
709        case "Text":
710          break;
711        default:
712      }
713      $Cached = false;
714    }
715    else
716    $Cached = true;
717
718    if (!$this->OutputToStdout) {
719      return($V);
720    }
721    print "$V";
722    $Time = microtime(true) - $uTime;  // convert usecs to secs
723    $text = _("Elapsed time: %.2f seconds");
724    printf( "<small>$text</small>", $Time);
725
726    /**/
727    if ($Cached)
728    {
729      $text = _("cached");
730      $text1 = _("Update");
731      echo " <i>$text</i>   <a href=\"$_SERVER[REQUEST_URI]&updcache=1\"> $text1 </a>";
732    }
733    else
734    {
735      //  Cache Report if this took longer than 1/2 second
736      if ($Time > 0.5) ReportCachePut($CacheKey, $V);
737    }
738    /**/
739    return;
740  }  /* End Output() */
741
742}  /* End Class */
743
744$NewPlugin = new ui_nomos_diff;
745$NewPlugin->Initialize();
746
747?>
748