source: trunk/include/ws_functions.inc.php @ 2481

Last change on this file since 2481 was 2463, checked in by plg, 16 years ago

feature 839, first step : early proof of concept, no error handling. A
remote client can add a photo in a category thanks to the web API. A new
"upload" directory is created (write access required on the base
directory). Uploaded photo have path such as
upload/<year>/<month>/<day>/<datetime>-random.jpg. The thumbnail must come
with the "web sized" photo. The photo has no storage_category_id.

Bugs still need to be fixed and a discussion must occur before next steps.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 34.1 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based picture gallery                                  |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008      Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24/**** IMPLEMENTATION OF WEB SERVICE METHODS ***********************************/
25
26/**
27 * Event handler for method invocation security check. Should return a PwgError
28 * if the preconditions are not satifsied for method invocation.
29 */
30function ws_isInvokeAllowed($res, $methodName, $params)
31{
32  global $conf, $calling_partner_id;
33
34  if ( strpos($methodName,'reflection.')===0 )
35  { // OK for reflection
36    return $res;
37  }
38
39  if ( !is_autorize_status(ACCESS_GUEST) and
40      strpos($methodName,'pwg.session.')!==0 )
41  {
42    return new PwgError(401, 'Access denied');
43  }
44
45  if ( !$conf['ws_access_control'] )
46  {
47    return $res; // No controls are requested
48  }
49  $query = '
50SELECT * FROM '.WEB_SERVICES_ACCESS_TABLE."
51 WHERE `name` = '$calling_partner_id'
52   AND NOW() <= end; ";
53  $result = pwg_query($query);
54  $row = mysql_fetch_assoc($result);
55  if ( empty($row) )
56  {
57    return new PwgError(403, 'Partner id does not exist or is expired');
58  }
59  if ( !empty($row['request'])
60      and strpos($methodName, $row['request'])==false
61      and strpos($methodName, 'session')==false
62      and strpos($methodName, 'getVersion')==false )
63  { // session and getVersion are allowed to diagnose any failure reason
64    return new PwgError(403, 'Method not allowed');
65  }
66
67  return $res;
68}
69
70/**
71 * ws_addControls
72 * returns additionnal controls if requested
73 * usable for 99% of Web Service methods
74 *
75 * - Args
76 * $methodName: is the requested method
77 * $partner: is the key
78 * $tbl_name: is the alias_name in the query (sometimes called correlation name)
79 *            null if !getting picture informations
80 * - Logic
81 * Access_control is not active: Return
82 * Key is incorrect: Return 0 = 1 (False condition for MySQL)
83 * One of Params doesn't match with type of request: return 0 = 1 again
84 * Access list(id/cat/tag) is converted in expended image-id list
85 * image-id list: converted to an in-where-clause
86 *
87 * The additionnal in-where-clause is return
88 */
89function ws_addControls( $methodName, &$params, $tbl_name )
90{
91  global $conf, $calling_partner_id;
92  if ( !$conf['ws_access_control'] or !isset($calling_partner_id) )
93  {
94    return '1=1'; // No controls are requested
95  }
96
97// Is it an active Partner?
98  $query = '
99SELECT * FROM '.WEB_SERVICES_ACCESS_TABLE."
100 WHERE `name` = '$calling_partner_id'
101   AND NOW() <= end; ";
102$result = pwg_query($query);
103  if ( mysql_num_rows( $result ) == 0 )
104  {
105    return '0=1'; // Unknown partner or Obsolate agreement
106  }
107
108  $row = mysql_fetch_array($result);
109
110// Overide general object limit
111  $params['per_page'] = $row['limit'];
112
113// Target restrict
114// 3 cases: list, cat or tag
115// Behind / we could found img-ids, cat-ids or tag-ids
116  $target = $row['access'];
117  if ( $target == '')
118  {
119    return '1=1'; // No controls are requested
120  }
121  list($type, $str_ids) = explode('/',$target); // Find type list
122
123// (array) 1,2,21,3,22,4,5,9-12,6,11,12,13,2,4,6,
124  $arr_ids = expand_id_list( explode( ',',$str_ids ) );
125  $addings = implode(',', $arr_ids);
126// (string) 1,2,3,4,5,6,9,10,11,12,13,21,22,
127  if ( $type == 'list')
128  {
129    return $tbl_name . 'id IN ( ' . $addings . ' ) ';
130  }
131
132  if ( $type == 'cat' )
133  {
134    $addings = implode(',', get_image_ids_for_cats($arr_ids));
135    return $tbl_name . 'id IN ( ' . $addings . ' ) ';
136  }
137
138  if ( $type == 'tag' )
139  {
140    $addings = implode(',', get_image_ids_for_tags($arr_ids, 'OR'));
141    return $tbl_name . 'id IN ( ' . $addings . ' ) ';
142  }
143  // Unmanaged new type?
144  return ' 0 = 1 '; // ???
145}
146
147/**
148 * returns a "standard" (for our web service) array of sql where clauses that
149 * filters the images (images table only)
150 */
151function ws_std_image_sql_filter( $params, $tbl_name='' )
152{
153  $clauses = array();
154  if ( is_numeric($params['f_min_rate']) )
155  {
156    $clauses[] = $tbl_name.'average_rate>'.$params['f_min_rate'];
157  }
158  if ( is_numeric($params['f_max_rate']) )
159  {
160    $clauses[] = $tbl_name.'average_rate<='.$params['f_max_rate'];
161  }
162  if ( is_numeric($params['f_min_hit']) )
163  {
164    $clauses[] = $tbl_name.'hit>'.$params['f_min_hit'];
165  }
166  if ( is_numeric($params['f_max_hit']) )
167  {
168    $clauses[] = $tbl_name.'hit<='.$params['f_max_hit'];
169  }
170  if ( isset($params['f_min_date_posted']) )
171  {
172    $clauses[] = $tbl_name."date_available>='".$params['f_min_date_posted']."'";
173  }
174  if ( isset($params['f_max_date_posted']) )
175  {
176    $clauses[] = $tbl_name."date_available<'".$params['f_max_date_posted']."'";
177  }
178  if ( isset($params['f_min_date_created']) )
179  {
180    $clauses[] = $tbl_name."date_creation>='".$params['f_min_date_created']."'";
181  }
182  if ( isset($params['f_max_date_created']) )
183  {
184    $clauses[] = $tbl_name."date_creation<'".$params['f_max_date_created']."'";
185  }
186  if ( is_numeric($params['f_min_ratio']) )
187  {
188    $clauses[] = $tbl_name.'width/'.$tbl_name.'height>'.$params['f_min_ratio'];
189  }
190  if ( is_numeric($params['f_max_ratio']) )
191  {
192    $clauses[] = $tbl_name.'width/'.$tbl_name.'height<='.$params['f_max_ratio'];
193  }
194  if ( $params['f_with_thumbnail'] )
195  {
196    $clauses[] = $tbl_name.'tn_ext IS NOT NULL';
197  }
198  return $clauses;
199}
200
201/**
202 * returns a "standard" (for our web service) ORDER BY sql clause for images
203 */
204function ws_std_image_sql_order( $params, $tbl_name='' )
205{
206  $ret = '';
207  if ( empty($params['order']) )
208  {
209    return $ret;
210  }
211  $matches = array();
212  preg_match_all('/([a-z_]+) *(?:(asc|desc)(?:ending)?)? *(?:, *|$)/i',
213    $params['order'], $matches);
214  for ($i=0; $i<count($matches[1]); $i++)
215  {
216    switch ($matches[1][$i])
217    {
218      case 'date_created':
219        $matches[1][$i] = 'date_creation'; break;
220      case 'date_posted':
221        $matches[1][$i] = 'date_available'; break;
222      case 'rand': case 'random':
223        $matches[1][$i] = 'RAND()'; break;
224    }
225    $sortable_fields = array('id', 'file', 'name', 'hit', 'average_rate',
226      'date_creation', 'date_available', 'RAND()' );
227    if ( in_array($matches[1][$i], $sortable_fields) )
228    {
229      if (!empty($ret))
230        $ret .= ', ';
231      if ($matches[1][$i] != 'RAND()' )
232      {
233        $ret .= $tbl_name;
234      }
235      $ret .= $matches[1][$i];
236      $ret .= ' '.$matches[2][$i];
237    }
238  }
239  return $ret;
240}
241
242/**
243 * returns an array map of urls (thumb/element) for image_row - to be returned
244 * in a standard way by different web service methods
245 */
246function ws_std_get_urls($image_row)
247{
248  $ret = array(
249    'tn_url' => get_thumbnail_url($image_row),
250    'element_url' => get_element_url($image_row)
251  );
252  global $user;
253  if ($user['enabled_high'] and $image_row['has_high'] )
254  {
255    $ret['high_url'] = get_high_url($image_row);
256  }
257  return $ret;
258}
259
260/**
261 * returns an array of image attributes that are to be encoded as xml attributes
262 * instead of xml elements
263 */
264function ws_std_get_image_xml_attributes()
265{
266  return array(
267    'id','tn_url','element_url','high_url', 'file','width','height','hit'
268    );
269}
270
271/**
272 * returns PWG version (web service method)
273 */
274function ws_getVersion($params, &$service)
275{
276  global $conf;
277  if ($conf['show_version'])
278    return PHPWG_VERSION;
279  else
280    return new PwgError(403, 'Forbidden');
281}
282
283function ws_caddie_add($params, &$service)
284{
285  if (!is_admin())
286  {
287    return new PwgError(401, 'Access denied');
288  }
289  if ( empty($params['image_id']) )
290  {
291    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id");
292  }
293  global $user;
294  $query = '
295SELECT id
296  FROM '.IMAGES_TABLE.' LEFT JOIN '.CADDIE_TABLE.' ON id=element_id AND user_id='.$user['id'].'
297  WHERE id IN ('.implode(',',$params['image_id']).')
298    AND element_id IS NULL';
299  $datas = array();
300  foreach ( array_from_query($query, 'id') as $id )
301  {
302    array_push($datas, array('element_id'=>$id, 'user_id'=>$user['id']) );
303  }
304  if (count($datas))
305  {
306    include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
307    mass_inserts(CADDIE_TABLE, array('element_id','user_id'), $datas);
308  }
309  return count($datas);
310}
311
312/**
313 * returns images per category (web service method)
314 */
315function ws_categories_getImages($params, &$service)
316{
317  @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
318  global $user, $conf;
319
320  $images = array();
321
322  //------------------------------------------------- get the related categories
323  $where_clauses = array();
324  foreach($params['cat_id'] as $cat_id)
325  {
326    $cat_id = (int)$cat_id;
327    if ($cat_id<=0)
328      continue;
329    if ($params['recursive'])
330    {
331      $where_clauses[] = 'uppercats REGEXP \'(^|,)'.$cat_id.'(,|$)\'';
332    }
333    else
334    {
335      $where_clauses[] = 'id='.$cat_id;
336    }
337  }
338  if (!empty($where_clauses))
339  {
340    $where_clauses = array( '('.
341    implode('
342    OR ', $where_clauses) . ')'
343      );
344  }
345  $where_clauses[] = get_sql_condition_FandF(
346        array('forbidden_categories' => 'id'),
347        NULL, true
348      );
349
350  $query = '
351SELECT id, name, permalink, image_order
352  FROM '.CATEGORIES_TABLE.'
353  WHERE '. implode('
354    AND ', $where_clauses);
355  $result = pwg_query($query);
356  $cats = array();
357  while ($row = mysql_fetch_assoc($result))
358  {
359    $row['id'] = (int)$row['id'];
360    $cats[ $row['id'] ] = $row;
361  }
362
363  //-------------------------------------------------------- get the images
364  if ( !empty($cats) )
365  {
366    $where_clauses = ws_std_image_sql_filter( $params, 'i.' );
367    $where_clauses[] = 'category_id IN ('
368      .implode(',', array_keys($cats) )
369      .')';
370    $where_clauses[] = get_sql_condition_FandF( array(
371          'visible_images' => 'i.id'
372        ), null, true
373      );
374    $where_clauses[] = ws_addControls( 'categories.getImages', $params, 'i.' );
375
376    $order_by = ws_std_image_sql_order($params, 'i.');
377    if ( empty($order_by)
378          and count($params['cat_id'])==1
379          and isset($cats[ $params['cat_id'][0] ]['image_order'])
380        )
381    {
382      $order_by = $cats[ $params['cat_id'][0] ]['image_order'];
383    }
384    $order_by = empty($order_by) ? $conf['order_by'] : 'ORDER BY '.$order_by;
385
386    $query = '
387SELECT i.*, GROUP_CONCAT(category_id) cat_ids
388  FROM '.IMAGES_TABLE.' i
389    INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id
390  WHERE '. implode('
391    AND ', $where_clauses).'
392GROUP BY i.id
393'.$order_by.'
394LIMIT '.$params['per_page']*$params['page'].','.$params['per_page'];
395
396    $result = pwg_query($query);
397    while ($row = mysql_fetch_assoc($result))
398    {
399      $image = array();
400      foreach ( array('id', 'width', 'height', 'hit') as $k )
401      {
402        if (isset($row[$k]))
403        {
404          $image[$k] = (int)$row[$k];
405        }
406      }
407      foreach ( array('file', 'name', 'comment') as $k )
408      {
409        $image[$k] = $row[$k];
410      }
411      $image = array_merge( $image, ws_std_get_urls($row) );
412
413      $image_cats = array();
414      foreach ( explode(',', $row['cat_ids']) as $cat_id )
415      {
416        $url = make_index_url(
417                array(
418                  'category' => $cats[$cat_id],
419                  )
420                );
421        $page_url = make_picture_url(
422                array(
423                  'category' => $cats[$cat_id],
424                  'image_id' => $row['id'],
425                  'image_file' => $row['file'],
426                  )
427                );
428        array_push( $image_cats,  array(
429              WS_XML_ATTRIBUTES => array (
430                  'id' => (int)$cat_id,
431                  'url' => $url,
432                  'page_url' => $page_url,
433                )
434            )
435          );
436      }
437
438      $image['categories'] = new PwgNamedArray(
439            $image_cats,'category', array('id','url','page_url')
440          );
441      array_push($images, $image);
442    }
443  }
444
445  return array( 'images' =>
446    array (
447      WS_XML_ATTRIBUTES =>
448        array(
449            'page' => $params['page'],
450            'per_page' => $params['per_page'],
451            'count' => count($images)
452          ),
453       WS_XML_CONTENT => new PwgNamedArray($images, 'image',
454          ws_std_get_image_xml_attributes() )
455      )
456    );
457}
458
459
460/**
461 * returns a list of categories (web service method)
462 */
463function ws_categories_getList($params, &$service)
464{
465  global $user,$conf;
466
467  $where = array();
468
469  if (!$params['recursive'])
470  {
471    if ($params['cat_id']>0)
472      $where[] = '(id_uppercat='.(int)($params['cat_id']).'
473    OR id='.(int)($params['cat_id']).')';
474    else
475      $where[] = 'id_uppercat IS NULL';
476  }
477  else if ($params['cat_id']>0)
478  {
479    $where[] = 'uppercats REGEXP \'(^|,)'.
480      (int)($params['cat_id'])
481      .'(,|$)\'';
482  }
483
484  if ($params['public'])
485  {
486    $where[] = 'status = "public"';
487    $where[] = 'visible = "true"';
488    $where[]= 'user_id='.$conf['guest_id'];
489  }
490  else
491  {
492    $where[]= 'user_id='.$user['id'];
493  }
494
495  $query = '
496SELECT id, name, permalink, uppercats, global_rank,
497    nb_images, count_images AS total_nb_images,
498    date_last, max_date_last, count_categories AS nb_categories
499  FROM '.CATEGORIES_TABLE.'
500   INNER JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id
501  WHERE '. implode('
502    AND ', $where);
503
504  $result = pwg_query($query);
505
506  $cats = array();
507  while ($row = mysql_fetch_assoc($result))
508  {
509    $row['url'] = make_index_url(
510        array(
511          'category' => $row
512          )
513      );
514    foreach( array('id','nb_images','total_nb_images','nb_categories') as $key)
515    {
516      $row[$key] = (int)$row[$key];
517    }
518    array_push($cats, $row);
519  }
520  usort($cats, 'global_rank_compare');
521  return array(
522      'categories' =>
523          new PwgNamedArray($cats,'category',
524            array('id','url','nb_images','total_nb_images','nb_categories','date_last','max_date_last')
525          )
526    );
527}
528
529
530/**
531 * returns detailed information for an element (web service method)
532 */
533function ws_images_addComment($params, &$service)
534{
535  if (!$service->isPost())
536  {
537    return new PwgError(405, "This method requires HTTP POST");
538  }
539  $params['image_id'] = (int)$params['image_id'];
540  $query = '
541SELECT DISTINCT image_id
542  FROM '.IMAGE_CATEGORY_TABLE.' INNER JOIN '.CATEGORIES_TABLE.' ON category_id=id
543  WHERE commentable="true"
544    AND image_id='.$params['image_id'].
545    get_sql_condition_FandF(
546      array(
547        'forbidden_categories' => 'id',
548        'visible_categories' => 'id',
549        'visible_images' => 'image_id'
550      ),
551      ' AND'
552    );
553  if ( !mysql_num_rows( pwg_query( $query ) ) )
554  {
555    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id");
556  }
557
558  include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
559
560  $comm = array(
561    'author' => trim( stripslashes($params['author']) ),
562    'content' => trim( stripslashes($params['content']) ),
563    'image_id' => $params['image_id'],
564   );
565
566  include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
567
568  $comment_action = insert_user_comment(
569      $comm, $params['key'], $infos
570    );
571
572  switch ($comment_action)
573  {
574    case 'reject':
575      array_push($infos, l10n('comment_not_added') );
576      return new PwgError(403, implode("\n", $infos) );
577    case 'validate':
578    case 'moderate':
579      $ret = array(
580          'id' => $comm['id'],
581          'validation' => $comment_action=='validate',
582        );
583      return new PwgNamedStruct(
584          'comment',
585          $ret,
586          null, array()
587        );
588    default:
589      return new PwgError(500, "Unknown comment action ".$comment_action );
590  }
591}
592
593/**
594 * returns detailed information for an element (web service method)
595 */
596function ws_images_getInfo($params, &$service)
597{
598  @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
599  global $user, $conf;
600  $params['image_id'] = (int)$params['image_id'];
601  if ( $params['image_id']<=0 )
602  {
603    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id");
604  }
605
606  $query='
607SELECT * FROM '.IMAGES_TABLE.'
608  WHERE id='.$params['image_id'].
609    get_sql_condition_FandF(
610      array('visible_images' => 'id'),
611      ' AND'
612    ).' AND '.
613    ws_addControls( 'images.getInfo', $params, '' ).'
614LIMIT 1;';
615
616  $image_row = mysql_fetch_assoc(pwg_query($query));
617  if ($image_row==null)
618  {
619    return new PwgError(404, "image_id not found");
620  }
621  $image_row = array_merge( $image_row, ws_std_get_urls($image_row) );
622
623  //-------------------------------------------------------- related categories
624  $query = '
625SELECT id, name, permalink, uppercats, global_rank, commentable
626  FROM '.IMAGE_CATEGORY_TABLE.'
627    INNER JOIN '.CATEGORIES_TABLE.' ON category_id = id
628  WHERE image_id = '.$image_row['id'].
629  get_sql_condition_FandF(
630      array( 'forbidden_categories' => 'category_id' ),
631      ' AND'
632    ).'
633;';
634  $result = pwg_query($query);
635  $is_commentable = false;
636  $related_categories = array();
637  while ($row = mysql_fetch_assoc($result))
638  {
639    if ($row['commentable']=='true')
640    {
641      $is_commentable = true;
642    }
643    unset($row['commentable']);
644    $row['url'] = make_index_url(
645        array(
646          'category' => $row
647          )
648      );
649
650    $row['page_url'] = make_picture_url(
651        array(
652          'image_id' => $image_row['id'],
653          'image_file' => $image_row['file'],
654          'category' => $row
655          )
656      );
657    $row['id']=(int)$row['id'];
658    array_push($related_categories, $row);
659  }
660  usort($related_categories, 'global_rank_compare');
661  if ( empty($related_categories) )
662  {
663    return new PwgError(401, 'Access denied');
664  }
665
666  //-------------------------------------------------------------- related tags
667  $related_tags = get_common_tags( array($image_row['id']), -1 );
668  foreach( $related_tags as $i=>$tag)
669  {
670    $tag['url'] = make_index_url(
671        array(
672          'tags' => array($tag)
673          )
674      );
675    $tag['page_url'] = make_picture_url(
676        array(
677          'image_id' => $image_row['id'],
678          'image_file' => $image_row['file'],
679          'tags' => array($tag),
680          )
681      );
682    unset($tag['counter']);
683    $tag['id']=(int)$tag['id'];
684    $related_tags[$i]=$tag;
685  }
686  //------------------------------------------------------------- related rates
687  $query = '
688SELECT COUNT(rate) AS count
689     , ROUND(AVG(rate),2) AS average
690     , ROUND(STD(rate),2) AS stdev
691  FROM '.RATE_TABLE.'
692  WHERE element_id = '.$image_row['id'].'
693;';
694  $rating = mysql_fetch_assoc(pwg_query($query));
695  $rating['count'] = (int)$rating['count'];
696
697  //---------------------------------------------------------- related comments
698  $related_comments = array();
699
700  $where_comments = 'image_id = '.$image_row['id'];
701  if ( !is_admin() )
702  {
703    $where_comments .= '
704    AND validated="true"';
705  }
706
707  $query = '
708SELECT COUNT(id) nb_comments
709  FROM '.COMMENTS_TABLE.'
710  WHERE '.$where_comments;
711  list($nb_comments) = array_from_query($query, 'nb_comments');
712  $nb_comments = (int)$nb_comments;
713
714  if ( $nb_comments>0 and $params['comments_per_page']>0 )
715  {
716    $query = '
717SELECT id, date, author, content
718  FROM '.COMMENTS_TABLE.'
719  WHERE '.$where_comments.'
720  ORDER BY date
721  LIMIT '.$params['comments_per_page']*(int)$params['comments_page'].
722    ','.$params['comments_per_page'];
723
724    $result = pwg_query($query);
725    while ($row = mysql_fetch_assoc($result))
726    {
727      $row['id']=(int)$row['id'];
728      array_push($related_comments, $row);
729    }
730  }
731
732  $comment_post_data = null;
733  if ($is_commentable and
734      (!is_a_guest()
735        or (is_a_guest() and $conf['comments_forall'] )
736      )
737      )
738  {
739    include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
740    $comment_post_data['author'] = $user['username'];
741    $comment_post_data['key'] = get_comment_post_key($params['image_id']);
742  }
743
744  $ret = $image_row;
745  foreach ( array('id','width','height','hit','filesize') as $k )
746  {
747    if (isset($ret[$k]))
748    {
749      $ret[$k] = (int)$ret[$k];
750    }
751  }
752  foreach ( array('path', 'storage_category_id') as $k )
753  {
754    unset($ret[$k]);
755  }
756
757  $ret['rates'] = array( WS_XML_ATTRIBUTES => $rating );
758  $ret['categories'] = new PwgNamedArray($related_categories, 'category', array('id','url', 'page_url') );
759  $ret['tags'] = new PwgNamedArray($related_tags, 'tag', array('id','url_name','url','page_url') );
760  if ( isset($comment_post_data) )
761  {
762    $ret['comment_post'] = array( WS_XML_ATTRIBUTES => $comment_post_data );
763  }
764  $ret['comments'] = array(
765     WS_XML_ATTRIBUTES =>
766        array(
767          'page' => $params['comments_page'],
768          'per_page' => $params['comments_per_page'],
769          'count' => count($related_comments),
770          'nb_comments' => $nb_comments,
771        ),
772     WS_XML_CONTENT => new PwgNamedArray($related_comments, 'comment', array('id','date') )
773      );
774
775  return new PwgNamedStruct('image',$ret, null, array('name','comment') );
776}
777
778
779/**
780 * rates the image_id in the parameter
781 */
782function ws_images_Rate($params, &$service)
783{
784  $image_id = (int)$params['image_id'];
785  $query = '
786SELECT DISTINCT id FROM '.IMAGES_TABLE.'
787  INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=image_id
788  WHERE id='.$image_id
789  .get_sql_condition_FandF(
790    array(
791        'forbidden_categories' => 'category_id',
792        'forbidden_images' => 'id',
793      ),
794    '    AND'
795    ).'
796    LIMIT 1';
797  if ( mysql_num_rows( pwg_query($query) )==0 )
798  {
799    return new PwgError(404, "Invalid image_id or access denied" );
800  }
801  $rate = (int)$params['rate'];
802  include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
803  $res = rate_picture( $image_id, $rate );
804  if ($res==false)
805  {
806    global $conf;
807    return new PwgError( 403, "Forbidden or rate not in ". implode(',',$conf['rate_items']));
808  }
809  return $res;
810}
811
812
813/**
814 * returns a list of elements corresponding to a query search
815 */
816function ws_images_search($params, &$service)
817{
818  global $page;
819  $images = array();
820  include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' );
821  include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
822
823  $where_clauses = ws_std_image_sql_filter( $params, 'i.' );
824  $order_by = ws_std_image_sql_order($params, 'i.');
825
826  $super_order_by = false;
827  if ( !empty($order_by) )
828  {
829    global $conf;
830    $conf['order_by'] = 'ORDER BY '.$order_by;
831    $super_order_by=true; // quick_search_result might be faster
832  }
833
834  $search_result = get_quick_search_results($params['query'],
835      $super_order_by,
836      implode(',', $where_clauses)
837    );
838
839  $image_ids = array_slice(
840      $search_result['items'],
841      $params['page']*$params['per_page'],
842      $params['per_page']
843    );
844
845  if ( count($image_ids) )
846  {
847    $query = '
848SELECT * FROM '.IMAGES_TABLE.'
849  WHERE id IN ('.implode(',', $image_ids).')';
850
851    $image_ids = array_flip($image_ids);
852    $result = pwg_query($query);
853    while ($row = mysql_fetch_assoc($result))
854    {
855      $image = array();
856      foreach ( array('id', 'width', 'height', 'hit') as $k )
857      {
858        if (isset($row[$k]))
859        {
860          $image[$k] = (int)$row[$k];
861        }
862      }
863      foreach ( array('file', 'name', 'comment') as $k )
864      {
865        $image[$k] = $row[$k];
866      }
867      $image = array_merge( $image, ws_std_get_urls($row) );
868      $images[$image_ids[$image['id']]] = $image;
869    }
870    ksort($images, SORT_NUMERIC);
871    $images = array_values($images);
872  }
873
874
875  return array( 'images' =>
876    array (
877      WS_XML_ATTRIBUTES =>
878        array(
879            'page' => $params['page'],
880            'per_page' => $params['per_page'],
881            'count' => count($images)
882          ),
883       WS_XML_CONTENT => new PwgNamedArray($images, 'image',
884          ws_std_get_image_xml_attributes() )
885      )
886    );
887}
888
889function ws_images_setPrivacyLevel($params, &$service)
890{
891  if (!is_admin() || is_adviser() )
892  {
893    return new PwgError(401, 'Access denied');
894  }
895  if ( empty($params['image_id']) )
896  {
897    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id");
898  }
899  global $conf;
900  if ( !in_array( (int)$params['level'], $conf['available_permission_levels']) )
901  {
902    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid level");
903  }
904  $query = '
905UPDATE '.IMAGES_TABLE.'
906  SET level='.(int)$params['level'].'
907  WHERE id IN ('.implode(',',$params['image_id']).')';
908  $result = pwg_query($query);
909  $affected_rows = mysql_affected_rows();
910  if ($affected_rows)
911  {
912    include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
913    invalidate_user_cache();
914  }
915  return $affected_rows;
916}
917
918function ws_images_add($params, &$service)
919{
920  global $conf;
921 
922  // name
923  // category_id
924  // file_content
925  // file_sum
926  // thumbnail_content
927  // thumbnail_sum
928 
929  // $fh_log = fopen('/tmp/php.log', 'w');
930  // fwrite($fh_log, time()."\n");
931  // fwrite($fh_log, 'input:  '.$params['file_sum']."\n");
932  // fwrite($fh_log, 'input:  '.$params['thumbnail_sum']."\n");
933
934  // current date
935  list($dbnow) = mysql_fetch_row(pwg_query('SELECT NOW();'));
936  list($year, $month, $day) = preg_split('/[^\d]/', $dbnow, 4);
937 
938  $upload_dir = sprintf(
939    PHPWG_ROOT_PATH.'upload/%s/%s/%s',
940    $year,
941    $month,
942    $day
943    );
944
945  fwrite($fh_log, $upload_dir."\n");
946 
947  if (!is_dir($upload_dir)) {
948    umask(0000);
949    $recursive = true;
950    mkdir($upload_dir, 0777, $recursive);
951  }
952
953  $date_string = preg_replace('/[^\d]/', '', $dbnow);
954  $random_string = substr($params['file_sum'], 0, 8);
955
956  $filename_wo_ext = $date_string.'-'.$random_string;
957 
958  $file_path = $upload_dir.'/'.$filename_wo_ext.'.jpg';
959  $fh_file = fopen($file_path, 'w');
960  fwrite($fh_file, base64_decode($params['file_content']));
961  fclose($fh_file);
962
963  // check dumped file md5sum with expected md5sum
964
965  $thumbnail_dir = $upload_dir.'/thumbnail';
966  if (!is_dir($thumbnail_dir)) {
967    umask(0000);
968    mkdir($thumbnail_dir, 0777);
969  }
970 
971  $thumbnail_path = sprintf(
972    '%s/%s%s.%s',
973    $thumbnail_dir,
974    $conf['prefix_thumbnail'],
975    $filename_wo_ext,
976    'jpg'
977    );
978  $fh_thumbnail = fopen($thumbnail_path, 'w');
979  fwrite($fh_thumbnail, base64_decode($params['thumbnail_content']));
980  fclose($fh_thumbnail);
981
982  // check dumped thumbnail md5
983
984  // fwrite($fh_log, 'output: '.md5_file($file_path)."\n");
985  // fwrite($fh_log, 'output: '.md5_file($thumbnail_path)."\n");
986
987  // database registration
988  $insert = array(
989    'file' => $filename_wo_ext.'.jpg',
990    'date_available' => $dbnow,
991    'tn_ext' => 'jpg',
992    'name' => $params['name'],
993    'path' => $file_path,
994    );
995
996  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
997  mass_inserts(
998    IMAGES_TABLE,
999    array_keys($insert),
1000    array($insert)
1001    );
1002
1003  $image_id = mysql_insert_id();
1004
1005  $insert = array(
1006    'category_id' => $params['category_id'],
1007    'image_id'=> $image_id,
1008    );
1009  mass_inserts(
1010    IMAGE_CATEGORY_TABLE,
1011    array_keys($insert),
1012    array($insert)
1013    );
1014 
1015  // fclose($fh_log);
1016}
1017
1018/**
1019 * perform a login (web service method)
1020 */
1021function ws_session_login($params, &$service)
1022{
1023  global $conf;
1024
1025  if (!$service->isPost())
1026  {
1027    return new PwgError(405, "This method requires HTTP POST");
1028  }
1029  if (try_log_user($params['username'], $params['password'],false))
1030  {
1031    return true;
1032  }
1033  return new PwgError(999, 'Invalid username/password');
1034}
1035
1036
1037/**
1038 * performs a logout (web service method)
1039 */
1040function ws_session_logout($params, &$service)
1041{
1042  global $user, $conf;
1043  if (!is_a_guest())
1044  {
1045    $_SESSION = array();
1046    session_unset();
1047    session_destroy();
1048    setcookie(session_name(),'',0,
1049        ini_get('session.cookie_path'),
1050        ini_get('session.cookie_domain')
1051      );
1052    setcookie($conf['remember_me_name'], '', 0, cookie_path());
1053  }
1054  return true;
1055}
1056
1057function ws_session_getStatus($params, &$service)
1058{
1059  global $user;
1060  $res = array();
1061  $res['username'] = is_a_guest() ? 'guest' : $user['username'];
1062  foreach ( array('status', 'template', 'theme', 'language') as $k )
1063  {
1064    $res[$k] = $user[$k];
1065  }
1066  $res['charset'] = get_pwg_charset();
1067  return $res;
1068}
1069
1070
1071/**
1072 * returns a list of tags (web service method)
1073 */
1074function ws_tags_getList($params, &$service)
1075{
1076  $tags = get_available_tags();
1077  if ($params['sort_by_counter'])
1078  {
1079    usort($tags, create_function('$a,$b', 'return -$a["counter"]+$b["counter"];') );
1080  }
1081  else
1082  {
1083    usort($tags, 'tag_alpha_compare');
1084  }
1085  for ($i=0; $i<count($tags); $i++)
1086  {
1087    $tags[$i]['id'] = (int)$tags[$i]['id'];
1088    $tags[$i]['counter'] = (int)$tags[$i]['counter'];
1089    $tags[$i]['url'] = make_index_url(
1090        array(
1091          'section'=>'tags',
1092          'tags'=>array($tags[$i])
1093        )
1094      );
1095  }
1096  return array('tags' => new PwgNamedArray($tags, 'tag', array('id','url_name','url', 'counter' )) );
1097}
1098
1099
1100/**
1101 * returns a list of images for tags (web service method)
1102 */
1103function ws_tags_getImages($params, &$service)
1104{
1105  @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
1106  global $conf;
1107
1108  // first build all the tag_ids we are interested in
1109  $params['tag_id'] = array_map( 'intval',$params['tag_id'] );
1110  $tags = find_tags($params['tag_id'], $params['tag_url_name'], $params['tag_name']);
1111  $tags_by_id = array();
1112  foreach( $tags as $tag )
1113  {
1114    $tags['id'] = (int)$tag['id'];
1115    $tags_by_id[ $tag['id'] ] = $tag;
1116  }
1117  unset($tags);
1118  $tag_ids = array_keys($tags_by_id);
1119
1120
1121  $image_ids = array();
1122  $image_tag_map = array();
1123
1124  if ( !empty($tag_ids) )
1125  { // build list of image ids with associated tags per image
1126    if ($params['tag_mode_and'])
1127    {
1128      $image_ids = get_image_ids_for_tags( $tag_ids );
1129    }
1130    else
1131    {
1132      $query = '
1133SELECT image_id, GROUP_CONCAT(tag_id) tag_ids
1134  FROM '.IMAGE_TAG_TABLE.'
1135  WHERE tag_id IN ('.implode(',',$tag_ids).')
1136  GROUP BY image_id';
1137      $result = pwg_query($query);
1138      while ( $row=mysql_fetch_assoc($result) )
1139      {
1140        $row['image_id'] = (int)$row['image_id'];
1141        array_push( $image_ids, $row['image_id'] );
1142        $image_tag_map[ $row['image_id'] ] = explode(',', $row['tag_ids']);
1143      }
1144    }
1145  }
1146
1147  $images = array();
1148  if ( !empty($image_ids))
1149  {
1150    $where_clauses = ws_std_image_sql_filter($params);
1151    $where_clauses[] = get_sql_condition_FandF(
1152        array
1153          (
1154            'forbidden_categories' => 'category_id',
1155            'visible_categories' => 'category_id',
1156            'visible_images' => 'i.id'
1157          ),
1158        '', true
1159      );
1160    $where_clauses[] = 'id IN ('.implode(',',$image_ids).')';
1161    $where_clauses[] = ws_addControls( 'tags.getImages', $params, 'i.' );
1162
1163    $order_by = ws_std_image_sql_order($params);
1164    if (empty($order_by))
1165    {
1166      $order_by = $conf['order_by'];
1167    }
1168    else
1169    {
1170      $order_by = 'ORDER BY '.$order_by;
1171    }
1172
1173    $query = '
1174SELECT DISTINCT i.* FROM '.IMAGES_TABLE.' i
1175  INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id
1176  WHERE '. implode('
1177    AND ', $where_clauses).'
1178'.$order_by.'
1179LIMIT '.$params['per_page']*$params['page'].','.$params['per_page'];
1180
1181    $result = pwg_query($query);
1182    while ($row = mysql_fetch_assoc($result))
1183    {
1184      $image = array();
1185      foreach ( array('id', 'width', 'height', 'hit') as $k )
1186      {
1187        if (isset($row[$k]))
1188        {
1189          $image[$k] = (int)$row[$k];
1190        }
1191      }
1192      foreach ( array('file', 'name', 'comment') as $k )
1193      {
1194        $image[$k] = $row[$k];
1195      }
1196      $image = array_merge( $image, ws_std_get_urls($row) );
1197
1198      $image_tag_ids = ($params['tag_mode_and']) ? $tag_ids : $image_tag_map[$image['id']];
1199      $image_tags = array();
1200      foreach ($image_tag_ids as $tag_id)
1201      {
1202        $url = make_index_url(
1203                 array(
1204                  'section'=>'tags',
1205                  'tags'=> array($tags_by_id[$tag_id])
1206                )
1207              );
1208        $page_url = make_picture_url(
1209                 array(
1210                  'section'=>'tags',
1211                  'tags'=> array($tags_by_id[$tag_id]),
1212                  'image_id' => $row['id'],
1213                  'image_file' => $row['file'],
1214                )
1215              );
1216        array_push($image_tags, array(
1217                'id' => (int)$tag_id,
1218                'url' => $url,
1219                'page_url' => $page_url,
1220              )
1221            );
1222      }
1223      $image['tags'] = new PwgNamedArray($image_tags, 'tag',
1224              array('id','url_name','url','page_url')
1225            );
1226      array_push($images, $image);
1227    }
1228  }
1229
1230  return array( 'images' =>
1231    array (
1232      WS_XML_ATTRIBUTES =>
1233        array(
1234            'page' => $params['page'],
1235            'per_page' => $params['per_page'],
1236            'count' => count($images)
1237          ),
1238       WS_XML_CONTENT => new PwgNamedArray($images, 'image',
1239          ws_std_get_image_xml_attributes() )
1240      )
1241    );
1242}
1243
1244
1245/**
1246 * expand_id_list($ids) convert a human list expression to a full ordered list
1247 * example : expand_id_list( array(5,2-3,2) ) returns array( 2, 3, 5)
1248 * */
1249function expand_id_list($ids)
1250{
1251  $tid = array();
1252  foreach ( $ids as $id )
1253  {
1254    if ( is_numeric($id) )
1255    {
1256      $tid[] = (int) $id;
1257    }
1258    else
1259    {
1260      $range = explode( '-', $id );
1261      if ( is_numeric($range[0]) and is_numeric($range[1]) )
1262      {
1263        $from = min($range[0],$range[1]);
1264        $to = max($range[0],$range[1]);
1265        for ($i = $from; $i <= $to; $i++)
1266        {
1267          $tid[] = (int) $i;
1268        }
1269      }
1270    }
1271  }
1272  $result = array_unique ($tid); // remove duplicates...
1273  sort ($result);
1274  return $result;
1275}
1276
1277
1278/**
1279 * converts a cat-ids array in image-ids array
1280 * FIXME Function which should already exist somewhere else
1281 * */
1282function get_image_ids_for_cats($cat_ids)
1283{
1284  $cat_list = implode(',', $cat_ids);
1285  $ret_ids = array();
1286  $query = '
1287  SELECT DISTINCT image_id
1288    FROM '.IMAGE_CATEGORY_TABLE.'
1289  WHERE category_id in ('.$cat_list.')
1290  ;';
1291  return array_from_query($query, 'image_id');
1292}
1293
1294?>
Note: See TracBrowser for help on using the repository browser.