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