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

Last change on this file since 29299 was 29299, checked in by mistic100, 10 years ago

when vimeo provides default thumbnail without extension

File size: 18.4 KB
Line 
1<?php
2defined('PHPWG_ROOT_PATH') or die('Hacking attempt!');
3
4function parse_video_url($source_url, $safe_mode=false)
5{
6  $source_url = 'http://'.preg_replace('#^http(s?)://#', null, trim($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        if ($url['host'][1] != 'be') return false;
41        $url['path'] = explode('/', $url['path']);
42        $video['video_id'] = $url['path'][1];
43      }
44     
45      $video['url'] = 'http://youtube.com/watch?v='.$video['video_id'];
46      $video['title'] = 'YouTube #'.$video['video_id'];
47     
48      if (!$safe_mode)
49      {
50        $api_url = 'http://gdata.youtube.com/feeds/api/videos/'.$video['video_id'].'?v=2&alt=json';
51        $json = gvideo_download_remote_file($api_url, true);
52       
53        if ($json===false || $json=='file_error') return false;
54        if (strip_tags($json) == 'GDataInvalidRequestUriExceptionInvalid id') return false; // unknown video
55        if (strip_tags($json) == 'GDataServiceForbiddenExceptionPrivate video') return false; // private video
56       
57        $json = json_decode($json, true);
58        $video = array_merge($video, array(
59          'title' => $json['entry']['media$group']['media$title']['$t'],
60          'description' => $json['entry']['media$group']['media$description']['$t'],
61          'thumbnail' => $json['entry']['media$group']['media$thumbnail'][2]['url'],
62          'author' => $json['entry']['author'][0]['name']['$t'],
63          ));
64        if (!empty($json['entry']['media$group']['media$keywords']['$t']))
65        {
66          $video['tags'] = $json['entry']['media$group']['media$keywords']['$t'];
67        }
68      }
69     
70      break;
71    }
72     
73    /* vimeo */
74    case 'vimeo':
75    {
76      $video['type'] = 'vimeo';
77     
78      $url['path'] = explode('/', $url['path']);
79      $video['video_id'] = $url['path'][1];
80     
81      $video['url'] = 'http://vimeo.com/'.$video['video_id'];
82      $video['title'] = 'Vimeo #'.$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        if ($video['thumbnail'] == 'http://i.vimeocdn.com/video/default_640')
119        {
120          $video['thumbnail'] = 'http://i.vimeocdn.com/video/default_640.jpg';
121        }
122      }
123     
124      break;
125    }
126     
127    /* dailymotion */
128    case 'dailymotion':
129    {
130      $url['path'] = explode('/', $url['path']);
131      if ($url['path'][1] != 'video') return false;
132      $video['video_id'] = $url['path'][2];
133    }
134   
135    case 'dai':  // dai.ly (short-url service)
136    {
137      $video['type'] = 'dailymotion';
138     
139      if (empty($video['video_id']))
140      {
141        if ($url['host'][1] != 'ly') return false;
142        $video['video_id'] = ltrim($url['path'], '/');
143      }
144     
145      $video['url'] = 'http://dailymotion.com/video/'.$video['video_id'];
146      $video['title'] = 'Dailymotion #'.$video['video_id'];
147     
148      if (!$safe_mode)
149      {
150        $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
151        $json = gvideo_download_remote_file($api_url, true);
152       
153        if ($json===false || $json=='file_error') return false;
154       
155        $json = json_decode($json, true);
156        if (@$json['error']['type'] == 'access_forbidden') return false; // private video
157        $json['thumbnail_large_url'] = preg_replace('#\?([0-9]+)$#', null, $json['thumbnail_large_url']);
158       
159        $video = array_merge($video, array(
160          'title' => $json['title'],
161          'description' => $json['description'],
162          'thumbnail' => $json['thumbnail_large_url'],
163          'author' => $json['owner.username'],
164          'tags' => implode(',', $json['tags']),
165          ));
166      }
167     
168      break;
169    }
170     
171    /* wat */
172    case 'wat':
173    {
174      if ($safe_mode) return false;
175     
176      $html = gvideo_download_remote_file($source_url, true);
177
178      if ($html===false || $html=='file_error') return false;
179     
180      $video['type'] = 'wat';
181      $video['url'] = $source_url;
182     
183      preg_match('#<meta name="twitter:player" content="https://www.wat.tv/embedframe/([^">]+)">#', $html, $matches);
184      if (empty($matches[1])) return false;
185      $video['video_id'] = $matches[1];
186
187      preg_match('#<meta property="og:title" content="([^">]*)">#', $html, $matches);
188      $video['title'] = $matches[1];
189     
190      preg_match('#<meta property="og:description" content="([^">]*)">#s', $html, $matches);
191      $video['description'] = $matches[1];
192     
193      preg_match('#<meta property="og:image" content="([^">]+)">#', $html, $matches);
194      $video['thumbnail'] = $matches[1];
195     
196      preg_match('#<meta property="video:director" content="http://www.wat.tv/([^">]+)">#', $html, $matches);
197      $video['author'] = $matches[1];
198     
199      preg_match_all('#<meta property="video:tag" content="([^">]+)">#', $html, $matches);
200      $video['tags'] = implode(',',  $matches[1]);
201     
202      break;
203    }
204     
205    /* wideo */
206    case 'wideo':
207    {
208      $video['type'] = 'wideo';
209     
210      $url['path'] = explode('/', $url['path']);
211      $video['video_id'] = rtrim($url['path'][2], '.html');
212     
213      $video['url'] = 'http://wideo.fr/video/'.$video['video_id'].'.html';
214      $video['title'] = 'Wideo #'.$video['video_id'];
215     
216      if (!$safe_mode)
217      {
218        $html = gvideo_download_remote_file($source_url, true);
219       
220        if ($html===false || $html=='file_error') return false;
221       
222        preg_match('#<meta property="og:title" content="([^">]*)" />#', $html, $matches);
223        $video['title'] = $matches[1];
224       
225        preg_match('#<meta property="og:description" content="([^">]*)" />#s', $html, $matches);
226        $video['description'] = $matches[1];
227       
228        preg_match('#<meta property="og:image" content="([^">]+)" />#', $html, $matches);
229        $video['thumbnail'] = $matches[1];
230       
231        preg_match('#<li id="li_author">Auteur :  <a href=(?:[^>]*)><span>(.*?)</span></a>#', $html, $matches);
232        $video['author'] = $matches[1];
233       
234        preg_match('#<meta name="keywords" content="([^">]+)" />#', $html, $matches);
235        $video['tags'] = $matches[1];
236      }
237     
238      break;
239    }
240
241    default:
242      return false;   
243  }
244 
245  return $video;
246}
247
248/**
249 * @params:
250 *  $video (from parse_video_url)
251 *  $config :
252 *    - category, integer
253 *    - add_film_frame, boolean
254 *    - sync_description, boolean
255 *    - sync_tags, boolean
256 *    - with, integer
257 *    - height, integer
258 *    - autoplay, integer (0-1)
259 */
260function add_video($video, $config)
261{
262  global $page, $conf;
263 
264  $query = '
265SELECT picture_id
266  FROM '.GVIDEO_TABLE.'
267  WHERE type = "'.$video['type'].'"
268    AND video_id = "'.$video['video_id'].'"
269;';
270  $result = pwg_query($query);
271 
272  if (pwg_db_num_rows($result))
273  {
274    $page['warnings'][] = l10n('This video was already registered');
275    list($image_id) = pwg_db_fetch_row($result);
276    return $image_id;
277  }
278 
279  include_once(PHPWG_ROOT_PATH . 'admin/include/functions_upload.inc.php');
280 
281  // download thumbnail
282  $thumb_ext = empty($video['thumbnail']) ? 'jpg' : get_extension($video['thumbnail']);
283  $thumb_name = $video['type'].'-'.$video['video_id'].'-'.uniqid().'.'.$thumb_ext;
284  $thumb_source = $conf['data_location'].$thumb_name;
285 
286  if (empty($video['thumbnail']) or gvideo_download_remote_file($video['thumbnail'], $thumb_source) !== true)
287  {
288    $thumb_source = $conf['data_location'].get_filename_wo_extension($thumb_name).'.jpg';
289    copy(GVIDEO_PATH.'mimetypes/'.$video['type'].'.jpg', $thumb_source);
290  }
291 
292  if ($config['add_film_frame'])
293  {
294    add_film_frame($thumb_source);
295  }
296 
297  // add image and update infos
298  $image_id = add_uploaded_file($thumb_source, $thumb_name, array($config['category']));
299 
300  $updates = array(
301    'name' => pwg_db_real_escape_string($video['title']),
302    'author' => pwg_db_real_escape_string($video['author']),
303    'is_gvideo' => 1,
304    );
305   
306  if ($config['sync_description'] and !empty($video['description']))
307  {
308    $updates['comment'] = pwg_db_real_escape_string($video['description']);
309  }
310 
311  if ($config['sync_tags'] and !empty($video['tags']))
312  {
313    $tags = pwg_db_real_escape_string($video['tags']);
314    set_tags(get_tag_ids($tags), $image_id);
315  }
316 
317  single_update(
318    IMAGES_TABLE,
319    $updates,
320    array('id' => $image_id),
321    true
322    );
323 
324  // register video
325  if (!preg_match('#^([0-9]*)$#', $config['width']) or !preg_match('#^([0-9]*)$#', $config['height']))
326  {
327    $config['width'] = $config['height'] = '';
328  }
329  if ($config['autoplay']!='0' and $config['autoplay']!='1')
330  {
331    $config['autoplay'] = '';
332  }
333 
334  $insert = array(
335    'picture_id' => $image_id,
336    'url' => $video['url'],
337    'type' => $video['type'],
338    'video_id' => $video['video_id'],
339    'width' => $config['width'],
340    'height' => $config['height'],
341    'autoplay' => $config['autoplay'],
342    );
343   
344  single_insert(
345    GVIDEO_TABLE,
346    $insert
347    );
348   
349  return $image_id;
350}
351
352/**
353 * @params:
354 *  $config :
355 *    - url, string
356 *    - category, integer
357 *    - add_film_frame, boolean
358 *    - title, string
359 *    - embed_code, string
360 */
361function add_video_embed($config)
362{
363  global $page, $conf;
364 
365  $query = '
366SELECT picture_id
367  FROM '.GVIDEO_TABLE.'
368  WHERE url = "'.$config['url'].'"
369;';
370  $result = pwg_query($query);
371 
372  if (pwg_db_num_rows($result))
373  {
374    $page['warnings'][] = l10n('This video was already registered');
375    list($image_id) = pwg_db_fetch_row($result);
376    return $image_id;
377  }
378 
379  include_once(PHPWG_ROOT_PATH . 'admin/include/functions_upload.inc.php');
380 
381  // upload thumbnail
382  if (isset($_FILES['thumbnail_file']) && $_FILES['thumbnail_file']['error'] === UPLOAD_ERR_OK)
383  {
384    $source_filepath = $_FILES['thumbnail_file']['tmp_name'];
385    list(,, $type) = getimagesize($source_filepath);
386   
387    if (IMAGETYPE_PNG == $type || IMAGETYPE_GIF == $type || IMAGETYPE_JPEG == $type)
388    {
389      $thumb_name = $_FILES['thumbnail_file']['name'];
390      $thumb_source = $conf['data_location'].$thumb_name;
391      move_uploaded_file($source_filepath, $thumb_source);
392    }
393  }
394 
395  if (!isset($thumb_source))
396  {
397    $thumb_name = 'embed-'.uniqid().'.jpg';
398    $thumb_source = $conf['data_location'].$thumb_name;
399    copy(GVIDEO_PATH.'mimetypes/any.jpg', $thumb_source);
400  }
401 
402  if ($config['add_film_frame'])
403  {
404    add_film_frame($thumb_source);
405  }
406 
407  // add image and update infos
408  $image_id = add_uploaded_file($thumb_source, $thumb_name, array($config['category']));
409 
410  if (empty($config['title']))
411  {
412    $config['title'] = get_filename_wo_extension($thumb_name);
413  }
414 
415  $updates = array(
416    'name' => pwg_db_real_escape_string($config['title']),
417    'is_gvideo' => 1,
418    );
419 
420  single_update(
421    IMAGES_TABLE,
422    $updates,
423    array('id' => $image_id),
424    true
425    );
426
427  $insert = array(
428    'picture_id' => $image_id,
429    'url' => $config['url'],
430    'type' => 'embed',
431    'video_id' => 'embed',
432    'width' => '',
433    'height' => '',
434    'autoplay' => '',
435    'embed' => $config['embed_code']
436    );
437
438  single_insert(
439    GVIDEO_TABLE,
440    $insert
441    );
442   
443  return $image_id;
444}
445
446/**
447 * test if a download method is available
448 * @return: bool
449 */
450if (!function_exists('test_remote_download'))
451{
452  function test_remote_download()
453  {
454    return function_exists('curl_init') || ini_get('allow_url_fopen');
455  }
456}
457
458/**
459 * download a remote file
460 *  - needs cURL or allow_url_fopen
461 *  - take care of SSL urls
462 *
463 * @param: string source url
464 * @param: mixed destination file (if true, file content is returned)
465 */
466function gvideo_download_remote_file($src, $dest, $headers=array())
467{
468  if (empty($src))
469  {
470    return false;
471  }
472 
473  $return = ($dest === true) ? true : false;
474 
475  $headers[] = 'Accept-language: en';
476 
477  /* curl */
478  if (function_exists('curl_init'))
479  {
480    if (!$return)
481    {
482      $newf = fopen($dest, "wb");
483    }
484    $ch = curl_init();
485   
486    curl_setopt($ch, CURLOPT_URL, $src);
487    curl_setopt($ch, CURLOPT_HEADER, false);
488    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
489    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
490    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
491    if (!ini_get('safe_mode'))
492    {
493      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
494      curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
495    }
496    if (strpos($src, 'https://') !== false)
497    {
498      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
499      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
500    }
501    if (!$return)
502    {
503      curl_setopt($ch, CURLOPT_FILE, $newf);
504    }
505    else
506    {
507      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
508    }
509   
510    $out = curl_exec($ch);
511    curl_close($ch);
512   
513    if ($out === false)
514    {
515      return 'file_error';
516    }
517    else if (!$return)
518    {
519      fclose($newf);
520      return true;
521    }
522    else
523    {
524      return $out;
525    }
526  }
527  /* file get content */
528  else if (ini_get('allow_url_fopen'))
529  {
530    if (strpos($src, 'https://') !== false and !extension_loaded('openssl'))
531    {
532      return false;
533    }
534   
535    $opts = array(
536      'http' => array(
537        'method' => "GET",
538        'user_agent' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
539        'header' => implode("\r\n", $headers),
540      )
541    );
542
543    $context = stream_context_create($opts);
544   
545    if (($file = file_get_contents($src, false, $context)) === false)
546    {
547      return 'file_error';
548    }
549   
550    if (!$return)
551    {
552      file_put_contents($dest, $file);
553      return true;
554    }
555    else
556    {
557      return $file;
558    }
559  }
560 
561  return false;
562}
563
564/**
565 * and film frame to an image (need GD library)
566 * @param: string source
567 * @param: string destination (if null, the source is modified)
568 * @return: void
569 */
570function add_film_frame($src, $dest=null)
571{
572  if (empty($dest))
573  {
574    $dest = $src;
575  }
576 
577  // we need gd library
578  if (!function_exists('imagecreatetruecolor'))
579  {
580    if ($dest != $src) copy($src, $dest);
581    return;
582  }
583 
584  // open source image
585  switch (strtolower(get_extension($src)))
586  {
587    case 'jpg':
588    case 'jpeg':
589      $srcImage = imagecreatefromjpeg($src);
590      break;
591    case 'png':
592      $srcImage = imagecreatefrompng($src);
593      break;
594    case 'gif':
595      $srcImage = imagecreatefromgif($src);
596      break;
597    default:
598      if ($dest != $src) copy($src, $dest);
599      return;
600  }
601 
602  // source properties
603  $srcWidth = imagesx($srcImage);
604  $srcHeight = imagesy($srcImage);
605  $const = intval($srcWidth * 0.04);
606  $bandRadius = floor($const/8);
607
608  // band properties
609  $imgBand = imagecreatetruecolor($srcWidth + 6*$const, $srcHeight + 3*$const);
610 
611  $black = imagecolorallocate($imgBand, 0, 0, 0);
612  $white = imagecolorallocate($imgBand, 245, 245, 245);
613 
614  // and dots
615  $y_start = intval(($srcHeight + 3*$const) / 2);
616  $aug = intval($y_start / 5) + 1;
617  $i = 0;
618
619  while ($y_start + $i*$aug < $srcHeight + 3*$const)
620  {
621    imagefilledroundrectangle($imgBand, (3/4)*$const, $y_start + $i*$aug - $const/2, (9/4)*$const - 1, $y_start + $i*$aug + $const/2 - 1, $white, $bandRadius);
622    imagefilledroundrectangle($imgBand, (3/4)*$const, $y_start - $i*$aug - $const/2, (9/4)*$const - 1, $y_start - $i*$aug + $const/2 - 1, $white, $bandRadius);
623
624    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);
625    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);
626
627    ++$i;
628  }
629
630  // add source to band
631  imagecopy($imgBand, $srcImage, 3*$const, (3/2)*$const, 0, 0, $srcWidth, $srcHeight);
632 
633  // save image
634  switch (strtolower(get_extension($dest)))
635  {
636    case 'jpg':
637    case 'jpeg':
638      imagejpeg($imgBand, $dest, 85);
639      break;
640    case 'png':
641      imagepng($imgBand, $dest);
642      break;
643    case 'gif':
644      imagegif($imgBand, $dest);
645      break;
646  }
647}
648
649/**
650 * create a rectangle with round corners
651 * http://www.php.net/manual/fr/function.imagefilledrectangle.php#42815
652 */
653function imagefilledroundrectangle(&$img, $x1, $y1, $x2, $y2, $color, $radius)
654{
655  imagefilledrectangle($img, $x1+$radius, $y1, $x2-$radius, $y2, $color);
656 
657  if ($radius > 0)
658  {
659    imagefilledrectangle($img, $x1, $y1+$radius, $x2, $y2-$radius, $color);
660    imagefilledellipse($img, $x1+$radius, $y1+$radius, $radius*2, $radius*2, $color);
661    imagefilledellipse($img, $x2-$radius, $y1+$radius, $radius*2, $radius*2, $color);
662    imagefilledellipse($img, $x1+$radius, $y2-$radius, $radius*2, $radius*2, $color);
663    imagefilledellipse($img, $x2-$radius, $y2-$radius, $radius*2, $radius*2, $color);
664  }
665}
Note: See TracBrowser for help on using the repository browser.