FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
ReportImportAgent.php
1 <?php
2 /*
3  * Copyright (C) 2015-2017, Siemens AG
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 namespace Fossology\ReportImport;
19 
28 require_once 'SpdxTwoImportSource.php';
29 require_once 'XmlImportSource.php';
30 require_once 'ReportImportSink.php';
31 require_once 'ReportImportHelper.php';
32 require_once 'ReportImportConfiguration.php';
33 
34 use EasyRdf_Graph;
35 
36 require_once 'version.php';
37 require_once 'services.php';
38 
39 class ReportImportAgent extends Agent
40 {
41  const REPORT_KEY = "report";
42  const ACLA_KEY = "addConcludedAsDecisions";
43 
45  private $uploadDao;
47  private $userDao;
49  private $permissionDao;
51  protected $dbManager;
53  protected $licenseDao;
55  protected $clearingDao;
57  private $copyrightDao;
58 
59  protected $agent_pk;
60 
61  function __construct()
62  {
63  parent::__construct(AGENT_REPORTIMPORT_NAME, AGENT_REPORTIMPORT_VERSION, AGENT_REPORTIMPORT_REV);
64  $this->uploadDao = $this->container->get('dao.upload');
65  $this->permissionDao = $this->container->get('dao.upload.permission');
66  $this->dbManager = $this->container->get('db.manager');
67  $this->userDao = $this->container->get('dao.user');
68  $this->licenseDao = $this->container->get('dao.license');
69  $this->clearingDao = $this->container->get('dao.clearing');
70  $this->copyrightDao = $this->container->get('dao.copyright');
71  $this->agentSpecifLongOptions[] = self::REPORT_KEY.':';
72  $this->agentSpecifLongOptions[] = self::ACLA_KEY.':';
73 
74  $this->setAgent_PK();
75  }
76 
77  private function setAgent_PK()
78  {
79  // should be already set in $this->agentId?
80  $row = $this->dbManager->getSingleRow(
81  "SELECT agent_pk FROM agent WHERE agent_name = $1 order by agent_ts desc limit 1",
82  array(AGENT_REPORTIMPORT_NAME), __METHOD__."select"
83  );
84 
85  if ($row === false)
86  {
87  throw new \Exception("agent_pk could not be determined");
88  }
89  $this->agent_pk = intval($row['agent_pk']);
90  }
91 
98  static private function preWorkOnArgsFlp(&$args,$longArgsKey)
99  {
100  if (is_array($args) &&
101  array_key_exists($longArgsKey, $args)){
102  echo "DEBUG: unrefined \$longArgs are: ".$args[$longArgsKey]."\n";
103  $chunks = explode(" --", $args[$longArgsKey]);
104  if(sizeof($chunks) > 1)
105  {
106  $args[$longArgsKey] = $chunks[0];
107  foreach(array_slice($chunks, 1) as $chunk)
108  {
109  if (strpos($chunk, '=') !== false)
110  {
111  list($key, $value) = explode('=', $chunk, 2);
112  $args[$key] = $value;
113  }
114  else
115  {
116  $args[$chunk] = true;
117  }
118  }
119  }
120  }
121  }
122 
123  function processUploadId($uploadId)
124  {
125  $this->heartbeat(0);
126 
127  self::preWorkOnArgsFlp($this->args, self::REPORT_KEY);
128  if (!$this->permissionDao->isEditable($uploadId, $this->groupId)) {
129  return false;
130  }
131 
132  $reportPre = array_key_exists(self::REPORT_KEY,$this->args) ? $this->args[self::REPORT_KEY] : "";
133  global $SysConf;
134  $fileBase = $SysConf['FOSSOLOGY']['path']."/ReportImport/";
135  $report = $fileBase.$reportPre;
136  if(empty($reportPre) || !is_readable($report))
137  {
138  echo "No report was uploaded\n";
139  echo "Maybe the permissions on ".htmlspecialchars($fileBase)." are not sufficient\n";
140  return false;
141  }
142 
143  $this->dbManager->insertTableRow('reportgen',
144  array('upload_fk'=>$uploadId, 'job_fk'=>$this->jobId, 'filepath'=>$report),
145  __METHOD__.'addToReportgen');
146 
147  $configuration = new ReportImportConfiguration($this->args);
148 
149  $this->walkAllFiles($report, $uploadId, $configuration);
150 
151  return true;
152  }
153 
154  private function getItemTreeBounds($upload_pk)
155  {
156  $uploadtreeTablename = GetUploadtreeTableName($upload_pk);
157 
158  $uploadtreeRec = $this->dbManager->getSingleRow(
159  'SELECT uploadtree_pk FROM uploadtree WHERE parent IS NULL AND upload_fk=$1',
160  array($upload_pk),
161  __METHOD__.'.find.uploadtree.to.use.in.browse.link');
162  $uploadtree_pk = $uploadtreeRec['uploadtree_pk'];
164  return $this->uploadDao->getItemTreeBounds($uploadtree_pk, $uploadtreeTablename);
165  }
166 
167  static private function getEntries($fileId, $fileName, &$pfilePerFileName, &$hashMap=NULL, &$pfilesPerHash=NULL, $hashAlgo="sha1")
168  {
169  $pfilesByFilename = self::getEntriesForFilename($fileName, $pfilePerFileName);
170 
171  if (($pfilesByFilename !== null || sizeof($pfilesByFilename) === 0))
172  {
173  if ( $hashMap !== null && sizeof($hashMap) > 0 )
174  {
175  $pfiles = array();
176  foreach ($pfilesByFilename as $pfile)
177  {
178  if (strtolower($pfile[$hashAlgo]) !== strtolower($hashMap[$hashAlgo]))
179  {
180  print "INFO: the file with fileName=[$fileName] does not match the hash of pfile_pk=[" . $pfile['pfile_pk'] . "] and uploadtree_pk=[" . $pfile['uploadtree_pk'] . "]\n";
181  }
182  else
183  {
184  $pfiles[] = $pfile;
185  }
186  }
187  return $pfiles;
188  }
189  else
190  {
191  return $pfilesByFilename;
192  }
193  }
194 
195  if ($pfilesPerHash !== null && sizeof($pfilesPerHash) > 0 &&
196  $hashMap !== null && sizeof($hashMap) > 0 )
197  {
198  return self::getEntriesForHash($hashMap, $pfilesPerHash, 'sha1');
199  }
200 
201  return array();
202  }
203 
204  static private function getEntriesForFilename($filename, &$pfilesPerFileName)
205  {
206  if(array_key_exists($filename, $pfilesPerFileName))
207  {
208  return array($pfilesPerFileName[$filename]);
209  }
210  $length = strlen($filename);
211  if($length > 3)
212  {
213  foreach(array_keys($pfilesPerFileName) as $key)
214  {
215  if(substr($key, -$length) === $filename)
216  {
217  return array($pfilesPerFileName[$key]);
218  }
219  }
220  }
221  return array();
222  }
223 
224  static private function getEntriesForHash(&$hashMap, &$pfilesPerHash, $hashAlgo)
225  {
226  if(!array_key_exists($hashAlgo, $hashMap))
227  {
228  return array();
229  }
230 
231  $hash = strtolower($hashMap[$hashAlgo]);
232  if(!array_key_exists($hash, $pfilesPerHash))
233  {
234  return array();
235  }
236  return $pfilesPerHash[$hash];
237  }
238 
244  private function getImportSource($reportFilename)
245  {
246 
247  if(substr($reportFilename, -4) === ".xml")
248  {
249  $importSource = new XmlImportSource($reportFilename);
250  if($importSource->parse())
251  {
252  return $importSource;
253  }
254  }
255 
256  if(substr($reportFilename, -4) === ".rdf")
257  {
258  $importSource = new SpdxTwoImportSource($reportFilename);
259  if($importSource->parse())
260  {
261  return $importSource;
262  }
263  }
264 
265  error_log("ERROR: can not handle report");
266  throw new \Exception("unsupported report type with filename: $reportFilename");
267  }
268 
269  public function walkAllFiles($reportFilename, $upload_pk, $configuration)
270  {
272  $source = $this->getImportSource($reportFilename);
273  if($source === NULL)
274  {
275  return;
276  }
277 
279  $sink = new ReportImportSink($this->agent_pk, $this->userDao, $this->licenseDao, $this->clearingDao, $this->copyrightDao,
280  $this->dbManager, $this->groupId, $this->userId, $this->jobId, $configuration);
281 
282  // Prepare data from DB
283  $itemTreeBounds = $this->getItemTreeBounds($upload_pk);
284  $pfilePerFileName = $this->uploadDao->getPFileDataPerFileName($itemTreeBounds);
285  $pfilesPerHash = $this->uploadDao->getPFilesDataPerHashAlgo($itemTreeBounds, 'sha1');
286 
287  foreach ($source->getAllFiles() as $fileId => $fileName)
288  {
289  $hashMap = NULL;
290  if ($pfilesPerHash !== NULL && sizeof($pfilesPerHash) > 0)
291  {
292  $hashMap = $source->getHashesMap($fileId);
293  }
294 
295  $pfiles = self::getEntries($fileId,
296  $fileName, $pfilePerFileName,
297  $hashMap, $pfilesPerHash, 'sha1');
298 
299  if ($pfiles === null || sizeof($pfiles) === 0)
300  {
301  print "WARN: no match for fileId=[".$fileId."] with filename=[".$fileName."]\n";
302  continue;
303  }
304 
305  $this->heartbeat(sizeof($pfiles));
306 
307  $data = $source->getDataForFile($fileId)
308  ->setPfiles($pfiles);
309  $sink->handleData($data);
310  }
311  }
312 }
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
heartbeat($newProcessed)
Send hear beat to the scheduler.
Definition: Agent.php:214
Structure of an Agent with all required parameters.
Definition: Agent.php:51
int jobId
The id of the job.
static preWorkOnArgsFlp(&$args, $longArgsKey)
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:28
int agent_pk
Definition: agent.h:85