PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.5
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.5
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
jetpack / _inc / lib / class-jetpack-podcast-feed-locator.php

class-jetpack-podcast-feed-locator.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.5, at _inc/lib/class-jetpack-podcast-feed-locator.php

125 lines 4.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Extension of the SimplePie\Locator class, to detect podcast feeds
4 *
5 * @package automattic/jetpack
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit( 0 );
10 }
11
12 /**
13 * Class Jetpack_Podcast_Feed_Locator
14 */
15 class Jetpack_Podcast_Feed_Locator extends SimplePie\Locator {
16
17 /**
18 * Overrides the locator is_feed function to check for
19 * appropriate podcast elements.
20 *
21 * @param SimplePie\HTTP\Response $file The file being checked.
22 * @param boolean $check_html Adds text/html to the mimetypes checked.
23 */
24 public function is_feed( $file, $check_html = false ) {
25 return parent::is_feed( $file, $check_html ) &&
26 $file instanceof SimplePie\File &&
27 $this->is_podcast_feed( $file );
28 }
29
30 /**
31 * Checks the contents of the file for elements that make
32 * it a podcast feed.
33 *
34 * @param SimplePie\File $file The file being checked.
35 */
36 private function is_podcast_feed( $file ) {
37 // If we can't read the DOM assume it's a podcast feed, we'll work
38 // it out later.
39 if ( ! class_exists( 'DOMDocument' ) ) {
40 return true;
41 }
42
43 // @todo Drop is_callable check once WordPress.com Simple gets the SimplePie update that came with WordPress 6.9.
44 if ( is_callable( array( $file, 'get_body_content' ) ) ) {
45 $feed_dom = $this->safely_load_xml( $file->get_body_content() );
46 } else {
47 // @phan-suppress-next-line PhanDeprecatedProperty -- For compatibility only.
48 $feed_dom = $this->safely_load_xml( (string) $file->body );
49 }
50
51 // Do this as either/or but prioritise the itunes namespace. It's pretty likely
52 // that it's a podcast feed we've found if that namespace is present.
53 return $feed_dom && $this->has_itunes_ns( $feed_dom ) && $this->has_audio_enclosures( $feed_dom );
54 }
55
56 /**
57 * Safely loads an XML file
58 *
59 * @param string $xml A string of XML to load.
60 * @return DOMDocument|false A resulting DOM document or `false` if there is an error.
61 */
62 private function safely_load_xml( $xml ) {
63 if ( empty( $xml ) ) {
64 return false;
65 }
66
67 $disable_entity_loader = PHP_VERSION_ID < 80000;
68
69 if ( $disable_entity_loader ) {
70 // This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading
71 // is disabled by default, so this function is no longer needed to protect against XXE attacks.
72 // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated, PHPCompatibility.FunctionUse.RemovedFunctions.libxml_disable_entity_loaderDeprecated
73 $loader = libxml_disable_entity_loader( true );
74 }
75
76 $errors = libxml_use_internal_errors( true );
77
78 $return = new DOMDocument();
79 if ( ! $return->loadXML( $xml ) ) {
80 return false;
81 }
82
83 libxml_use_internal_errors( $errors );
84
85 if ( $disable_entity_loader && isset( $loader ) ) {
86 // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated, PHPCompatibility.FunctionUse.RemovedFunctions.libxml_disable_entity_loaderDeprecated
87 libxml_disable_entity_loader( $loader );
88 }
89
90 return $return;
91 }
92
93 /**
94 * Checks the RSS feed for the presence of the itunes podcast namespace.
95 * It's pretty loose and just checks the URI for itunes.com
96 *
97 * @param DOMDocument $dom The XML document to check.
98 * @return boolean Whether the itunes namespace is defined.
99 */
100 private function has_itunes_ns( $dom ) {
101 $xpath = new DOMXPath( $dom );
102 foreach ( $xpath->query( 'namespace::*' ) as $node ) {
103 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
104 // nodeValue is not valid, but it's part of the DOM API that we don't control.
105 if ( strstr( $node->nodeValue, 'itunes.com' ) ) {
106 return true;
107 }
108 // phpcs:enable
109 }
110 return false;
111 }
112
113 /**
114 * Checks the RSS feed for the presence of enclosures with an audio mimetype.
115 *
116 * @param DOMDocument $dom The XML document to check.
117 * @return boolean Whether enclosures were found.
118 */
119 private function has_audio_enclosures( $dom ) {
120 $xpath = new DOMXPath( $dom );
121 $enclosures = $xpath->query( "//enclosure[starts-with(@type,'audio/')]" );
122 return ! $enclosures ? false : $enclosures->length > 0;
123 }
124 }
125