1 | <?php |
||||||||
2 | class Af_RedditImgur extends Plugin { |
||||||||
3 | |||||||||
4 | /* @var PluginHost $host */ |
||||||||
5 | private $host; |
||||||||
6 | |||||||||
7 | public function about() { |
||||||||
8 | return array(1.0, |
||||||||
9 | "Inline images (and other content) in Reddit RSS feeds", |
||||||||
10 | "fox"); |
||||||||
11 | } |
||||||||
12 | |||||||||
13 | public function flags() { |
||||||||
14 | return array("needs_curl" => true); |
||||||||
15 | } |
||||||||
16 | |||||||||
17 | public function init($host) { |
||||||||
18 | $this->host = $host; |
||||||||
19 | |||||||||
20 | $host->add_hook($host::HOOK_ARTICLE_FILTER, $this); |
||||||||
21 | $host->add_hook($host::HOOK_PREFS_TAB, $this); |
||||||||
22 | } |
||||||||
23 | |||||||||
24 | public function hook_prefs_tab($args) { |
||||||||
25 | if ($args != "prefFeeds") { |
||||||||
26 | return; |
||||||||
27 | } |
||||||||
28 | |||||||||
29 | print "<div dojoType=\"dijit.layout.AccordionPane\" |
||||||||
30 | title=\"<i class='material-icons'>extension</i> ".__('Reddit content settings (af_redditimgur)')."\">"; |
||||||||
31 | |||||||||
32 | $enable_readability = $this->host->get($this, "enable_readability"); |
||||||||
33 | $enable_content_dupcheck = $this->host->get($this, "enable_content_dupcheck"); |
||||||||
34 | |||||||||
35 | if (version_compare(PHP_VERSION, '5.6.0', '<')) { |
||||||||
36 | print_error("Readability requires PHP version 5.6."); |
||||||||
0 ignored issues
–
show
The call to
print_error() has too many arguments starting with 'Readability requires PHP version 5.6.' .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||||
37 | } |
||||||||
38 | |||||||||
39 | print "<form dojoType='dijit.form.Form'>"; |
||||||||
40 | |||||||||
41 | print "<script type='dojo/method' event='onSubmit' args='evt'> |
||||||||
42 | evt.preventDefault(); |
||||||||
43 | if (this.validate()) { |
||||||||
44 | console.log(dojo.objectToQuery(this.getValues())); |
||||||||
45 | new Ajax.Request('backend.php', { |
||||||||
46 | parameters: dojo.objectToQuery(this.getValues()), |
||||||||
47 | onComplete: function(transport) { |
||||||||
48 | Notify.info(transport.responseText); |
||||||||
49 | } |
||||||||
50 | }); |
||||||||
51 | //this.reset(); |
||||||||
52 | } |
||||||||
53 | </script>"; |
||||||||
54 | |||||||||
55 | print_hidden("op", "pluginhandler"); |
||||||||
56 | print_hidden("method", "save"); |
||||||||
57 | print_hidden("plugin", "af_redditimgur"); |
||||||||
58 | |||||||||
59 | print "<fieldset class='narrow'>"; |
||||||||
60 | print "<label class='checkbox'>"; |
||||||||
61 | print_checkbox("enable_readability", $enable_readability); |
||||||||
62 | print " ".__("Extract missing content using Readability (requires af_readability)")."</label>"; |
||||||||
63 | print "</fieldset>"; |
||||||||
64 | |||||||||
65 | print "<fieldset class='narrow'>"; |
||||||||
66 | print "<label class='checkbox'>"; |
||||||||
67 | print_checkbox("enable_content_dupcheck", $enable_content_dupcheck); |
||||||||
68 | print " ".__("Enable additional duplicate checking")."</label>"; |
||||||||
69 | print "</fieldset>"; |
||||||||
70 | |||||||||
71 | print_button("submit", __("Save"), 'class="alt-primary"'); |
||||||||
72 | print "</form>"; |
||||||||
73 | |||||||||
74 | print "</div>"; |
||||||||
75 | } |
||||||||
76 | |||||||||
77 | public function save() { |
||||||||
78 | $enable_readability = checkbox_to_sql_bool($_POST["enable_readability"]); |
||||||||
79 | $enable_content_dupcheck = checkbox_to_sql_bool($_POST["enable_content_dupcheck"]); |
||||||||
80 | |||||||||
81 | $this->host->set($this, "enable_readability", $enable_readability, false); |
||||||||
82 | $this->host->set($this, "enable_content_dupcheck", $enable_content_dupcheck); |
||||||||
83 | |||||||||
84 | echo __("Configuration saved"); |
||||||||
85 | } |
||||||||
86 | |||||||||
87 | /** |
||||||||
88 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
||||||||
89 | */ |
||||||||
90 | private function inline_stuff($article, &$doc, $xpath) { |
||||||||
0 ignored issues
–
show
The parameter
$article is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||||
91 | |||||||||
92 | $entries = $xpath->query('(//a[@href]|//img[@src])'); |
||||||||
93 | $img_entries = $xpath->query("(//img[@src])"); |
||||||||
94 | |||||||||
95 | $found = false; |
||||||||
96 | //$debug = 1; |
||||||||
97 | |||||||||
98 | foreach ($entries as $entry) { |
||||||||
99 | if ($entry->hasAttribute("href") && strpos($entry->getAttribute("href"), "reddit.com") === false) { |
||||||||
100 | |||||||||
101 | Debug::log("processing href: ".$entry->getAttribute("href"), Debug::$LOG_VERBOSE); |
||||||||
102 | |||||||||
103 | $matches = array(); |
||||||||
104 | |||||||||
105 | if (!$found && preg_match("/^https?:\/\/twitter.com\/(.*?)\/status\/(.*)/", $entry->getAttribute("href"), $matches)) { |
||||||||
106 | Debug::log("handling as twitter: ".$matches[1]." ".$matches[2], Debug::$LOG_VERBOSE); |
||||||||
107 | |||||||||
108 | $oembed_result = fetch_file_contents("https://publish.twitter.com/oembed?url=".urlencode($entry->getAttribute("href"))); |
||||||||
109 | |||||||||
110 | if ($oembed_result) { |
||||||||
111 | $oembed_result = json_decode($oembed_result, true); |
||||||||
0 ignored issues
–
show
It seems like
$oembed_result can also be of type true ; however, parameter $json of json_decode() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
112 | |||||||||
113 | if ($oembed_result && isset($oembed_result["html"])) { |
||||||||
114 | |||||||||
115 | $tmp = new DOMDocument(); |
||||||||
116 | if ($tmp->loadHTML('<?xml encoding="utf-8" ?>'.$oembed_result["html"])) { |
||||||||
117 | $p = $doc->createElement("p"); |
||||||||
118 | |||||||||
119 | $p->appendChild($doc->importNode( |
||||||||
120 | $tmp->getElementsByTagName("blockquote")->item(0), true)); |
||||||||
121 | |||||||||
122 | $br = $doc->createElement('br'); |
||||||||
123 | $entry->parentNode->insertBefore($p, $entry); |
||||||||
124 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
125 | |||||||||
126 | $found = 1; |
||||||||
127 | } |
||||||||
128 | } |
||||||||
129 | } |
||||||||
130 | } |
||||||||
131 | |||||||||
132 | if (!$found && preg_match("/\.gfycat.com\/([a-z]+)?(\.[a-z]+)$/i", $entry->getAttribute("href"), $matches)) { |
||||||||
133 | $entry->setAttribute("href", "http://www.gfycat.com/".$matches[1]); |
||||||||
134 | } |
||||||||
135 | |||||||||
136 | if (!$found && preg_match("/https?:\/\/(www\.)?gfycat.com\/([a-z]+)$/i", $entry->getAttribute("href"), $matches)) { |
||||||||
137 | |||||||||
138 | Debug::log("Handling as Gfycat", Debug::$LOG_VERBOSE); |
||||||||
139 | |||||||||
140 | $source_stream = 'https://giant.gfycat.com/'.$matches[2].'.mp4'; |
||||||||
141 | $poster_url = 'https://thumbs.gfycat.com/'.$matches[2].'-mobile.jpg'; |
||||||||
142 | |||||||||
143 | $content_type = $this->get_content_type($source_stream); |
||||||||
144 | |||||||||
145 | if (strpos($content_type, "video/") !== false) { |
||||||||
0 ignored issues
–
show
It seems like
$content_type can also be of type false ; however, parameter $haystack of strpos() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
146 | $this->handle_as_video($doc, $entry, $source_stream, $poster_url); |
||||||||
147 | $found = 1; |
||||||||
148 | } |
||||||||
149 | } |
||||||||
150 | |||||||||
151 | if (!$found && preg_match("/https?:\/\/v\.redd\.it\/(.*)$/i", $entry->getAttribute("href"), $matches)) { |
||||||||
152 | |||||||||
153 | Debug::log("Handling as reddit inline video", Debug::$LOG_VERBOSE); |
||||||||
154 | |||||||||
155 | $img = $img_entries->item(0); |
||||||||
156 | |||||||||
157 | if ($img) { |
||||||||
158 | $poster_url = $img->getAttribute("src"); |
||||||||
159 | } else { |
||||||||
160 | $poster_url = false; |
||||||||
161 | } |
||||||||
162 | |||||||||
163 | // Get original article URL from v.redd.it redirects |
||||||||
164 | $source_article_url = $this->get_location($matches[0]); |
||||||||
165 | Debug::log("Resolved ".$matches[0]." to ".$source_article_url, Debug::$LOG_VERBOSE); |
||||||||
0 ignored issues
–
show
Are you sure
$source_article_url of type false|mixed can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
166 | |||||||||
167 | $source_stream = false; |
||||||||
168 | |||||||||
169 | if ($source_article_url) { |
||||||||
170 | $j = json_decode(fetch_file_contents($source_article_url.".json"), true); |
||||||||
171 | |||||||||
172 | if ($j) { |
||||||||
173 | foreach ($j as $listing) { |
||||||||
174 | foreach ($listing["data"]["children"] as $child) { |
||||||||
175 | if ($child["data"]["url"] == $matches[0]) { |
||||||||
176 | try { |
||||||||
177 | $source_stream = $child["data"]["media"]["reddit_video"]["fallback_url"]; |
||||||||
178 | } catch (Exception $e) { |
||||||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||||||||
179 | } |
||||||||
180 | break 2; |
||||||||
181 | } |
||||||||
182 | } |
||||||||
183 | } |
||||||||
184 | } |
||||||||
185 | } |
||||||||
186 | |||||||||
187 | if (!$source_stream) { |
||||||||
188 | $source_stream = "https://v.redd.it/".$matches[1]."/DASH_600_K"; |
||||||||
189 | } |
||||||||
190 | |||||||||
191 | $this->handle_as_video($doc, $entry, $source_stream, $poster_url); |
||||||||
192 | $found = 1; |
||||||||
193 | } |
||||||||
194 | |||||||||
195 | if (!$found && preg_match("/https?:\/\/(www\.)?streamable.com\//i", $entry->getAttribute("href"))) { |
||||||||
196 | |||||||||
197 | Debug::log("Handling as Streamable", Debug::$LOG_VERBOSE); |
||||||||
198 | |||||||||
199 | $tmp = fetch_file_contents($entry->getAttribute("href")); |
||||||||
200 | |||||||||
201 | if ($tmp) { |
||||||||
202 | $tmpdoc = new DOMDocument(); |
||||||||
203 | |||||||||
204 | if (@$tmpdoc->loadHTML($tmp)) { |
||||||||
0 ignored issues
–
show
It seems like
$tmp can also be of type true ; however, parameter $source of DOMDocument::loadHTML() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
205 | $tmpxpath = new DOMXPath($tmpdoc); |
||||||||
206 | |||||||||
207 | $source_node = $tmpxpath->query("//video[contains(@class,'video-player-tag')]//source[contains(@src, '.mp4')]")->item(0); |
||||||||
208 | $poster_node = $tmpxpath->query("//video[contains(@class,'video-player-tag') and @poster]")->item(0); |
||||||||
209 | |||||||||
210 | if ($source_node && $poster_node) { |
||||||||
211 | $source_stream = $source_node->getAttribute("src"); |
||||||||
212 | $poster_url = $poster_node->getAttribute("poster"); |
||||||||
213 | |||||||||
214 | $this->handle_as_video($doc, $entry, $source_stream, $poster_url); |
||||||||
215 | $found = 1; |
||||||||
216 | } |
||||||||
217 | } |
||||||||
218 | } |
||||||||
219 | } |
||||||||
220 | |||||||||
221 | // imgur .gif -> .gifv |
||||||||
222 | if (!$found && preg_match("/i\.imgur\.com\/(.*?)\.gif$/i", $entry->getAttribute("href"))) { |
||||||||
223 | Debug::log("Handling as imgur gif (->gifv)", Debug::$LOG_VERBOSE); |
||||||||
224 | |||||||||
225 | $entry->setAttribute("href", |
||||||||
226 | str_replace(".gif", ".gifv", $entry->getAttribute("href"))); |
||||||||
227 | } |
||||||||
228 | |||||||||
229 | if (!$found && preg_match("/\.(gifv|mp4)$/i", $entry->getAttribute("href"))) { |
||||||||
230 | Debug::log("Handling as imgur gifv", Debug::$LOG_VERBOSE); |
||||||||
231 | |||||||||
232 | $source_stream = str_replace(".gifv", ".mp4", $entry->getAttribute("href")); |
||||||||
233 | |||||||||
234 | if (strpos($source_stream, "imgur.com") !== false) { |
||||||||
235 | $poster_url = str_replace(".mp4", "h.jpg", $source_stream); |
||||||||
236 | } |
||||||||
237 | |||||||||
238 | $this->handle_as_video($doc, $entry, $source_stream, $poster_url); |
||||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||||
239 | |||||||||
240 | $found = true; |
||||||||
241 | } |
||||||||
242 | |||||||||
243 | $matches = array(); |
||||||||
244 | if (!$found && preg_match("/youtube\.com\/v\/([\w-]+)/", $entry->getAttribute("href"), $matches) || |
||||||||
245 | preg_match("/youtube\.com\/.*?[\&\?]v=([\w-]+)/", $entry->getAttribute("href"), $matches) || |
||||||||
246 | preg_match("/youtube\.com\/watch\?v=([\w-]+)/", $entry->getAttribute("href"), $matches) || |
||||||||
247 | preg_match("/\/\/youtu.be\/([\w-]+)/", $entry->getAttribute("href"), $matches)) { |
||||||||
248 | |||||||||
249 | $vid_id = $matches[1]; |
||||||||
250 | |||||||||
251 | Debug::log("Handling as youtube: $vid_id", Debug::$LOG_VERBOSE); |
||||||||
252 | |||||||||
253 | $iframe = $doc->createElement("iframe"); |
||||||||
254 | $iframe->setAttribute("class", "youtube-player"); |
||||||||
255 | $iframe->setAttribute("type", "text/html"); |
||||||||
256 | $iframe->setAttribute("width", "640"); |
||||||||
257 | $iframe->setAttribute("height", "385"); |
||||||||
258 | $iframe->setAttribute("src", "https://www.youtube.com/embed/$vid_id"); |
||||||||
259 | $iframe->setAttribute("allowfullscreen", "1"); |
||||||||
260 | $iframe->setAttribute("frameborder", "0"); |
||||||||
261 | |||||||||
262 | $br = $doc->createElement('br'); |
||||||||
263 | $entry->parentNode->insertBefore($iframe, $entry); |
||||||||
264 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
265 | |||||||||
266 | $found = true; |
||||||||
267 | } |
||||||||
268 | |||||||||
269 | if (!$found && preg_match("/\.(jpg|jpeg|gif|png)(\?[0-9][0-9]*)?$/i", $entry->getAttribute("href")) || |
||||||||
270 | mb_strpos($entry->getAttribute("href"), "i.reddituploads.com") !== false || |
||||||||
271 | mb_strpos($this->get_content_type($entry->getAttribute("href")), "image/") !== false) { |
||||||||
0 ignored issues
–
show
It seems like
$this->get_content_type(...->getAttribute('href')) can also be of type false ; however, parameter $haystack of mb_strpos() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
272 | |||||||||
273 | Debug::log("Handling as a picture", Debug::$LOG_VERBOSE); |
||||||||
274 | |||||||||
275 | $img = $doc->createElement('img'); |
||||||||
276 | $img->setAttribute("src", $entry->getAttribute("href")); |
||||||||
277 | |||||||||
278 | $br = $doc->createElement('br'); |
||||||||
279 | $entry->parentNode->insertBefore($img, $entry); |
||||||||
280 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
281 | |||||||||
282 | $found = true; |
||||||||
283 | } |
||||||||
284 | |||||||||
285 | // imgur via link rel="image_src" href="..." |
||||||||
286 | if (!$found && preg_match("/imgur/", $entry->getAttribute("href"))) { |
||||||||
287 | |||||||||
288 | Debug::log("handling as imgur page/whatever", Debug::$LOG_VERBOSE); |
||||||||
289 | |||||||||
290 | $content = fetch_file_contents(["url" => $entry->getAttribute("href"), |
||||||||
291 | "http_accept" => "text/*"]); |
||||||||
292 | |||||||||
293 | if ($content) { |
||||||||
294 | $cdoc = new DOMDocument(); |
||||||||
295 | |||||||||
296 | if (@$cdoc->loadHTML($content)) { |
||||||||
297 | $cxpath = new DOMXPath($cdoc); |
||||||||
298 | |||||||||
299 | $rel_image = $cxpath->query("//link[@rel='image_src']")->item(0); |
||||||||
300 | |||||||||
301 | if ($rel_image) { |
||||||||
302 | |||||||||
303 | $img = $doc->createElement('img'); |
||||||||
304 | $img->setAttribute("src", $rel_image->getAttribute("href")); |
||||||||
305 | |||||||||
306 | $br = $doc->createElement('br'); |
||||||||
307 | $entry->parentNode->insertBefore($img, $entry); |
||||||||
308 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
309 | |||||||||
310 | $found = true; |
||||||||
311 | } |
||||||||
312 | } |
||||||||
313 | } |
||||||||
314 | } |
||||||||
315 | |||||||||
316 | // wtf is this even |
||||||||
317 | if (!$found && preg_match("/^https?:\/\/gyazo\.com\/([^\.\/]+$)/", $entry->getAttribute("href"), $matches)) { |
||||||||
318 | $img_id = $matches[1]; |
||||||||
319 | |||||||||
320 | Debug::log("handling as gyazo: $img_id", Debug::$LOG_VERBOSE); |
||||||||
321 | |||||||||
322 | $img = $doc->createElement('img'); |
||||||||
323 | $img->setAttribute("src", "https://i.gyazo.com/$img_id.jpg"); |
||||||||
324 | |||||||||
325 | $br = $doc->createElement('br'); |
||||||||
326 | $entry->parentNode->insertBefore($img, $entry); |
||||||||
327 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
328 | |||||||||
329 | $found = true; |
||||||||
330 | } |
||||||||
331 | |||||||||
332 | // let's try meta properties |
||||||||
333 | if (!$found) { |
||||||||
334 | Debug::log("looking for meta og:image", Debug::$LOG_VERBOSE); |
||||||||
335 | |||||||||
336 | $content = fetch_file_contents(["url" => $entry->getAttribute("href"), |
||||||||
337 | "http_accept" => "text/*"]); |
||||||||
338 | |||||||||
339 | if ($content) { |
||||||||
340 | $cdoc = new DOMDocument(); |
||||||||
341 | |||||||||
342 | if (@$cdoc->loadHTML($content)) { |
||||||||
343 | $cxpath = new DOMXPath($cdoc); |
||||||||
344 | |||||||||
345 | $og_image = $cxpath->query("//meta[@property='og:image']")->item(0); |
||||||||
346 | $og_video = $cxpath->query("//meta[@property='og:video']")->item(0); |
||||||||
347 | |||||||||
348 | if ($og_video) { |
||||||||
349 | |||||||||
350 | $source_stream = $og_video->getAttribute("content"); |
||||||||
351 | |||||||||
352 | if ($source_stream) { |
||||||||
353 | |||||||||
354 | if ($og_image) { |
||||||||
355 | $poster_url = $og_image->getAttribute("content"); |
||||||||
356 | } else { |
||||||||
357 | $poster_url = false; |
||||||||
358 | } |
||||||||
359 | |||||||||
360 | $this->handle_as_video($doc, $entry, $source_stream, $poster_url); |
||||||||
361 | $found = true; |
||||||||
362 | } |
||||||||
363 | |||||||||
364 | } else if ($og_image) { |
||||||||
365 | |||||||||
366 | $og_src = $og_image->getAttribute("content"); |
||||||||
367 | |||||||||
368 | if ($og_src) { |
||||||||
369 | $img = $doc->createElement('img'); |
||||||||
370 | $img->setAttribute("src", $og_src); |
||||||||
371 | |||||||||
372 | $br = $doc->createElement('br'); |
||||||||
373 | $entry->parentNode->insertBefore($img, $entry); |
||||||||
374 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
375 | |||||||||
376 | $found = true; |
||||||||
377 | } |
||||||||
378 | } |
||||||||
379 | } |
||||||||
380 | } |
||||||||
381 | } |
||||||||
382 | |||||||||
383 | } |
||||||||
384 | |||||||||
385 | // remove tiny thumbnails |
||||||||
386 | if ($entry->hasAttribute("src")) { |
||||||||
387 | if ($entry->parentNode && $entry->parentNode->parentNode) { |
||||||||
388 | $entry->parentNode->parentNode->removeChild($entry->parentNode); |
||||||||
389 | } |
||||||||
390 | } |
||||||||
391 | } |
||||||||
392 | |||||||||
393 | return $found; |
||||||||
394 | } |
||||||||
395 | |||||||||
396 | public function hook_article_filter($article) { |
||||||||
397 | |||||||||
398 | if (strpos($article["link"], "reddit.com/r/") !== false) { |
||||||||
399 | $doc = new DOMDocument(); |
||||||||
400 | @$doc->loadHTML($article["content"]); |
||||||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
loadHTML() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||||||
401 | $xpath = new DOMXPath($doc); |
||||||||
402 | |||||||||
403 | $content_link = $xpath->query("(//a[contains(., '[link]')])")->item(0); |
||||||||
404 | |||||||||
405 | if ($this->host->get($this, "enable_content_dupcheck")) { |
||||||||
406 | |||||||||
407 | if ($content_link) { |
||||||||
408 | $content_href = $content_link->getAttribute("href"); |
||||||||
409 | $entry_guid = $article["guid_hashed"]; |
||||||||
410 | $owner_uid = $article["owner_uid"]; |
||||||||
411 | |||||||||
412 | if (DB_TYPE == "pgsql") { |
||||||||
0 ignored issues
–
show
|
|||||||||
413 | $interval_qpart = "date_entered < NOW() - INTERVAL '1 day'"; |
||||||||
414 | } else { |
||||||||
415 | $interval_qpart = "date_entered < DATE_SUB(NOW(), INTERVAL 1 DAY)"; |
||||||||
416 | } |
||||||||
417 | |||||||||
418 | $sth = $this->pdo->prepare("SELECT COUNT(id) AS cid |
||||||||
419 | FROM ttrss_entries, ttrss_user_entries WHERE |
||||||||
420 | ref_id = id AND |
||||||||
421 | $interval_qpart AND |
||||||||
422 | guid != ? AND |
||||||||
423 | owner_uid = ? AND |
||||||||
424 | content LIKE ?"); |
||||||||
425 | |||||||||
426 | $sth->execute([$entry_guid, $owner_uid, "%href=\"$content_href\">[link]%"]); |
||||||||
427 | |||||||||
428 | if ($row = $sth->fetch()) { |
||||||||
429 | $num_found = $row['cid']; |
||||||||
430 | |||||||||
431 | if ($num_found > 0) { |
||||||||
432 | $article["force_catchup"] = true; |
||||||||
433 | } |
||||||||
434 | } |
||||||||
435 | } |
||||||||
436 | } |
||||||||
437 | |||||||||
438 | $found = $this->inline_stuff($article, $doc, $xpath); |
||||||||
439 | |||||||||
440 | $node = $doc->getElementsByTagName('body')->item(0); |
||||||||
441 | |||||||||
442 | if ($node && $found) { |
||||||||
443 | $article["content"] = $doc->saveHTML($node); |
||||||||
444 | } else if ($content_link) { |
||||||||
445 | $article = $this->readability($article, $content_link->getAttribute("href"), $doc, $xpath); |
||||||||
446 | } |
||||||||
447 | } |
||||||||
448 | |||||||||
449 | return $article; |
||||||||
450 | } |
||||||||
451 | |||||||||
452 | public function api_version() { |
||||||||
453 | return 2; |
||||||||
454 | } |
||||||||
455 | |||||||||
456 | private function handle_as_video($doc, $entry, $source_stream, $poster_url = false) { |
||||||||
457 | |||||||||
458 | Debug::log("handle_as_video: $source_stream", Debug::$LOG_VERBOSE); |
||||||||
459 | |||||||||
460 | $video = $doc->createElement('video'); |
||||||||
461 | $video->setAttribute("autoplay", "1"); |
||||||||
462 | $video->setAttribute("controls", "1"); |
||||||||
463 | $video->setAttribute("loop", "1"); |
||||||||
464 | |||||||||
465 | if ($poster_url) { |
||||||||
466 | $video->setAttribute("poster", $poster_url); |
||||||||
467 | } |
||||||||
468 | |||||||||
469 | $source = $doc->createElement('source'); |
||||||||
470 | $source->setAttribute("src", $source_stream); |
||||||||
471 | $source->setAttribute("type", "video/mp4"); |
||||||||
472 | |||||||||
473 | $video->appendChild($source); |
||||||||
474 | |||||||||
475 | $br = $doc->createElement('br'); |
||||||||
476 | $entry->parentNode->insertBefore($video, $entry); |
||||||||
477 | $entry->parentNode->insertBefore($br, $entry); |
||||||||
478 | |||||||||
479 | $img = $doc->createElement('img'); |
||||||||
480 | $img->setAttribute("src", |
||||||||
481 | "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D"); |
||||||||
482 | |||||||||
483 | $entry->parentNode->insertBefore($img, $entry); |
||||||||
484 | } |
||||||||
485 | |||||||||
486 | public function testurl() { |
||||||||
487 | $url = htmlspecialchars($_REQUEST["url"]); |
||||||||
488 | |||||||||
489 | header("Content-type: text/plain"); |
||||||||
490 | |||||||||
491 | print "URL: $url\n"; |
||||||||
492 | |||||||||
493 | $doc = new DOMDocument(); |
||||||||
494 | @$doc->loadHTML("<html><body><a href=\"$url\">[link]</a></body>"); |
||||||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
loadHTML() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||||||
495 | $xpath = new DOMXPath($doc); |
||||||||
496 | |||||||||
497 | $found = $this->inline_stuff([], $doc, $xpath); |
||||||||
498 | |||||||||
499 | print "Inline result: $found\n"; |
||||||||
500 | |||||||||
501 | if (!$found) { |
||||||||
502 | print "\nReadability result:\n"; |
||||||||
503 | |||||||||
504 | $article = $this->readability([], $url, $doc, $xpath); |
||||||||
505 | |||||||||
506 | print_r($article); |
||||||||
507 | } else { |
||||||||
508 | print "\nResulting HTML:\n"; |
||||||||
509 | |||||||||
510 | print $doc->saveHTML(); |
||||||||
511 | } |
||||||||
512 | } |
||||||||
513 | |||||||||
514 | private function get_header($url, $useragent = SELF_USER_AGENT, $header) { |
||||||||
515 | $ret = false; |
||||||||
516 | |||||||||
517 | if (function_exists("curl_init") && !defined("NO_CURL")) { |
||||||||
518 | $ch = curl_init($url); |
||||||||
519 | curl_setopt($ch, CURLOPT_TIMEOUT, 5); |
||||||||
0 ignored issues
–
show
It seems like
$ch can also be of type false ; however, parameter $ch of curl_setopt() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
520 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
||||||||
521 | curl_setopt($ch, CURLOPT_HEADER, true); |
||||||||
522 | curl_setopt($ch, CURLOPT_NOBODY, true); |
||||||||
523 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, !ini_get("open_basedir")); |
||||||||
524 | curl_setopt($ch, CURLOPT_USERAGENT, $useragent); |
||||||||
525 | |||||||||
526 | @curl_exec($ch); |
||||||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
curl_exec() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() It seems like
$ch can also be of type false ; however, parameter $ch of curl_exec() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
527 | $ret = curl_getinfo($ch, $header); |
||||||||
0 ignored issues
–
show
It seems like
$ch can also be of type false ; however, parameter $ch of curl_getinfo() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
528 | } |
||||||||
529 | |||||||||
530 | return $ret; |
||||||||
531 | } |
||||||||
532 | |||||||||
533 | private function get_content_type($url, $useragent = SELF_USER_AGENT) { |
||||||||
534 | return $this->get_header($url, $useragent, CURLINFO_CONTENT_TYPE); |
||||||||
535 | } |
||||||||
536 | |||||||||
537 | private function get_location($url, $useragent = SELF_USER_AGENT) { |
||||||||
538 | return $this->get_header($url, $useragent, CURLINFO_EFFECTIVE_URL); |
||||||||
539 | } |
||||||||
540 | |||||||||
541 | /** |
||||||||
542 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
||||||||
543 | */ |
||||||||
544 | private function readability($article, $url, $doc, $xpath, $debug = false) { |
||||||||
0 ignored issues
–
show
The parameter
$debug is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$doc is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$xpath is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||||
545 | |||||||||
546 | if (!defined('NO_CURL') && function_exists("curl_init") && $this->host->get($this, "enable_readability") && |
||||||||
547 | mb_strlen(strip_tags($article["content"])) <= 150) { |
||||||||
548 | |||||||||
549 | // do not try to embed posts linking back to other reddit posts |
||||||||
550 | // readability.php requires PHP 5.6 |
||||||||
551 | if ($url && strpos($url, "reddit.com") === false && version_compare(PHP_VERSION, '5.6.0', '>=')) { |
||||||||
552 | |||||||||
553 | /* link may lead to a huge video file or whatever, we need to check content type before trying to |
||||||||
554 | parse it which p much requires curl */ |
||||||||
555 | |||||||||
556 | $useragent_compat = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"; |
||||||||
557 | $content_type = $this->get_content_type($url, $useragent_compat); |
||||||||
558 | |||||||||
559 | if ($content_type && strpos($content_type, "text/html") !== false) { |
||||||||
560 | |||||||||
561 | foreach ($this->host->get_hooks(PluginHost::HOOK_GET_FULL_TEXT) as $p) { |
||||||||
562 | $extracted_content = $p->hook_get_full_text($url); |
||||||||
563 | |||||||||
564 | if ($extracted_content) { |
||||||||
565 | $article["content"] = $extracted_content; |
||||||||
566 | break; |
||||||||
567 | } |
||||||||
568 | } |
||||||||
569 | } |
||||||||
570 | } |
||||||||
571 | } |
||||||||
572 | |||||||||
573 | return $article; |
||||||||
574 | } |
||||||||
575 | } |
||||||||
576 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.