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

Last change on this file since 17434 was 17434, checked in by mistic100, 12 years ago

bug with albums with close names
bug with apostrophe in albums name and description

File size: 11.4 KB
RevLine 
[17225]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);
[17434]13  $cache_id_prefix = preg_replace('#([^a-z0-9-_]+)#i', null, $cache_id_prefix);
[17225]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 */
[17314]311if (!function_exists('test_remote_download'))
[17225]312{
[17314]313  function test_remote_download()
314  {
315    return function_exists('curl_init') || ini_get('allow_url_fopen');
316  }
[17225]317}
318
319/**
320 * download a remote file
[17314]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)
[17225]326 */
[17314]327if (!function_exists('download_remote_file'))
[17225]328{
[17314]329  function download_remote_file($src, $dest)
[17225]330  {
[17314]331    if (empty($src))
[17225]332    {
[17314]333      return false;
[17225]334    }
335   
[17314]336    $return = ($dest === true) ? true : false;
[17225]337   
[17314]338    /* curl */
339    if (function_exists('curl_init'))
[17225]340    {
[17314]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      }
[17225]383    }
[17314]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    }
[17225]417   
[17314]418    return false;
[17225]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 */
[17314]452if (!function_exists('array_unique_deep'))
[17225]453{
[17314]454  function array_unique_deep(&$array, $key)
[17225]455  {
[17314]456    $values = array();
457    foreach ($array as $k1 => $row)
[17225]458    {
[17314]459      foreach ($row as $k2 => $v)
[17225]460      {
[17314]461        if ($k2 == $key)
462        {
463          $values[ $k1 ] = $v;
464          continue;
465        }
[17225]466      }
467    }
[17314]468    return array_unique($values);
[17225]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 */
[17314]481if (!function_exists('array_pos'))
[17225]482{
[17314]483  function array_pos($needle, &$haystack, $match_all=false, $preg_mode=false)
[17225]484  {
[17314]485    if ($match_all) $matches = array();
486   
487    foreach ($haystack as $i => $row)
[17225]488    {
[17314]489      if (!is_array($row))
[17225]490      {
[17314]491        if (!$preg_mode)
[17225]492        {
[17314]493          if (strpos($row, $needle) !== false)
494          {
495            if (!$match_all) return $i;
496            else array_push($matches, $i);
497          }
[17225]498        }
[17314]499        else
[17225]500        {
[17314]501          if (preg_match($needle, $row) === 1)
502          {
503            if (!$match_all) return $i;
504            else array_push($matches, $i);
505          }
[17225]506        }
507      }
508    }
[17314]509   
510    if ( !$match_all or !count($matches) ) return false;
511    return $matches;
[17225]512  }
513}
514
515?>
Note: See TracBrowser for help on using the repository browser.