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

Last change on this file since 20809 was 20809, checked in by mistic100, 11 years ago

better handle of private videos, show info about privacy

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