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

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

remove "safe mode" checkbox, now fully automatic

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