source: extensions/gvideo/include/functions.inc.php @ 20804

Last change on this file since 20804 was 20804, checked in by mistic100, 11 years ago
  • add support for semi-private Vimeo videos
  • escape tags
  • compatible with safe_mode=On
  • deactivate autosize
File size: 15.6 KB
Line 
1<?php
2if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
3
4function parse_video_url($source_url, $safe_mode=false)
5{
6  $source_url = 'http://'.preg_replace('#^http(s?)://#', null, $source_url);
7 
8  $url = parse_url($source_url);
9  $url['host'] = str_replace('www.', null, $url['host']);
10  $url['host'] = explode('.', $url['host']);
11 
12  $video = array(
13    'type' => null,
14    'video_id' => null,
15    'url' => null,
16    'title' => null,
17    'description' => null,
18    'thumbnail' => null,
19    'author' => null,
20    'tags' => null,
21  );
22 
23  switch ($url['host'][0])
24  {
25    /* youtube */
26    case 'youtube':
27    {
28      parse_str($url['query'], $url['query']);
29      if (empty($url['query']['v'])) return false;
30     
31      $video['video_id'] = $url['query']['v'];
32    }
33   
34    case 'youtu': // youtu.be (short-url service)
35    {
36      $video['type'] = 'youtube';
37     
38      if (empty($video['video_id']))
39      {
40        $url['path'] = explode('/', $url['path']);
41        $video['video_id'] = $url['path'][1];
42      }
43     
44      $video['url'] = 'http://youtube.com/watch?v='.$video['video_id'];
45     
46      if (!$safe_mode)
47      {
48        $fields = 'entry(id,author,media:group(media:title(text()),media:description(text()),media:thumbnail(@url),media:keywords))';
49        $api_url = 'http://gdata.youtube.com/feeds/api/videos/'.$video['video_id'].'?v=2&alt=json&fields='.$fields;
50        $json = gvideo_download_remote_file($api_url, true);
51       
52        if ($json===false || $json=='file_error') return false;
53       
54        $json = json_decode($json, true);
55        $video = array_merge($video, array(
56          'title' => $json['entry']['media$group']['media$title']['$t'],
57          'description' => $json['entry']['media$group']['media$description']['$t'],
58          'thumbnail' => $json['entry']['media$group']['media$thumbnail'][0]['url'],
59          'author' => $json['entry']['author'][0]['name']['$t'],
60          ));
61        if (!empty($json['entry']['media$group']['media$keywords']['$t']))
62        {
63          $video['tags'] = $json['entry']['media$group']['media$keywords']['$t'];
64        }
65      }
66      else
67      {
68        $video['title'] = 'YouTube #'.$video['video_id'];
69      }
70     
71      break;
72    }
73     
74    /* vimeo */
75    case 'vimeo':
76    {
77      $video['type'] = 'vimeo';
78     
79      $url['path'] = explode('/', $url['path']);
80      $video['video_id'] = $url['path'][1];
81     
82      $video['url'] = 'http://vimeo.com/'.$video['video_id'];
83     
84      if (!$safe_mode)
85      {
86        // simple API for public videos
87        $api_url_1 = 'http://vimeo.com/api/v2/video/'.$video['video_id'].'.json';
88        $json = gvideo_download_remote_file($api_url_1, true);
89       
90        if ($json!==false && $json!='file_error' && trim($json)!=$video['video_id'].' not found.')
91        {
92          $json = json_decode($json, true);
93          $video = array_merge($video, array(
94            'title' => $json[0]['title'],
95            'description' => $json[0]['description'],
96            'thumbnail' => $json[0]['thumbnail_large'],
97            'author' => $json[0]['user_name'],
98            'tags' => $json[0]['tags'],
99            ));
100        }
101        else
102        {
103          // oEmbed API, for private videos, doesn't return keywords
104          $api_url_2 = 'http://vimeo.com/api/oembed.json?url='.rawurlencode($video['url']);
105          $json = gvideo_download_remote_file($api_url_2, true);
106         
107          if ($json===false || $json=='file_error') return false;
108         
109          $json = json_decode($json, true);
110          $video = array_merge($video, array(
111            'title' => $json['title'],
112            'description' => $json['description'],
113            'thumbnail' => $json['thumbnail_url'],
114            'author' => $json['author_name'],
115            ));
116        }
117      }
118      else
119      {
120        $video['title'] = 'Vimeo #'.$video['video_id'];
121      }
122     
123      break;
124    }
125     
126    /* dailymotion */
127    case 'dailymotion':
128    {
129      $video['type'] = 'dailymotion';
130     
131      $url['path'] = explode('/', $url['path']);
132      if ($url['path'][1] != 'video') return false;
133      $video['video_id'] = $url['path'][2];
134     
135      $video['url'] = 'http://dailymotion.com/video/'.$video['video_id'];
136     
137      if (!$safe_mode)
138      {
139        $api_url = 'https://api.dailymotion.com/video/'.$video['video_id'].'?fields=description,thumbnail_large_url,title,owner.username,tags'; // DM doesn't accept non secure connection
140        $json = gvideo_download_remote_file($api_url, true);
141       
142        if ($json===false || $json=='file_error') return false;
143       
144        $json = json_decode($json, true);
145        $json['thumbnail_large_url'] = preg_replace('#\?([0-9]+)$#', null, $json['thumbnail_large_url']);
146       
147        $video = array_merge($video, array(
148          'title' => $json['title'],
149          'description' => $json['description'],
150          'thumbnail' => $json['thumbnail_large_url'],
151          'author' => $json['owner.username'],
152          'tags' => implode(',', $json['tags']),
153          ));
154      }
155      else
156      {
157        $video['title'] = $video['video_id'];
158      }
159     
160      break;
161    }
162     
163    /* wat */
164    case 'wat':
165    {
166      $video['type'] = 'wat';
167     
168      // no safe_mode for wat.tv
169      $html = gvideo_download_remote_file($source_url, true);
170     
171      if ($html===false || $html=='file_error') return false;
172     
173      preg_match('#<meta property="og:video" content="http://www.wat.tv/swf2/([^"/>]+)" />#', $html, $matches);
174      if (empty($matches[1])) return false;
175      $video['video_id'] = $matches[1];
176     
177      $video['url'] = $source_url;
178     
179      preg_match('#<meta name="name" content="([^">]*)" />#', $html, $matches);
180      $video['title'] = $matches[1];
181     
182      preg_match('#<p class="description"(?:[^>]*)>(.*?)</p>#s', $html, $matches);
183      $video['description'] = $matches[1];
184     
185      preg_match('#<meta property="og:image" content="([^">]+)" />#', $html, $matches);
186      $video['thumbnail'] = $matches[1];
187     
188      $video['author'] = null;
189     
190      preg_match_all('#<meta property="video:tag" content="([^">]+)" />#', $html, $matches);
191      $video['tags'] = implode(',',  $matches[1]);
192      break;
193    }
194     
195    /* wideo */
196    case 'wideo':
197    {
198      $video['type'] = 'wideo';
199     
200      $url['path'] = explode('/', $url['path']);
201      $video['video_id'] = rtrim($url['path'][2], '.html');
202     
203      $video['url'] = 'http://wideo.fr/video/'.$video['video_id'].'.html';
204     
205      if (!$safe_mode)
206      {
207        $html = gvideo_download_remote_file($source_url, true);
208       
209        if ($html===false || $html=='file_error') return false;
210       
211        preg_match('#<meta property="og:title" content="([^">]*)" />#', $html, $matches);
212        $video['title'] = $matches[1];
213       
214        preg_match('#<meta property="og:description" content="([^">]*)" />#', $html, $matches);
215        $video['description'] = $matches[1];
216       
217        preg_match('#<meta property="og:image" content="([^">]+)" />#', $html, $matches);
218        $video['thumbnail'] = $matches[1];
219       
220        preg_match('#<li id="li_author">Auteur :  <a href=(?:[^>]*)><span>(.*?)</span></a>#', $html, $matches);
221        $video['author'] = $matches[1];
222       
223        preg_match('#<meta name="keywords" content="([^">]+)" />#', $html, $matches);
224        $video['tags'] = $matches[1];
225      }
226      else
227      {
228        $video['title'] = $video['video_id'];
229      }
230     
231      break;
232    }
233     
234    default:
235      return false;   
236  }
237 
238  return $video;
239}
240
241/**
242 * @params:
243 *  $video (from parse_video_url)
244 *  $config :
245 *    - category, integer
246 *    - add_film_frame, boolean
247 *    - sync_description, boolean
248 *    - sync_tags, boolean
249 *    - with, integer
250 *    - height, integer
251 *    - autoplay, integer (0-1)
252 */
253function add_video($video, $config)
254{
255  global $page, $conf;
256 
257  $query = '
258SELECT picture_id
259  FROM '.GVIDEO_TABLE.'
260  WHERE type = "'.$video['type'].'"
261    AND video_id = "'.$video['video_id'].'"
262;';
263  $result = pwg_query($query);
264 
265  if (pwg_db_num_rows($result))
266  {
267    $page['warnings'][] = l10n('This video was already registered');
268    list($image_id) = pwg_db_fetch_row($result);
269    return $image_id;
270  }
271 
272  include_once(PHPWG_ROOT_PATH . 'admin/include/functions_upload.inc.php');
273 
274  // download thumbnail
275  $thumb_ext = empty($video['thumbnail']) ? 'jpg' : get_extension($video['thumbnail']);
276  $thumb_name = $video['type'].'-'.$video['video_id'].'-'.uniqid().'.'.$thumb_ext;
277  $thumb_source = $conf['data_location'].$thumb_name;
278  if ( empty($video['thumbnail']) or gvideo_download_remote_file($video['thumbnail'], $thumb_source) !== true )
279  {
280    $thumb_source = $conf['data_location'].get_filename_wo_extension($thumb_name).'.jpg';
281    copy(GVIDEO_PATH.'mimetypes/'.$video['type'].'.jpg', $thumb_source);
282  }
283 
284  if ($config['add_film_frame'])
285  {
286    add_film_frame($thumb_source);
287  }
288 
289  // add image and update infos
290  $image_id = add_uploaded_file($thumb_source, $thumb_name, array($config['category']));
291 
292  $updates = array(
293    'name' => pwg_db_real_escape_string($video['title']),
294    'author' => pwg_db_real_escape_string($video['author']),
295    'is_gvideo' => 1,
296    );
297   
298  if ( $config['sync_description'] and !empty($video['description']) )
299  {
300    $updates['comment'] = pwg_db_real_escape_string($video['description']);
301  }
302 
303  if ( $config['sync_tags'] and !empty($video['tags']) )
304  {
305    $tags = pwg_db_real_escape_string($video['tags']);
306    set_tags(get_tag_ids($tags), $image_id);
307  }
308 
309  single_update(
310    IMAGES_TABLE,
311    $updates,
312    array('id' => $image_id),
313    true
314    );
315 
316  // register video
317  if ( !preg_match('#^([0-9]*)$#', $config['width']) or !preg_match('#^([0-9]*)$#', $config['height']) )
318  {
319    $config['width'] = $config['height'] = '';
320  }
321  if ( $config['autoplay']!='0' and $config['autoplay']!='1' )
322  {
323    $config['autoplay'] = '';
324  }
325 
326  $insert = array(
327    'picture_id' => $image_id,
328    'url' => $video['url'],
329    'type' => $video['type'],
330    'video_id' => $video['video_id'],
331    'width' => $config['width'],
332    'height' => $config['height'],
333    'autoplay' => $config['autoplay'],
334    );
335   
336  single_insert(
337    GVIDEO_TABLE,
338    $insert
339    );
340   
341  return $image_id;
342}
343
344/**
345 * test if a download method is available
346 * @return: bool
347 */
348if (!function_exists('test_remote_download'))
349{
350  function test_remote_download()
351  {
352    return function_exists('curl_init') || ini_get('allow_url_fopen');
353  }
354}
355
356/**
357 * download a remote file
358 *  - needs cURL or allow_url_fopen
359 *  - take care of SSL urls
360 *
361 * @param: string source url
362 * @param: mixed destination file (if true, file content is returned)
363 */
364function gvideo_download_remote_file($src, $dest, $headers=array())
365{
366  if (empty($src))
367  {
368    return false;
369  }
370 
371  $return = ($dest === true) ? true : false;
372 
373  array_push($headers, 'Accept-language: en');
374 
375  /* curl */
376  if (function_exists('curl_init'))
377  {
378    if (!$return)
379    {
380      $newf = fopen($dest, "wb");
381    }
382    $ch = curl_init();
383   
384    curl_setopt($ch, CURLOPT_URL, $src);
385    curl_setopt($ch, CURLOPT_HEADER, false);
386    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
387    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
388    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
389    if (!ini_get('safe_mode'))
390    {
391      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
392      curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
393    }
394    if (strpos($src, 'https://') !== false)
395    {
396      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
397      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
398    }
399    if (!$return)
400    {
401      curl_setopt($ch, CURLOPT_FILE, $newf);
402    }
403    else
404    {
405      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
406    }
407   
408    $out = curl_exec($ch);
409    curl_close($ch);
410   
411    if ($out === false)
412    {
413      return 'file_error';
414    }
415    else if (!$return)
416    {
417      fclose($newf);
418      return true;
419    }
420    else
421    {
422      return $out;
423    }
424  }
425  /* file get content */
426  else if (ini_get('allow_url_fopen'))
427  {
428    if (strpos($src, 'https://') !== false and !extension_loaded('openssl'))
429    {
430      return false;
431    }
432   
433    $opts = array(
434      'http' => array(
435        'method' => "GET",
436        'user_agent' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
437        'header' => implode("\r\n", $headers),
438      )
439    );
440
441    $context = stream_context_create($opts);
442   
443    if (($file = file_get_contents($src, false, $context)) === false)
444    {
445      return 'file_error';
446    }
447   
448    if (!$return)
449    {
450      file_put_contents($dest, $file);
451      return true;
452    }
453    else
454    {
455      return $file;
456    }
457  }
458 
459  return false;
460}
461
462/**
463 * and film frame to an image (need GD library)
464 * @param: string source
465 * @param: string destination (if null, the source si modified)
466 * @return: void
467 */
468function add_film_frame($src, $dest=null)
469{
470  if (empty($dest))
471  {
472    $dest = $src;
473  }
474 
475  // we need gd library
476  if (!function_exists('imagecreatetruecolor'))
477  {
478    if ($dest != $src) copy($src, $dest);
479    return;
480  }
481 
482  // open source image
483  switch (strtolower(get_extension($src)))
484  {
485    case 'jpg':
486    case 'jpeg':
487      $srcImage = imagecreatefromjpeg($src);
488      break;
489    case 'png':
490      $srcImage = imagecreatefrompng($src);
491      break;
492    case 'gif':
493      $srcImage = imagecreatefromgif($src);
494      break;
495    default:
496      if ($dest != $src) copy($src, $dest);
497      return;
498  }
499 
500  // source properties
501  $srcWidth = imagesx($srcImage);
502  $srcHeight = imagesy($srcImage);
503  $const = intval($srcWidth * 0.04);
504  $bandRadius = floor($const/8);
505
506  // band properties
507  $imgBand = imagecreatetruecolor($srcWidth + 6*$const, $srcHeight + 3*$const);
508 
509  $black = imagecolorallocate($imgBand, 0, 0, 0);
510  $white = imagecolorallocate($imgBand, 245, 245, 245);
511 
512  // and dots
513  $y_start = intval(($srcHeight + 3*$const) / 2);
514  $aug = intval($y_start / 5) + 1;
515  $i = 0;
516
517  while ($y_start + $i*$aug < $srcHeight + 3*$const)
518  {
519    imagefilledroundrectangle($imgBand, (3/4)*$const, $y_start + $i*$aug - $const/2, (9/4)*$const - 1, $y_start + $i*$aug + $const/2 - 1, $white, $bandRadius);
520    imagefilledroundrectangle($imgBand, (3/4)*$const, $y_start - $i*$aug - $const/2, (9/4)*$const - 1, $y_start - $i*$aug + $const/2 - 1, $white, $bandRadius);
521
522    imagefilledroundrectangle($imgBand, $srcWidth + (15/4)*$const, $y_start + $i*$aug - $const/2, $srcWidth + (21/4)*$const - 1, $y_start + $i*$aug + $const/2 - 1, $white, $bandRadius);
523    imagefilledroundrectangle($imgBand, $srcWidth + (15/4)*$const, $y_start - $i*$aug - $const/2, $srcWidth + (21/4)*$const - 1, $y_start - $i*$aug + $const/2 - 1, $white, $bandRadius);
524
525    ++$i;
526  }
527
528  // add source to band
529  imagecopy($imgBand, $srcImage, 3*$const, (3/2)*$const, 0, 0, $srcWidth, $srcHeight);
530 
531  // save image
532  switch (strtolower(get_extension($dest)))
533  {
534    case 'jpg':
535    case 'jpeg':
536      imagejpeg($imgBand, $dest, 85);
537      break;
538    case 'png':
539      imagepng($imgBand, $dest);
540      break;
541    case 'gif':
542      imagegif($imgBand, $dest);
543      break;
544  }
545}
546
547/**
548 * create a rectangle with round corners
549 * http://www.php.net/manual/fr/function.imagefilledrectangle.php#42815
550 */
551function imagefilledroundrectangle(&$img, $x1, $y1, $x2, $y2, $color, $radius)
552{
553  imagefilledrectangle($img, $x1+$radius, $y1, $x2-$radius, $y2, $color);
554 
555  if ($radius > 0)
556  {
557    imagefilledrectangle($img, $x1, $y1+$radius, $x2, $y2-$radius, $color);
558    imagefilledellipse($img, $x1+$radius, $y1+$radius, $radius*2, $radius*2, $color);
559    imagefilledellipse($img, $x2-$radius, $y1+$radius, $radius*2, $radius*2, $color);
560    imagefilledellipse($img, $x1+$radius, $y2-$radius, $radius*2, $radius*2, $color);
561    imagefilledellipse($img, $x2-$radius, $y2-$radius, $radius*2, $radius*2, $color);
562  }
563}
564
565?>
Note: See TracBrowser for help on using the repository browser.