FOSSology  4.4.0
Open Source License Compliance by Open Source Software
softwareHeritageAgent.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2019 Sandip Kumar Bhuyan <sandipbhuyan@gmail.com>
4  SPDX-FileCopyrightText: © 2020 Siemens AG
5  Author: Sandip Kumar Bhuyan<sandipbhuyan@gmail.com>,
6  Shaheem Azmal M MD<shaheem.azmal@siemens.com>
7 
8  SPDX-License-Identifier: GPL-2.0-only
9 */
10 
11 namespace Fossology\SoftwareHeritage;
12 
19 use \GuzzleHttp\Client;
20 use GuzzleHttp\Psr7;
21 use GuzzleHttp\Exception\RequestException;
22 
23 include_once(__DIR__ . "/version.php");
24 
32 {
36  private $uploadDao;
37 
41  private $licenseDao;
42 
47  private $configuration;
48 
53  private $dbManeger;
54 
59  protected $agentDao;
60 
65  private $softwareHeritageDao;
66 
71  function __construct()
72  {
73  global $SysConf;
74  parent::__construct(SOFTWARE_HERITAGE_AGENT_NAME, AGENT_VERSION, AGENT_REV);
75  $this->uploadDao = $this->container->get('dao.upload');
76  $this->licenseDao = $this->container->get('dao.license');
77  $this->dbManeger = $this->container->get('db.manager');
78  $this->agentDao = $this->container->get('dao.agent');
79  $this->softwareHeritageDao = $this->container->get('dao.softwareHeritage');
80  $sysconfig = $SysConf['SYSCONFIG'];
81  $this->configuration = [
82  'url' => trim($sysconfig['SwhURL']),
83  'uri' => trim($sysconfig['SwhBaseURL']),
84  'content' => trim($sysconfig['SwhContent']),
85  'maxtime' => intval($sysconfig['SwhSleep']),
86  'token' => trim($sysconfig['SwhToken'])
87  ];
88 
89  $proxy = [];
90  if (array_key_exists('http_proxy', $SysConf['FOSSOLOGY']) &&
91  ! empty($SysConf['FOSSOLOGY']['http_proxy'])) {
92  $proxy['http'] = $SysConf['FOSSOLOGY']['http_proxy'];
93  }
94  if (array_key_exists('https_proxy', $SysConf['FOSSOLOGY']) &&
95  ! empty($SysConf['FOSSOLOGY']['https_proxy'])) {
96  $proxy['https'] = $SysConf['FOSSOLOGY']['https_proxy'];
97  }
98  if (array_key_exists('no_proxy', $SysConf['FOSSOLOGY']) &&
99  ! empty($SysConf['FOSSOLOGY']['no_proxy'])) {
100  $proxy['no'] = explode(',', $SysConf['FOSSOLOGY']['no_proxy']);
101  }
102 
103  $version = $SysConf['BUILD']['VERSION'];
104  $headers = ['User-Agent' => "fossology/$version"];
105  if (!empty($this->configuration['token'])) {
106  $headers['Authorization'] = 'Bearer ' . $this->configuration['token'];
107  }
108 
109  $this->guzzleClient = new Client([
110  'http_errors' => false,
111  'proxy' => $proxy,
112  'base_uri' => $this->configuration['url'],
113  'headers' => $headers
114  ]);
115  }
116 
124  function processUploadId($uploadId)
125  {
126  $itemTreeBounds = $this->uploadDao->getParentItemBounds($uploadId);
127  $pfileFileDetails = $this->uploadDao->getPFileDataPerFileName($itemTreeBounds);
128  $pfileFks = $this->softwareHeritageDao->getSoftwareHeritagePfileFk($uploadId);
129  $agentId = $this->agentDao->getCurrentAgentId("softwareHeritage");
130  $maxTime = $this->configuration['maxtime'];
131  $maxTime = ($maxTime < 2) ? 2 : $maxTime;
132  foreach ($pfileFileDetails as $pfileDetail) {
133  if (!in_array($pfileDetail['pfile_pk'], array_column($pfileFks, 'pfile_fk'))) {
134  $this->processEachPfileForSWH($pfileDetail, $agentId, $maxTime);
135  }
136  $this->heartbeat(1);
137  }
138  return true;
139  }
140 
148  function processEachPfileForSWH($pfileDetail, $agentId, $maxTime)
149  {
150  list ($currentStatus, $currentResult) = $this->getSoftwareHeritageLicense($pfileDetail['sha256']);
151  if (SoftwareHeritageDao::SWH_RATELIMIT_EXCEED == $currentStatus) {
152  $this->heartbeat(0); //Fake heartbeat to keep the agent alive.
153  $timeToReset = $currentResult - time();
154  print "INFO :Software Heritage X-RateLimit-Limit reached. Next slot unlocks in ".gmdate("H:i:s", $timeToReset)."\n";
155  if ($timeToReset > $maxTime) {
156  sleep($maxTime);
157  } else {
158  sleep($timeToReset);
159  }
160  $this->processEachPfileForSWH($pfileDetail, $agentId, $maxTime);
161  } else {
162  $this->insertSoftwareHeritageRecord($pfileDetail['pfile_pk'], $currentResult, $agentId, $currentStatus);
163  }
164 
165  return true;
166  }
167 
174  protected function getSoftwareHeritageLicense($sha256)
175  {
176  $sha256 = strtolower($sha256);
177  $URIToGetContent = $this->configuration['uri'] . $sha256;
178  $URIToGetLicenses = $URIToGetContent . $this->configuration['content'];
179 
180  try {
181  $response = $this->guzzleClient->get($URIToGetLicenses);
182  $statusCode = $response->getStatusCode();
183  $cookedResult = array();
184  if ($statusCode == SoftwareHeritageDao::SWH_STATUS_OK) {
185  $responseContent = json_decode($response->getBody()->getContents(),true);
186  $cookedResult = $responseContent["facts"][0]["licenses"];
187  } else if ($statusCode == SoftwareHeritageDao::SWH_RATELIMIT_EXCEED) {
188  $responseContent = $response->getHeaders();
189  $cookedResult = $responseContent["X-RateLimit-Reset"][0];
190  } else if ($statusCode == SoftwareHeritageDao::SWH_NOT_FOUND) {
191  $response = $this->guzzleClient->get($URIToGetContent);
192  $responseContent = json_decode($response->getBody(),true);
193  if (isset($responseContent["status"])) {
194  $statusCode = SoftwareHeritageDao::SWH_STATUS_OK;
195  }
196  }
197  return array($statusCode, $cookedResult);
198  } catch (RequestException $e) {
199  echo "Sorry, something went wrong. check if the host is accessible!\n";
200  echo Psr7\str($e->getRequest());
201  if ($e->hasResponse()) {
202  echo Psr7\str($e->getResponse());
203  }
204  $this->scheduler_disconnect(1);
205  exit;
206  }
207  }
208 
216  protected function insertSoftwareHeritageRecord($pfileId, $licenses, $agentId, $status)
217  {
218  $licenseString = !empty($licenses) ? implode(", ", $licenses) : '';
219  $this->softwareHeritageDao->setSoftwareHeritageDetails($pfileId,
220  $licenseString, $status);
221  if (!empty($licenses)) {
222  foreach ($licenses as $license) {
223  $l = $this->licenseDao->getLicenseByShortName($license);
224  if ($l != NULL) {
225  $this->dbManeger->insertTableRow('license_file',['agent_fk' => $agentId,
226  'pfile_fk' => $pfileId,'rf_fk'=> $l->getId()]);
227  }
228  }
229  return true;
230  }
231  }
232 }
Structure of an Agent with all required parameters.
Definition: Agent.php:41
heartbeat($newProcessed)
Send hear beat to the scheduler.
Definition: Agent.php:203
scheduler_disconnect($exitvalue)
Closes connection from scheduler.
Definition: Agent.php:236
processUploadId($uploadId)
Run software heritage for a package.
processEachPfileForSWH($pfileDetail, $agentId, $maxTime)
process each pfile for software heritage and wait till the reset time
insertSoftwareHeritageRecord($pfileId, $licenses, $agentId, $status)
Insert the License Details in softwareHeritage table.
getSoftwareHeritageLicense($sha256)
Get the license details from software heritage.
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:690