source: tags/build-A01/web_service.php @ 10440

Last change on this file since 10440 was 1677, checked in by rub, 17 years ago

Feature Issue ID 0000601: Filter all public pages with only recent elements

It's a finalized version.
Obsolete code of draft are removed.

You can filter categories and images with recent date period on your screen selection.
In the future, filter could be easy done on other type data (plugin?)

You can flat categories and sub-categories with a recent date period of your choice.

Next, perhaps, a panel to choice recent date for the 2 features.

On draft, there have problem with MySql 5, be careful!

Css problem not resolved:

  • Menu "Categories" is bad centered
  • Icon on dark too on the top
File size: 20.4 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | PhpWebGallery - a PHP based picture gallery                           |
4// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
5// | Copyright (C) 2003-2006 PhpWebGallery Team - http://phpwebgallery.net |
6// +-----------------------------------------------------------------------+
7// | branch        : BSF (Best So Far)
8// | file          : $RCSfile$
9// | last update   : $Date: 2006-12-15 23:16:37 +0200 (ven., 15 dec. 2006) $
10// | last modifier : $Author: vdigital $
11// | revision      : $Revision: 1658 $
12// +-----------------------------------------------------------------------+
13// | This program is free software; you can redistribute it and/or modify  |
14// | it under the terms of the GNU General Public License as published by  |
15// | the Free Software Foundation                                          |
16// |                                                                       |
17// | This program is distributed in the hope that it will be useful, but   |
18// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
19// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
20// | General Public License for more details.                              |
21// |                                                                       |
22// | You should have received a copy of the GNU General Public License     |
23// | along with this program; if not, write to the Free Software           |
24// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
25// | USA.                                                                  |
26// +-----------------------------------------------------------------------+
27define('PHPWG_ROOT_PATH','./');
28include_once( PHPWG_ROOT_PATH.'include/common.inc.php' );
29
30if ( !$conf['allow_web_services'] )
31{
32  die('Hacking attempt!');
33}
34
35// Full call syntax sample:
36//-----------------------------------------------------------------------------
37// web_service.php?key=123456789012
38// &pos=5&acc=cat/23,25-32&req=landscape&lim=5&tpl=myxml
39
40// &pos=is position defined by caller to substring, see key below, (default 0)
41// key=substr(md5(partner_id),&pos,12)
42// &acc=cat/23,25-35 or list/1-125,136,141-162 or tag/27,45,54-55
43//      (the specified access list will be respected
44//       ONLY if access is not specified in web_services access table)
45// req=any request (except if limited to a specific one in ws access table)
46// lim=number (returned picture count and limited it self by ws access table)
47
48// the tpl file must exist in ./template/"default template"/xml/
49// tpl=myxml (xml/myxml.tpl will be used, by default: xml/default.tpl)
50
51// All are facultative EXCEPT key
52//
53
54// Check call process (Keyed call)
55//
56
57if (!isset($_GET['key'])) 
58{
59  die('Hacking attempt!');
60}
61if ( strlen($_GET['key']) < 12 )
62{
63  die('Invalid key (Length issue)!');
64}
65
66// Is service active (Temporary it could be inactive / Online parameter)
67//
68$query = '
69SELECT value FROM '.CONFIG_TABLE.'
70WHERE param = \'ws_status\'
71;';
72$active = mysql_fetch_array(pwg_query($query));
73if ( $active['value']=='false' )
74{
75  die('Web service is temporary inactive');
76}
77
78// Look for partner_key
79//
80$key = $_GET['key'];
81$key = ( strlen($key) > 20 ) ? substr($key,0,20) : $key;
82$len = strlen($key);
83$hash = 0;
84if (isset($_GET['pos']))
85{
86  $hash = (!is_numeric($_GET['pos'])) ? 0 : $_GET['pos'];
87  $hash = (int) $hash;
88  $hash = $hash % 12; 
89}
90$query = '
91SELECT `id`, `name`, `access`, `start`, `end`, `request`,
92  `high`, `normal`, `limit`, `comment`
93  FROM '.WEB_SERVICES_ACCESS_TABLE.'
94;';
95
96$result = pwg_query($query);
97
98while ($row = mysql_fetch_array($result))
99{
100  if ( substr( md5($row['name']),$hash,$len) == $key )
101  {
102    $len = 0;
103    $def = $row;
104    continue;
105  }
106}
107if ( $len > 0 )
108{
109  die('Invalid key!');
110}
111
112// $def = Web service already defined partner access
113
114//
115// Now, the partner will get a reply in time
116//
117$stat_id = 'Web Service';
118if (isset($_SERVER["HTTP_REFERER"]) and
119   !eregi($_SERVER["HTTP_HOST"],$_SERVER["HTTP_REFERER"]))
120{
121  $stats_id = substr($_SERVER["HTTP_REFERER"],7);
122  $pos = strpos($stats_id,'/');
123  $stats_id = ( $pos>0 ) ? substr($stats_id,0,$pos) : $stats_id;
124}
125
126// Check keywords
127// Key and pos are correct
128// &acc=cat/23,25-32&req=landscape&lim=5&tpl=myxml
129
130// Requested id list and authorized id list
131// Both may empty
132// Both can be build on differents basis cat/tag/list
133// Both have to be convert in id list format
134$req_access ='';
135if (isset($_GET['pos']))
136{
137  $req_access = check_target($_GET['acc']);
138}
139// on one hand $req_access, requested ids
140$req_type = explode('/',$req_access); 
141$req_ids = explode( ',',$req_type[1] );
142$req_list = expand_id_list( $req_ids ); 
143if ($req_type[0]=='cat')
144{
145  $req_list = convert_catlist($req_list);
146}
147if ($req_type[0]=='tag')
148{
149  $req_list = get_image_ids_for_tags($req_list);
150}
151// echo $def['name'].'<br />';
152// on the other hand $def['access'], authorized default ids
153$def_type = explode('/',$def['access']); 
154$def_ids = explode( ',',$def_type[1] );
155$def_list = expand_id_list( $def_ids );
156if ($def_type[0]=='cat')
157{
158  $def_list = convert_catlist($def_list);
159}
160if ($def_type[0]=='tag')
161{
162  $def_list = get_image_ids_for_tags($def_list);
163}
164
165// could be no necessary, a surplus but we are obliged to
166// Filter on forbidden_categories (default can have change from creation time)
167$list = implode(',',$def_list);
168
169$ret_ids = array();
170$query = '
171SELECT DISTINCT image_id
172  FROM '.IMAGE_CATEGORY_TABLE.'
173WHERE
174'.get_sql_condition_FandF
175  (
176    array
177      (
178        'forbidden_categories' => 'category_id',
179        'visible_categories' => 'category_id',
180        'visible_images' => 'image_id'
181      ),
182    '', true
183  ).'
184  AND  image_id IN ('.$list.')
185;';
186$result = pwg_query($query);
187while ($row = mysql_fetch_array($result))
188{
189  $ret_ids[] = $row['image_id'];
190}
191$def_ids = $ret_ids;
192
193// Notice: Filtering on forbidden_categories (from requested id list)
194// is completely superfluous (see few lines below).
195$req_ids = $req_list;
196
197// if no requested ids then is the complete default
198if (count($req_ids)==0)
199{
200  $req_ids = $def_ids;
201} 
202
203// Removing requested ids not in authorized access list
204// if requested ids they must be in the complete default and only those
205// will be assumed. (Including forbidden... )
206$final = array();
207foreach ( $req_ids as $req_id )
208{
209  if ( in_array($req_id, $def_ids) ) 
210  {
211    $final[] = $req_id; 
212  }
213}
214
215$final = array_unique ($final); 
216sort ($final);
217 
218// 77f1180bd215a0edf66939
219// web_service.php?key=77f1180bd215&pos=3&acc=list/41,73,142,178,190,204,235-238&req=recent&lim=1&tpl=myxml
220
221$request = (isset($_GET['req']))? $_GET['req']:$def['request'];
222// if type of request is different from the authorized type then force it
223if ( $def['request'] !== '' and $request !== $def['request'] )
224
225{
226  $request = $def['request'];
227}
228// if it is not an official request then force it
229// (remark that default request can no longer exist
230// (later an Upgrade, or a remove) so...
231$official = official_req();
232if ( !in_array($request, $official ) )
233{
234  $request = $official[0]; // default request is the first one
235}
236// limit belong default (remember $def['limit'] is always set)
237$limit = (isset($_GET['limit']))? $_GET['limit']:$def['limit'];
238$limit = (is_numeric($limit))? $limit:$def['limit']; 
239$limit = ( $limit < $def['limit'] ) ? $limit:$def['limit'];
240
241// XML template
242$tplfile = (isset($_GET['tpl']))? $_GET['tpl']:'default';
243// FIXME additional controls are maybe needed on $tplfile
244
245
246trigger_action('loc_begin_'.$request);
247$template->set_filenames(array( $tplfile => 'XML/'. $tplfile .'.tpl'));
248
249// Generate the request
250include(PHPWG_ROOT_PATH. 'services/' .$request. '.php');
251
252
253// +-----------------------------------------------------------------------+
254// |                       XML/xhtml code display                          |
255// +-----------------------------------------------------------------------+
256header('Content-Type: text/xml; charset=UTF-8');
257//header('Content-Type: text/html; charset='.$lang_info['charset']);
258$template->parse($tplfile);
259
260// echo '<strong>Trace temporaire<strong><br />';
261// echo '$final:<br />' . var_dump($final);
262//
263die('');
264// FIXME// FIXME// FIXME// FIXME// FIXME// FIXME// FIXME// FIXME
265
266//------------------------------------------------------------ log informations
267pwg_log($request, $stats_id, $tplfile); // or something like that
268
269
270
271
272
273
274// Check requested XML template
275//
276
277// Generate query
278//
279
280// Generate XML
281//
282
283// Log it
284//
285
286
287
288// Old code below
289
290//------------ Main security strategy ---------------------
291$partner_id = 'default';
292// Security considerations: HTTP_REFERER and FOPEN
293// 1 - FOPEN doesn't update current HTTP_REFERER
294// 2 - HTTP_REFERER may be hidden/altered for lot of reasons.
295// 3 - By this process, you can log HTTP_REFERER of your partner (not yours).
296// 4 - Logging HTTP_REFERER needs declarative procedures in some countries.
297// 5 - Following those links can be considered as risky.
298// 6 - You can turn off, referer logging by $conf['ws-refback'] = false;
299// 7 - In the other hand, your partner may give his key to another web site.
300// Above all, this information is just an indication.
301// $conf['ws-refback'] : Default value is false.
302
303if (isset($_SERVER["HTTP_REFERER"]) and
304   !eregi($_SERVER["HTTP_HOST"],$_SERVER["HTTP_REFERER"]))
305{
306  $partner_id = substr($_SERVER["HTTP_REFERER"],7);
307  $pos = strpos($partner_id,'/');
308  $partner_id = ( $pos>0 ) ? substr($partner_id,0,$pos) : $partner_id;
309} 
310// $partner_id = Is used to check prohibited REFER site (but not only)
311// example: www.prohibited-access.be
312
313if ( isset($conf['ws-refback']) and $conf['ws-refback'])
314{
315  $log_id = $partner_id;
316}
317else
318{
319  $log_id = ''; // Would be set in time by process end
320}
321// $log_id = History log information
322// examples: forum.phpwebgallery.net
323//           phpwebgallery.net
324//           demo.phpwebgallery.net
325
326//
327$partner_id = strtolower($partner_id);
328// Prohibited REFER: $partner_id is compared (strtolower).
329//
330//----------------------------- Is a prohibited refer?
331if ( $partner_id !== 'default' )
332{
333  // Is Referer a prohibited site?
334  //  Compare requestor site to web service key table
335  //  Found and limit = 0 => die
336  foreach ( $conf['ws_keys'] as $key => $vkey )
337  {
338    if ( strtolower($vkey['id']) == $partner_id and $vkey['limit'] == 0 ) 
339    {
340      pwg_log( 'WS Prohibited', 'Req.:'.$type, 'From: ws_keys['.$key.']' );
341      die($lang['access_forbiden']); 
342    }
343  }
344}
345//----------------------------- Which access he will use?
346$access = check_ws_access( $conf['ws_keys'] ); 
347// given key arg is compared asis (Take care of upper/lower case).
348
349parse_str($access['force'], $force);
350// $force contains all forced arguments
351// get requested arguments and apply limits
352$force['limit'] = ( isset($access['limit']) ) ? $access['limit'] :
353        $conf['ws_limit'] ;
354$arg = force_arg_ws_limit( $force, $conf['ws_limit'] ); 
355// $arg contains all retain query arguments
356
357// Warning about $arg !!! Warning !!! Warning !!! Warning !!! Warning !!!
358// specially to MOD developpers :
359// FOR SECURITY REASON NEVER USE extract() AGAINST $arg
360// ( $arg is like $_GET )
361
362if ( is_numeric(isset($arg['cat'])) )
363{
364  $arg['cat']=floor($arg['cat']);
365}
366else
367{
368  unset($arg['cat']);
369}
370// AND category_id is concatenated if requested or forced
371$cat_criterion = '';
372if ( isset($arg['cat']) and ($arg['cat']) > 0 )
373{
374  $cat_criterion = ' AND ic.`category_id` ='.$arg['cat'].' ';
375}
376//-------------------------------------------- SQL Query statement building
377// Has to be tested against a LARGE configuration
378// for performance consideration
379// and maybe rewrite in some cases.
380
381// All below has to be check to respect code writing rule convention
382
383
384
385$query='
386  SELECT DISTINCT (i.`id`),
387         i.`path` , i.`file` , i.`date_available` ,
388         i.`date_creation`, i.`tn_ext` , i.`name` ,
389         i.`filesize` , i.`storage_category_id` , i.`average_rate`,
390         i.`comment` , i.`author` , i.`hit` ,i.`width` ,
391         i.`height`
392     FROM `'.IMAGES_TABLE.'` AS i
393     INNER JOIN `'.IMAGE_CATEGORY_TABLE.'`
394           AS ic ON i.`id` = ic.`image_id`
395     INNER JOIN `'.CATEGORIES_TABLE.'`
396           AS c ON c.`id` = ic.`category_id`
397     WHERE c.`status` = \'public\'
398       AND i.`width` > 0
399       AND i.`height` > 0
400       AND i.`representative_ext` IS NULL
401       '.$cat_criterion.'
402       '.get_sql_condition_FandF
403         (
404            array
405             (
406               'forbidden_categories' => 'c.id',
407               'visible_categories' => 'c.id',
408               'visible_images' => 'i.id'
409              ),
410           'AND'
411         );
412
413//     AND c.`agreed_ws` = \'true\' (Obsolete specification replaced by force)
414
415$list = ( isset($arg['list']) ) ? $arg['list'] : '';
416$type = $arg['type'];
417switch($type) 
418{
419  case ($type === 'random' or $type === 'listcat'):     /* Random order */
420    $query .= ' ORDER BY RAND() DESC ';
421    break;
422  case ($type === 'list'):             /* list on MBt & z0rglub request */
423    $query .= ' AND i.`id` IN ('.$list.') ';
424    break;
425  case $type === 'maxviewed':             /* hit > 0 and hit desc order */
426    $query .= ' AND  i.`hit` > 0
427                ORDER BY i.`hit` DESC, RAND() DESC ';
428    break;
429  case $type === 'recent':        /* recent = Date_available desc order */
430    $query .= ' ORDER BY i.`date_available` DESC, RAND() DESC ';
431    break;
432  case $type === 'highrated':            /* avg_rate > 0 and desc order */
433// French Joke : Cette requete s'appelle officieusement l' "ail_gratte"
434    $query .= ' AND  i.`average_rate` > 0
435                ORDER BY i.`average_rate` DESC, RAND() DESC ';
436    break;
437  case $type === 'oldest':                  /* Date_available asc order */
438    $query .= ' ORDER BY i.`date_available` ASC, RAND() DESC ';
439    break;
440  case $type === 'lessviewed':                         /* hit asc order */
441// French Joke : Cette requete s'appelle officieusement la "lessive"
442    $query .= ' ORDER BY i.`hit` ASC, RAND() DESC ';
443    break;
444  case $type === 'lowrated':                      /* avg_rate asc order */
445    $query .= ' AND  i.`average_rate` IS NOT NULL
446                ORDER BY i.`average_rate` ASC, RAND() DESC ';
447    break;
448  case $type === 'undescribed':                  /* description missing */
449// US/UK Joke : This request is unofficially named 'indiscribable' horror
450    $query .= ' AND  i.`comment` IS NULL
451                ORDER BY RAND() DESC ';
452    break;
453  case $type === 'unnamed':                         /* new name missing */
454    $query .= ' AND  i.`comment` IS NULL
455                ORDER BY RAND() DESC ';
456    break;
457  case $type === 'portraits':     /* width < height (portrait oriented) */
458    $query .= ' AND  `width` < (`height` * 0.95)
459                ORDER BY RAND() DESC ';
460    break;
461  case $type === 'landscapes':   /* width > height (landscape oriented) */
462    $query .= ' AND `width` > (`height` * 1.05)
463                ORDER BY RAND() DESC ';
464    break;
465  case $type === 'squares':             /* width ~ height (square form) */
466    $query .= ' AND  `width` BETWEEN (`height` * 0.95)
467                                 AND (`height` * 1.05)
468                ORDER BY RAND() DESC ';
469    break;
470  default:                                     /* Just say: Goodbye !!! */
471    die($lang['access_forbiden']); 
472} /* End switch */
473$query .= ' LIMIT 0 , '.$arg['limit'].';';
474$result = pwg_query( $query );
475$attributes = array( 'width', 'height', 'author', 'date_creation',
476                    'date_available', 'hit', 'filesize');
477$xml = '<items> ';
478$hr_nbr = 0; $ns_nbr = 0; $tn_nbr = 0;
479if ( $log_id == '')
480{
481  foreach ( $conf['ws_keys'] as $key => $vkey )
482  {
483    if ( $vkey['id'] == $access['id'] ) 
484    {
485      $log_id = 'R:#'.$key; 
486      break;
487    }
488  }
489}
490while ( $row = mysql_fetch_array( $result ) )
491{
492  $tn_nbr++;
493  $item = '<item ';
494  $path = strtolower(strtok($_SERVER['SERVER_PROTOCOL'],
495    '/')).'://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'],0,-16).
496    substr($row['path'],1);
497  if ( isset($access['pwg_n']) and $access['pwg_n'] )
498  {
499    $ns_nbr++;
500    $item .= ' src="'.$path.'"'; 
501  }
502  else
503  {
504  unset($attributes['width']);
505  unset($attributes['height']);
506  unset($attributes['filesize']);
507  }
508  foreach ( $attributes as $attribute )
509  {
510    if ( isset($row{$attribute}) )
511    {
512      $item.= ' '.$attribute.'="'.$row{$attribute}.'"';
513    }
514  }
515  if ( isset($row['comment']) ) 
516  {
517    $item .= ' description="'.$row['comment'].'"';
518  }
519  $tnsrc = get_thumbnail_src( $path, $row['tn_ext'] ); 
520  $item .= ' tnsrc="'.$tnsrc.'"';
521  $tnsize = @getimagesize($tnsrc);
522  $item .= ' tnwidth="'.$tnsize[0].'"';
523  $item .= ' tnheight="'.$tnsize[1].'"';
524  if ( isset($access['pwg_h']) and $access['pwg_h'] )
525  { 
526    $high = dirname( $path ).'/pwg_high/'.$row['file'];
527    $hrsize = @getimagesize($high);
528    if ( $hrsize[0] > 0 ) 
529    {
530      $hr_nbr++;
531      $item .= ' hrsrc="'.$high.'"';
532      $item .= ' hrwidth="'.$hrsize[0].'"';
533      $item .= ' hrheight="'.$hrsize[1].'"';
534    }
535  }
536  $xml .= $item.' />';
537  //-------------------------------------- picture ----- log informations
538//      request_type ( R:#id_requester ),  real_category_id [ request_number ],   image_file_name );
539  pwg_log( $type.'('.$log_id.')',       $row['storage_category_id'].'['.$tn_nbr.']',      $row['file'] );
540}
541$xml .= ' </items>';
542echo $xml; // Send XML
543//---------------------------------------- service ----- log informations
544$size = 'tn('.$tn_nbr.')'; // thumbnails
545if ( $ns_nbr > 0 )
546{
547  $size = '('.$ns_nbr.')'; // pictures
548}
549if  ( $hr_nbr > 0 )
550{
551  $size = 'HR('.$hr_nbr.'/'.$tn_nbr.')'; // high res.
552}
553
554//pwg_log( 'Web service',          'Req.:'.$type,                 'From:'.$log_id );
555
556
557
558
559
560
561  /*-- Web Service function
562  Which access is correct for this resquest?
563  Compare requestor key to  web service key table
564  If 'defined' => use that one
565  If not => use default access
566  If no 'defined' default => exit
567  'defined' : Obviously check period and not only defined access
568 
569  Return corresponding access (= an entry from web service key table)
570  --*/
571function check_ws_access( $ws_keys )
572{
573  $partnr = ( isset($_GET['key']) ) ? $_GET['key'] : 'default'; 
574   
575  foreach ( $ws_keys as $key => $access )
576  {
577    if ( $access['id'] == $partnr ) 
578    {
579      break; 
580    }
581  }
582  if ( $access['id'] !== $partnr )            // Not found? =default.
583  {
584    $access = $ws_keys[0];
585    if ( $access['id'] !== 'default' )    // Check if it's really default
586    {                                     // definition
587      die($lang['access_forbiden']);      // No default access
588    }
589  }
590  // Checking Dates...
591  // Take care of that: my partner can be out of dates
592  //   but via default... Answer is NO.
593  // With out of date period, a partner can be seen as prohibited partner
594  //   if you want to authorise him/her change $conf['ws_keys']
595   
596  // Tests are done with server local time...
597  if (isset($access['end']) and date('Y-m-d H:i:s')>$access['end']) 
598  {                                            //-- Access ended?
599     die($lang['access_forbiden']);            //-- BTW prohibited     
600  }
601  if (isset($access['start']) and date('Y-m-d H:i:s')<$access['start'])
602  {                                            //-- Access started?
603    die($lang['access_forbiden']);
604  }
605  return $access;
606}
607
608  /*-- Web Sevice function
609  Force global arguments to ensure access restriction
610  ( access defined in web service key table )
611  Considering the default limit as well and prohibited site case
612 
613  Return overided request ( overided $_GET )
614  --*/
615function force_arg_ws_limit( $use, $default )
616{
617  if ( $use['limit'] < 1 )
618  {                                            //-- Access deny
619    die($lang['access_forbiden']);
620  }
621  $arg = $_GET;             // what is required?
622  if (!isset($arg['limit']))
623  {
624    $arg['limit']=$use['limit'];
625  }
626  if (!is_numeric($arg['limit']))
627  {
628    $arg['limit']=$use['limit'];
629  }
630  // ----------- use force arg if they are some
631  foreach ( $use as $kuse => $vuse )
632  {
633    if ( $kuse !== 'limit' )
634    {
635      $arg[$kuse] = $vuse;
636    }
637  }
638  $arg['limit'] = floor(min($arg['limit'], $use['limit']));
639  return $arg;
640}
641?>
Note: See TracBrowser for help on using the repository browser.