source: extensions/pbase2piwigo/include/functions.inc.php @ 17314

Last change on this file since 17314 was 17314, checked in by mistic100, 12 years ago
  • many small improvements
  • protect "generic" functions
  • complete localization
File size: 11.4 KB
Line 
1<?php
2if (!defined('PBASE_PATH')) die('Hacking attempt!');
3
4/**
5 * get the content of web-page, with cache management
6 * @param: string url
7 * @return: string
8 */
9function get_file_cached($url)
10{
11  // html files are cached 10000 seconds
12  $cache_id_prefix = str_replace('http://www.pbase.com/', null, $url);
13  $cache_id_prefix = preg_replace('#([^a-z0-9]+)#i', null, $cache_id_prefix);
14  $cache_id = $cache_id_prefix.'-'.substr(time(), 0, -4);
15 
16  if (!file_exists(PBASE_FS_CACHE.$cache_id))
17  {
18    $files = glob(PBASE_FS_CACHE.$cache_id_prefix.'-*');
19    foreach ($files as $file) unlink($file);
20   
21    if (($result = download_remote_file($url, PBASE_FS_CACHE.$cache_id)) !== true)
22    {
23      return $result;
24    }
25  }
26 
27  $html = file_get_contents(PBASE_FS_CACHE.$cache_id);
28 
29  return utf8_encode($html);
30}
31
32/**
33 * helper to navigate throught the tree
34 * @param: &array tree
35 * @param: string path
36 * @return: reference to a branch of the tree
37 */
38function &get_current_cat(&$tree, $path)
39{
40  if (empty($path)) return $tree;
41 
42  $path = ltrim($path, '/');
43  $path = explode('/', $path);
44  $current = &$tree[ $path[0] ];
45  array_shift($path);
46 
47  foreach ($path as $folder)
48  {
49    $current = &$current['categories'][$folder];
50  }
51 
52  return $current;
53}
54
55/**
56 * check if give account (http://pbase.com/login/root) exists
57 * @param: string url
58 * @return: bool
59 */
60function check_account($url)
61{
62  $html = get_file_cached($url);
63  return !(bool)preg_match('#<h2>Unknown Account</h2>#i', $html);
64}
65
66/**
67 * parse a category page
68 * @param: string category url
69 * @param: bool parse only sub-categories
70 * @param: bool parse only one level
71 * @return: array category
72 */
73function parse_category($url, $path, $cats_only=false, $one_level=false)
74{
75  $url = str_replace('&page=all', null, $url);
76 
77  $current = array(
78    'url' => $url,
79    'path' => null,
80    'id' => null,
81    );
82   
83  // id
84  $temp = parse_url($url);
85  $temp = explode('/', $temp['path']);
86  $current['id'] = $temp[ count($temp)-1 ];
87  $current['path'] = $path.'/'.$current['id'];
88 
89  if ($one_level === 'stop')
90  {
91    return $current;
92  }
93   
94  $current = array_merge($current, array(
95    'title' => null,
96    'description' => null,
97    'pictures' => array(),
98    'categories' => array(),
99    'nb_pictures' => 0,
100    'nb_categories' => 0, 
101    ));
102   
103 
104  $url.= '&page=all'; // seriously... (should be ? not &)
105 
106 
107  $html = get_file_cached($url);
108  if ($html == 'file_error')
109  {
110    return $current;
111  }
112 
113  preg_match('#<body>(.*)</body>#is', $html, $matches);
114  $body = $matches[1];
115 
116  // content
117  // if (preg_match('#<CENTER>(.*)</CENTER>#is', $body, $matches) === 0) return 'null1';
118  if (preg_match_all('#<A HREF="([^">]*)" class="thumbnail">#i', $body, $matches) === 0) return $current;
119  $links = $matches[1];
120 
121  // title
122  if (preg_match('#<h2>(.*?)</h2>#i', $body, $matches))
123  {
124    $current['title'] = trim($matches[1]);
125  }
126  else
127  {
128    $current['title'] = $current['id'];
129  }
130 
131  // description
132  if (preg_match('#<!-- BEGIN user desc -->(.*?)<!-- END user desc -->#s', $body, $matches))
133  {
134    $current['description'] = trim($matches[1]);
135  }
136 
137  // sub-cats and pictures
138  foreach ($links as $link)
139  {
140    if (strpos($link, '/image/') !== false)
141    {
142      if (($image = parse_image($link, $cats_only)) !== null)
143      {
144        $current['pictures'][ $image['id'] ] = $image;
145      }
146      $current['nb_pictures']++;
147    }
148    else
149    {
150      $next_level = ($one_level === true) ? 'stop' : false;
151      if (($category = parse_category($link, $current['path'], $cats_only, $next_level)) !== null)
152      {
153        $current['categories'][ $category['id'] ] = $category;
154      }
155      $current['nb_categories']++;
156    }
157  }
158 
159  return $current;
160}
161
162/**
163 * parse a picture page
164 * @param: string picture url
165 * @param: bool return only url and id
166 * @return: array picture
167 */
168function parse_image($url, $light=false)
169{
170  $url = preg_replace('#/(small|medium|large|original)$#', null, $url);
171 
172  $current = array(
173    'url' => $url,
174    'id' => null,
175    );
176   
177  // id
178  $temp = parse_url($url);
179  $temp = explode('/', $temp['path']);
180  $current['id'] = $temp[ count($temp)-1 ];
181 
182  if ($light)
183  {
184    return $current;
185  }
186 
187  $current = array_merge($current, array(
188    'title' => null,
189    'path' => null,
190    'description' => null,
191    'date' => null,
192    'author' => null,
193    'keywords' => array(),
194    ));
195   
196  $url.= '/original';
197 
198 
199  $html = get_file_cached($url);
200  if ($html == 'file_error')
201  {
202    return $current;
203  }
204 
205  preg_match('#<body>(.*)</body>#is', $html, $matches);
206  $body = $matches[1];
207 
208  // path
209  if (preg_match('#<IMG ([^>]*)class="display" src="([^">]*)"#i', $body, $matches) ===0) return null;
210  $current['path'] = $matches[2];
211 
212  // title
213  preg_match('#<span class="title">(.*?)</span>#i', $body, $matches);
214  if (!empty($matches[1]))
215  {
216    $current['title'] = trim($matches[1]);
217    $current['title'] = get_filename_wo_extension($current['title']);
218  }
219  else
220  {
221    $current['title'] = $current['id'];
222  }
223 
224  // description
225  if (preg_match('#<p class="caption">(.*?)</p>#is', $body, $matches))
226  {
227    $current['description'] = trim($matches[1]);
228  }
229 
230  // date
231  if (preg_match('#<span class=date>(.*?)</span>#i', $body, $matches))
232  {
233    $current['date'] = trim($matches[1]);
234  }
235 
236  // author
237  if (preg_match('#<span class=artist>(.*?)</span>#i', $body, $matches))
238  {
239    $current['author'] = trim($matches[1]);
240  }
241 
242 
243  preg_match('#<head>(.*)</head>#is', $html, $matches);
244  $head = $matches[1];
245 
246  // keywords
247  if (preg_match('#<meta name="keywords" content="([^">]*)">#i', $head, $matches))
248  {
249    $words = explode(',', $matches[1]);
250    foreach ($words as $word)
251    {
252      if (!empty($word)) $current['keywords'][] = trim($word);
253    }
254  }
255 
256  return $current;
257}
258
259/**
260 * print categories tree (list or select)
261 * @param: array tree
262 * @param: int level
263 * @param: string tree type (list|select)
264 * @return: string
265 */
266function print_tree(&$tree, $level=0, $type='list')
267{
268  $out = '';
269 
270  if ($type == 'list')
271  {
272    $out.= '<ul>';
273    foreach ($tree as $item)
274    {
275      $out.= '<li>';
276      $out.= '<a href="'.$item['url'].'">'.$item['title'].'</a> ['.$item['nb_pictures'].']';
277      if (!empty($item['categories']))
278        $out.= print_tree($item['categories'], $level+1, 'list');
279      $out.= '</li>';
280    }
281    $out.= '</ul>';
282  }
283  else if ($type == 'select')
284  {
285    $i=0;
286    foreach ($tree as $item)
287    {
288      $out.= '<option value="'.$item['path'].'"';
289      if ($level==0 and $i==0) $out.= ' selected="selected"';
290      $out.= '>';
291     
292      $out.= str_repeat('&nbsp;', $level*4);
293      $out.= '- '.$item['title'].' ['.$item['nb_pictures'].']';
294     
295      $out.= '</option>';
296     
297      if (!empty($item['categories']))
298        $out.= print_tree($item['categories'], $level+1, 'select');
299       
300      $i++;
301    }
302  }
303 
304  return $out;
305}
306
307/**
308 * test if a download method is available
309 * @return: bool
310 */
311if (!function_exists('test_remote_download'))
312{
313  function test_remote_download()
314  {
315    return function_exists('curl_init') || ini_get('allow_url_fopen');
316  }
317}
318
319/**
320 * download a remote file
321 *  - needs cURL or allow_url_fopen
322 *  - take care of SSL urls
323 *
324 * @param: string source url
325 * @param: mixed destination file (if true, file content is returned)
326 */
327if (!function_exists('download_remote_file'))
328{
329  function download_remote_file($src, $dest)
330  {
331    if (empty($src))
332    {
333      return false;
334    }
335   
336    $return = ($dest === true) ? true : false;
337   
338    /* curl */
339    if (function_exists('curl_init'))
340    {
341      if (!$return)
342      {
343        $newf = fopen($dest, "wb");
344      }
345      $ch = curl_init();
346     
347      curl_setopt($ch, CURLOPT_URL, $src);
348      curl_setopt($ch, CURLOPT_HEADER, 0);
349      curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept-language: en"));
350      curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
351      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
352      curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
353      if (strpos($src, 'https://') !== false)
354      {
355        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
356        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
357      }
358      if (!$return)
359      {
360        curl_setopt($ch, CURLOPT_FILE, $newf);
361      }
362      else
363      {
364        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
365      }
366     
367      if (($out = curl_exec($ch)) === false)
368      {
369        return 'file_error';
370      }
371     
372      curl_close($ch);
373     
374      if (!$return)
375      {
376        fclose($newf);
377        return true;
378      }
379      else
380      {
381        return $out;
382      }
383    }
384    /* file get content */
385    else if (ini_get('allow_url_fopen'))
386    {
387      if (strpos($src, 'https://') !== false and !extension_loaded('openssl'))
388      {
389        return false;
390      }
391     
392      $opts = array(
393        'http' => array(
394          'method' => "GET",
395          'user_agent' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
396          'header' => "Accept-language: en",
397        )
398      );
399
400      $context = stream_context_create($opts);
401     
402      if (($file = file_get_contents($src, false, $context)) === false)
403      {
404        return 'file_error';
405      }
406     
407      if (!$return)
408      {
409        file_put_contents($dest, $file);
410        return true;
411      }
412      else
413      {
414        return $file;
415      }
416    }
417   
418    return false;
419  }
420}
421
422/**
423 * count pictures and cats in the selected cat
424 * @param: &array tree
425 * @param: string $path
426 * @param: &int nb pictures
427 * @param: &int nb categories
428 * @param: bool recursive
429 * @return: void
430 */
431function count_pictures_cats(&$tree, $path, &$nb_pictures, &$nb_categories, $recursive=true)
432{
433  $current = &get_current_cat($tree, $path);
434  $nb_pictures+= $current['nb_pictures'];
435  $nb_categories++;
436 
437  if ( $recursive and !empty($current['categories']) )
438  {
439    foreach ($current['categories'] as $cat)
440    {
441      count_pictures_cats($tree, $cat['path'], $nb_pictures, $nb_categories, $recursive);
442    }
443  }
444}
445
446/**
447 * extract unique values of the specified key in a two dimensional array
448 * @param: array
449 * @param: mixed key name
450 * @return: array
451 */
452if (!function_exists('array_unique_deep'))
453{
454  function array_unique_deep(&$array, $key)
455  {
456    $values = array();
457    foreach ($array as $k1 => $row)
458    {
459      foreach ($row as $k2 => $v)
460      {
461        if ($k2 == $key)
462        {
463          $values[ $k1 ] = $v;
464          continue;
465        }
466      }
467    }
468    return array_unique($values);
469  }
470}
471
472/**
473 * search a string in array values
474 * // http://www.strangeplanet.fr/blog/dev/php-une-fonction-pour-rechercher-dans-un-tableau
475 * @param string needle
476 * @param array haystack
477 * @param bool return all instances
478 * @param bool search in PCRE mode
479 * @return key or array of keys
480 */
481if (!function_exists('array_pos'))
482{
483  function array_pos($needle, &$haystack, $match_all=false, $preg_mode=false)
484  {
485    if ($match_all) $matches = array();
486   
487    foreach ($haystack as $i => $row)
488    {
489      if (!is_array($row))
490      {
491        if (!$preg_mode)
492        {
493          if (strpos($row, $needle) !== false)
494          {
495            if (!$match_all) return $i;
496            else array_push($matches, $i);
497          }
498        }
499        else
500        {
501          if (preg_match($needle, $row) === 1)
502          {
503            if (!$match_all) return $i;
504            else array_push($matches, $i);
505          }
506        }
507      }
508    }
509   
510    if ( !$match_all or !count($matches) ) return false;
511    return $matches;
512  }
513}
514
515?>
Note: See TracBrowser for help on using the repository browser.