xref: /dokuwiki/vendor/simplepie/simplepie/src/Enclosure.php (revision 8e88a29b81301f78509349ab1152bb09c229123e)
1<?php
2
3// SPDX-FileCopyrightText: 2004-2023 Ryan Parman, Sam Sneddon, Ryan McCue
4// SPDX-License-Identifier: BSD-3-Clause
5
6declare(strict_types=1);
7
8namespace SimplePie;
9
10/**
11 * Handles everything related to enclosures (including Media RSS and iTunes RSS)
12 *
13 * Used by {@see \SimplePie\Item::get_enclosure()} and {@see \SimplePie\Item::get_enclosures()}
14 *
15 * This class can be overloaded with {@see \SimplePie\SimplePie::set_enclosure_class()}
16 */
17class Enclosure
18{
19    /**
20     * @var ?string
21     * @see get_bitrate()
22     */
23    public $bitrate;
24
25    /**
26     * @var Caption[]|null
27     * @see get_captions()
28     */
29    public $captions;
30
31    /**
32     * @var Category[]|null
33     * @see get_categories()
34     */
35    public $categories;
36
37    /**
38     * @var ?int
39     * @see get_channels()
40     */
41    public $channels;
42
43    /**
44     * @var ?Copyright
45     * @see get_copyright()
46     */
47    public $copyright;
48
49    /**
50     * @var Credit[]|null
51     * @see get_credits()
52     */
53    public $credits;
54
55    /**
56     * @var ?string
57     * @see get_description()
58     */
59    public $description;
60
61    /**
62     * @var ?int
63     * @see get_duration()
64     */
65    public $duration;
66
67    /**
68     * @var ?string
69     * @see get_expression()
70     */
71    public $expression;
72
73    /**
74     * @var ?string
75     * @see get_framerate()
76     */
77    public $framerate;
78
79    /**
80     * @var ?string
81     * @see get_handler()
82     */
83    public $handler;
84
85    /**
86     * @var string[]|null
87     * @see get_hashes()
88     */
89    public $hashes;
90
91    /**
92     * @var ?string
93     * @see get_height()
94     */
95    public $height;
96
97    /**
98     * @deprecated
99     * @var null
100     */
101    public $javascript;
102
103    /**
104     * @var string[]|null
105     * @see get_keywords()
106     */
107    public $keywords;
108
109    /**
110     * @var ?string
111     * @see get_language()
112     */
113    public $lang;
114
115    /**
116     * @var ?int
117     * @see get_length()
118     */
119    public $length;
120
121    /**
122     * @var ?string
123     * @see get_link()
124     */
125    public $link;
126
127    /**
128     * @var ?string
129     * @see get_medium()
130     */
131    public $medium;
132
133    /**
134     * @var ?string
135     * @see get_player()
136     */
137    public $player;
138
139    /**
140     * @var Rating[]|null
141     * @see get_ratings()
142     */
143    public $ratings;
144
145    /**
146     * @var ?Restriction[]
147     * @see get_restrictions()
148     */
149    public $restrictions;
150
151    /**
152     * @var ?string
153     * @see get_sampling_rate()
154     */
155    public $samplingrate;
156
157    /**
158     * @var string[]|null
159     * @see get_thumbnails()
160     */
161    public $thumbnails;
162
163    /**
164     * @var ?string
165     * @see get_title()
166     */
167    public $title;
168
169    /**
170     * @var ?string
171     * @see get_type()
172     */
173    public $type;
174
175    /**
176     * @var ?string
177     * @see get_width()
178     */
179    public $width;
180
181    /**
182     * Constructor, used to input the data
183     *
184     * For documentation on all the parameters, see the corresponding
185     * properties and their accessors
186     *
187     * @uses idn_to_ascii If available, this will convert an IDN
188     *
189     * @param null $javascript
190     * @param Caption[]|null $captions
191     * @param Category[]|null $categories
192     * @param Credit[]|null $credits
193     * @param string[]|null $hashes
194     * @param string[]|null $keywords
195     * @param Rating[]|null $ratings
196     * @param Restriction[]|null $restrictions
197     * @param string[]|null $thumbnails
198     */
199    public function __construct(
200        ?string $link = null,
201        ?string $type = null,
202        ?int $length = null,
203        $javascript = null,
204        ?string $bitrate = null,
205        ?array $captions = null,
206        ?array $categories = null,
207        ?int $channels = null,
208        ?Copyright $copyright = null,
209        ?array $credits = null,
210        ?string $description = null,
211        ?int $duration = null,
212        ?string $expression = null,
213        ?string $framerate = null,
214        ?array $hashes = null,
215        ?string $height = null,
216        ?array $keywords = null,
217        ?string $lang = null,
218        ?string $medium = null,
219        ?string $player = null,
220        ?array $ratings = null,
221        ?array $restrictions = null,
222        ?string $samplingrate = null,
223        ?array $thumbnails = null,
224        ?string $title = null,
225        ?string $width = null
226    ) {
227        $this->bitrate = $bitrate;
228        $this->captions = $captions;
229        $this->categories = $categories;
230        $this->channels = $channels;
231        $this->copyright = $copyright;
232        $this->credits = $credits;
233        $this->description = $description;
234        $this->duration = $duration;
235        $this->expression = $expression;
236        $this->framerate = $framerate;
237        $this->hashes = $hashes;
238        $this->height = $height;
239        $this->keywords = $keywords;
240        $this->lang = $lang;
241        $this->length = $length;
242        $this->link = $link;
243        $this->medium = $medium;
244        $this->player = $player;
245        $this->ratings = $ratings;
246        $this->restrictions = $restrictions;
247        $this->samplingrate = $samplingrate;
248        $this->thumbnails = $thumbnails;
249        $this->title = $title;
250        $this->type = $type;
251        $this->width = $width;
252
253        if (function_exists('idn_to_ascii')) {
254            $parsed = \SimplePie\Misc::parse_url($link ?? '');
255            if ($parsed['authority'] !== '' && !ctype_print($parsed['authority'])) {
256                $authority = (string) \idn_to_ascii($parsed['authority'], \IDNA_NONTRANSITIONAL_TO_ASCII, \INTL_IDNA_VARIANT_UTS46);
257                $this->link = \SimplePie\Misc::compress_parse_url($parsed['scheme'], $authority, $parsed['path'], $parsed['query'], $parsed['fragment']);
258            }
259        }
260        $this->handler = $this->get_handler(); // Needs to load last
261    }
262
263    /**
264     * String-ified version
265     *
266     * @return string
267     */
268    public function __toString()
269    {
270        // There is no $this->data here
271        return md5(serialize($this));
272    }
273
274    /**
275     * Get the bitrate
276     *
277     * @return string|null
278     */
279    public function get_bitrate()
280    {
281        if ($this->bitrate !== null) {
282            return $this->bitrate;
283        }
284
285        return null;
286    }
287
288    /**
289     * Get a single caption
290     *
291     * @param int $key
292     * @return \SimplePie\Caption|null
293     */
294    public function get_caption(int $key = 0)
295    {
296        $captions = $this->get_captions();
297        if (isset($captions[$key])) {
298            return $captions[$key];
299        }
300
301        return null;
302    }
303
304    /**
305     * Get all captions
306     *
307     * @return Caption[]|null
308     */
309    public function get_captions()
310    {
311        if ($this->captions !== null) {
312            return $this->captions;
313        }
314
315        return null;
316    }
317
318    /**
319     * Get a single category
320     *
321     * @param int $key
322     * @return \SimplePie\Category|null
323     */
324    public function get_category(int $key = 0)
325    {
326        $categories = $this->get_categories();
327        if (isset($categories[$key])) {
328            return $categories[$key];
329        }
330
331        return null;
332    }
333
334    /**
335     * Get all categories
336     *
337     * @return \SimplePie\Category[]|null
338     */
339    public function get_categories()
340    {
341        if ($this->categories !== null) {
342            return $this->categories;
343        }
344
345        return null;
346    }
347
348    /**
349     * Get the number of audio channels
350     *
351     * @return int|null
352     */
353    public function get_channels()
354    {
355        if ($this->channels !== null) {
356            return $this->channels;
357        }
358
359        return null;
360    }
361
362    /**
363     * Get the copyright information
364     *
365     * @return \SimplePie\Copyright|null
366     */
367    public function get_copyright()
368    {
369        if ($this->copyright !== null) {
370            return $this->copyright;
371        }
372
373        return null;
374    }
375
376    /**
377     * Get a single credit
378     *
379     * @param int $key
380     * @return \SimplePie\Credit|null
381     */
382    public function get_credit(int $key = 0)
383    {
384        $credits = $this->get_credits();
385        if (isset($credits[$key])) {
386            return $credits[$key];
387        }
388
389        return null;
390    }
391
392    /**
393     * Get all credits
394     *
395     * @return Credit[]|null
396     */
397    public function get_credits()
398    {
399        if ($this->credits !== null) {
400            return $this->credits;
401        }
402
403        return null;
404    }
405
406    /**
407     * Get the description of the enclosure
408     *
409     * @return string|null
410     */
411    public function get_description()
412    {
413        if ($this->description !== null) {
414            return $this->description;
415        }
416
417        return null;
418    }
419
420    /**
421     * Get the duration of the enclosure
422     *
423     * @param bool $convert Convert seconds into hh:mm:ss
424     * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found)
425     */
426    public function get_duration(bool $convert = false)
427    {
428        if ($this->duration !== null) {
429            if ($convert) {
430                $time = \SimplePie\Misc::time_hms($this->duration);
431                return $time;
432            }
433
434            return $this->duration;
435        }
436
437        return null;
438    }
439
440    /**
441     * Get the expression
442     *
443     * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full'
444     */
445    public function get_expression()
446    {
447        if ($this->expression !== null) {
448            return $this->expression;
449        }
450
451        return 'full';
452    }
453
454    /**
455     * Get the file extension
456     *
457     * @return string|null
458     */
459    public function get_extension()
460    {
461        if ($this->link !== null) {
462            $url = \SimplePie\Misc::parse_url($this->link);
463            if ($url['path'] !== '') {
464                return pathinfo($url['path'], PATHINFO_EXTENSION);
465            }
466        }
467        return null;
468    }
469
470    /**
471     * Get the framerate (in frames-per-second)
472     *
473     * @return string|null
474     */
475    public function get_framerate()
476    {
477        if ($this->framerate !== null) {
478            return $this->framerate;
479        }
480
481        return null;
482    }
483
484    /**
485     * Get the preferred handler
486     *
487     * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3'
488     */
489    public function get_handler()
490    {
491        return $this->get_real_type(true);
492    }
493
494    /**
495     * Get a single hash
496     *
497     * @link http://www.rssboard.org/media-rss#media-hash
498     * @param int $key
499     * @return string|null Hash as per `media:hash`, prefixed with "$algo:"
500     */
501    public function get_hash(int $key = 0)
502    {
503        $hashes = $this->get_hashes();
504        if (isset($hashes[$key])) {
505            return $hashes[$key];
506        }
507
508        return null;
509    }
510
511    /**
512     * Get all credits
513     *
514     * @return string[]|null Array of strings, see {@see get_hash()}
515     */
516    public function get_hashes()
517    {
518        if ($this->hashes !== null) {
519            return $this->hashes;
520        }
521
522        return null;
523    }
524
525    /**
526     * Get the height
527     *
528     * @return string|null
529     */
530    public function get_height()
531    {
532        if ($this->height !== null) {
533            return $this->height;
534        }
535
536        return null;
537    }
538
539    /**
540     * Get the language
541     *
542     * @link http://tools.ietf.org/html/rfc3066
543     * @return string|null Language code as per RFC 3066
544     */
545    public function get_language()
546    {
547        if ($this->lang !== null) {
548            return $this->lang;
549        }
550
551        return null;
552    }
553
554    /**
555     * Get a single keyword
556     *
557     * @param int $key
558     * @return string|null
559     */
560    public function get_keyword(int $key = 0)
561    {
562        $keywords = $this->get_keywords();
563        if (isset($keywords[$key])) {
564            return $keywords[$key];
565        }
566
567        return null;
568    }
569
570    /**
571     * Get all keywords
572     *
573     * @return string[]|null
574     */
575    public function get_keywords()
576    {
577        if ($this->keywords !== null) {
578            return $this->keywords;
579        }
580
581        return null;
582    }
583
584    /**
585     * Get length
586     *
587     * @return ?int Length in bytes
588     */
589    public function get_length()
590    {
591        if ($this->length !== null) {
592            return $this->length;
593        }
594
595        return null;
596    }
597
598    /**
599     * Get the URL
600     *
601     * @return string|null
602     */
603    public function get_link()
604    {
605        if ($this->link !== null) {
606            return $this->link;
607        }
608
609        return null;
610    }
611
612    /**
613     * Get the medium
614     *
615     * @link http://www.rssboard.org/media-rss#media-content
616     * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable'
617     */
618    public function get_medium()
619    {
620        if ($this->medium !== null) {
621            return $this->medium;
622        }
623
624        return null;
625    }
626
627    /**
628     * Get the player URL
629     *
630     * Typically the same as {@see get_permalink()}
631     * @return string|null Player URL
632     */
633    public function get_player()
634    {
635        if ($this->player !== null) {
636            return $this->player;
637        }
638
639        return null;
640    }
641
642    /**
643     * Get a single rating
644     *
645     * @param int $key
646     * @return \SimplePie\Rating|null
647     */
648    public function get_rating(int $key = 0)
649    {
650        $ratings = $this->get_ratings();
651        if (isset($ratings[$key])) {
652            return $ratings[$key];
653        }
654
655        return null;
656    }
657
658    /**
659     * Get all ratings
660     *
661     * @return Rating[]|null
662     */
663    public function get_ratings()
664    {
665        if ($this->ratings !== null) {
666            return $this->ratings;
667        }
668
669        return null;
670    }
671
672    /**
673     * Get a single restriction
674     *
675     * @param int $key
676     * @return \SimplePie\Restriction|null
677     */
678    public function get_restriction(int $key = 0)
679    {
680        $restrictions = $this->get_restrictions();
681        if (isset($restrictions[$key])) {
682            return $restrictions[$key];
683        }
684
685        return null;
686    }
687
688    /**
689     * Get all restrictions
690     *
691     * @return Restriction[]|null
692     */
693    public function get_restrictions()
694    {
695        if ($this->restrictions !== null) {
696            return $this->restrictions;
697        }
698
699        return null;
700    }
701
702    /**
703     * Get the sampling rate (in kHz)
704     *
705     * @return string|null
706     */
707    public function get_sampling_rate()
708    {
709        if ($this->samplingrate !== null) {
710            return $this->samplingrate;
711        }
712
713        return null;
714    }
715
716    /**
717     * Get the file size (in MiB)
718     *
719     * @return float|null File size in mebibytes (1048 bytes)
720     */
721    public function get_size()
722    {
723        $length = $this->get_length();
724        if ($length !== null) {
725            return round($length / 1048576, 2);
726        }
727
728        return null;
729    }
730
731    /**
732     * Get a single thumbnail
733     *
734     * @param int $key
735     * @return string|null Thumbnail URL
736     */
737    public function get_thumbnail(int $key = 0)
738    {
739        $thumbnails = $this->get_thumbnails();
740        if (isset($thumbnails[$key])) {
741            return $thumbnails[$key];
742        }
743
744        return null;
745    }
746
747    /**
748     * Get all thumbnails
749     *
750     * @return string[]|null Array of thumbnail URLs
751     */
752    public function get_thumbnails()
753    {
754        if ($this->thumbnails !== null) {
755            return $this->thumbnails;
756        }
757
758        return null;
759    }
760
761    /**
762     * Get the title
763     *
764     * @return string|null
765     */
766    public function get_title()
767    {
768        if ($this->title !== null) {
769            return $this->title;
770        }
771
772        return null;
773    }
774
775    /**
776     * Get mimetype of the enclosure
777     *
778     * @see get_real_type()
779     * @return string|null MIME type
780     */
781    public function get_type()
782    {
783        if ($this->type !== null) {
784            return $this->type;
785        }
786
787        return null;
788    }
789
790    /**
791     * Get the width
792     *
793     * @return string|null
794     */
795    public function get_width()
796    {
797        if ($this->width !== null) {
798            return $this->width;
799        }
800
801        return null;
802    }
803
804    /**
805     * Embed the enclosure using `<embed>`
806     *
807     * @deprecated Use the second parameter to {@see embed} instead
808     *
809     * @param array<string, mixed>|string $options See first parameter to {@see embed}
810     * @return string HTML string to output
811     */
812    public function native_embed($options = '')
813    {
814        return $this->embed($options, true);
815    }
816
817    /**
818     * Embed the enclosure using Javascript
819     *
820     * `$options` is an array or comma-separated key:value string, with the
821     * following properties:
822     *
823     * - `alt` (string): Alternate content for when an end-user does not have
824     *    the appropriate handler installed or when a file type is
825     *    unsupported. Can be any text or HTML. Defaults to blank.
826     * - `altclass` (string): If a file type is unsupported, the end-user will
827     *    see the alt text (above) linked directly to the content. That link
828     *    will have this value as its class name. Defaults to blank.
829     * - `audio` (string): This is an image that should be used as a
830     *    placeholder for audio files before they're loaded (QuickTime-only).
831     *    Can be any relative or absolute URL. Defaults to blank.
832     * - `bgcolor` (string): The background color for the media, if not
833     *    already transparent. Defaults to `#ffffff`.
834     * - `height` (integer): The height of the embedded media. Accepts any
835     *    numeric pixel value (such as `360`) or `auto`. Defaults to `auto`,
836     *    and it is recommended that you use this default.
837     * - `loop` (boolean): Do you want the media to loop when it's done?
838     *    Defaults to `false`.
839     * - `mediaplayer` (string): The location of the included
840     *    `mediaplayer.swf` file. This allows for the playback of Flash Video
841     *    (`.flv`) files, and is the default handler for non-Odeo MP3's.
842     *    Defaults to blank.
843     * - `video` (string): This is an image that should be used as a
844     *    placeholder for video files before they're loaded (QuickTime-only).
845     *    Can be any relative or absolute URL. Defaults to blank.
846     * - `width` (integer): The width of the embedded media. Accepts any
847     *    numeric pixel value (such as `480`) or `auto`. Defaults to `auto`,
848     *    and it is recommended that you use this default.
849     * - `widescreen` (boolean): Is the enclosure widescreen or standard?
850     *    This applies only to video enclosures, and will automatically resize
851     *    the content appropriately.  Defaults to `false`, implying 4:3 mode.
852     *
853     * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto`
854     * will default to 480x360 video resolution.  Widescreen (16:9) mode with
855     * `width` and `height` set to `auto` will default to 480x270 video resolution.
856     *
857     * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
858     * @param array<string, mixed>|string $options Comma-separated key:value list, or array
859     * @param bool $native Use `<embed>`
860     * @return string HTML string to output
861     */
862    public function embed($options = '', bool $native = false)
863    {
864        // Set up defaults
865        $audio = '';
866        $video = '';
867        $alt = '';
868        $altclass = '';
869        $loop = 'false';
870        $width = 'auto';
871        $height = 'auto';
872        $bgcolor = '#ffffff';
873        $mediaplayer = '';
874        $widescreen = false;
875        $handler = $this->get_handler();
876        $type = $this->get_real_type();
877        $placeholder = '';
878
879        // Process options and reassign values as necessary
880        if (is_array($options)) {
881            extract($options);
882        } else {
883            $options = explode(',', $options);
884            foreach ($options as $option) {
885                $opt = explode(':', $option, 2);
886                if (isset($opt[0], $opt[1])) {
887                    $opt[0] = trim($opt[0]);
888                    $opt[1] = trim($opt[1]);
889                    switch ($opt[0]) {
890                        case 'audio':
891                            $audio = $opt[1];
892                            break;
893
894                        case 'video':
895                            $video = $opt[1];
896                            break;
897
898                        case 'alt':
899                            $alt = $opt[1];
900                            break;
901
902                        case 'altclass':
903                            $altclass = $opt[1];
904                            break;
905
906                        case 'loop':
907                            $loop = $opt[1];
908                            break;
909
910                        case 'width':
911                            $width = $opt[1];
912                            break;
913
914                        case 'height':
915                            $height = $opt[1];
916                            break;
917
918                        case 'bgcolor':
919                            $bgcolor = $opt[1];
920                            break;
921
922                        case 'mediaplayer':
923                            $mediaplayer = $opt[1];
924                            break;
925
926                        case 'widescreen':
927                            $widescreen = $opt[1];
928                            break;
929                    }
930                }
931            }
932        }
933
934        $mime = explode('/', (string) $type, 2);
935        $mime = $mime[0];
936
937        // Process values for 'auto'
938        if ($width === 'auto') {
939            if ($mime === 'video') {
940                if ($height === 'auto') {
941                    $width = 480;
942                } elseif ($widescreen) {
943                    $width = round((intval($height) / 9) * 16);
944                } else {
945                    $width = round((intval($height) / 3) * 4);
946                }
947            } else {
948                $width = '100%';
949            }
950        }
951
952        if ($height === 'auto') {
953            if ($mime === 'audio') {
954                $height = 0;
955            } elseif ($mime === 'video') {
956                if ($width === 'auto') {
957                    if ($widescreen) {
958                        $height = 270;
959                    } else {
960                        $height = 360;
961                    }
962                } elseif ($widescreen) {
963                    $height = round((intval($width) / 16) * 9);
964                } else {
965                    $height = round((intval($width) / 4) * 3);
966                }
967            } else {
968                $height = 376;
969            }
970        } elseif ($mime === 'audio') {
971            $height = 0;
972        }
973
974        // Set proper placeholder value
975        if ($mime === 'audio') {
976            $placeholder = $audio;
977        } elseif ($mime === 'video') {
978            $placeholder = $video;
979        }
980
981        $embed = '';
982
983        // Flash
984        if ($handler === 'flash') {
985            if ($native) {
986                $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
987            } else {
988                $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
989            }
990        }
991
992        // Flash Media Player file types.
993        // Preferred handler for MP3 file types.
994        elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) {
995            if (is_numeric($height)) {
996                $height += 20;
997            }
998
999            if ($native) {
1000                $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
1001            } else {
1002                $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
1003            }
1004        }
1005
1006        // QuickTime 7 file types.  Need to test with QuickTime 6.
1007        // Only handle MP3's if the Flash Media Player is not present.
1008        elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) {
1009            if (is_numeric($height)) {
1010                $height += 16;
1011            }
1012
1013            if ($native) {
1014                if ($placeholder !== '') {
1015                    $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
1016                } else {
1017                    $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
1018                }
1019            } else {
1020                $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
1021            }
1022        }
1023
1024        // Windows Media
1025        elseif ($handler === 'wmedia') {
1026            if (is_numeric($height)) {
1027                $height += 45;
1028            }
1029
1030            if ($native) {
1031                $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
1032            } else {
1033                $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
1034            }
1035        }
1036
1037        // Everything else
1038        else {
1039            $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
1040        }
1041
1042        return $embed;
1043    }
1044
1045    /**
1046     * Get the real media type
1047     *
1048     * Often, feeds lie to us, necessitating a bit of deeper inspection. This
1049     * converts types to their canonical representations based on the file
1050     * extension
1051     *
1052     * @see get_type()
1053     * @param bool $find_handler Internal use only, use {@see get_handler()} instead
1054     * @return string|null MIME type
1055     */
1056    public function get_real_type(bool $find_handler = false)
1057    {
1058        // Mime-types by handler.
1059        $types_flash = ['application/x-shockwave-flash', 'application/futuresplash']; // Flash
1060        $types_fmedia = ['video/flv', 'video/x-flv','flv-application/octet-stream']; // Flash Media Player
1061        $types_quicktime = ['audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video']; // QuickTime
1062        $types_wmedia = ['application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx']; // Windows Media
1063        $types_mp3 = ['audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg']; // MP3
1064
1065        $type = $this->get_type();
1066        if ($type !== null) {
1067            $type = strtolower($type);
1068        }
1069
1070        // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
1071        if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) {
1072            $extension = $this->get_extension();
1073            if ($extension === null) {
1074                return null;
1075            }
1076
1077            switch (strtolower($extension)) {
1078                // Audio mime-types
1079                case 'aac':
1080                case 'adts':
1081                    $type = 'audio/acc';
1082                    break;
1083
1084                case 'aif':
1085                case 'aifc':
1086                case 'aiff':
1087                case 'cdda':
1088                    $type = 'audio/aiff';
1089                    break;
1090
1091                case 'bwf':
1092                    $type = 'audio/wav';
1093                    break;
1094
1095                case 'kar':
1096                case 'mid':
1097                case 'midi':
1098                case 'smf':
1099                    $type = 'audio/midi';
1100                    break;
1101
1102                case 'm4a':
1103                    $type = 'audio/x-m4a';
1104                    break;
1105
1106                case 'mp3':
1107                case 'swa':
1108                    $type = 'audio/mp3';
1109                    break;
1110
1111                case 'wav':
1112                    $type = 'audio/wav';
1113                    break;
1114
1115                case 'wax':
1116                    $type = 'audio/x-ms-wax';
1117                    break;
1118
1119                case 'wma':
1120                    $type = 'audio/x-ms-wma';
1121                    break;
1122
1123                case '3gp':
1124                case '3gpp':
1125                    // Video mime-types
1126                    $type = 'video/3gpp';
1127                    break;
1128
1129                case '3g2':
1130                case '3gp2':
1131                    $type = 'video/3gpp2';
1132                    break;
1133
1134                case 'asf':
1135                    $type = 'video/x-ms-asf';
1136                    break;
1137
1138                case 'flv':
1139                    $type = 'video/x-flv';
1140                    break;
1141
1142                case 'm1a':
1143                case 'm1s':
1144                case 'm1v':
1145                case 'm15':
1146                case 'm75':
1147                case 'mp2':
1148                case 'mpa':
1149                case 'mpeg':
1150                case 'mpg':
1151                case 'mpm':
1152                case 'mpv':
1153                    $type = 'video/mpeg';
1154                    break;
1155
1156                case 'm4v':
1157                    $type = 'video/x-m4v';
1158                    break;
1159
1160                case 'mov':
1161                case 'qt':
1162                    $type = 'video/quicktime';
1163                    break;
1164
1165                case 'mp4':
1166                case 'mpg4':
1167                    $type = 'video/mp4';
1168                    break;
1169
1170                case 'sdv':
1171                    $type = 'video/sd-video';
1172                    break;
1173
1174                case 'wm':
1175                    $type = 'video/x-ms-wm';
1176                    break;
1177
1178                case 'wmv':
1179                    $type = 'video/x-ms-wmv';
1180                    break;
1181
1182                case 'wvx':
1183                    $type = 'video/x-ms-wvx';
1184                    break;
1185
1186                case 'spl':
1187                    // Flash mime-types
1188                    $type = 'application/futuresplash';
1189                    break;
1190
1191                case 'swf':
1192                    $type = 'application/x-shockwave-flash';
1193                    break;
1194            }
1195        }
1196
1197        if ($find_handler) {
1198            if (in_array($type, $types_flash)) {
1199                return 'flash';
1200            } elseif (in_array($type, $types_fmedia)) {
1201                return 'fmedia';
1202            } elseif (in_array($type, $types_quicktime)) {
1203                return 'quicktime';
1204            } elseif (in_array($type, $types_wmedia)) {
1205                return 'wmedia';
1206            } elseif (in_array($type, $types_mp3)) {
1207                return 'mp3';
1208            }
1209
1210            return null;
1211        }
1212
1213        return $type;
1214    }
1215}
1216
1217class_alias('SimplePie\Enclosure', 'SimplePie_Enclosure');
1218