36 const NAME =
"oneshot-monk";
39 private $highlightProcessor;
41 private $highlightRenderer;
43 private $textRenderer;
45 function __construct()
47 parent::__construct(self::NAME, array(
48 self::TITLE =>
"One-Shot Monk",
49 self::MENU_LIST =>
"Upload::One-Shot Monk",
51 self::REQUIRES_LOGIN =>
true 54 $this->highlightProcessor = $this->
getObject(
'view.highlight_processor');
55 $this->highlightRenderer = $this->
getObject(
'view.highlight_renderer');
56 $this->textRenderer = $this->
getObject(
'view.text_renderer');
63 protected function handle(Request $request)
66 $uploadFile = $request->files->get(
'file_input');
67 if ($uploadFile === null) {
70 $fullpath = $uploadFile->getPath().
'/'.$uploadFile->getFilename();
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);
78 public function scanMonkRendered($text)
80 $tmpFileName = tempnam(
"/tmp",
"monk");
82 throw new \Exception(
"cannot create temporary file");
84 $handle = fopen($tmpFileName,
"w");
85 fwrite($handle, $text);
87 list($licenseIds, $highlights) = $this->scanMonk($tmpFileName);
90 $this->highlightProcessor->addReferenceTexts($highlights);
91 $splitPositions = $this->highlightProcessor->calculateSplitPositions($highlights);
94 $rendered = $this->textRenderer->renderText($textFragment, $splitPositions);
96 return array($licenseIds, $rendered);
100 public function scanMonkFileRendered($tmpfname)
102 list($licenseIds, $highlights) = $this->scanMonk($tmpfname);
104 $text = file_get_contents($tmpfname);
106 $this->highlightProcessor->addReferenceTexts($highlights);
107 $splitPositions = $this->highlightProcessor->calculateSplitPositions($highlights);
110 $rendered = $this->textRenderer->renderText($textFragment, $splitPositions);
112 return array($licenseIds, $rendered);
116 public function scanMonk($fileName)
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");
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);
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;
139 $start = $lineMatches[
'start'];
140 $end = $start + $lineMatches[
'len'];
142 $type = Highlight::MATCH;
144 $highlight =
new Highlight($start, $end, $type);
145 $highlight->setLicenseId($licenseId);
147 $highlights[] = $highlight;
151 return array($licenseIds, $highlights);
154 private function addDiffsToHighlights($licenseId, $lineMatches, &$highlights)
156 foreach (explode(
',', $lineMatches[
'diff']) as $diff) {
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'];
164 switch ($diffMatches[
'type']) {
166 $type = Highlight::MATCH;
169 $type = Highlight::CHANGED;
172 $type = Highlight::DELETED;
175 $type = Highlight::ADDED;
178 throw new \Exception(
'unrecognized diff type');
180 $highlight =
new Highlight($start, $end, $type, $rfStart, $rfEnd);
181 $highlight->setLicenseId($licenseId);
183 $highlights[] = $highlight;
185 throw new \Exception(
'failed parsing diff element: '.$diff);
191 public function renderLicenseList($licenseIds)
196 $licenseDao = $container->get(
'dao.license');
197 $isLoggedIn = $this->isLoggedIn();
198 foreach ($licenseIds as $licenseId) {
200 $license = $licenseDao->getLicenseById($licenseId);
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>';
205 $content .=
'<li>' . $license->getShortName() .
'</li>';
208 return $content ? _(
'Possible licenses').
":<ul>$content</ul>" : _(
'No match found').
'<hr/>';
212 register_plugin(
new OneShot());
render($templateName, $vars=null, $headers=null)