FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
oneshot.php
1 <?php
2 /*
3 Copyright (C) 2014, 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 
19 namespace Fossology\Monk\UI;
20 
33 
34 class OneShot extends DefaultPlugin
35 {
36  const NAME = "oneshot-monk";
37 
39  private $highlightProcessor;
41  private $highlightRenderer;
43  private $textRenderer;
44 
45  function __construct()
46  {
47  parent::__construct(self::NAME, array(
48  self::TITLE => "One-Shot Monk",
49  self::MENU_LIST => "Upload::One-Shot Monk",
50  self::PERMISSION => Auth::PERM_WRITE,
51  self::REQUIRES_LOGIN => true
52  ));
53 
54  $this->highlightProcessor = $this->getObject('view.highlight_processor');
55  $this->highlightRenderer = $this->getObject('view.highlight_renderer');
56  $this->textRenderer = $this->getObject('view.text_renderer');
57  }
58 
63  protected function handle(Request $request)
64  {
66  $uploadFile = $request->files->get('file_input');
67  if ($uploadFile === null) {
68  return $this->render('oneshot-upload.html.twig', $this->getDefaultVars());
69  }
70  $fullpath = $uploadFile->getPath().'/'.$uploadFile->getFilename();
71 
72  list($licenseIds, $rendered) = $this->scanMonkFileRendered($fullpath);
73  $vars = $this->mergeWithDefault(array('content' => $this->renderLicenseList($licenseIds).$rendered));
74  $vars['styles'] .= "<link rel='stylesheet' href='css/highlights.css'>\n";
75  return $this->render('include/base.html.twig', $vars);
76  }
77 
78  public function scanMonkRendered($text)
79  {
80  $tmpFileName = tempnam("/tmp", "monk");
81  if (!$tmpFileName) {
82  throw new \Exception("cannot create temporary file");
83  }
84  $handle = fopen($tmpFileName, "w");
85  fwrite($handle, $text);
86  fclose($handle);
87  list($licenseIds, $highlights) = $this->scanMonk($tmpFileName);
88  unlink($tmpFileName);
89 
90  $this->highlightProcessor->addReferenceTexts($highlights);
91  $splitPositions = $this->highlightProcessor->calculateSplitPositions($highlights);
92  $textFragment = new TextFragment(0, $text);
93 
94  $rendered = $this->textRenderer->renderText($textFragment, $splitPositions);
95 
96  return array($licenseIds, $rendered);
97  }
98 
99 
100  public function scanMonkFileRendered($tmpfname)
101  {
102  list($licenseIds, $highlights) = $this->scanMonk($tmpfname);
103 
104  $text = file_get_contents($tmpfname);
105 
106  $this->highlightProcessor->addReferenceTexts($highlights);
107  $splitPositions = $this->highlightProcessor->calculateSplitPositions($highlights);
108  $textFragment = new TextFragment(0, $text);
109 
110  $rendered = $this->textRenderer->renderText($textFragment, $splitPositions);
111 
112  return array($licenseIds, $rendered);
113  }
114 
115 
116  public function scanMonk($fileName)
117  {
118  global $SYSCONFDIR;
119  $cmd = dirname(__DIR__).'/agent/monk -c '.$SYSCONFDIR.' '.$fileName;
120  exec($cmd, $output, $returnVar);
121  if ($returnVar != 0) {
122  throw new \Exception("scan failed with $returnVar");
123  }
124 
125  $qFileName = preg_quote($fileName, "/");
126  $licenseIds = array();
127  $highlights = array();
128  foreach ($output as $line) {
129  $lineMatches = array();
130  if (preg_match('/found diff match between "'.$qFileName.'" and "[^"]*" \(rf_pk=(?P<rf>[0-9]+)\); rank (?P<rank>[0-9]{1,3}); diffs: \{(?P<diff>[st\[\]0-9, MR+-]+)}/', $line, $lineMatches)) {
131  $licenseId = $lineMatches['rf'];
132  $licenseIds[] = $licenseId;
133  $this->addDiffsToHighlights($licenseId, $lineMatches, $highlights);
134  }
135  if (preg_match('/found full match between "'.$qFileName.'" and "[^"]*" \(rf_pk=(?P<rf>[0-9]+)\); matched: (?P<start>[0-9]*)\+?(?P<len>[0-9]*)?/', $line, $lineMatches)) {
136  $licenseId = $lineMatches['rf'];
137  $licenseIds[] = $licenseId;
138 
139  $start = $lineMatches['start'];
140  $end = $start + $lineMatches['len'];
141 
142  $type = Highlight::MATCH;
143 
144  $highlight = new Highlight($start, $end, $type);
145  $highlight->setLicenseId($licenseId);
146 
147  $highlights[] = $highlight;
148  }
149  }
150 
151  return array($licenseIds, $highlights);
152  }
153 
154  private function addDiffsToHighlights($licenseId, $lineMatches, &$highlights)
155  {
156  foreach (explode(',', $lineMatches['diff']) as $diff) {
157  // t[0+4798] M0 s[0+4834]
158  if (preg_match('/t\[(?P<start>[0-9]*)\+?(?P<len>[0-9]*)?\] M(?P<type>.?) s\[(?P<rf_start>[0-9]*)\+?(?P<rf_len>[0-9]*)?\]/', $diff, $diffMatches)) {
159  $start = $diffMatches['start'];
160  $end = $start + $diffMatches['len'];
161  $rfStart = intval($diffMatches['rf_start']);
162  $rfEnd = $rfStart + $diffMatches['rf_len'];
163 
164  switch ($diffMatches['type']) {
165  case '0':
166  $type = Highlight::MATCH;
167  break;
168  case 'R':
169  $type = Highlight::CHANGED;
170  break;
171  case '-':
172  $type = Highlight::DELETED;
173  break;
174  case '+':
175  $type = Highlight::ADDED;
176  break;
177  default:
178  throw new \Exception('unrecognized diff type');
179  }
180  $highlight = new Highlight($start, $end, $type, $rfStart, $rfEnd);
181  $highlight->setLicenseId($licenseId);
182 
183  $highlights[] = $highlight;
184  } else {
185  throw new \Exception('failed parsing diff element: '.$diff);
186  }
187  }
188  }
189 
190 
191  public function renderLicenseList($licenseIds)
192  {
193  $content = '';
194  global $container;
196  $licenseDao = $container->get('dao.license');
197  $isLoggedIn = $this->isLoggedIn();
198  foreach ($licenseIds as $licenseId) {
200  $license = $licenseDao->getLicenseById($licenseId);
201  if ($isLoggedIn) {
202  $js = "javascript:window.open('?mod=popup-license&rf=" . $license->getId() . "','License text','width=600,height=400,toolbar=no,scrollbars=yes,resizable=yes');";
203  $content .= '<li><a onclick="' . $js . '" href="javascript:;">' . $license->getShortName() . '</a></li>';
204  } else {
205  $content .= '<li>' . $license->getShortName() . '</li>';
206  }
207  }
208  return $content ? _('Possible licenses').":<ul>$content</ul>" : _('No match found').'<hr/>';
209  }
210 }
211 
212 register_plugin(new OneShot());
render($templateName, $vars=null, $headers=null)