Changeset 25281


Ignore:
Timestamp:
11/01/13 12:03:10 (6 years ago)
Author:
mistic100
Message:

splits ws_functions.inc.php in 8 files + comments + code cleaning

Location:
trunk
Files:
10 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/ws_functions.inc.php

    r25276 r25281  
    2222// +-----------------------------------------------------------------------+ 
    2323 
    24 /**** IMPLEMENTATION OF WEB SERVICE METHODS ***********************************/ 
    25  
    2624/** 
    2725 * Event handler for method invocation security check. Should return a PwgError 
     
    207205} 
    208206 
    209 function ws_getMissingDerivatives($params, $service) 
    210 { 
    211   if ( empty($params['types']) ) 
    212   { 
    213     $types = array_keys(ImageStdParams::get_defined_type_map()); 
    214   } 
    215   else 
    216   { 
    217     $types = array_intersect(array_keys(ImageStdParams::get_defined_type_map()), $params['types']); 
    218     if (count($types)==0) 
    219     { 
    220       return new PwgError(WS_ERR_INVALID_PARAM, "Invalid types"); 
    221     } 
    222   } 
    223  
    224   $max_urls = $params['max_urls']; 
    225   list($max_id, $image_count) = pwg_db_fetch_row( pwg_query('SELECT MAX(id)+1, COUNT(*) FROM '.IMAGES_TABLE) ); 
    226  
    227   if (0 == $image_count) 
    228   { 
    229     return array(); 
    230   } 
    231  
    232   $start_id = intval($params['prev_page']); 
    233   if ($start_id<=0) 
    234   { 
    235     $start_id = $max_id; 
    236   } 
    237  
    238   $uid = '&b='.time(); 
     207/** 
     208 * Writes info to the log file 
     209 */ 
     210function ws_logfile($string) 
     211{ 
    239212  global $conf; 
    240   $conf['question_mark_in_urls'] = $conf['php_extension_in_urls'] = true; 
    241   $conf['derivative_url_style']=2; //script 
    242  
    243   $qlimit = min(5000, ceil(max($image_count/500, $max_urls/count($types)))); 
    244   $where_clauses = ws_std_image_sql_filter( $params, '' ); 
    245   $where_clauses[] = 'id<start_id'; 
    246   if ( !empty($params['ids']) ) 
    247   { 
    248     $where_clauses[] = 'id IN ('.implode(',',$params['ids']).')'; 
    249   } 
    250  
    251   $query_model = 'SELECT id, path, representative_ext, width,height,rotation 
    252   FROM '.IMAGES_TABLE.' 
    253   WHERE '.implode(' AND ', $where_clauses).' 
    254   ORDER BY id DESC 
    255   LIMIT '.$qlimit; 
    256  
    257   $urls=array(); 
    258   do 
    259   { 
    260     $result = pwg_query( str_replace('start_id', $start_id, $query_model)); 
    261     $is_last = pwg_db_num_rows($result) < $qlimit; 
    262     while ($row=pwg_db_fetch_assoc($result)) 
    263     { 
    264       $start_id = $row['id']; 
    265       $src_image = new SrcImage($row); 
    266       if ($src_image->is_mimetype()) 
    267         continue; 
    268       foreach($types as $type) 
    269       { 
    270         $derivative = new DerivativeImage($type, $src_image); 
    271         if ($type != $derivative->get_type()) 
    272           continue; 
    273         if (@filemtime($derivative->get_path())===false) 
    274         { 
    275           $urls[] = $derivative->get_url().$uid; 
    276         } 
    277       } 
    278       if (count($urls)>=$max_urls && !$is_last) 
    279         break; 
    280     } 
    281     if ($is_last) 
    282     { 
    283       $start_id = 0; 
    284     } 
    285   }while (count($urls)<$max_urls && $start_id); 
    286  
    287   $ret = array(); 
    288   if ($start_id) 
    289   { 
    290     $ret['next_page']=$start_id; 
    291   } 
    292   $ret['urls']=$urls; 
    293   return $ret; 
    294 } 
    295  
    296 /** 
    297  * returns PWG version (web service method) 
    298  */ 
    299 function ws_getVersion($params, $service) 
    300 { 
    301   global $conf; 
    302   if ( $conf['show_version'] or is_admin() ) 
    303   { 
    304     return PHPWG_VERSION; 
    305   } 
    306   else 
    307   { 
    308     return new PwgError(403, 'Forbidden'); 
    309   } 
    310 } 
    311  
    312 /** 
    313  * returns general informations (web service method) 
    314  */ 
    315 function ws_getInfos($params, $service) 
    316 { 
    317   $infos['version'] = PHPWG_VERSION; 
    318  
    319   $query = 'SELECT COUNT(*) FROM '.IMAGES_TABLE.';'; 
    320   list($infos['nb_elements']) = pwg_db_fetch_row(pwg_query($query)); 
    321  
    322   $query = 'SELECT COUNT(*) FROM '.CATEGORIES_TABLE.';'; 
    323   list($infos['nb_categories']) = pwg_db_fetch_row(pwg_query($query)); 
    324  
    325   $query = 'SELECT COUNT(*) FROM '.CATEGORIES_TABLE.' WHERE dir IS NULL;'; 
    326   list($infos['nb_virtual']) = pwg_db_fetch_row(pwg_query($query)); 
    327  
    328   $query = 'SELECT COUNT(*) FROM '.CATEGORIES_TABLE.' WHERE dir IS NOT NULL;'; 
    329   list($infos['nb_physical']) = pwg_db_fetch_row(pwg_query($query)); 
    330  
    331   $query = 'SELECT COUNT(*) FROM '.IMAGE_CATEGORY_TABLE.';'; 
    332   list($infos['nb_image_category']) = pwg_db_fetch_row(pwg_query($query)); 
    333  
    334   $query = 'SELECT COUNT(*) FROM '.TAGS_TABLE.';'; 
    335   list($infos['nb_tags']) = pwg_db_fetch_row(pwg_query($query)); 
    336  
    337   $query = 'SELECT COUNT(*) FROM '.IMAGE_TAG_TABLE.';'; 
    338   list($infos['nb_image_tag']) = pwg_db_fetch_row(pwg_query($query)); 
    339  
    340   $query = 'SELECT COUNT(*) FROM '.USERS_TABLE.';'; 
    341   list($infos['nb_users']) = pwg_db_fetch_row(pwg_query($query)); 
    342  
    343   $query = 'SELECT COUNT(*) FROM '.GROUPS_TABLE.';'; 
    344   list($infos['nb_groups']) = pwg_db_fetch_row(pwg_query($query)); 
    345  
    346   $query = 'SELECT COUNT(*) FROM '.COMMENTS_TABLE.';'; 
    347   list($infos['nb_comments']) = pwg_db_fetch_row(pwg_query($query)); 
    348  
    349   // first element 
    350   if ($infos['nb_elements'] > 0) 
    351   { 
    352     $query = 'SELECT MIN(date_available) FROM '.IMAGES_TABLE.';'; 
    353     list($infos['first_date']) = pwg_db_fetch_row(pwg_query($query)); 
    354   } 
    355  
    356   // unvalidated comments 
    357   if ($infos['nb_comments'] > 0) 
    358   { 
    359     $query = 'SELECT COUNT(*) FROM '.COMMENTS_TABLE.' WHERE validated=\'false\';'; 
    360     list($infos['nb_unvalidated_comments']) = pwg_db_fetch_row(pwg_query($query)); 
    361   } 
    362  
    363   foreach ($infos as $name => $value) 
    364   { 
    365     $output[] = array( 
    366       'name' => $name, 
    367       'value' => $value, 
    368     ); 
    369   } 
    370  
    371   return array('infos' => new PwgNamedArray($output, 'item')); 
    372 } 
    373  
    374 function ws_caddie_add($params, $service) 
    375 { 
    376   global $user; 
    377   $query = ' 
    378 SELECT id 
    379   FROM '.IMAGES_TABLE.' LEFT JOIN '.CADDIE_TABLE.' ON id=element_id AND user_id='.$user['id'].' 
    380   WHERE id IN ('.implode(',',$params['image_id']).') 
    381     AND element_id IS NULL'; 
    382   $datas = array(); 
    383   foreach ( array_from_query($query, 'id') as $id ) 
    384   { 
    385     $datas[] = array('element_id'=>$id, 'user_id'=>$user['id']); 
    386   } 
    387   if (count($datas)) 
    388   { 
    389     mass_inserts( 
    390       CADDIE_TABLE, 
    391       array('element_id','user_id'), 
    392       $datas 
    393       ); 
    394   } 
    395   return count($datas); 
    396 } 
    397  
    398 /** 
    399  * returns images per category (web service method) 
    400  */ 
    401 function ws_categories_getImages($params, $service) 
    402 { 
    403   global $user, $conf; 
    404  
    405   $images = array(); 
    406  
    407   //------------------------------------------------- get the related categories 
    408   $where_clauses = array(); 
    409   foreach($params['cat_id'] as $cat_id) 
    410   { 
    411     if ($params['recursive']) 
    412     { 
    413       $where_clauses[] = 'uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'.$cat_id.'(,|$)\''; 
    414     } 
    415     else 
    416     { 
    417       $where_clauses[] = 'id='.$cat_id; 
    418     } 
    419   } 
    420   if (!empty($where_clauses)) 
    421   { 
    422     $where_clauses = array( '('. 
    423     implode(' 
    424     OR ', $where_clauses) . ')' 
    425       ); 
    426   } 
    427   $where_clauses[] = get_sql_condition_FandF( 
    428         array('forbidden_categories' => 'id'), 
    429         NULL, true 
    430       ); 
    431  
    432   $query = ' 
    433 SELECT id, name, permalink, image_order 
    434   FROM '.CATEGORIES_TABLE.' 
    435   WHERE '. implode(' 
    436     AND ', $where_clauses); 
    437   $result = pwg_query($query); 
    438   $cats = array(); 
    439   while ($row = pwg_db_fetch_assoc($result)) 
    440   { 
    441     $row['id'] = (int)$row['id']; 
    442     $cats[ $row['id'] ] = $row; 
    443   } 
    444  
    445   //-------------------------------------------------------- get the images 
    446   if ( !empty($cats) ) 
    447   { 
    448     $where_clauses = ws_std_image_sql_filter( $params, 'i.' ); 
    449     $where_clauses[] = 'category_id IN (' 
    450       .implode(',', array_keys($cats) ) 
    451       .')'; 
    452     $where_clauses[] = get_sql_condition_FandF( array( 
    453           'visible_images' => 'i.id' 
    454         ), null, true 
    455       ); 
    456  
    457     $order_by = ws_std_image_sql_order($params, 'i.'); 
    458     if ( empty($order_by) 
    459           and count($params['cat_id'])==1 
    460           and isset($cats[ $params['cat_id'][0] ]['image_order']) 
    461         ) 
    462     { 
    463       $order_by = $cats[ $params['cat_id'][0] ]['image_order']; 
    464     } 
    465     $order_by = empty($order_by) ? $conf['order_by'] : 'ORDER BY '.$order_by; 
    466  
    467     $query = ' 
    468 SELECT i.*, GROUP_CONCAT(category_id) AS cat_ids 
    469   FROM '.IMAGES_TABLE.' i 
    470     INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id 
    471   WHERE '. implode(' 
    472     AND ', $where_clauses).' 
    473 GROUP BY i.id 
    474 '.$order_by.' 
    475 LIMIT '.$params['per_page'].' OFFSET '.($params['per_page']*$params['page']); 
    476  
    477     $result = pwg_query($query); 
    478     while ($row = pwg_db_fetch_assoc($result)) 
    479     { 
    480       $image = array(); 
    481       foreach ( array('id', 'width', 'height', 'hit') as $k ) 
    482       { 
    483         if (isset($row[$k])) 
    484         { 
    485           $image[$k] = (int)$row[$k]; 
    486         } 
    487       } 
    488       foreach ( array('file', 'name', 'comment', 'date_creation', 'date_available') as $k ) 
    489       { 
    490         $image[$k] = $row[$k]; 
    491       } 
    492       $image = array_merge( $image, ws_std_get_urls($row) ); 
    493  
    494       $image_cats = array(); 
    495       foreach ( explode(',', $row['cat_ids']) as $cat_id ) 
    496       { 
    497         $url = make_index_url( 
    498                 array( 
    499                   'category' => $cats[$cat_id], 
    500                   ) 
    501                 ); 
    502         $page_url = make_picture_url( 
    503                 array( 
    504                   'category' => $cats[$cat_id], 
    505                   'image_id' => $row['id'], 
    506                   'image_file' => $row['file'], 
    507                   ) 
    508                 ); 
    509         $image_cats[] = array ( 
    510                 'id' => (int)$cat_id, 
    511                 'url' => $url, 
    512                 'page_url' => $page_url, 
    513             ); 
    514       } 
    515  
    516       $image['categories'] = new PwgNamedArray( 
    517             $image_cats,'category', array('id','url','page_url') 
    518           ); 
    519       $images[] = $image; 
    520     } 
    521   } 
    522  
    523   return array ( 
    524       'paging' => new PwgNamedStruct( 
    525         array( 
    526             'page' => $params['page'], 
    527             'per_page' => $params['per_page'], 
    528             'count' => count($images) 
    529           ) ), 
    530        'images' => new PwgNamedArray($images, 'image', ws_std_get_image_xml_attributes() ) 
    531     ); 
    532 } 
    533  
    534  
    535 /** 
    536  * create a tree from a flat list of categories, no recursivity for high speed 
    537  */ 
    538 function categories_flatlist_to_tree($categories) 
    539 { 
    540   $tree = array(); 
    541   $key_of_cat = array(); 
    542  
    543   foreach ($categories as $key => &$node) 
    544   { 
    545     $key_of_cat[$node['id']] = $key; 
    546  
    547     if (!isset($node['id_uppercat'])) 
    548     { 
    549       $tree[] = &$node; 
    550     } 
    551     else 
    552     { 
    553       if (!isset($categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'])) 
    554       { 
    555         $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'] = new PwgNamedArray(array(), 'category', ws_std_get_category_xml_attributes()); 
    556       } 
    557  
    558       $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories']->_content[] = &$node; 
    559     } 
    560   } 
    561  
    562   return $tree; 
    563 } 
    564  
    565 /** 
    566  * returns a list of categories (web service method) 
    567  */ 
    568 function ws_categories_getList($params, $service) 
    569 { 
    570   global $user,$conf; 
    571  
    572   $where = array('1=1'); 
    573   $join_type = 'INNER'; 
    574   $join_user = $user['id']; 
    575  
    576   if (!$params['recursive']) 
    577   { 
    578     if ($params['cat_id']>0) 
    579       $where[] = '(id_uppercat='.(int)($params['cat_id']).' 
    580     OR id='.(int)($params['cat_id']).')'; 
    581     else 
    582       $where[] = 'id_uppercat IS NULL'; 
    583   } 
    584   elseif ($params['cat_id']>0) 
    585   { 
    586     $where[] = 'uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'. 
    587       (int)($params['cat_id']) 
    588       .'(,|$)\''; 
    589   } 
    590  
    591   if ($params['public']) 
    592   { 
    593     $where[] = 'status = "public"'; 
    594     $where[] = 'visible = "true"'; 
    595  
    596     $join_user = $conf['guest_id']; 
    597   } 
    598   elseif (is_admin()) 
    599   { 
    600     // in this very specific case, we don't want to hide empty 
    601     // categories. Function calculate_permissions will only return 
    602     // categories that are either locked or private and not permitted 
    603     // 
    604     // calculate_permissions does not consider empty categories as forbidden 
    605     $forbidden_categories = calculate_permissions($user['id'], $user['status']); 
    606     $where[]= 'id NOT IN ('.$forbidden_categories.')'; 
    607     $join_type = 'LEFT'; 
    608   } 
    609  
    610   $query = ' 
    611 SELECT id, name, permalink, uppercats, global_rank, id_uppercat, 
    612     comment, 
    613     nb_images, count_images AS total_nb_images, 
    614     representative_picture_id, user_representative_picture_id, count_images, count_categories, 
    615     date_last, max_date_last, count_categories AS nb_categories 
    616   FROM '.CATEGORIES_TABLE.' 
    617    '.$join_type.' JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id AND user_id='.$join_user.' 
    618   WHERE '. implode(' 
    619     AND ', $where); 
    620  
    621   $result = pwg_query($query); 
    622  
    623   // management of the album thumbnail -- starts here 
    624   $image_ids = array(); 
    625   $categories = array(); 
    626   $user_representative_updates_for = array(); 
    627   // management of the album thumbnail -- stops here 
    628  
    629   $cats = array(); 
    630   while ($row = pwg_db_fetch_assoc($result)) 
    631   { 
    632     $row['url'] = make_index_url( 
    633         array( 
    634           'category' => $row 
    635           ) 
    636       ); 
    637     foreach( array('id','nb_images','total_nb_images','nb_categories') as $key) 
    638     { 
    639       $row[$key] = (int)$row[$key]; 
    640     } 
    641  
    642     if ($params['fullname']) 
    643     { 
    644       $row['name'] = strip_tags(get_cat_display_name_cache($row['uppercats'], null, false)); 
    645     } 
    646     else 
    647     { 
    648       $row['name'] = strip_tags( 
    649         trigger_event( 
    650           'render_category_name', 
    651           $row['name'], 
    652           'ws_categories_getList' 
    653           ) 
    654         ); 
    655     } 
    656  
    657     $row['comment'] = strip_tags( 
    658       trigger_event( 
    659         'render_category_description', 
    660         $row['comment'], 
    661         'ws_categories_getList' 
    662         ) 
    663       ); 
    664  
    665     // management of the album thumbnail -- starts here 
    666     // 
    667     // on branch 2.3, the algorithm is duplicated from 
    668     // include/category_cats, but we should use a common code for Piwigo 2.4 
    669     // 
    670     // warning : if the API method is called with $params['public'], the 
    671     // album thumbnail may be not accurate. The thumbnail can be viewed by 
    672     // the connected user, but maybe not by the guest. Changing the 
    673     // filtering method would be too complicated for now. We will simply 
    674     // avoid to persist the user_representative_picture_id in the database 
    675     // if $params['public'] 
    676     if (!empty($row['user_representative_picture_id'])) 
    677     { 
    678       $image_id = $row['user_representative_picture_id']; 
    679     } 
    680     elseif (!empty($row['representative_picture_id'])) 
    681     { // if a representative picture is set, it has priority 
    682       $image_id = $row['representative_picture_id']; 
    683     } 
    684     elseif ($conf['allow_random_representative']) 
    685     { 
    686       // searching a random representant among elements in sub-categories 
    687       $image_id = get_random_image_in_category($row); 
    688     } 
    689     else 
    690     { // searching a random representant among representant of sub-categories 
    691       if ($row['count_categories']>0 and $row['count_images']>0) 
    692       { 
    693         $query = ' 
    694   SELECT representative_picture_id 
    695     FROM '.CATEGORIES_TABLE.' INNER JOIN '.USER_CACHE_CATEGORIES_TABLE.' 
    696     ON id = cat_id and user_id = '.$user['id'].' 
    697     WHERE uppercats LIKE \''.$row['uppercats'].',%\' 
    698       AND representative_picture_id IS NOT NULL' 
    699           .get_sql_condition_FandF 
    700           ( 
    701             array 
    702             ( 
    703               'visible_categories' => 'id', 
    704               ), 
    705             "\n  AND" 
    706             ).' 
    707     ORDER BY '.DB_RANDOM_FUNCTION.'() 
    708     LIMIT 1 
    709   ;'; 
    710         $subresult = pwg_query($query); 
    711         if (pwg_db_num_rows($subresult) > 0) 
    712         { 
    713           list($image_id) = pwg_db_fetch_row($subresult); 
    714         } 
    715       } 
    716     } 
    717  
    718     if (isset($image_id)) 
    719     { 
    720       if ($conf['representative_cache_on_subcats'] and $row['user_representative_picture_id'] != $image_id) 
    721       { 
    722         $user_representative_updates_for[ $row['id'] ] = $image_id; 
    723       } 
    724  
    725       $row['representative_picture_id'] = $image_id; 
    726       $image_ids[] = $image_id; 
    727       $categories[] = $row; 
    728     } 
    729     unset($image_id); 
    730     // management of the album thumbnail -- stops here 
    731  
    732  
    733     $cats[] = $row; 
    734   } 
    735   usort($cats, 'global_rank_compare'); 
    736  
    737   // management of the album thumbnail -- starts here 
    738   if (count($categories) > 0) 
    739   { 
    740     $thumbnail_src_of = array(); 
    741     $new_image_ids = array(); 
    742  
    743     $query = ' 
    744 SELECT id, path, representative_ext, level 
    745   FROM '.IMAGES_TABLE.' 
    746   WHERE id IN ('.implode(',', $image_ids).') 
    747 ;'; 
    748     $result = pwg_query($query); 
    749     while ($row = pwg_db_fetch_assoc($result)) 
    750     { 
    751       if ($row['level'] <= $user['level']) 
    752       { 
    753         $thumbnail_src_of[$row['id']] = DerivativeImage::thumb_url($row); 
    754       } 
    755       else 
    756       { 
    757         // problem: we must not display the thumbnail of a photo which has a 
    758         // higher privacy level than user privacy level 
    759         // 
    760         // * what is the represented category? 
    761         // * find a random photo matching user permissions 
    762         // * register it at user_representative_picture_id 
    763         // * set it as the representative_picture_id for the category 
    764  
    765         foreach ($categories as &$category) 
    766         { 
    767           if ($row['id'] == $category['representative_picture_id']) 
    768           { 
    769             // searching a random representant among elements in sub-categories 
    770             $image_id = get_random_image_in_category($category); 
    771  
    772             if (isset($image_id) and !in_array($image_id, $image_ids)) 
    773             { 
    774               $new_image_ids[] = $image_id; 
    775             } 
    776  
    777             if ($conf['representative_cache_on_level']) 
    778             { 
    779               $user_representative_updates_for[ $category['id'] ] = $image_id; 
    780             } 
    781  
    782             $category['representative_picture_id'] = $image_id; 
    783           } 
    784         } 
    785         unset($category); 
    786       } 
    787     } 
    788  
    789     if (count($new_image_ids) > 0) 
    790     { 
    791       $query = ' 
    792 SELECT id, path, representative_ext 
    793   FROM '.IMAGES_TABLE.' 
    794   WHERE id IN ('.implode(',', $new_image_ids).') 
    795 ;'; 
    796       $result = pwg_query($query); 
    797       while ($row = pwg_db_fetch_assoc($result)) 
    798       { 
    799         $thumbnail_src_of[$row['id']] = DerivativeImage::thumb_url($row); 
    800       } 
    801     } 
    802   } 
    803  
    804   // compared to code in include/category_cats, we only persist the new 
    805   // user_representative if we have used $user['id'] and not the guest id, 
    806   // or else the real guest may see thumbnail that he should not 
    807   if (!$params['public'] and count($user_representative_updates_for)) 
    808   { 
    809     $updates = array(); 
    810  
    811     foreach ($user_representative_updates_for as $cat_id => $image_id) 
    812     { 
    813       $updates[] = array( 
    814         'user_id' => $user['id'], 
    815         'cat_id' => $cat_id, 
    816         'user_representative_picture_id' => $image_id, 
    817         ); 
    818     } 
    819  
    820     mass_updates( 
    821       USER_CACHE_CATEGORIES_TABLE, 
    822       array( 
    823         'primary' => array('user_id', 'cat_id'), 
    824         'update'  => array('user_representative_picture_id') 
    825         ), 
    826       $updates 
    827       ); 
    828   } 
    829  
    830   foreach ($cats as &$cat) 
    831   { 
    832     foreach ($categories as $category) 
    833     { 
    834       if ($category['id'] == $cat['id'] and isset($category['representative_picture_id'])) 
    835       { 
    836         $cat['tn_url'] = $thumbnail_src_of[$category['representative_picture_id']]; 
    837       } 
    838     } 
    839     // we don't want them in the output 
    840     unset($cat['user_representative_picture_id']); 
    841     unset($cat['count_images']); 
    842     unset($cat['count_categories']); 
    843   } 
    844   unset($cat); 
    845   // management of the album thumbnail -- stops here 
    846  
    847   if ($params['tree_output']) 
    848   { 
    849     $cats = categories_flatlist_to_tree($cats); 
    850   } 
    851  
    852   return array( 
    853     'categories' => new PwgNamedArray($cats, 'category', ws_std_get_category_xml_attributes()) 
    854     ); 
    855 } 
    856  
    857 /** 
    858  * returns the list of categories as you can see them in administration (web 
    859  * service method). 
    860  * 
    861  * Only admin can run this method and permissions are not taken into 
    862  * account. 
    863  */ 
    864 function ws_categories_getAdminList($params, $service) 
    865 { 
    866   $query = ' 
    867 SELECT 
    868     category_id, 
    869     COUNT(*) AS counter 
    870   FROM '.IMAGE_CATEGORY_TABLE.' 
    871   GROUP BY category_id 
    872 ;'; 
    873   $nb_images_of = simple_hash_from_query($query, 'category_id', 'counter'); 
    874  
    875   $query = ' 
    876 SELECT 
    877     id, 
    878     name, 
    879     comment, 
    880     uppercats, 
    881     global_rank 
    882   FROM '.CATEGORIES_TABLE.' 
    883 ;'; 
    884   $result = pwg_query($query); 
    885   $cats = array(); 
    886  
    887   while ($row = pwg_db_fetch_assoc($result)) 
    888   { 
    889     $id = $row['id']; 
    890     $row['nb_images'] = isset($nb_images_of[$id]) ? $nb_images_of[$id] : 0; 
    891     $row['name'] = strip_tags( 
    892       trigger_event( 
    893         'render_category_name', 
    894         $row['name'], 
    895         'ws_categories_getAdminList' 
    896         ) 
    897       ); 
    898     $row['comment'] = strip_tags( 
    899       trigger_event( 
    900         'render_category_description', 
    901         $row['comment'], 
    902         'ws_categories_getAdminList' 
    903         ) 
    904       ); 
    905     $cats[] = $row; 
    906   } 
    907  
    908   usort($cats, 'global_rank_compare'); 
    909   return array( 
    910     'categories' => new PwgNamedArray( 
    911       $cats, 
    912       'category', 
    913       array( 
    914         'id', 
    915         'nb_images', 
    916         'name', 
    917         'uppercats', 
    918         'global_rank', 
    919         ) 
    920       ) 
    921     ); 
    922 } 
    923  
    924 /** 
    925  * returns detailed information for an element (web service method) 
    926  */ 
    927 function ws_images_addComment($params, $service) 
    928 { 
    929   $query = ' 
    930 SELECT DISTINCT image_id 
    931   FROM '.IMAGE_CATEGORY_TABLE.' INNER JOIN '.CATEGORIES_TABLE.' ON category_id=id 
    932   WHERE commentable="true" 
    933     AND image_id='.$params['image_id']. 
    934     get_sql_condition_FandF( 
    935       array( 
    936         'forbidden_categories' => 'id', 
    937         'visible_categories' => 'id', 
    938         'visible_images' => 'image_id' 
    939       ), 
    940       ' AND' 
    941     ); 
    942   if ( !pwg_db_num_rows( pwg_query( $query ) ) ) 
    943   { 
    944     return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id"); 
    945   } 
    946  
    947   $comm = array( 
    948     'author' => trim( $params['author'] ), 
    949     'content' => trim( $params['content'] ), 
    950     'image_id' => $params['image_id'], 
    951    ); 
    952  
    953   include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); 
    954  
    955   $comment_action = insert_user_comment( 
    956       $comm, $params['key'], $infos 
    957     ); 
    958  
    959   switch ($comment_action) 
    960   { 
    961     case 'reject': 
    962       $infos[] = l10n('Your comment has NOT been registered because it did not pass the validation rules'); 
    963       return new PwgError(403, implode("; ", $infos) ); 
    964     case 'validate': 
    965     case 'moderate': 
    966       $ret = array( 
    967         'id' => $comm['id'], 
    968         'validation' => $comment_action=='validate', 
    969         ); 
    970       return array( 'comment' =>  new PwgNamedStruct($ret) ); 
    971     default: 
    972       return new PwgError(500, "Unknown comment action ".$comment_action ); 
    973   } 
    974 } 
    975  
    976 /** 
    977  * returns detailed information for an element (web service method) 
    978  */ 
    979 function ws_images_getInfo($params, $service) 
    980 { 
    981   global $user, $conf; 
    982  
    983   $query=' 
    984 SELECT * FROM '.IMAGES_TABLE.' 
    985   WHERE id='.$params['image_id']. 
    986     get_sql_condition_FandF( 
    987       array('visible_images' => 'id'), 
    988       ' AND' 
    989     ).' 
    990 LIMIT 1'; 
    991   $result = pwg_query($query); 
    992    
    993   if (pwg_db_num_rows($result) == 0) 
    994   { 
    995     return new PwgError(404, "image_id not found"); 
    996   } 
    997    
    998   $image_row = pwg_db_fetch_assoc($result); 
    999   $image_row = array_merge( $image_row, ws_std_get_urls($image_row) ); 
    1000  
    1001   //-------------------------------------------------------- related categories 
    1002   $query = ' 
    1003 SELECT id, name, permalink, uppercats, global_rank, commentable 
    1004   FROM '.IMAGE_CATEGORY_TABLE.' 
    1005     INNER JOIN '.CATEGORIES_TABLE.' ON category_id = id 
    1006   WHERE image_id = '.$image_row['id']. 
    1007   get_sql_condition_FandF( 
    1008       array( 'forbidden_categories' => 'category_id' ), 
    1009       ' AND' 
    1010     ).' 
    1011 ;'; 
    1012   $result = pwg_query($query); 
    1013   $is_commentable = false; 
    1014   $related_categories = array(); 
    1015   while ($row = pwg_db_fetch_assoc($result)) 
    1016   { 
    1017     if ($row['commentable']=='true') 
    1018     { 
    1019       $is_commentable = true; 
    1020     } 
    1021     unset($row['commentable']); 
    1022     $row['url'] = make_index_url( 
    1023         array( 
    1024           'category' => $row 
    1025           ) 
    1026       ); 
    1027  
    1028     $row['page_url'] = make_picture_url( 
    1029         array( 
    1030           'image_id' => $image_row['id'], 
    1031           'image_file' => $image_row['file'], 
    1032           'category' => $row 
    1033           ) 
    1034       ); 
    1035     $row['id']=(int)$row['id']; 
    1036     $related_categories[] = $row; 
    1037   } 
    1038   usort($related_categories, 'global_rank_compare'); 
    1039   if ( empty($related_categories) ) 
    1040   { 
    1041     return new PwgError(401, 'Access denied'); 
    1042   } 
    1043  
    1044   //-------------------------------------------------------------- related tags 
    1045   $related_tags = get_common_tags( array($image_row['id']), -1 ); 
    1046   foreach( $related_tags as $i=>$tag) 
    1047   { 
    1048     $tag['url'] = make_index_url( 
    1049         array( 
    1050           'tags' => array($tag) 
    1051           ) 
    1052       ); 
    1053     $tag['page_url'] = make_picture_url( 
    1054         array( 
    1055           'image_id' => $image_row['id'], 
    1056           'image_file' => $image_row['file'], 
    1057           'tags' => array($tag), 
    1058           ) 
    1059       ); 
    1060     unset($tag['counter']); 
    1061     $tag['id']=(int)$tag['id']; 
    1062     $related_tags[$i]=$tag; 
    1063   } 
    1064   //------------------------------------------------------------- related rates 
    1065         $rating = array('score'=>$image_row['rating_score'], 'count'=>0, 'average'=>null); 
    1066         if (isset($rating['score'])) 
    1067         { 
    1068                 $query = ' 
    1069 SELECT COUNT(rate) AS count 
    1070      , ROUND(AVG(rate),2) AS average 
    1071   FROM '.RATE_TABLE.' 
    1072   WHERE element_id = '.$image_row['id'].' 
    1073 ;'; 
    1074                 $row = pwg_db_fetch_assoc(pwg_query($query)); 
    1075                 $rating['score'] = (float)$rating['score']; 
    1076                 $rating['average'] = (float)$row['average']; 
    1077                 $rating['count'] = (int)$row['count']; 
    1078         } 
    1079  
    1080   //---------------------------------------------------------- related comments 
    1081   $related_comments = array(); 
    1082  
    1083   $where_comments = 'image_id = '.$image_row['id']; 
    1084   if ( !is_admin() ) 
    1085   { 
    1086     $where_comments .= ' 
    1087     AND validated="true"'; 
    1088   } 
    1089  
    1090   $query = ' 
    1091 SELECT COUNT(id) AS nb_comments 
    1092   FROM '.COMMENTS_TABLE.' 
    1093   WHERE '.$where_comments; 
    1094   list($nb_comments) = array_from_query($query, 'nb_comments'); 
    1095   $nb_comments = (int)$nb_comments; 
    1096  
    1097   if ( $nb_comments>0 and $params['comments_per_page']>0 ) 
    1098   { 
    1099     $query = ' 
    1100 SELECT id, date, author, content 
    1101   FROM '.COMMENTS_TABLE.' 
    1102   WHERE '.$where_comments.' 
    1103   ORDER BY date 
    1104   LIMIT '.(int)$params['comments_per_page']. 
    1105     ' OFFSET '.(int)($params['comments_per_page']*$params['comments_page']); 
    1106  
    1107     $result = pwg_query($query); 
    1108     while ($row = pwg_db_fetch_assoc($result)) 
    1109     { 
    1110       $row['id']=(int)$row['id']; 
    1111       $related_comments[] = $row; 
    1112     } 
    1113   } 
    1114  
    1115   $comment_post_data = null; 
    1116   if ($is_commentable and 
    1117       (!is_a_guest() 
    1118         or (is_a_guest() and $conf['comments_forall'] ) 
    1119       ) 
    1120       ) 
    1121   { 
    1122     $comment_post_data['author'] = stripslashes($user['username']); 
    1123     $comment_post_data['key'] = get_ephemeral_key(2, $params['image_id']); 
    1124   } 
    1125  
    1126   $ret = $image_row; 
    1127   foreach ( array('id','width','height','hit','filesize') as $k ) 
    1128   { 
    1129     if (isset($ret[$k])) 
    1130     { 
    1131       $ret[$k] = (int)$ret[$k]; 
    1132     } 
    1133   } 
    1134   foreach ( array('path', 'storage_category_id') as $k ) 
    1135   { 
    1136     unset($ret[$k]); 
    1137   } 
    1138  
    1139   $ret['rates'] = array( WS_XML_ATTRIBUTES => $rating ); 
    1140   $ret['categories'] = new PwgNamedArray($related_categories, 'category', array('id','url', 'page_url') ); 
    1141   $ret['tags'] = new PwgNamedArray($related_tags, 'tag', ws_std_get_tag_xml_attributes() ); 
    1142   if ( isset($comment_post_data) ) 
    1143   { 
    1144     $ret['comment_post'] = array( WS_XML_ATTRIBUTES => $comment_post_data ); 
    1145   } 
    1146   $ret['comments_paging'] = new PwgNamedStruct( array( 
    1147         'page' => $params['comments_page'], 
    1148         'per_page' => $params['comments_per_page'], 
    1149         'count' => count($related_comments), 
    1150         'total_count' => $nb_comments, 
    1151       ) ); 
    1152  
    1153   $ret['comments'] = new PwgNamedArray($related_comments, 'comment', array('id','date') ); 
    1154  
    1155   if ($service->_responseFormat != 'rest') 
    1156     return $ret; // for backward compatibility only 
    1157   else 
    1158     return array( 'image' => new PwgNamedStruct($ret, null, array('name','comment') ) ); 
    1159 } 
    1160  
    1161  
    1162 /** 
    1163  * rates the image_id in the parameter 
    1164  */ 
    1165 function ws_images_Rate($params, $service) 
    1166 { 
    1167   $query = ' 
    1168 SELECT DISTINCT id FROM '.IMAGES_TABLE.' 
    1169   INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=image_id 
    1170   WHERE id='.$params['image_id'] 
    1171   .get_sql_condition_FandF( 
    1172     array( 
    1173         'forbidden_categories' => 'category_id', 
    1174         'forbidden_images' => 'id', 
    1175       ), 
    1176     '    AND' 
    1177     ).' 
    1178     LIMIT 1'; 
    1179   if ( pwg_db_num_rows( pwg_query($query) )==0 ) 
    1180   { 
    1181     return new PwgError(404, "Invalid image_id or access denied" ); 
    1182   } 
    1183   $rate = (int)$params['rate']; 
    1184   include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php'); 
    1185   $res = rate_picture( $params['image_id'], $rate ); 
    1186   if ($res==false) 
    1187   { 
    1188     global $conf; 
    1189     return new PwgError( 403, "Forbidden or rate not in ". implode(',',$conf['rate_items'])); 
    1190   } 
    1191   return $res; 
    1192 } 
    1193  
    1194  
    1195 /** 
    1196  * returns a list of elements corresponding to a query search 
    1197  */ 
    1198 function ws_images_search($params, $service) 
    1199 { 
    1200   global $page; 
    1201   $images = array(); 
    1202   include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' ); 
    1203  
    1204   $where_clauses = ws_std_image_sql_filter( $params, 'i.' ); 
    1205   $order_by = ws_std_image_sql_order($params, 'i.'); 
    1206  
    1207   $super_order_by = false; 
    1208   if ( !empty($order_by) ) 
    1209   { 
    1210     global $conf; 
    1211     $conf['order_by'] = 'ORDER BY '.$order_by; 
    1212     $super_order_by=true; // quick_search_result might be faster 
    1213   } 
    1214  
    1215   $search_result = get_quick_search_results($params['query'], 
    1216       $super_order_by, 
    1217       implode(' AND ', $where_clauses) 
    1218     ); 
    1219  
    1220   $image_ids = array_slice( 
    1221       $search_result['items'], 
    1222       $params['page']*$params['per_page'], 
    1223       $params['per_page'] 
    1224     ); 
    1225  
    1226   if ( count($image_ids) ) 
    1227   { 
    1228     $query = ' 
    1229 SELECT * FROM '.IMAGES_TABLE.' 
    1230   WHERE id IN ('.implode(',', $image_ids).')'; 
    1231  
    1232     $image_ids = array_flip($image_ids); 
    1233     $result = pwg_query($query); 
    1234     while ($row = pwg_db_fetch_assoc($result)) 
    1235     { 
    1236       $image = array(); 
    1237       foreach ( array('id', 'width', 'height', 'hit') as $k ) 
    1238       { 
    1239         if (isset($row[$k])) 
    1240         { 
    1241           $image[$k] = (int)$row[$k]; 
    1242         } 
    1243       } 
    1244       foreach ( array('file', 'name', 'comment', 'date_creation', 'date_available') as $k ) 
    1245       { 
    1246         $image[$k] = $row[$k]; 
    1247       } 
    1248       $image = array_merge( $image, ws_std_get_urls($row) ); 
    1249       $images[$image_ids[$image['id']]] = $image; 
    1250     } 
    1251     ksort($images, SORT_NUMERIC); 
    1252     $images = array_values($images); 
    1253   } 
    1254  
    1255   return array ( 
    1256     'paging' => new PwgNamedStruct( 
    1257       array( 
    1258         'page' => $params['page'], 
    1259         'per_page' => $params['per_page'], 
    1260         'count' => count($images), 
    1261         'total_count' => count($search_result['items']), 
    1262         ) ), 
    1263      'images' => new PwgNamedArray($images, 'image', 
    1264         ws_std_get_image_xml_attributes() ) 
    1265     ); 
    1266 } 
    1267  
    1268 function ws_images_setPrivacyLevel($params, $service) 
    1269 { 
    1270   global $conf; 
    1271   if ( !in_array($params['level'], $conf['available_permission_levels']) ) 
    1272   { 
    1273     return new PwgError(WS_ERR_INVALID_PARAM, "Invalid level"); 
    1274   } 
    1275  
    1276   $query = ' 
    1277 UPDATE '.IMAGES_TABLE.' 
    1278   SET level='.(int)$params['level'].' 
    1279   WHERE id IN ('.implode(',',$params['image_id']).')'; 
    1280   $result = pwg_query($query); 
    1281   $affected_rows = pwg_db_changes($result); 
    1282   if ($affected_rows) 
    1283   { 
    1284     include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    1285     invalidate_user_cache(); 
    1286   } 
    1287   return $affected_rows; 
    1288 } 
    1289  
    1290 function ws_images_setRank($params, $service) 
    1291 { 
    1292   // does the image really exist? 
    1293   $query=' 
    1294 SELECT COUNT(*) 
    1295   FROM '.IMAGES_TABLE.' 
    1296   WHERE id = '.$params['image_id'].' 
    1297 ;'; 
    1298  
    1299   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    1300   if ($count == 0) 
    1301   { 
    1302     return new PwgError(404, "image_id not found"); 
    1303   } 
    1304  
    1305   // is the image associated to this category? 
    1306   $query = ' 
    1307 SELECT COUNT(*) 
    1308   FROM '.IMAGE_CATEGORY_TABLE.' 
    1309   WHERE image_id = '.$params['image_id'].' 
    1310     AND category_id = '.$params['category_id'].' 
    1311 ;'; 
    1312   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    1313   if ($count == 0) 
    1314   { 
    1315     return new PwgError(404, "This image is not associated to this category"); 
    1316   } 
    1317  
    1318   // what is the current higher rank for this category? 
    1319   $query = ' 
    1320 SELECT 
    1321     MAX(rank) AS max_rank 
    1322   FROM '.IMAGE_CATEGORY_TABLE.' 
    1323   WHERE category_id = '.$params['category_id'].' 
    1324 ;'; 
    1325   $result = pwg_query($query); 
    1326   $row = pwg_db_fetch_assoc($result); 
    1327  
    1328   if (is_numeric($row['max_rank'])) 
    1329   { 
    1330     if ($params['rank'] > $row['max_rank']) 
    1331     { 
    1332       $params['rank'] = $row['max_rank'] + 1; 
    1333     } 
    1334   } 
    1335   else 
    1336   { 
    1337     $params['rank'] = 1; 
    1338   } 
    1339  
    1340   // update rank for all other photos in the same category 
    1341   $query = ' 
    1342 UPDATE '.IMAGE_CATEGORY_TABLE.' 
    1343   SET rank = rank + 1 
    1344   WHERE category_id = '.$params['category_id'].' 
    1345     AND rank IS NOT NULL 
    1346     AND rank >= '.$params['rank'].' 
    1347 ;'; 
    1348   pwg_query($query); 
    1349  
    1350   // set the new rank for the photo 
    1351   $query = ' 
    1352 UPDATE '.IMAGE_CATEGORY_TABLE.' 
    1353   SET rank = '.$params['rank'].' 
    1354   WHERE image_id = '.$params['image_id'].' 
    1355     AND category_id = '.$params['category_id'].' 
    1356 ;'; 
    1357   pwg_query($query); 
    1358  
    1359   // return data for client 
    1360   return array( 
    1361     'image_id' => $params['image_id'], 
    1362     'category_id' => $params['category_id'], 
    1363     'rank' => $params['rank'], 
    1364     ); 
    1365 } 
    1366  
    1367 function ws_images_add_chunk($params, $service) 
    1368 { 
    1369   global $conf; 
    1370  
    1371   // data 
    1372   // original_sum 
    1373   // type {thumb, file, high} 
    1374   // position 
    1375  
    1376   foreach ($params as $param_key => $param_value) { 
    1377     if ('data' == $param_key) { 
    1378       continue; 
    1379     } 
    1380  
    1381     ws_logfile( 
    1382       sprintf( 
    1383         '[ws_images_add_chunk] input param "%s" : "%s"', 
    1384         $param_key, 
    1385         is_null($param_value) ? 'NULL' : $param_value 
    1386         ) 
    1387       ); 
    1388   } 
    1389  
    1390   $upload_dir = $conf['upload_dir'].'/buffer'; 
    1391  
    1392   // create the upload directory tree if not exists 
    1393   if (!mkgetdir($upload_dir, MKGETDIR_DEFAULT&~MKGETDIR_DIE_ON_ERROR)) 
    1394   { 
    1395     return new PwgError(500, 'error during buffer directory creation'); 
    1396   } 
    1397  
    1398   $filename = sprintf( 
    1399     '%s-%s-%05u.block', 
    1400     $params['original_sum'], 
    1401     $params['type'], 
    1402     $params['position'] 
    1403     ); 
    1404  
    1405   ws_logfile('[ws_images_add_chunk] data length : '.strlen($params['data'])); 
    1406  
    1407   $bytes_written = file_put_contents( 
    1408     $upload_dir.'/'.$filename, 
    1409     base64_decode($params['data']) 
    1410     ); 
    1411  
    1412   if (false === $bytes_written) { 
    1413     return new PwgError( 
    1414       500, 
    1415       'an error has occured while writting chunk '.$params['position'].' for '.$params['type'] 
    1416       ); 
    1417   } 
    1418 } 
    1419  
    1420 function merge_chunks($output_filepath, $original_sum, $type) 
    1421 { 
    1422   global $conf; 
    1423  
    1424   ws_logfile('[merge_chunks] input parameter $output_filepath : '.$output_filepath); 
    1425  
    1426   if (is_file($output_filepath)) 
    1427   { 
    1428     unlink($output_filepath); 
    1429  
    1430     if (is_file($output_filepath)) 
    1431     { 
    1432       return new PwgError(500, '[merge_chunks] error while trying to remove existing '.$output_filepath); 
    1433     } 
    1434   } 
    1435  
    1436   $upload_dir = $conf['upload_dir'].'/buffer'; 
    1437   $pattern = '/'.$original_sum.'-'.$type.'/'; 
    1438   $chunks = array(); 
    1439  
    1440   if ($handle = opendir($upload_dir)) 
    1441   { 
    1442     while (false !== ($file = readdir($handle))) 
    1443     { 
    1444       if (preg_match($pattern, $file)) 
    1445       { 
    1446         ws_logfile($file); 
    1447         $chunks[] = $upload_dir.'/'.$file; 
    1448       } 
    1449     } 
    1450     closedir($handle); 
    1451   } 
    1452  
    1453   sort($chunks); 
    1454  
    1455   if (function_exists('memory_get_usage')) { 
    1456     ws_logfile('[merge_chunks] memory_get_usage before loading chunks: '.memory_get_usage()); 
    1457   } 
    1458  
    1459   $i = 0; 
    1460  
    1461   foreach ($chunks as $chunk) 
    1462   { 
    1463     $string = file_get_contents($chunk); 
    1464  
    1465     if (function_exists('memory_get_usage')) { 
    1466       ws_logfile('[merge_chunks] memory_get_usage on chunk '.++$i.': '.memory_get_usage()); 
    1467     } 
    1468  
    1469     if (!file_put_contents($output_filepath, $string, FILE_APPEND)) 
    1470     { 
    1471       return new PwgError(500, '[merge_chunks] error while writting chunks for '.$output_filepath); 
    1472     } 
    1473  
    1474     unlink($chunk); 
    1475   } 
    1476  
    1477   if (function_exists('memory_get_usage')) { 
    1478     ws_logfile('[merge_chunks] memory_get_usage after loading chunks: '.memory_get_usage()); 
    1479   } 
    1480 } 
    1481  
    1482 /** 
    1483  * Function introduced for Piwigo 2.4 and the new "multiple size" 
    1484  * (derivatives) feature. As we only need the biggest sent photo as 
    1485  * "original", we remove chunks for smaller sizes. We can't make it earlier 
    1486  * in ws_images_add_chunk because at this moment we don't know which $type 
    1487  * will be the biggest (we could remove the thumb, but let's use the same 
    1488  * algorithm) 
    1489  */ 
    1490 function remove_chunks($original_sum, $type) 
    1491 { 
    1492   global $conf; 
    1493  
    1494   $upload_dir = $conf['upload_dir'].'/buffer'; 
    1495   $pattern = '/'.$original_sum.'-'.$type.'/'; 
    1496   $chunks = array(); 
    1497  
    1498   if ($handle = opendir($upload_dir)) 
    1499   { 
    1500     while (false !== ($file = readdir($handle))) 
    1501     { 
    1502       if (preg_match($pattern, $file)) 
    1503       { 
    1504         $chunks[] = $upload_dir.'/'.$file; 
    1505       } 
    1506     } 
    1507     closedir($handle); 
    1508   } 
    1509  
    1510   foreach ($chunks as $chunk) 
    1511   { 
    1512     unlink($chunk); 
    1513   } 
    1514 } 
    1515  
    1516 function ws_images_addFile($params, $service) 
    1517 { 
    1518   ws_logfile(__FUNCTION__.', input :  '.var_export($params, true)); 
    1519   // image_id 
    1520   // type {thumb, file, high} 
    1521   // sum -> not used currently (Piwigo 2.4) 
    1522  
    1523   global $conf; 
    1524  
    1525   // 
    1526   // what is the path and other infos about the photo? 
    1527   // 
    1528   $query = ' 
    1529 SELECT 
    1530     path, 
    1531     file, 
    1532     md5sum, 
    1533     width, 
    1534     height, 
    1535     filesize 
    1536   FROM '.IMAGES_TABLE.' 
    1537   WHERE id = '.$params['image_id'].' 
    1538 ;'; 
    1539   $result = pwg_query($query); 
    1540  
    1541   if (pwg_db_num_rows($result) == 0) 
    1542   { 
    1543     return new PwgError(404, "image_id not found"); 
    1544   } 
    1545    
    1546   $image = pwg_db_fetch_assoc($result); 
    1547  
    1548   // since Piwigo 2.4 and derivatives, we do not take the imported "thumb" 
    1549   // into account 
    1550   if ('thumb' == $params['type']) 
    1551   { 
    1552     remove_chunks($image['md5sum'], $type); 
    1553     return true; 
    1554   } 
    1555  
    1556   // since Piwigo 2.4 and derivatives, we only care about the "original" 
    1557   $original_type = 'file'; 
    1558   if ('high' == $params['type']) 
    1559   { 
    1560     $original_type = 'high'; 
    1561   } 
    1562  
    1563   $file_path = $conf['upload_dir'].'/buffer/'.$image['md5sum'].'-original'; 
    1564  
    1565   merge_chunks($file_path, $image['md5sum'], $original_type); 
    1566   chmod($file_path, 0644); 
    1567  
    1568   include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 
    1569  
    1570   // if we receive the "file", we only update the original if the "file" is 
    1571   // bigger than current original 
    1572   if ('file' == $params['type']) 
    1573   { 
    1574     $do_update = false; 
    1575  
    1576     $infos = pwg_image_infos($file_path); 
    1577  
    1578     foreach (array('width', 'height', 'filesize') as $image_info) 
    1579     { 
    1580       if ($infos[$image_info] > $image[$image_info]) 
    1581       { 
    1582         $do_update = true; 
    1583       } 
    1584     } 
    1585  
    1586     if (!$do_update) 
    1587     { 
    1588       unlink($file_path); 
    1589       return true; 
    1590     } 
    1591   } 
    1592  
    1593   $image_id = add_uploaded_file( 
    1594     $file_path, 
    1595     $image['file'], 
    1596     null, 
    1597     null, 
    1598     $params['image_id'], 
    1599     $image['md5sum'] // we force the md5sum to remain the same 
    1600     ); 
    1601 } 
    1602  
    1603 function ws_images_add($params, $service) 
    1604 { 
    1605   global $conf, $user; 
    1606  
    1607   foreach ($params as $param_key => $param_value) { 
    1608     ws_logfile( 
    1609       sprintf( 
    1610         '[pwg.images.add] input param "%s" : "%s"', 
    1611         $param_key, 
    1612         is_null($param_value) ? 'NULL' : $param_value 
    1613         ) 
    1614       ); 
    1615   } 
    1616  
    1617   if ($params['image_id'] > 0) 
    1618   { 
    1619     $query=' 
    1620 SELECT COUNT(*) 
    1621   FROM '.IMAGES_TABLE.' 
    1622   WHERE id = '.$params['image_id'].' 
    1623 ;'; 
    1624  
    1625     list($count) = pwg_db_fetch_row(pwg_query($query)); 
    1626     if ($count == 0) 
    1627     { 
    1628       return new PwgError(404, "image_id not found"); 
    1629     } 
    1630   } 
    1631  
    1632   // does the image already exists ? 
    1633   if ($params['check_uniqueness']) 
    1634   { 
    1635     if ('md5sum' == $conf['uniqueness_mode']) 
    1636     { 
    1637       $where_clause = "md5sum = '".$params['original_sum']."'"; 
    1638     } 
    1639     if ('filename' == $conf['uniqueness_mode']) 
    1640     { 
    1641       $where_clause = "file = '".$params['original_filename']."'"; 
    1642     } 
    1643  
    1644     $query = ' 
    1645 SELECT COUNT(*) 
    1646   FROM '.IMAGES_TABLE.' 
    1647   WHERE '.$where_clause.' 
    1648 ;'; 
    1649     list($counter) = pwg_db_fetch_row(pwg_query($query)); 
    1650     if ($counter != 0) { 
    1651       return new PwgError(500, 'file already exists'); 
    1652     } 
    1653   } 
    1654  
    1655   // due to the new feature "derivatives" (multiple sizes) introduced for 
    1656   // Piwigo 2.4, we only take the biggest photos sent on 
    1657   // pwg.images.addChunk. If "high" is available we use it as "original" 
    1658   // else we use "file". 
    1659   remove_chunks($params['original_sum'], 'thumb'); 
    1660  
    1661   if (isset($params['high_sum'])) 
    1662   { 
    1663     $original_type = 'high'; 
    1664     remove_chunks($params['original_sum'], 'file'); 
    1665   } 
    1666   else 
    1667   { 
    1668     $original_type = 'file'; 
    1669   } 
    1670  
    1671   $file_path = $conf['upload_dir'].'/buffer/'.$params['original_sum'].'-original'; 
    1672  
    1673   merge_chunks($file_path, $params['original_sum'], $original_type); 
    1674   chmod($file_path, 0644); 
    1675  
    1676   include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 
    1677  
    1678   $image_id = add_uploaded_file( 
    1679     $file_path, 
    1680     $params['original_filename'], 
    1681     null, // categories 
    1682     isset($params['level']) ? $params['level'] : null, 
    1683     $params['image_id'] > 0 ? $params['image_id'] : null, 
    1684     $params['original_sum'] 
    1685     ); 
    1686  
    1687   $info_columns = array( 
    1688     'name', 
    1689     'author', 
    1690     'comment', 
    1691     'date_creation', 
    1692     ); 
    1693  
    1694   $update = array(); 
    1695  
    1696   foreach ($info_columns as $key) 
    1697   { 
    1698     if (isset($params[$key])) 
    1699     { 
    1700       $update[$key] = $params[$key]; 
    1701     } 
    1702   } 
    1703  
    1704   if (count(array_keys($update)) > 0) 
    1705   { 
    1706     single_update( 
    1707       IMAGES_TABLE, 
    1708       $update, 
    1709       array('id' => $image_id) 
    1710       ); 
    1711   } 
    1712  
    1713   $url_params = array('image_id' => $image_id); 
    1714  
    1715   // let's add links between the image and the categories 
    1716   if (isset($params['categories'])) 
    1717   { 
    1718     ws_add_image_category_relations($image_id, $params['categories']); 
    1719  
    1720     if (preg_match('/^\d+/', $params['categories'], $matches)) { 
    1721       $category_id = $matches[0]; 
    1722  
    1723       $query = ' 
    1724 SELECT id, name, permalink 
    1725   FROM '.CATEGORIES_TABLE.' 
    1726   WHERE id = '.$category_id.' 
    1727 ;'; 
    1728       $result = pwg_query($query); 
    1729       $category = pwg_db_fetch_assoc($result); 
    1730  
    1731       $url_params['section'] = 'categories'; 
    1732       $url_params['category'] = $category; 
    1733     } 
    1734   } 
    1735  
    1736   // and now, let's create tag associations 
    1737   if (isset($params['tag_ids']) and !empty($params['tag_ids'])) 
    1738   { 
    1739     set_tags( 
    1740       explode(',', $params['tag_ids']), 
    1741       $image_id 
    1742       ); 
    1743   } 
    1744  
    1745   invalidate_user_cache(); 
    1746  
    1747   return array( 
    1748     'image_id' => $image_id, 
    1749     'url' => make_picture_url($url_params), 
    1750     ); 
    1751 } 
    1752  
    1753 function ws_images_addSimple($params, $service) 
    1754 { 
    1755   global $conf; 
    1756  
    1757   if (!isset($_FILES['image'])) 
    1758   { 
    1759     return new PwgError(405, "The image (file) is missing"); 
    1760   } 
    1761  
    1762   if ($params['image_id'] > 0) 
    1763   { 
    1764     $query=' 
    1765 SELECT COUNT(*) 
    1766   FROM '.IMAGES_TABLE.' 
    1767   WHERE id = '.$params['image_id'].' 
    1768 ;'; 
    1769  
    1770     list($count) = pwg_db_fetch_row(pwg_query($query)); 
    1771     if ($count == 0) 
    1772     { 
    1773       return new PwgError(404, "image_id not found"); 
    1774     } 
    1775   } 
    1776  
    1777   include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 
    1778  
    1779   $image_id = add_uploaded_file( 
    1780     $_FILES['image']['tmp_name'], 
    1781     $_FILES['image']['name'], 
    1782     $params['category'], 
    1783     8, 
    1784     $params['image_id'] > 0 ? $params['image_id'] : null 
    1785     ); 
    1786  
    1787   $info_columns = array( 
    1788     'name', 
    1789     'author', 
    1790     'comment', 
    1791     'level', 
    1792     'date_creation', 
    1793     ); 
    1794  
    1795   foreach ($info_columns as $key) 
    1796   { 
    1797     if (isset($params[$key])) 
    1798     { 
    1799       $update[$key] = $params[$key]; 
    1800     } 
    1801   } 
    1802  
    1803   if (count($update) > 0) 
    1804   { 
    1805     $update['id'] = $image_id; 
    1806      
    1807     single_update( 
    1808       IMAGES_TABLE, 
    1809       $update, 
    1810       array('id' => $update['id']) 
    1811       ); 
    1812   } 
    1813  
    1814  
    1815   if (isset($params['tags']) and !empty($params['tags'])) 
    1816   { 
    1817     include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    1818      
    1819     $tag_ids = array(); 
    1820     if (is_array($params['tags'])) 
    1821     { 
    1822       foreach ($params['tags'] as $tag_name) 
    1823       { 
    1824         $tag_ids[] = tag_id_from_tag_name($tag_name); 
    1825       } 
    1826     } 
    1827     else 
    1828     { 
    1829       $tag_names = preg_split('~(?<!\\\),~', $params['tags']); 
    1830       foreach ($tag_names as $tag_name) 
    1831       { 
    1832         $tag_ids[] = tag_id_from_tag_name(preg_replace('#\\\\*,#', ',', $tag_name)); 
    1833       } 
    1834     } 
    1835  
    1836     add_tags($tag_ids, array($image_id)); 
    1837   } 
    1838  
    1839   $url_params = array('image_id' => $image_id); 
    1840  
    1841   if (!empty($params['category'])) 
    1842   { 
    1843     $query = ' 
    1844 SELECT id, name, permalink 
    1845   FROM '.CATEGORIES_TABLE.' 
    1846   WHERE id = '.$params['category'][0].' 
    1847 ;'; 
    1848     $result = pwg_query($query); 
    1849     $category = pwg_db_fetch_assoc($result); 
    1850  
    1851     $url_params['section'] = 'categories'; 
    1852     $url_params['category'] = $category; 
    1853   } 
    1854  
    1855   // update metadata from the uploaded file (exif/iptc), even if the sync 
    1856   // was already performed by add_uploaded_file(). 
    1857  
    1858   require_once(PHPWG_ROOT_PATH.'admin/include/functions_metadata.php'); 
    1859   sync_metadata(array($image_id)); 
    1860  
    1861   return array( 
    1862     'image_id' => $image_id, 
    1863     'url' => make_picture_url($url_params), 
    1864     ); 
    1865 } 
    1866  
    1867 function ws_rates_delete($params, $service) 
    1868 { 
    1869   $query = ' 
    1870 DELETE FROM '.RATE_TABLE.' 
    1871   WHERE user_id='.$params['user_id']; 
    1872  
    1873   if (!empty($params['anonymous_id'])) 
    1874   { 
    1875     $query .= ' AND anonymous_id=\''.$params['anonymous_id'].'\''; 
    1876   } 
    1877  
    1878   $changes = pwg_db_changes(pwg_query($query)); 
    1879   if ($changes) 
    1880   { 
    1881     include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php'); 
    1882     update_rating_score(); 
    1883   } 
    1884   return $changes; 
    1885 } 
    1886  
    1887  
    1888 /** 
    1889  * perform a login (web service method) 
    1890  */ 
    1891 function ws_session_login($params, $service) 
    1892 { 
    1893   if (try_log_user($params['username'], $params['password'],false)) 
    1894   { 
    1895     return true; 
    1896   } 
    1897   return new PwgError(999, 'Invalid username/password'); 
    1898 } 
    1899  
    1900  
    1901 /** 
    1902  * performs a logout (web service method) 
    1903  */ 
    1904 function ws_session_logout($params, $service) 
    1905 { 
    1906   if (!is_a_guest()) 
    1907   { 
    1908     logout_user(); 
    1909   } 
    1910   return true; 
    1911 } 
    1912  
    1913 function ws_session_getStatus($params, $service) 
    1914 { 
    1915   global $user; 
    1916   $res = array(); 
    1917   $res['username'] = is_a_guest() ? 'guest' : stripslashes($user['username']); 
    1918   foreach ( array('status', 'theme', 'language') as $k ) 
    1919   { 
    1920     $res[$k] = $user[$k]; 
    1921   } 
    1922   $res['pwg_token'] = get_pwg_token(); 
    1923   $res['charset'] = get_pwg_charset(); 
    1924  
    1925   list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();')); 
    1926   $res['current_datetime'] = $dbnow; 
    1927  
    1928   return $res; 
    1929 } 
    1930  
    1931  
    1932 /** 
    1933  * returns a list of tags (web service method) 
    1934  */ 
    1935 function ws_tags_getList($params, $service) 
    1936 { 
    1937   $tags = get_available_tags(); 
    1938   if ($params['sort_by_counter']) 
    1939   { 
    1940     usort($tags, create_function('$a,$b', 'return -$a["counter"]+$b["counter"];') ); 
    1941   } 
    1942   else 
    1943   { 
    1944     usort($tags, 'tag_alpha_compare'); 
    1945   } 
    1946   for ($i=0; $i<count($tags); $i++) 
    1947   { 
    1948     $tags[$i]['id'] = (int)$tags[$i]['id']; 
    1949     $tags[$i]['counter'] = (int)$tags[$i]['counter']; 
    1950     $tags[$i]['url'] = make_index_url( 
    1951         array( 
    1952           'section'=>'tags', 
    1953           'tags'=>array($tags[$i]) 
    1954         ) 
    1955       ); 
    1956   } 
    1957   return array('tags' => new PwgNamedArray($tags, 'tag', ws_std_get_tag_xml_attributes()) ); 
    1958 } 
    1959  
    1960 /** 
    1961  * returns the list of tags as you can see them in administration (web 
    1962  * service method). 
    1963  * 
    1964  * Only admin can run this method and permissions are not taken into 
    1965  * account. 
    1966  */ 
    1967 function ws_tags_getAdminList($params, $service) 
    1968 { 
    1969   $tags = get_all_tags(); 
    1970   return array( 
    1971     'tags' => new PwgNamedArray( 
    1972       $tags, 
    1973       'tag', 
    1974       ws_std_get_tag_xml_attributes() 
    1975       ) 
    1976     ); 
    1977 } 
    1978  
    1979 /** 
    1980  * returns a list of images for tags (web service method) 
    1981  */ 
    1982 function ws_tags_getImages($params, $service) 
    1983 { 
    1984   global $conf; 
    1985  
    1986   // first build all the tag_ids we are interested in 
    1987   $tags = find_tags($params['tag_id'], $params['tag_url_name'], $params['tag_name']); 
    1988   $tags_by_id = array(); 
    1989   foreach( $tags as $tag ) 
    1990   { 
    1991     $tags['id'] = (int)$tag['id']; 
    1992     $tags_by_id[ $tag['id'] ] = $tag; 
    1993   } 
    1994   unset($tags); 
    1995   $tag_ids = array_keys($tags_by_id); 
    1996  
    1997  
    1998   $where_clauses = ws_std_image_sql_filter($params); 
    1999   if (!empty($where_clauses)) 
    2000   { 
    2001     $where_clauses = implode( ' AND ', $where_clauses); 
    2002   } 
    2003   $image_ids = get_image_ids_for_tags( 
    2004     $tag_ids, 
    2005     $params['tag_mode_and'] ? 'AND' : 'OR', 
    2006     $where_clauses, 
    2007     ws_std_image_sql_order($params) ); 
    2008  
    2009   $count_set = count($image_ids); 
    2010   $image_ids = array_slice($image_ids, $params['per_page']*$params['page'], $params['per_page'] ); 
    2011  
    2012   $image_tag_map = array(); 
    2013   if ( !empty($image_ids) and !$params['tag_mode_and'] ) 
    2014   { // build list of image ids with associated tags per image 
    2015     $query = ' 
    2016 SELECT image_id, GROUP_CONCAT(tag_id) AS tag_ids 
    2017   FROM '.IMAGE_TAG_TABLE.' 
    2018   WHERE tag_id IN ('.implode(',',$tag_ids).') AND image_id IN ('.implode(',',$image_ids).') 
    2019   GROUP BY image_id'; 
    2020     $result = pwg_query($query); 
    2021     while ( $row=pwg_db_fetch_assoc($result) ) 
    2022     { 
    2023       $row['image_id'] = (int)$row['image_id']; 
    2024       $image_ids[] = $row['image_id']; 
    2025       $image_tag_map[ $row['image_id'] ] = explode(',', $row['tag_ids']); 
    2026     } 
    2027   } 
    2028  
    2029   $images = array(); 
    2030   if (!empty($image_ids)) 
    2031   { 
    2032     $rank_of = array_flip($image_ids); 
    2033     $result = pwg_query(' 
    2034 SELECT * FROM '.IMAGES_TABLE.' 
    2035   WHERE id IN ('.implode(',',$image_ids).')'); 
    2036     while ($row = pwg_db_fetch_assoc($result)) 
    2037     { 
    2038       $image = array(); 
    2039       $image['rank'] = $rank_of[ $row['id'] ]; 
    2040       foreach ( array('id', 'width', 'height', 'hit') as $k ) 
    2041       { 
    2042         if (isset($row[$k])) 
    2043         { 
    2044           $image[$k] = (int)$row[$k]; 
    2045         } 
    2046       } 
    2047       foreach ( array('file', 'name', 'comment', 'date_creation', 'date_available') as $k ) 
    2048       { 
    2049         $image[$k] = $row[$k]; 
    2050       } 
    2051       $image = array_merge( $image, ws_std_get_urls($row) ); 
    2052  
    2053       $image_tag_ids = ($params['tag_mode_and']) ? $tag_ids : $image_tag_map[$image['id']]; 
    2054       $image_tags = array(); 
    2055       foreach ($image_tag_ids as $tag_id) 
    2056       { 
    2057         $url = make_index_url( 
    2058                  array( 
    2059                   'section'=>'tags', 
    2060                   'tags'=> array($tags_by_id[$tag_id]) 
    2061                 ) 
    2062               ); 
    2063         $page_url = make_picture_url( 
    2064                  array( 
    2065                   'section'=>'tags', 
    2066                   'tags'=> array($tags_by_id[$tag_id]), 
    2067                   'image_id' => $row['id'], 
    2068                   'image_file' => $row['file'], 
    2069                 ) 
    2070               ); 
    2071         $image_tags[] = array( 
    2072                 'id' => (int)$tag_id, 
    2073                 'url' => $url, 
    2074                 'page_url' => $page_url, 
    2075               ); 
    2076       } 
    2077       $image['tags'] = new PwgNamedArray($image_tags, 'tag', ws_std_get_tag_xml_attributes() ); 
    2078       $images[] = $image; 
    2079     } 
    2080     usort($images, 'rank_compare'); 
    2081     unset($rank_of); 
    2082   } 
    2083  
    2084   return array(  
    2085       'paging' => new PwgNamedStruct( 
    2086         array( 
    2087           'page' => $params['page'], 
    2088           'per_page' => $params['per_page'], 
    2089           'count' => count($images), 
    2090           'total_count' => $count_set, 
    2091           ) ), 
    2092        'images' => new PwgNamedArray($images, 'image', 
    2093           ws_std_get_image_xml_attributes() ) 
    2094     ); 
    2095 } 
    2096  
    2097 function ws_categories_add($params, $service) 
    2098 { 
    2099   if (!is_admin()) 
    2100   { 
    2101     return new PwgError(401, 'Access denied'); 
    2102   } 
    2103  
    2104   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2105  
    2106   $options = array(); 
    2107   if (!empty($params['status']) and in_array($params['status'], array('private','public'))) 
    2108   { 
    2109     $options['status'] = $params['status']; 
    2110   } 
    2111    
    2112   if (!empty($params['comment'])) 
    2113   { 
    2114     $options['comment'] = $params['comment']; 
    2115   } 
    2116    
    2117  
    2118   $creation_output = create_virtual_category( 
    2119     $params['name'], 
    2120     $params['parent'], 
    2121     $options 
    2122     ); 
    2123  
    2124   if (isset($creation_output['error'])) 
    2125   { 
    2126     return new PwgError(500, $creation_output['error']); 
    2127   } 
    2128  
    2129   invalidate_user_cache(); 
    2130  
    2131   return $creation_output; 
    2132 } 
    2133  
    2134 function ws_tags_add($params, $service) 
    2135 { 
    2136   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2137  
    2138   $creation_output = create_tag($params['name']); 
    2139  
    2140   if (isset($creation_output['error'])) 
    2141   { 
    2142     return new PwgError(500, $creation_output['error']); 
    2143   } 
    2144  
    2145   return $creation_output; 
    2146 } 
    2147  
    2148 function ws_images_exist($params, $service) 
    2149 { 
    2150   ws_logfile(__FUNCTION__.' '.var_export($params, true)); 
    2151  
    2152   global $conf; 
    2153  
    2154   $split_pattern = '/[\s,;\|]/'; 
    2155  
    2156   if ('md5sum' == $conf['uniqueness_mode']) 
    2157   { 
    2158     // search among photos the list of photos already added, based on md5sum 
    2159     // list 
    2160     $md5sums = preg_split( 
    2161       $split_pattern, 
    2162       $params['md5sum_list'], 
    2163       -1, 
    2164       PREG_SPLIT_NO_EMPTY 
    2165     ); 
    2166  
    2167     $query = ' 
    2168 SELECT 
    2169     id, 
    2170     md5sum 
    2171   FROM '.IMAGES_TABLE.' 
    2172   WHERE md5sum IN (\''.implode("','", $md5sums).'\') 
    2173 ;'; 
    2174     $id_of_md5 = simple_hash_from_query($query, 'md5sum', 'id'); 
    2175  
    2176     $result = array(); 
    2177  
    2178     foreach ($md5sums as $md5sum) 
    2179     { 
    2180       $result[$md5sum] = null; 
    2181       if (isset($id_of_md5[$md5sum])) 
    2182       { 
    2183         $result[$md5sum] = $id_of_md5[$md5sum]; 
    2184       } 
    2185     } 
    2186   } 
    2187   else if ('filename' == $conf['uniqueness_mode']) 
    2188   { 
    2189     // search among photos the list of photos already added, based on 
    2190     // filename list 
    2191     $filenames = preg_split( 
    2192       $split_pattern, 
    2193       $params['filename_list'], 
    2194       -1, 
    2195       PREG_SPLIT_NO_EMPTY 
    2196     ); 
    2197  
    2198     $query = ' 
    2199 SELECT 
    2200     id, 
    2201     file 
    2202   FROM '.IMAGES_TABLE.' 
    2203   WHERE file IN (\''.implode("','", $filenames).'\') 
    2204 ;'; 
    2205     $id_of_filename = simple_hash_from_query($query, 'file', 'id'); 
    2206  
    2207     $result = array(); 
    2208  
    2209     foreach ($filenames as $filename) 
    2210     { 
    2211       $result[$filename] = null; 
    2212       if (isset($id_of_filename[$filename])) 
    2213       { 
    2214         $result[$filename] = $id_of_filename[$filename]; 
    2215       } 
    2216     } 
    2217   } 
    2218  
    2219   return $result; 
    2220 } 
    2221  
    2222 function ws_images_checkFiles($params, $service) 
    2223 { 
    2224   ws_logfile(__FUNCTION__.', input :  '.var_export($params, true)); 
    2225  
    2226   // input parameters 
    2227   // 
    2228   // image_id 
    2229   // thumbnail_sum 
    2230   // file_sum 
    2231   // high_sum 
    2232  
    2233   $query = ' 
    2234 SELECT 
    2235     path 
    2236   FROM '.IMAGES_TABLE.' 
    2237   WHERE id = '.$params['image_id'].' 
    2238 ;'; 
    2239   $result = pwg_query($query); 
    2240   if (pwg_db_num_rows($result) == 0) 
    2241   { 
    2242     return new PwgError(404, "image_id not found"); 
    2243   } 
    2244   list($path) = pwg_db_fetch_row($result); 
    2245  
    2246   $ret = array(); 
    2247  
    2248   if (isset($params['thumbnail_sum'])) 
    2249   { 
    2250     // We always say the thumbnail is equal to create no reaction on the 
    2251     // other side. Since Piwigo 2.4 and derivatives, the thumbnails and web 
    2252     // sizes are always generated by Piwigo 
    2253     $ret['thumbnail'] = 'equals'; 
    2254   } 
    2255  
    2256   if (isset($params['high_sum'])) 
    2257   { 
    2258     $ret['file'] = 'equals'; 
    2259     $compare_type = 'high'; 
    2260   } 
    2261   elseif (isset($params['file_sum'])) 
    2262   { 
    2263     $compare_type = 'file'; 
    2264   } 
    2265  
    2266   if (isset($compare_type)) 
    2267   { 
    2268     ws_logfile(__FUNCTION__.', md5_file($path) = '.md5_file($path)); 
    2269     if (md5_file($path) != $params[$compare_type.'_sum']) 
    2270     { 
    2271       $ret[$compare_type] = 'differs'; 
    2272     } 
    2273     else 
    2274     { 
    2275       $ret[$compare_type] = 'equals'; 
    2276     } 
    2277   } 
    2278  
    2279   ws_logfile(__FUNCTION__.', output :  '.var_export($ret, true)); 
    2280  
    2281   return $ret; 
    2282 } 
    2283  
    2284 function ws_images_setInfo($params, $service) 
    2285 { 
    2286   global $conf; 
    2287  
    2288   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2289  
    2290   $query=' 
    2291 SELECT * 
    2292   FROM '.IMAGES_TABLE.' 
    2293   WHERE id = '.$params['image_id'].' 
    2294 ;'; 
    2295   $result = pwg_query($query); 
    2296    
    2297   if (pwg_db_num_rows($result) == 0) 
    2298   { 
    2299     return new PwgError(404, "image_id not found"); 
    2300   } 
    2301    
    2302   $image_row = pwg_db_fetch_assoc($result); 
    2303  
    2304   // database registration 
    2305   $update = array(); 
    2306  
    2307   $info_columns = array( 
    2308     'name', 
    2309     'author', 
    2310     'comment', 
    2311     'level', 
    2312     'date_creation', 
    2313     ); 
    2314  
    2315   foreach ($info_columns as $key) 
    2316   { 
    2317     if (isset($params[$key])) 
    2318     { 
    2319       if ('fill_if_empty' == $params['single_value_mode']) 
    2320       { 
    2321         if (empty($image_row[$key])) 
    2322         { 
    2323           $update[$key] = $params[$key]; 
    2324         } 
    2325       } 
    2326       elseif ('replace' == $params['single_value_mode']) 
    2327       { 
    2328         $update[$key] = $params[$key]; 
    2329       } 
    2330       else 
    2331       { 
    2332         return new PwgError( 
    2333           500, 
    2334           '[ws_images_setInfo]' 
    2335           .' invalid parameter single_value_mode "'.$params['single_value_mode'].'"' 
    2336           .', possible values are {fill_if_empty, replace}.' 
    2337           ); 
    2338       } 
    2339     } 
    2340   } 
    2341  
    2342   if (isset($params['file'])) 
    2343   { 
    2344     if (!empty($image_row['storage_category_id'])) 
    2345     { 
    2346       return new PwgError(500, '[ws_images_setInfo] updating "file" is forbidden on photos added by synchronization'); 
    2347     } 
    2348  
    2349     $update['file'] = $params['file']; 
    2350   } 
    2351  
    2352   if (count(array_keys($update)) > 0) 
    2353   { 
    2354     $update['id'] = $params['image_id']; 
    2355  
    2356     single_update( 
    2357       IMAGES_TABLE, 
    2358       $update, 
    2359       array('id' => $update['id']) 
    2360       ); 
    2361   } 
    2362  
    2363   if (isset($params['categories'])) 
    2364   { 
    2365     ws_add_image_category_relations( 
    2366       $params['image_id'], 
    2367       $params['categories'], 
    2368       ('replace' == $params['multiple_value_mode'] ? true : false) 
    2369       ); 
    2370   } 
    2371  
    2372   // and now, let's create tag associations 
    2373   if (isset($params['tag_ids'])) 
    2374   { 
    2375     $tag_ids = array(); 
    2376  
    2377     foreach (explode(',', $params['tag_ids']) as $candidate) 
    2378     { 
    2379       $candidate = trim($candidate); 
    2380  
    2381       if (preg_match(PATTERN_ID, $candidate)) 
    2382       { 
    2383         $tag_ids[] = $candidate; 
    2384       } 
    2385     } 
    2386  
    2387     if ('replace' == $params['multiple_value_mode']) 
    2388     { 
    2389       set_tags( 
    2390         $tag_ids, 
    2391         $params['image_id'] 
    2392         ); 
    2393     } 
    2394     elseif ('append' == $params['multiple_value_mode']) 
    2395     { 
    2396       add_tags( 
    2397         $tag_ids, 
    2398         array($params['image_id']) 
    2399         ); 
    2400     } 
    2401     else 
    2402     { 
    2403       return new PwgError( 
    2404         500, 
    2405         '[ws_images_setInfo]' 
    2406         .' invalid parameter multiple_value_mode "'.$params['multiple_value_mode'].'"' 
    2407         .', possible values are {replace, append}.' 
    2408         ); 
    2409     } 
    2410   } 
    2411  
    2412   invalidate_user_cache(); 
    2413 } 
    2414  
    2415 function ws_images_delete($params, $service) 
    2416 { 
    2417   global $conf; 
    2418  
    2419   if (get_pwg_token() != $params['pwg_token']) 
    2420   { 
    2421     return new PwgError(403, 'Invalid security token'); 
    2422   } 
    2423  
    2424   if (!is_array($params['image_id'])) 
    2425   { 
    2426     $params['image_id'] = preg_split( 
    2427       '/[\s,;\|]/', 
    2428       $params['image_id'], 
    2429       -1, 
    2430       PREG_SPLIT_NO_EMPTY 
    2431       ); 
    2432   } 
    2433   $params['image_id'] = array_map('intval', $params['image_id']); 
    2434  
    2435   $image_ids = array(); 
    2436   foreach ($params['image_id'] as $image_id) 
    2437   { 
    2438     if ($image_id > 0) 
    2439     { 
    2440       $image_ids[] = $image_id; 
    2441     } 
    2442   } 
    2443  
    2444   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2445   delete_elements($image_ids, true); 
    2446   invalidate_user_cache(); 
    2447 } 
    2448  
    2449 function ws_add_image_category_relations($image_id, $categories_string, $replace_mode=false) 
    2450 { 
    2451   // let's add links between the image and the categories 
    2452   // 
    2453   // $params['categories'] should look like 123,12;456,auto;789 which means: 
    2454   // 
    2455   // 1. associate with category 123 on rank 12 
    2456   // 2. associate with category 456 on automatic rank 
    2457   // 3. associate with category 789 on automatic rank 
    2458   $cat_ids = array(); 
    2459   $rank_on_category = array(); 
    2460   $search_current_ranks = false; 
    2461  
    2462   $tokens = explode(';', $categories_string); 
    2463   foreach ($tokens as $token) 
    2464   { 
    2465     @list($cat_id, $rank) = explode(',', $token); 
    2466  
    2467     if (!preg_match('/^\d+$/', $cat_id)) 
    2468     { 
    2469       continue; 
    2470     } 
    2471  
    2472     $cat_ids[] = $cat_id; 
    2473  
    2474     if (!isset($rank)) 
    2475     { 
    2476       $rank = 'auto'; 
    2477     } 
    2478     $rank_on_category[$cat_id] = $rank; 
    2479  
    2480     if ($rank == 'auto') 
    2481     { 
    2482       $search_current_ranks = true; 
    2483     } 
    2484   } 
    2485  
    2486   $cat_ids = array_unique($cat_ids); 
    2487  
    2488   if (count($cat_ids) == 0) 
    2489   { 
    2490     return new PwgError( 
    2491       500, 
    2492       '[ws_add_image_category_relations] there is no category defined in "'.$categories_string.'"' 
    2493       ); 
    2494   } 
    2495  
    2496   $query = ' 
    2497 SELECT 
    2498     id 
    2499   FROM '.CATEGORIES_TABLE.' 
    2500   WHERE id IN ('.implode(',', $cat_ids).') 
    2501 ;'; 
    2502   $db_cat_ids = array_from_query($query, 'id'); 
    2503  
    2504   $unknown_cat_ids = array_diff($cat_ids, $db_cat_ids); 
    2505   if (count($unknown_cat_ids) != 0) 
    2506   { 
    2507     return new PwgError( 
    2508       500, 
    2509       '[ws_add_image_category_relations] the following categories are unknown: '.implode(', ', $unknown_cat_ids) 
    2510       ); 
    2511   } 
    2512  
    2513   $to_update_cat_ids = array(); 
    2514  
    2515   // in case of replace mode, we first check the existing associations 
    2516   $query = ' 
    2517 SELECT 
    2518     category_id 
    2519   FROM '.IMAGE_CATEGORY_TABLE.' 
    2520   WHERE image_id = '.$image_id.' 
    2521 ;'; 
    2522   $existing_cat_ids = array_from_query($query, 'category_id'); 
    2523  
    2524   if ($replace_mode) 
    2525   { 
    2526     $to_remove_cat_ids = array_diff($existing_cat_ids, $cat_ids); 
    2527     if (count($to_remove_cat_ids) > 0) 
    2528     { 
    2529       $query = ' 
    2530 DELETE 
    2531   FROM '.IMAGE_CATEGORY_TABLE.' 
    2532   WHERE image_id = '.$image_id.' 
    2533     AND category_id IN ('.implode(', ', $to_remove_cat_ids).') 
    2534 ;'; 
    2535       pwg_query($query); 
    2536       update_category($to_remove_cat_ids); 
    2537     } 
    2538   } 
    2539  
    2540   $new_cat_ids = array_diff($cat_ids, $existing_cat_ids); 
    2541   if (count($new_cat_ids) == 0) 
    2542   { 
    2543     return true; 
    2544   } 
    2545  
    2546   if ($search_current_ranks) 
    2547   { 
    2548     $query = ' 
    2549 SELECT 
    2550     category_id, 
    2551     MAX(rank) AS max_rank 
    2552   FROM '.IMAGE_CATEGORY_TABLE.' 
    2553   WHERE rank IS NOT NULL 
    2554     AND category_id IN ('.implode(',', $new_cat_ids).') 
    2555   GROUP BY category_id 
    2556 ;'; 
    2557     $current_rank_of = simple_hash_from_query( 
    2558       $query, 
    2559       'category_id', 
    2560       'max_rank' 
    2561       ); 
    2562  
    2563     foreach ($new_cat_ids as $cat_id) 
    2564     { 
    2565       if (!isset($current_rank_of[$cat_id])) 
    2566       { 
    2567         $current_rank_of[$cat_id] = 0; 
    2568       } 
    2569  
    2570       if ('auto' == $rank_on_category[$cat_id]) 
    2571       { 
    2572         $rank_on_category[$cat_id] = $current_rank_of[$cat_id] + 1; 
    2573       } 
    2574     } 
    2575   } 
    2576  
    2577   $inserts = array(); 
    2578  
    2579   foreach ($new_cat_ids as $cat_id) 
    2580   { 
    2581     $inserts[] = array( 
    2582       'image_id' => $image_id, 
    2583       'category_id' => $cat_id, 
    2584       'rank' => $rank_on_category[$cat_id], 
    2585       ); 
    2586   } 
    2587  
    2588   mass_inserts( 
    2589     IMAGE_CATEGORY_TABLE, 
    2590     array_keys($inserts[0]), 
    2591     $inserts 
    2592     ); 
    2593  
    2594   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2595   update_category($new_cat_ids); 
    2596 } 
    2597  
    2598 function ws_categories_setInfo($params, $service) 
    2599 { 
    2600   global $conf; 
    2601  
    2602   // category_id 
    2603   // name 
    2604   // comment 
    2605  
    2606   // database registration 
    2607   $update = array( 
    2608     'id' => $params['category_id'], 
    2609     ); 
    2610  
    2611   $info_columns = array( 
    2612     'name', 
    2613     'comment', 
    2614     ); 
    2615  
    2616   $perform_update = false; 
    2617   foreach ($info_columns as $key) 
    2618   { 
    2619     if (isset($params[$key])) 
    2620     { 
    2621       $perform_update = true; 
    2622       $update[$key] = $params[$key]; 
    2623     } 
    2624   } 
    2625  
    2626   if ($perform_update) 
    2627   { 
    2628     single_update( 
    2629       CATEGORIES_TABLE, 
    2630       $update, 
    2631       array('id' => $update['id']) 
    2632       ); 
    2633   } 
    2634 } 
    2635  
    2636 function ws_categories_setRepresentative($params, $service) 
    2637 { 
    2638   global $conf; 
    2639  
    2640   // category_id 
    2641   // image_id 
    2642  
    2643   // does the category really exist? 
    2644   $query=' 
    2645 SELECT COUNT(*) 
    2646   FROM '.CATEGORIES_TABLE.' 
    2647   WHERE id = '.$params['category_id'].' 
    2648 ;'; 
    2649   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    2650   if ($count == 0) 
    2651   { 
    2652     return new PwgError(404, "category_id not found"); 
    2653   } 
    2654  
    2655   // does the image really exist? 
    2656   $query=' 
    2657 SELECT COUNT(*) 
    2658   FROM '.IMAGES_TABLE.' 
    2659   WHERE id = '.$params['image_id'].' 
    2660 ;'; 
    2661  
    2662   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    2663   if ($count == 0) 
    2664   { 
    2665     return new PwgError(404, "image_id not found"); 
    2666   } 
    2667  
    2668   // apply change 
    2669   $query = ' 
    2670 UPDATE '.CATEGORIES_TABLE.' 
    2671   SET representative_picture_id = '.$params['image_id'].' 
    2672   WHERE id = '.$params['category_id'].' 
    2673 ;'; 
    2674   pwg_query($query); 
    2675  
    2676   $query = ' 
    2677 UPDATE '.USER_CACHE_CATEGORIES_TABLE.' 
    2678   SET user_representative_picture_id = NULL 
    2679   WHERE cat_id = '.$params['category_id'].' 
    2680 ;'; 
    2681   pwg_query($query); 
    2682 } 
    2683  
    2684 function ws_categories_delete($params, $service) 
    2685 { 
    2686   global $conf; 
    2687  
    2688   if (get_pwg_token() != $params['pwg_token']) 
    2689   { 
    2690     return new PwgError(403, 'Invalid security token'); 
    2691   } 
    2692  
    2693   $modes = array('no_delete', 'delete_orphans', 'force_delete'); 
    2694   if (!in_array($params['photo_deletion_mode'], $modes)) 
    2695   { 
    2696     return new PwgError( 
    2697       500, 
    2698       '[ws_categories_delete]' 
    2699       .' invalid parameter photo_deletion_mode "'.$params['photo_deletion_mode'].'"' 
    2700       .', possible values are {'.implode(', ', $modes).'}.' 
    2701       ); 
    2702   } 
    2703  
    2704   if (!is_array($params['category_id'])) 
    2705   { 
    2706     $params['category_id'] = preg_split( 
    2707       '/[\s,;\|]/', 
    2708       $params['category_id'], 
    2709       -1, 
    2710       PREG_SPLIT_NO_EMPTY 
    2711       ); 
    2712   } 
    2713   $params['category_id'] = array_map('intval', $params['category_id']); 
    2714  
    2715   $category_ids = array(); 
    2716   foreach ($params['category_id'] as $category_id) 
    2717   { 
    2718     if ($category_id > 0) 
    2719     { 
    2720       $category_ids[] = $category_id; 
    2721     } 
    2722   } 
    2723  
    2724   if (count($category_ids) == 0) 
    2725   { 
    2726     return; 
    2727   } 
    2728  
    2729   $query = ' 
    2730 SELECT id 
    2731   FROM '.CATEGORIES_TABLE.' 
    2732   WHERE id IN ('.implode(',', $category_ids).') 
    2733 ;'; 
    2734   $category_ids = array_from_query($query, 'id'); 
    2735  
    2736   if (count($category_ids) == 0) 
    2737   { 
    2738     return; 
    2739   } 
    2740  
    2741   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2742   delete_categories($category_ids, $params['photo_deletion_mode']); 
    2743   update_global_rank(); 
    2744 } 
    2745  
    2746 function ws_categories_move($params, $service) 
    2747 { 
    2748   global $conf, $page; 
    2749  
    2750   if (get_pwg_token() != $params['pwg_token']) 
    2751   { 
    2752     return new PwgError(403, 'Invalid security token'); 
    2753   } 
    2754  
    2755   if (!is_array($params['category_id'])) 
    2756   { 
    2757     $params['category_id'] = preg_split( 
    2758       '/[\s,;\|]/', 
    2759       $params['category_id'], 
    2760       -1, 
    2761       PREG_SPLIT_NO_EMPTY 
    2762       ); 
    2763   } 
    2764   $params['category_id'] = array_map('intval', $params['category_id']); 
    2765  
    2766   $category_ids = array(); 
    2767   foreach ($params['category_id'] as $category_id) 
    2768   { 
    2769     if ($category_id > 0) 
    2770     { 
    2771       $category_ids[] = $category_id; 
    2772     } 
    2773   } 
    2774  
    2775   if (count($category_ids) == 0) 
    2776   { 
    2777     return new PwgError(403, 'Invalid category_id input parameter, no category to move'); 
    2778   } 
    2779  
    2780   // we can't move physical categories 
    2781   $categories_in_db = array(); 
    2782  
    2783   $query = ' 
    2784 SELECT 
    2785     id, 
    2786     name, 
    2787     dir 
    2788   FROM '.CATEGORIES_TABLE.' 
    2789   WHERE id IN ('.implode(',', $category_ids).') 
    2790 ;'; 
    2791   $result = pwg_query($query); 
    2792   while ($row = pwg_db_fetch_assoc($result)) 
    2793   { 
    2794     $categories_in_db[$row['id']] = $row; 
    2795     // we break on error at first physical category detected 
    2796     if (!empty($row['dir'])) 
    2797     { 
    2798       $row['name'] = strip_tags( 
    2799         trigger_event( 
    2800           'render_category_name', 
    2801           $row['name'], 
    2802           'ws_categories_move' 
    2803           ) 
    2804         ); 
    2805  
    2806       return new PwgError( 
    2807         403, 
    2808         sprintf( 
    2809           'Category %s (%u) is not a virtual category, you cannot move it', 
    2810           $row['name'], 
    2811           $row['id'] 
    2812           ) 
    2813         ); 
    2814     } 
    2815   } 
    2816  
    2817   if (count($categories_in_db) != count($category_ids)) 
    2818   { 
    2819     $unknown_category_ids = array_diff($category_ids, array_keys($categories_in_db)); 
    2820  
    2821     return new PwgError( 
    2822       403, 
    2823       sprintf( 
    2824         'Category %u does not exist', 
    2825         $unknown_category_ids[0] 
    2826         ) 
    2827       ); 
    2828   } 
    2829  
    2830   // does this parent exists? This check should be made in the 
    2831   // move_categories function, not here 
    2832   // 0 as parent means "move categories at gallery root" 
    2833   if (0 != $params['parent']) { 
    2834     $subcat_ids = get_subcat_ids(array($params['parent'])); 
    2835     if (count($subcat_ids) == 0) 
    2836     { 
    2837       return new PwgError(403, 'Unknown parent category id'); 
    2838     } 
    2839   } 
    2840  
    2841   $page['infos'] = array(); 
    2842   $page['errors'] = array(); 
    2843   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2844   move_categories($category_ids, $params['parent']); 
    2845   invalidate_user_cache(); 
    2846  
    2847   if (count($page['errors']) != 0) 
    2848   { 
    2849     return new PwgError(403, implode('; ', $page['errors'])); 
    2850   } 
    2851 } 
    2852  
    2853 function ws_logfile($string) 
    2854 { 
    2855   global $conf; 
    2856  
    2857   if (!$conf['ws_enable_log']) { 
     213 
     214  if (!$conf['ws_enable_log']) 
     215  { 
    2858216    return true; 
    2859217  } 
     
    2866224} 
    2867225 
    2868 function ws_images_checkUpload($params, $service) 
    2869 { 
    2870   global $conf; 
    2871  
    2872   include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 
    2873   $ret['message'] = ready_for_upload_message(); 
    2874   $ret['ready_for_upload'] = true; 
    2875  
    2876   if (!empty($ret['message'])) 
    2877   { 
    2878     $ret['ready_for_upload'] = false; 
    2879   } 
    2880  
    2881   return $ret; 
    2882 } 
    2883  
    2884 function ws_plugins_getList($params, $service) 
    2885 { 
    2886   global $conf; 
    2887  
    2888   include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php'); 
    2889   $plugins = new plugins(); 
    2890   $plugins->sort_fs_plugins('name'); 
    2891   $plugin_list = array(); 
    2892  
    2893   foreach($plugins->fs_plugins as $plugin_id => $fs_plugin) 
    2894   { 
    2895     if (isset($plugins->db_plugins_by_id[$plugin_id])) 
    2896     { 
    2897       $state = $plugins->db_plugins_by_id[$plugin_id]['state']; 
     226/** 
     227 * create a tree from a flat list of categories, no recursivity for high speed 
     228 */ 
     229function categories_flatlist_to_tree($categories) 
     230{ 
     231  $tree = array(); 
     232  $key_of_cat = array(); 
     233 
     234  foreach ($categories as $key => &$node) 
     235  { 
     236    $key_of_cat[$node['id']] = $key; 
     237 
     238    if (!isset($node['id_uppercat'])) 
     239    { 
     240      $tree[] = &$node; 
    2898241    } 
    2899242    else 
    2900243    { 
    2901       $state = 'uninstalled'; 
    2902     } 
    2903  
    2904     $plugin_list[] = 
    2905       array( 
    2906         'id' => $plugin_id, 
    2907         'name' => $fs_plugin['name'], 
    2908         'version' => $fs_plugin['version'], 
    2909         'state' => $state, 
    2910         'description' => $fs_plugin['description'], 
    2911         ); 
    2912   } 
    2913  
    2914   return $plugin_list; 
    2915 } 
    2916  
    2917 function ws_plugins_performAction($params, &$service) 
    2918 { 
    2919   global $template; 
    2920  
    2921   if (get_pwg_token() != $params['pwg_token']) 
    2922   { 
    2923     return new PwgError(403, 'Invalid security token'); 
    2924   } 
    2925  
    2926   define('IN_ADMIN', true); 
    2927   include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php'); 
    2928   $plugins = new plugins(); 
    2929   $errors = $plugins->perform_action($params['action'], $params['plugin']); 
    2930  
    2931  
    2932   if (!empty($errors)) 
    2933   { 
    2934     return new PwgError(500, $errors); 
    2935   } 
    2936   else 
    2937   { 
    2938     if (in_array($params['action'], array('activate', 'deactivate'))) 
    2939     { 
    2940       $template->delete_compiled_templates(); 
    2941     } 
    2942     return true; 
    2943   } 
    2944 } 
    2945  
    2946 function ws_themes_performAction($params, $service) 
    2947 { 
    2948   global $template; 
    2949  
    2950   if (get_pwg_token() != $params['pwg_token']) 
    2951   { 
    2952     return new PwgError(403, 'Invalid security token'); 
    2953   } 
    2954  
    2955   define('IN_ADMIN', true); 
    2956   include_once(PHPWG_ROOT_PATH.'admin/include/themes.class.php'); 
    2957   $themes = new themes(); 
    2958   $errors = $themes->perform_action($params['action'], $params['theme']); 
    2959  
    2960   if (!empty($errors)) 
    2961   { 
    2962     return new PwgError(500, $errors); 
    2963   } 
    2964   else 
    2965   { 
    2966     if (in_array($params['action'], array('activate', 'deactivate'))) 
    2967     { 
    2968       $template->delete_compiled_templates(); 
    2969     } 
    2970     return true; 
    2971   } 
    2972 } 
    2973  
    2974 function ws_extensions_update($params, $service) 
    2975 { 
    2976   if (!is_webmaster()) 
    2977   { 
    2978     return new PwgError(401, l10n('Webmaster status is required.')); 
    2979   } 
    2980  
    2981   if (get_pwg_token() != $params['pwg_token']) 
    2982   { 
    2983     return new PwgError(403, 'Invalid security token'); 
    2984   } 
    2985  
    2986   if (!in_array($params['type'], array('plugins', 'themes', 'languages'))) 
    2987   { 
    2988     return new PwgError(403, "invalid extension type"); 
    2989   } 
    2990  
    2991   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    2992   include_once(PHPWG_ROOT_PATH.'admin/include/'.$params['type'].'.class.php'); 
    2993  
    2994   $type = $params['type']; 
    2995   $extension_id = $params['id']; 
    2996   $revision = $params['revision']; 
    2997  
    2998   $extension = new $type(); 
    2999  
    3000   if ($type == 'plugins') 
    3001   { 
    3002     if (isset($extension->db_plugins_by_id[$extension_id]) and $extension->db_plugins_by_id[$extension_id]['state'] == 'active') 
    3003     { 
    3004       $extension->perform_action('deactivate', $extension_id); 
    3005  
    3006       redirect(PHPWG_ROOT_PATH 
    3007         . 'ws.php' 
    3008         . '?method=pwg.extensions.update' 
    3009         . '&type=plugins' 
    3010         . '&id=' . $extension_id 
    3011         . '&revision=' . $revision 
    3012         . '&reactivate=true' 
    3013         . '&pwg_token=' . get_pwg_token() 
    3014         . '&format=json' 
    3015       ); 
    3016     } 
    3017  
    3018     $upgrade_status = $extension->extract_plugin_files('upgrade', $revision, $extension_id); 
    3019     $extension_name = $extension->fs_plugins[$extension_id]['name']; 
    3020  
    3021     if (isset($params['reactivate'])) 
    3022     { 
    3023       $extension->perform_action('activate', $extension_id); 
    3024     } 
    3025   } 
    3026   elseif ($type == 'themes') 
    3027   { 
    3028     $upgrade_status = $extension->extract_theme_files('upgrade', $revision, $extension_id); 
    3029     $extension_name = $extension->fs_themes[$extension_id]['name']; 
    3030   } 
    3031   elseif ($type == 'languages') 
    3032   { 
    3033     $upgrade_status = $extension->extract_language_files('upgrade', $revision, $extension_id); 
    3034     $extension_name = $extension->fs_languages[$extension_id]['name']; 
    3035   } 
    3036  
    3037   global $template; 
    3038   $template->delete_compiled_templates(); 
    3039  
    3040   switch ($upgrade_status) 
    3041   { 
    3042     case 'ok': 
    3043       return l10n('%s has been successfully updated.', $extension_name); 
    3044  
    3045     case 'temp_path_error': 
    3046       return new PwgError(null, l10n('Can\'t create temporary file.')); 
    3047  
    3048     case 'dl_archive_error': 
    3049       return new PwgError(null, l10n('Can\'t download archive.')); 
    3050  
    3051     case 'archive_error': 
    3052       return new PwgError(null, l10n('Can\'t read or extract archive.')); 
    3053  
    3054     default: 
    3055       return new PwgError(null, l10n('An error occured during extraction (%s).', $upgrade_status)); 
    3056   } 
    3057 } 
    3058  
    3059 function ws_extensions_ignoreupdate($params, $service) 
    3060 { 
    3061   global $conf; 
    3062  
    3063   define('IN_ADMIN', true); 
    3064   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    3065  
    3066   if (!is_webmaster()) 
    3067   { 
    3068     return new PwgError(401, 'Access denied'); 
    3069   } 
    3070  
    3071   if (get_pwg_token() != $params['pwg_token']) 
    3072   { 
    3073     return new PwgError(403, 'Invalid security token'); 
    3074   } 
    3075  
    3076   $conf['updates_ignored'] = unserialize($conf['updates_ignored']); 
    3077  
    3078   // Reset ignored extension 
    3079   if ($params['reset']) 
    3080   { 
    3081     if (!empty($params['type']) and isset($conf['updates_ignored'][$params['type']])) 
    3082     { 
    3083       $conf['updates_ignored'][$params['type']] = array(); 
    3084     } 
    3085     else 
    3086     { 
    3087       $conf['updates_ignored'] = array( 
    3088         'plugins'=>array(), 
    3089         'themes'=>array(), 
    3090         'languages'=>array() 
    3091       ); 
    3092     } 
    3093     conf_update_param('updates_ignored', pwg_db_real_escape_string(serialize($conf['updates_ignored']))); 
    3094     unset($_SESSION['extensions_need_update']); 
    3095     return true; 
    3096   } 
    3097  
    3098   if (empty($params['id']) or empty($params['type']) or !in_array($params['type'], array('plugins', 'themes', 'languages'))) 
    3099   { 
    3100     return new PwgError(403, 'Invalid parameters'); 
    3101   } 
    3102  
    3103   // Add or remove extension from ignore list 
    3104   if (!in_array($params['id'], $conf['updates_ignored'][$params['type']])) 
    3105   { 
    3106     $conf['updates_ignored'][ $params['type'] ][] = $params['id']; 
    3107   } 
    3108   conf_update_param('updates_ignored', pwg_db_real_escape_string(serialize($conf['updates_ignored']))); 
    3109   unset($_SESSION['extensions_need_update']); 
    3110   return true; 
    3111 } 
    3112  
    3113 function ws_extensions_checkupdates($params, $service) 
    3114 { 
    3115   global $conf; 
    3116  
    3117   define('IN_ADMIN', true); 
    3118   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    3119   include_once(PHPWG_ROOT_PATH.'admin/include/updates.class.php'); 
    3120   $update = new updates(); 
    3121  
    3122   $result = array(); 
    3123  
    3124   if (!isset($_SESSION['need_update'])) 
    3125     $update->check_piwigo_upgrade(); 
    3126  
    3127   $result['piwigo_need_update'] = $_SESSION['need_update']; 
    3128  
    3129   $conf['updates_ignored'] = unserialize($conf['updates_ignored']); 
    3130  
    3131   if (!isset($_SESSION['extensions_need_update'])) 
    3132     $update->check_extensions(); 
    3133   else 
    3134     $update->check_updated_extensions(); 
    3135  
    3136   if (!is_array($_SESSION['extensions_need_update'])) 
    3137     $result['ext_need_update'] = null; 
    3138   else 
    3139     $result['ext_need_update'] = !empty($_SESSION['extensions_need_update']); 
    3140  
    3141   return $result; 
    3142 } 
    3143  
    3144 /** 
    3145  * API method 
    3146  * Returns the list of groups 
    3147  * @param mixed[] $params 
    3148  *    @option int[] group_id (optional) 
    3149  *    @option string name (optional) 
    3150  */ 
    3151 function ws_groups_getList($params, &$service) 
    3152 { 
    3153   $where_clauses = array('1=1'); 
    3154    
    3155   if (!empty($params['name'])) 
    3156   { 
    3157     $where_clauses[] = 'LOWER(name) LIKE \''. pwg_db_real_escape_string($params['name']) .'\''; 
    3158   } 
    3159    
    3160   if (!empty($params['group_id'])) 
    3161   { 
    3162     $where_clauses[] = 'id IN('. implode(',', $params['group_id']) .')'; 
    3163   } 
    3164    
    3165   $query = ' 
    3166 SELECT 
    3167     g.*, 
    3168     COUNT(user_id) AS nb_users 
    3169   FROM '.GROUPS_TABLE.' AS g 
    3170     LEFT JOIN '.USER_GROUP_TABLE.' AS ug 
    3171     ON ug.group_id = g.id 
    3172   WHERE '. implode(' AND ', $where_clauses) .' 
    3173   GROUP BY id 
    3174   ORDER BY '.$params['order'].' 
    3175   LIMIT '.$params['per_page'].' 
    3176   OFFSET '.($params['per_page']*$params['page']).' 
    3177 ;'; 
    3178  
    3179   $groups = array_from_query($query); 
    3180  
    3181   return array( 
    3182     'paging' => new PwgNamedStruct(array( 
    3183       'page' => $params['page'], 
    3184       'per_page' => $params['per_page'], 
    3185       'count' => count($groups) 
    3186       )), 
    3187     'groups' => new PwgNamedArray($groups, 'group') 
    3188     ); 
    3189 } 
    3190  
    3191 /** 
    3192  * API method 
    3193  * Adds a group 
    3194  * @param mixed[] $params 
    3195  *    @option string name 
    3196  *    @option bool is_default 
    3197  */ 
    3198 function ws_groups_add($params, &$service) 
    3199 { 
    3200   $params['name'] = pwg_db_real_escape_string($params['name']); 
    3201    
    3202   // is the name not already used ? 
    3203   $query = ' 
    3204 SELECT COUNT(*) 
    3205   FROM '.GROUPS_TABLE.' 
    3206   WHERE name = \''.$params['name'].'\' 
    3207 ;'; 
    3208   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    3209   if ($count != 0) 
    3210   { 
    3211     return new PwgError(WS_ERR_INVALID_PARAM, 'This name is already used by another group.'); 
    3212   } 
    3213  
    3214   // creating the group 
    3215   single_insert( 
    3216     GROUPS_TABLE, 
    3217     array( 
    3218       'name' => $params['name'], 
    3219       'is_default' => boolean_to_string($params['is_default']), 
    3220       ) 
    3221     ); 
    3222      
    3223   return $service->invoke('pwg.groups.getList', array('group_id' => pwg_db_insert_id())); 
    3224 } 
    3225  
    3226 /** 
    3227  * API method 
    3228  * Deletes a group 
    3229  * @param mixed[] $params 
    3230  *    @option int[] group_id 
    3231  */ 
    3232 function ws_groups_delete($params, &$service) 
    3233 { 
    3234   $group_id_string = implode(',', $params['group_id']); 
    3235  
    3236   // destruction of the access linked to the group 
    3237   $query = ' 
    3238 DELETE 
    3239   FROM '.GROUP_ACCESS_TABLE.' 
    3240   WHERE group_id IN('. $group_id_string  .') 
    3241 ;'; 
    3242   pwg_query($query); 
    3243    
    3244   // destruction of the users links for this group 
    3245   $query = ' 
    3246 DELETE 
    3247   FROM '.USER_GROUP_TABLE.' 
    3248   WHERE group_id IN('. $group_id_string  .') 
    3249 ;'; 
    3250   pwg_query($query); 
    3251  
    3252   $query = ' 
    3253 SELECT name 
    3254   FROM '.GROUPS_TABLE.' 
    3255   WHERE id IN('. $group_id_string  .') 
    3256 ;'; 
    3257   $groupnames = array_from_query($query, 'name'); 
    3258    
    3259   // destruction of the group 
    3260   $query = ' 
    3261 DELETE 
    3262   FROM '.GROUPS_TABLE.' 
    3263   WHERE id IN('. $group_id_string  .') 
    3264 ;'; 
    3265   pwg_query($query); 
    3266  
    3267   return new PwgNamedArray($groupnames, 'group_deleted'); 
    3268 } 
    3269  
    3270 /** 
    3271  * API method 
    3272  * Updates a group 
    3273  * @param mixed[] $params 
    3274  *    @option int group_id 
    3275  *    @option string name (optional) 
    3276  *    @option bool is_default (optional) 
    3277  */ 
    3278 function ws_groups_setInfo($params, &$service) 
    3279 { 
    3280   $updates = array(); 
    3281    
    3282   // does the group exist ? 
    3283   $query = ' 
    3284 SELECT COUNT(*) 
    3285   FROM '.GROUPS_TABLE.' 
    3286   WHERE id = '.$params['group_id'].' 
    3287 ;'; 
    3288   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    3289   if ($count == 0) 
    3290   { 
    3291     return new PwgError(WS_ERR_INVALID_PARAM, 'This group does not exist.'); 
    3292   } 
    3293    
    3294   if (!empty($params['name'])) 
    3295   { 
    3296     $params['name'] = pwg_db_real_escape_string($params['name']); 
    3297      
    3298     // is the name not already used ? 
    3299     $query = ' 
    3300 SELECT COUNT(*) 
    3301   FROM '.GROUPS_TABLE.' 
    3302   WHERE name = \''.$params['name'].'\' 
    3303 ;'; 
    3304     list($count) = pwg_db_fetch_row(pwg_query($query)); 
    3305     if ($count != 0) 
    3306     { 
    3307       return new PwgError(WS_ERR_INVALID_PARAM, 'This name is already used by another group.'); 
    3308     } 
    3309      
    3310     $updates['name'] = $params['name']; 
    3311   } 
    3312    
    3313   if (!empty($params['is_default']) or @$params['is_default']===false) 
    3314   { 
    3315     $updates['is_default'] = boolean_to_string($params['is_default']); 
    3316   } 
    3317    
    3318   single_update( 
    3319     GROUPS_TABLE, 
    3320     $updates, 
    3321     array('id' => $params['group_id']) 
    3322     ); 
    3323    
    3324   return $service->invoke('pwg.groups.getList', array('group_id' => $params['group_id'])); 
    3325 } 
    3326  
    3327 /** 
    3328  * API method 
    3329  * Adds user(s) to a group 
    3330  * @param mixed[] $params 
    3331  *    @option int group_id 
    3332  *    @option int[] user_id 
    3333  */ 
    3334 function ws_groups_addUser($params, &$service) 
    3335 { 
    3336   // does the group exist ? 
    3337   $query = ' 
    3338 SELECT COUNT(*) 
    3339   FROM '.GROUPS_TABLE.' 
    3340   WHERE id = '.$params['group_id'].' 
    3341 ;'; 
    3342   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    3343   if ($count == 0) 
    3344   { 
    3345     return new PwgError(WS_ERR_INVALID_PARAM, 'This group does not exist.'); 
    3346   } 
    3347    
    3348   $inserts = array(); 
    3349   foreach ($params['user_id'] as $user_id) 
    3350   { 
    3351     $inserts[] = array( 
    3352       'group_id' => $params['group_id'], 
    3353       'user_id' => $user_id, 
    3354       ); 
    3355   } 
    3356  
    3357   mass_inserts( 
    3358     USER_GROUP_TABLE, 
    3359     array('group_id', 'user_id'), 
    3360     $inserts, 
    3361     array('ignore'=>true) 
    3362     ); 
    3363      
    3364   return $service->invoke('pwg.users.getList', array('group_id' => $params['group_id'])); 
    3365 } 
    3366  
    3367 /** 
    3368  * API method 
    3369  * Removes user(s) from a group 
    3370  * @param mixed[] $params 
    3371  *    @option int group_id 
    3372  *    @option int[] user_id 
    3373  */ 
    3374 function ws_groups_deleteUser($params, &$service) 
    3375 { 
    3376   // does the group exist ? 
    3377   $query = ' 
    3378 SELECT COUNT(*) 
    3379   FROM '.GROUPS_TABLE.' 
    3380   WHERE id = '.$params['group_id'].' 
    3381 ;'; 
    3382   list($count) = pwg_db_fetch_row(pwg_query($query)); 
    3383   if ($count == 0) 
    3384   { 
    3385     return new PwgError(WS_ERR_INVALID_PARAM, 'This group does not exist.'); 
    3386   } 
    3387    
    3388   $query = ' 
    3389 DELETE FROM '.USER_GROUP_TABLE.' 
    3390   WHERE 
    3391     group_id = '.$params['group_id'].' 
    3392     AND user_id IN('. implode(',', $params['user_id']) .') 
    3393 ;'; 
    3394   pwg_query($query); 
    3395  
    3396   return $service->invoke('pwg.users.getList', array('group_id' => $params['group_id'])); 
    3397 } 
    3398  
    3399 /** 
    3400  * API method 
    3401  * Returns a list of users 
    3402  * @param mixed[] $params 
    3403  *    @option int[] user_id (optional) 
    3404  *    @option string username (optional) 
    3405  *    @option string[] status (optional) 
    3406  *    @option int min_level (optional) 
    3407  *    @option int[] group_id (optional) 
    3408  *    @option int per_page 
    3409  *    @option int page 
    3410  *    @option string order 
    3411  */ 
    3412 function ws_users_getList($params, &$service) 
    3413 { 
    3414   global $conf; 
    3415    
    3416   $where_clauses = array('1=1'); 
    3417    
    3418   if (!empty($params['user_id'])) 
    3419   { 
    3420     $where_clauses[] = 'u.'.$conf['user_fields']['id'].' IN('. implode(',', $params['user_id']) .')'; 
    3421   } 
    3422    
    3423   if (!empty($params['username'])) 
    3424   { 
    3425     $where_clauses[] = 'u.'.$conf['user_fields']['username'].' LIKE \''.pwg_db_real_escape_string($params['username']).'\''; 
    3426   } 
    3427    
    3428   if (!empty($params['status'])) 
    3429   { 
    3430     $params['status'] = array_intersect($params['status'], get_enums(USER_INFOS_TABLE, 'status')); 
    3431     if (count($params['status']) > 0) 
    3432     { 
    3433       $where_clauses[] = 'ui.status IN("'. implode('","', $params['status']) .'")'; 
    3434     } 
    3435   } 
    3436    
    3437   if (!empty($params['min_level'])) 
    3438   { 
    3439     if ( !in_array($params['min_level'], $conf['available_permission_levels']) ) 
    3440     { 
    3441       return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid level'); 
    3442     } 
    3443     $where_clauses[] = 'ui.level >= '.$params['min_level']; 
    3444   } 
    3445    
    3446   if (!empty($params['group_id'])) 
    3447   { 
    3448     $where_clauses[] = 'ug.group_id IN('. implode(',', $params['group_id']) .')'; 
    3449   } 
    3450    
    3451   $display = array('u.'.$conf['user_fields']['id'] => 'id'); 
    3452    
    3453   if ($params['display'] != 'none') 
    3454   { 
    3455     $params['display'] = explode(',', $params['display']); 
    3456      
    3457     if (in_array('all', $params['display'])) 
    3458     { 
    3459       $params['display'] = array_merge($params['display'], array( 
    3460         'username','email','status','level','groups','language','theme', 
    3461         'nb_image_page','recent_period','expand','show_nb_comments','show_nb_hits', 
    3462         'enabled_high', 
    3463         )); 
    3464     } 
    3465     else if (in_array('basics', $params['display'])) 
    3466     { 
    3467       $params['display'] = array_merge($params['display'], array( 
    3468         'username','email','status','level','groups', 
    3469         )); 
    3470     } 
    3471      
    3472     if (in_array('username', $params['display'])) 
    3473     { 
    3474       $display['u.'.$conf['user_fields']['username']] = 'username'; 
    3475     } 
    3476     if (in_array('email', $params['display'])) 
    3477     { 
    3478       $display['u.'.$conf['user_fields']['email']] = 'email'; 
    3479     } 
    3480      
    3481     $ui_fields = array( 
    3482       'status','level','language','theme','nb_image_page','recent_period','expand', 
    3483       'show_nb_comments','show_nb_hits','enabled_high', 
    3484       ); 
    3485     foreach ($ui_fields as $field) 
    3486     { 
    3487       if (in_array($field, $params['display'])) 
     244      if (!isset($categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'])) 
    3488245      { 
    3489         $display['ui.'.$field] = $field; 
     246        $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'] = 
     247          new PwgNamedArray(array(), 'category', ws_std_get_category_xml_attributes()); 
    3490248      } 
    3491     } 
    3492   } 
    3493   else 
    3494   { 
    3495     $params['display'] = array(); 
    3496   } 
    3497  
    3498   $query = ' 
    3499 SELECT DISTINCT '; 
    3500  
    3501   $first = true; 
    3502   foreach ($display as $field => $name) 
    3503   { 
    3504     if (!$first) $query.= ', '; 
    3505     else $first = false; 
    3506     $query.= $field .' AS '. $name; 
    3507   } 
    3508   if (in_array('groups', $params['display'])) 
    3509   { 
    3510     if (!$first) $query.= ', '; 
    3511     $query.= '"" AS groups'; 
    3512   } 
    3513    
    3514   $query.= ' 
    3515   FROM '.USERS_TABLE.' AS u 
    3516     INNER JOIN '.USER_INFOS_TABLE.' AS ui 
    3517       ON u.'.$conf['user_fields']['id'].' = ui.user_id 
    3518     LEFT JOIN '.USER_GROUP_TABLE.' AS ug 
    3519       ON u.'.$conf['user_fields']['id'].' = ug.user_id 
    3520   WHERE 
    3521     '. implode(' AND ', $where_clauses) .' 
    3522   ORDER BY '.$params['order'].' 
    3523   LIMIT '.$params['per_page'].' 
    3524   OFFSET '.($params['per_page']*$params['page']).' 
    3525 ;'; 
    3526  
    3527   $users = hash_from_query($query, 'id'); 
    3528    
    3529   if ( count($users) > 0 and in_array('groups', $params['display']) ) 
    3530   { 
    3531     $query = ' 
    3532 SELECT user_id, group_id 
    3533   FROM '.USER_GROUP_TABLE.' 
    3534   WHERE user_id IN ('.implode(',', array_keys($users)).') 
    3535 ;'; 
    3536     $result = pwg_query($query); 
    3537      
    3538     while ($row = pwg_db_fetch_assoc($result)) 
    3539     { 
    3540       $users[ $row['user_id'] ]['groups'][] = $row['group_id']; 
    3541     } 
    3542   } 
    3543  
    3544   return array( 
    3545     'paging' => new PwgNamedStruct(array( 
    3546       'page' => $params['page'], 
    3547       'per_page' => $params['per_page'], 
    3548       'count' => count($users) 
    3549       )), 
    3550     'users' => new PwgNamedArray(array_values($users), 'user') 
    3551     ); 
    3552 } 
    3553  
    3554 /** 
    3555  * API method 
    3556  * Adds a user 
    3557  * @param mixed[] $params 
    3558  *    @option string username 
    3559  *    @option string password (optional) 
    3560  *    @option string email (optional) 
    3561  */ 
    3562 function ws_users_add($params, &$service) 
    3563 { 
    3564   global $conf; 
    3565  
    3566   if ($conf['double_password_type_in_admin']) 
    3567   { 
    3568     if ($params['password'] != $params['password_confirm']) 
    3569     { 
    3570       return new PwgError(WS_ERR_INVALID_PARAM, l10n('The passwords do not match')); 
    3571     } 
    3572   } 
    3573  
    3574   $user_id = register_user( 
    3575     $params['username'], 
    3576     $params['password'], 
    3577     $params['email'], 
    3578     false, // notify admin 
    3579     $errors, 
    3580     $params['send_password_by_mail'] 
    3581     ); 
    3582    
    3583   if (!$user_id) 
    3584   { 
    3585     return new PwgError(WS_ERR_INVALID_PARAM, $errors[0]); 
    3586   } 
    3587    
    3588   return $service->invoke('pwg.users.getList', array('user_id'=>$user_id)); 
    3589 } 
    3590  
    3591 /** 
    3592  * API method 
    3593  * Deletes users 
    3594  * @param mixed[] $params 
    3595  *    @option int[] user_id 
    3596  */ 
    3597 function ws_users_delete($params, &$service) 
    3598 { 
    3599   global $conf, $user; 
    3600    
    3601   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    3602    
    3603   // protect some users 
    3604   $params['user_id'] = array_diff( 
    3605     $params['user_id'], 
    3606     array( 
    3607       $user['id'], 
    3608       $conf['guest_id'], 
    3609       $conf['default_user_id'], 
    3610       $conf['webmaster_id'], 
    3611       ) 
    3612     ); 
    3613    
    3614   foreach ($params['user_id'] as $user_id) 
    3615   { 
    3616     delete_user($user_id); 
    3617   } 
    3618    
    3619   return l10n_dec( 
    3620         '%d user deleted', '%d users deleted', 
    3621         count($params['user_id']) 
    3622         ); 
    3623 } 
    3624  
    3625 /** 
    3626  * API method 
    3627  * Updates users 
    3628  * @param mixed[] $params 
    3629  *    @option int[] user_id 
    3630  *    @option string username (optional) 
    3631  *    @option string password (optional) 
    3632  *    @option string email (optional) 
    3633  *    @option string status (optional) 
    3634  *    @option int level (optional) 
    3635  *    @option string language (optional) 
    3636  *    @option string theme (optional) 
    3637  *    @option int nb_image_page (optional) 
    3638  *    @option int recent_period (optional) 
    3639  *    @option bool expand (optional) 
    3640  *    @option bool show_nb_comments (optional) 
    3641  *    @option bool show_nb_hits (optional) 
    3642  *    @option bool enabled_high (optional) 
    3643  */ 
    3644 function ws_users_setInfo($params, &$service) 
    3645 { 
    3646   global $conf, $user; 
    3647    
    3648   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    3649    
    3650   $updates = $updates_infos = array(); 
    3651   $update_status = null; 
    3652    
    3653   if (count($params['user_id']) == 1) 
    3654   { 
    3655     if (get_username($params['user_id'][0]) === false) 
    3656     { 
    3657       return new PwgError(WS_ERR_INVALID_PARAM, 'This user does not exist.'); 
    3658     } 
    3659      
    3660     if (!empty($params['username'])) 
    3661     { 
    3662       $user_id = get_userid($params['username']); 
    3663       if ($user_id and $user_id != $params['user_id'][0]) 
    3664       { 
    3665         return new PwgError(WS_ERR_INVALID_PARAM, l10n('this login is already used')); 
    3666       } 
    3667       if ($params['username'] != strip_tags($params['username'])) 
    3668       { 
    3669         return new PwgError(WS_ERR_INVALID_PARAM, l10n('html tags are not allowed in login')); 
    3670       } 
    3671       $updates[ $conf['user_fields']['username'] ] = $params['username']; 
    3672     } 
    3673      
    3674     if (!empty($params['email'])) 
    3675     { 
    3676       if ( ($error = validate_mail_address($params['user_id'][0], $params['email'])) != '') 
    3677       { 
    3678         return new PwgError(WS_ERR_INVALID_PARAM, $error); 
    3679       } 
    3680       $updates[ $conf['user_fields']['email'] ] = $params['email']; 
    3681     } 
    3682      
    3683     if (!empty($params['password'])) 
    3684     { 
    3685       $updates[ $conf['user_fields']['password'] ] = $conf['password_hash']($params['password']); 
    3686     } 
    3687   } 
    3688    
    3689   if (!empty($params['status'])) 
    3690   { 
    3691     if ( $params['status'] == 'webmaster' and !is_webmaster() ) 
    3692     { 
    3693       return new PwgError(403, 'Only webmasters can grant "webmaster" status'); 
    3694     } 
    3695     if ( !in_array($params['status'], array('guest','generic','normal','admin','webmaster')) ) 
    3696     { 
    3697       return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid status'); 
    3698     } 
    3699      
    3700     /* 
    3701      * status update query is separated from the rest as not applying to the same 
    3702      * set of users (current, guest and webmaster can't be changed) 
    3703      */ 
    3704     $params['user_id_for_status'] = array_diff( 
    3705       $params['user_id'], 
    3706       array( 
    3707         $user['id'], 
    3708         $conf['guest_id'], 
    3709         $conf['webmaster_id'], 
    3710         ) 
    3711       ); 
    3712      
    3713     $update_status = $params['status']; 
    3714   } 
    3715    
    3716   if (!empty($params['level']) or @$params['level']===0) 
    3717   { 
    3718     if ( !in_array($params['level'], $conf['available_permission_levels']) ) 
    3719     { 
    3720       return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid level'); 
    3721     } 
    3722     $updates_infos['level'] = $params['level']; 
    3723   } 
    3724    
    3725   if (!empty($params['language'])) 
    3726   { 
    3727     if ( !in_array($params['language'], array_keys(get_languages())) ) 
    3728     { 
    3729       return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid language'); 
    3730     } 
    3731     $updates_infos['language'] = $params['language']; 
    3732   } 
    3733    
    3734   if (!empty($params['theme'])) 
    3735   { 
    3736     if ( !in_array($params['theme'], array_keys(get_pwg_themes())) ) 
    3737     { 
    3738       return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid theme'); 
    3739     } 
    3740     $updates_infos['theme'] = $params['theme']; 
    3741   } 
    3742    
    3743   if (!empty($params['nb_image_page'])) 
    3744   { 
    3745     $updates_infos['nb_image_page'] = $params['nb_image_page']; 
    3746   } 
    3747    
    3748   if (!empty($params['recent_period']) or @$params['recent_period']===0) 
    3749   { 
    3750     $updates_infos['recent_period'] = $params['recent_period']; 
    3751   } 
    3752    
    3753   if (!empty($params['expand']) or @$params['expand']===false) 
    3754   { 
    3755     $updates_infos['expand'] = boolean_to_string($params['expand']); 
    3756   } 
    3757    
    3758   if (!empty($params['show_nb_comments']) or @$params['show_nb_comments']===false) 
    3759   { 
    3760     $updates_infos['show_nb_comments'] = boolean_to_string($params['show_nb_comments']); 
    3761   } 
    3762    
    3763   if (!empty($params['show_nb_hits']) or @$params['show_nb_hits']===false) 
    3764   { 
    3765     $updates_infos['show_nb_hits'] = boolean_to_string($params['show_nb_hits']); 
    3766   } 
    3767    
    3768   if (!empty($params['enabled_high']) or @$params['enabled_high']===false) 
    3769   { 
    3770     $updates_infos['enabled_high'] = boolean_to_string($params['enabled_high']); 
    3771   } 
    3772    
    3773   // perform updates 
    3774   single_update( 
    3775     USERS_TABLE, 
    3776     $updates, 
    3777     array($conf['user_fields']['id'] => $params['user_id'][0]) 
    3778     ); 
    3779      
    3780   if (isset($update_status) and count($params['user_id_for_status']) > 0) 
    3781   { 
    3782     $query = ' 
    3783 UPDATE '. USER_INFOS_TABLE .' SET 
    3784     status = "'. $update_status .'" 
    3785   WHERE user_id IN('. implode(',', $params['user_id_for_status']) .') 
    3786 ;'; 
    3787     pwg_query($query); 
    3788   } 
    3789    
    3790   if (count($updates_infos) > 0) 
    3791   { 
    3792     $query = ' 
    3793 UPDATE '. USER_INFOS_TABLE .' SET '; 
    3794  
    3795     $first = true; 
    3796     foreach ($updates_infos as $field => $value) 
    3797     { 
    3798       if (!$first) $query.= ', '; 
    3799       else $first = false; 
    3800       $query.= $field .' = "'. $value .'"'; 
    3801     } 
    3802      
    3803     $query.= ' 
    3804   WHERE user_id IN('. implode(',', $params['user_id']) .') 
    3805 ;'; 
    3806     pwg_query($query); 
    3807   } 
    3808  
    3809   return $service->invoke('pwg.users.getList', array( 
    3810     'user_id' => $params['user_id'], 
    3811     'display' => 'basics,'.implode(',', array_keys($updates_infos)), 
    3812     )); 
    3813 } 
    3814  
    3815 /** 
    3816  * API method 
    3817  * Returns permissions 
    3818  * @param mixed[] $params 
    3819  *    @option int[] cat_id (optional) 
    3820  *    @option int[] group_id (optional) 
    3821  *    @option int[] user_id (optional) 
    3822  */ 
    3823 function ws_permissions_getList($params, &$service) 
    3824 { 
    3825   $my_params = array_intersect(array_keys($params), array('cat_id','group_id','user_id')); 
    3826   if (count($my_params) > 1) 
    3827   { 
    3828     return new PwgError(WS_ERR_INVALID_PARAM, 'Too many parameters, provide cat_id OR user_id OR group_id'); 
    3829   } 
    3830    
    3831   $cat_filter = ''; 
    3832   if (!empty($params['cat_id'])) 
    3833   { 
    3834     $cat_filter = 'WHERE cat_id IN('. implode(',', $params['cat_id']) .')'; 
    3835   } 
    3836    
    3837   $perms = array(); 
    3838    
    3839   // direct users 
    3840   $query = ' 
    3841 SELECT user_id, cat_id 
    3842   FROM '. USER_ACCESS_TABLE .' 
    3843   '. $cat_filter .' 
    3844 ;'; 
    3845   $result = pwg_query($query); 
    3846  
    3847   while ($row = pwg_db_fetch_assoc($result)) 
    3848   { 
    3849     if (!isset($perms[ $row['cat_id'] ])) 
    3850     { 
    3851       $perms[ $row['cat_id'] ]['id'] = $row['cat_id']; 
    3852     } 
    3853     $perms[ $row['cat_id'] ]['users'][] = $row['user_id']; 
    3854   } 
    3855    
    3856   // indirect users 
    3857   $query = ' 
    3858 SELECT ug.user_id, ga.cat_id 
    3859   FROM '. USER_GROUP_TABLE .' AS ug 
    3860     INNER JOIN '. GROUP_ACCESS_TABLE .' AS ga 
    3861     ON ug.group_id = ga.group_id 
    3862   '. $cat_filter .' 
    3863 ;'; 
    3864   $result = pwg_query($query); 
    3865    
    3866   while ($row = pwg_db_fetch_assoc($result)) 
    3867   { 
    3868     if (!isset($perms[ $row['cat_id'] ])) 
    3869     { 
    3870       $perms[ $row['cat_id'] ]['id'] = $row['cat_id']; 
    3871     } 
    3872     $perms[ $row['cat_id'] ]['users_indirect'][] = $row['user_id']; 
    3873   } 
    3874    
    3875   // groups 
    3876   $query = ' 
    3877 SELECT group_id, cat_id 
    3878   FROM '. GROUP_ACCESS_TABLE .' 
    3879   '. $cat_filter .' 
    3880 ;'; 
    3881   $result = pwg_query($query); 
    3882    
    3883   while ($row = pwg_db_fetch_assoc($result)) 
    3884   { 
    3885     if (!isset($perms[ $row['cat_id'] ])) 
    3886     { 
    3887       $perms[ $row['cat_id'] ]['id'] = $row['cat_id']; 
    3888     } 
    3889     $perms[ $row['cat_id'] ]['groups'][] = $row['group_id']; 
    3890   } 
    3891    
    3892   // filter by group and user 
    3893   foreach ($perms as $cat_id => &$cat) 
    3894   { 
    3895     if (isset($filters['group_id'])) 
    3896     { 
    3897       if (empty($cat['groups']) or count(array_intersect($cat['groups'], $params['group_id'])) == 0) 
    3898       { 
    3899         unset($perms[$cat_id]); 
    3900         continue; 
    3901       } 
    3902     } 
    3903     if (isset($filters['user_id'])) 
    3904     { 
    3905       if ( 
    3906         (empty($cat['users_indirect']) or count(array_intersect($cat['users_indirect'], $params['user_id'])) == 0) 
    3907         and (empty($cat['users']) or count(array_intersect($cat['users'], $params['user_id'])) == 0) 
    3908       ) { 
    3909         unset($perms[$cat_id]); 
    3910         continue; 
    3911       } 
    3912     } 
    3913      
    3914     $cat['groups'] = !empty($cat['groups']) ? array_unique($cat['groups']) : array(); 
    3915     $cat['users'] = !empty($cat['users']) ? array_unique($cat['users']) : array(); 
    3916     $cat['users_indirect'] = !empty($cat['users_indirect']) ? array_unique($cat['users_indirect']) : array(); 
    3917   } 
    3918   unset($cat); 
    3919  
    3920   return array('categories' => new PwgNamedArray(array_values($perms), 'category', array('id'))); 
    3921 } 
    3922  
    3923 /** 
    3924  * API method 
    3925  * Add permissions 
    3926  * @param mixed[] $params 
    3927  *    @option int[] cat_id 
    3928  *    @option int[] group_id (optional) 
    3929  *    @option int[] user_id (optional) 
    3930  *    @option bool recursive 
    3931  */ 
    3932 function ws_permissions_add($params, &$service) 
    3933 { 
    3934   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    3935    
    3936   if (!empty($params['group_id'])) 
    3937   { 
    3938     $cat_ids = get_uppercat_ids($params['cat_id']); 
    3939     if ($params['recursive']) 
    3940     { 
    3941       $cat_ids = array_merge($cat_ids, get_subcat_ids($params['cat_id'])); 
    3942     } 
    3943      
    3944     $query = ' 
    3945 SELECT id 
    3946   FROM '.CATEGORIES_TABLE.' 
    3947   WHERE id IN ('.implode(',', $cat_ids).') 
    3948     AND status = \'private\' 
    3949 ;'; 
    3950     $private_cats = array_from_query($query, 'id'); 
    3951      
    3952     $inserts = array(); 
    3953     foreach ($private_cats as $cat_id) 
    3954     { 
    3955       foreach ($params['group_id'] as $group_id) 
    3956       { 
    3957         $inserts[] = array( 
    3958           'group_id' => $group_id, 
    3959           'cat_id' => $cat_id 
    3960           ); 
    3961       } 
    3962     } 
    3963      
    3964     mass_inserts( 
    3965       GROUP_ACCESS_TABLE, 
    3966       array('group_id','cat_id'), 
    3967       $inserts, 
    3968       array('ignore'=>true) 
    3969       ); 
    3970   } 
    3971    
    3972   if (!empty($params['user_id'])) 
    3973   { 
    3974     if ($params['recursive']) $_POST['apply_on_sub'] = true; 
    3975     add_permission_on_category($params['cat_id'], $params['user_id']); 
    3976   } 
    3977    
    3978   return $service->invoke('pwg.permissions.getList', array('cat_id'=>$params['cat_id'])); 
    3979 } 
    3980  
    3981 /** 
    3982  * API method 
    3983  * Removes permissions 
    3984  * @param mixed[] $params 
    3985  *    @option int[] cat_id 
    3986  *    @option int[] group_id (optional) 
    3987  *    @option int[] user_id (optional) 
    3988  */ 
    3989 function ws_permissions_remove($params, &$service) 
    3990 { 
    3991   include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 
    3992    
    3993   $cat_ids = get_subcat_ids($params['cat_id']); 
    3994    
    3995   if (!empty($params['group_id'])) 
    3996   { 
    3997     $query = ' 
    3998 DELETE 
    3999   FROM '. GROUP_ACCESS_TABLE .' 
    4000   WHERE group_id IN ('. implode(',', $params['group_id']).') 
    4001     AND cat_id IN ('. implode(',', $cat_ids).') 
    4002 ;'; 
    4003     pwg_query($query); 
    4004   } 
    4005    
    4006   if (!empty($params['user_id'])) 
    4007   { 
    4008     $query = ' 
    4009 DELETE 
    4010   FROM '. USER_ACCESS_TABLE .' 
    4011   WHERE user_id IN ('. implode(',', $params['user_id']) .') 
    4012     AND cat_id IN ('. implode(',', $cat_ids) .') 
    4013 ;'; 
    4014     pwg_query($query); 
    4015   } 
    4016    
    4017   return $service->invoke('pwg.permissions.getList', array('cat_id'=>$params['cat_id'])); 
     249 
     250      $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories']->_content[] = &$node; 
     251    } 
     252  } 
     253 
     254  return $tree; 
    4018255} 
    4019256 
  • trunk/ws.php

    r25264 r25281  
    2626include_once(PHPWG_ROOT_PATH.'include/common.inc.php'); 
    2727check_status(ACCESS_FREE); 
    28 include_once(PHPWG_ROOT_PATH.'include/ws_core.inc.php'); 
    2928 
    3029if ( !$conf['allow_web_services'] ) 
     
    3332} 
    3433 
     34include_once(PHPWG_ROOT_PATH.'include/ws_core.inc.php'); 
     35 
    3536add_event_handler('ws_add_methods', 'ws_addDefaultMethods'); 
    36  
    3737add_event_handler('ws_invoke_allowed', 'ws_isInvokeAllowed', EVENT_HANDLER_PRIORITY_NEUTRAL, 3); 
    3838 
     
    103103   
    104104  include_once(PHPWG_ROOT_PATH.'include/ws_functions.inc.php'); 
     105  $ws_functions_root = PHPWG_ROOT_PATH.'include/ws_functions/'; 
    105106   
    106107  $f_params = array( 
     
    129130      'ws_getVersion', 
    130131      null, 
    131       'Returns the Piwigo version.' 
     132      'Returns the Piwigo version.', 
     133      $ws_functions_root . 'pwg.php' 
    132134    ); 
    133135           
     
    137139      null, 
    138140      '<b>Admin only.</b> Returns general informations.', 
    139       null, 
     141      $ws_functions_root . 'pwg.php', 
    140142      array('admin_only'=>true) 
    141143    ); 
     
    149151        ), 
    150152      '<b>Admin only.</b> Adds elements to the caddie. Returns the number of elements added.', 
    151       null, 
     153      $ws_functions_root . 'pwg.php', 
    152154      array('admin_only'=>true) 
    153155    ); 
     
    172174      'Returns elements for the corresponding categories. 
    173175<br><b>cat_id</b> can be empty if <b>recursive</b> is true. 
    174 <br><b>order</b> comma separated fields for sorting' 
     176<br><b>order</b> comma separated fields for sorting', 
     177      $ws_functions_root . 'pwg.categories.php' 
    175178    ); 
    176179 
     
    191194                                'type'=>WS_TYPE_BOOL), 
    192195        ), 
    193       'Returns a list of categories.' 
     196      'Returns a list of categories.', 
     197      $ws_functions_root . 'pwg.categories.php' 
    194198    ); 
    195199 
     
    210214        ), $f_params), 
    211215      '<b>Admin only.</b> Returns a list of derivatives to build.', 
    212       null, 
     216      $ws_functions_root . 'pwg.php', 
    213217      array('admin_only'=>true) 
    214218    ); 
     
    224228        ), 
    225229      '<b>POST only.</b> Adds a comment to an image.', 
    226       null, 
     230      $ws_functions_root . 'pwg.images.php', 
    227231      array('post_only'=>true) 
    228232    ); 
     
    239243                                      'type'=>WS_TYPE_INT|WS_TYPE_POSITIVE), 
    240244        ), 
    241       'Returns information about an image.' 
     245      'Returns information about an image.', 
     246      $ws_functions_root . 'pwg.images.php' 
    242247    ); 
    243248 
     
    249254        'rate' =>     array('type'=>WS_TYPE_FLOAT), 
    250255      ), 
    251       'Rates an image.' 
     256      'Rates an image.', 
     257      $ws_functions_root . 'pwg.images.php' 
    252258    ); 
    253259 
     
    265271                                'info'=>'id, file, name, hit, rating_score, date_creation, date_available, random'), 
    266272        ), $f_params), 
    267       'Returns elements for the corresponding query search.' 
     273      'Returns elements for the corresponding query search.', 
     274      $ws_functions_root . 'pwg.images.php' 
    268275    ); 
    269276 
     
    278285        ), 
    279286      '<b>Admin & POST only.</b> Sets the privacy levels for the images.', 
    280       null, 
     287      $ws_functions_root . 'pwg.images.php', 
    281288      array('admin_only'=>true, 'post_only'=>true) 
    282289    ); 
     
    291298        ), 
    292299      '<b>Admin & POST only.</b> Sets the rank of a photo for a given album.', 
    293       null, 
     300      $ws_functions_root . 'pwg.images.php', 
    294301      array('admin_only'=>true, 'post_only'=>true) 
    295302    ); 
     
    303310        ), 
    304311      '<b>Admin & POST only.</b> Deletes all rates for a user.', 
    305       null, 
     312      $ws_functions_root . 'pwg.php', 
    306313      array('admin_only'=>true, 'post_only'=>true) 
    307314    ); 
     
    311318      'ws_session_getStatus', 
    312319      null, 
    313       'Gets information about the current session. Also provides a token useable with admin methods.' 
     320      'Gets information about the current session. Also provides a token useable with admin methods.', 
     321      $ws_functions_root . 'pwg.php' 
    314322    ); 
    315323 
     
    319327      array('username', 'password'), 
    320328      '<b>POST only.</b> Tries to login the user.', 
    321       null, 
     329      $ws_functions_root . 'pwg.php', 
    322330      array('post_only'=>true) 
    323331    ); 
     
    327335      'ws_session_logout', 
    328336      null, 
    329       'Ends the current session.' 
     337      'Ends the current session.', 
     338      $ws_functions_root . 'pwg.php' 
    330339    ); 
    331340 
     
    337346                                   'type'=>WS_TYPE_BOOL), 
    338347        ), 
    339       'Retrieves a list of available tags.' 
     348      'Retrieves a list of available tags.', 
     349      $ws_functions_root . 'pwg.tags.php' 
    340350    ); 
    341351 
     
    361371                                'info'=>'id, file, name, hit, rating_score, date_creation, date_available, random'), 
    362372        ), $f_params), 
    363       'Returns elements for the corresponding tags. Fill at least tag_id, tag_url_name or tag_name.' 
     373      'Returns elements for the corresponding tags. Fill at least tag_id, tag_url_name or tag_name.', 
     374      $ws_functions_root . 'pwg.tags.php' 
    364375    ); 
    365376 
     
    375386        ), 
    376387      '<b>Admin & POST only.</b> Add a chunk of a file.', 
    377       null, 
     388      $ws_functions_root . 'pwg.images.php', 
    378389      array('admin_only'=>true, 'post_only'=>true) 
    379390    ); 
     
    390401      '<b>Admin only.</b> Add or update a file for an existing photo. 
    391402<br>pwg.images.addChunk must have been called before (maybe several times).', 
    392       null, 
     403      $ws_functions_root . 'pwg.images.php', 
    393404      array('admin_only'=>true) 
    394405    ); 
     
    423434<br>pwg.images.addChunk must have been called before (maybe several times). 
    424435<br>Don\'t use "thumbnail_sum" and "high_sum", these parameters are here for backward compatibility.', 
    425       null, 
     436      $ws_functions_root . 'pwg.images.php', 
    426437      array('admin_only'=>true) 
    427438    ); 
     
    449460<br>Set the form encoding to "form-data". 
    450461<br>You can update an existing photo if you define an existing image_id.', 
    451       null, 
     462      $ws_functions_root . 'pwg.images.php', 
    452463      array('admin_only'=>true, 'post_only'=>true) 
    453464    ); 
     
    461472        ), 
    462473      '<b>Admin & POST only.</b> Deletes image(s).', 
    463       null, 
     474      $ws_functions_root . 'pwg.images.php', 
    464475      array('admin_only'=>true, 'post_only'=>true) 
    465476    ); 
     
    470481      null, 
    471482      '<b>Admin only.</b>', 
    472       null, 
     483      $ws_functions_root . 'pwg.categories.php', 
    473484      array('admin_only'=>true) 
    474485    ); 
     
    489500                                'type'=>WS_TYPE_BOOL), 
    490501        ), 
    491       '<b>Admin only.</b> Adds an album.' 
     502      '<b>Admin only.</b> Adds an album.', 
     503      $ws_functions_root . 'pwg.categories.php', 
     504      array('admin_only'=>true) 
    492505    ); 
    493506 
     
    503516<br><b>photo_deletion_mode</b> can be "no_delete" (may create orphan photos), "delete_orphans" 
    504517(default mode, only deletes photos linked to no other album) or "force_delete" (delete all photos, even those linked to other albums)', 
    505       null, 
     518      $ws_functions_root . 'pwg.categories.php', 
    506519      array('admin_only'=>true, 'post_only'=>true) 
    507520    ); 
     
    517530      '<b>Admin & POST only.</b> Move album(s). 
    518531<br>Set parent as 0 to move to gallery root. Only virtual categories can be moved.', 
    519       null, 
     532      $ws_functions_root . 'pwg.categories.php', 
    520533      array('admin_only'=>true, 'post_only'=>true) 
    521534    ); 
     
    529542        ), 
    530543      '<b>Admin & POST only.</b> Sets the representative photo for an album. The photo doesn\'t have to belong to the album.', 
    531       null, 
     544      $ws_functions_root . 'pwg.categories.php', 
    532545      array('admin_only'=>true, 'post_only'=>true) 
    533546    ); 
     
    538551      null, 
    539552      '<b>Admin only.</b>', 
    540       null, 
     553      $ws_functions_root . 'pwg.tags.php', 
    541554      array('admin_only'=>true) 
    542555    ); 
     
    547560      array('name'), 
    548561      '<b>Admin only.</b> Adds a new tag.', 
    549       null, 
     562      $ws_functions_root . 'pwg.tags.php', 
    550563      array('admin_only'=>true) 
    551564    ); 
     
    560573      '<b>Admin only.</b>  Checks existence of images. 
    561574<br>Give <b>md5sum_list</b> if $conf[uniqueness_mode]==md5sum. Give <b>filename_list</b> if $conf[uniqueness_mode]==filename.', 
    562       null, 
     575      $ws_functions_root . 'pwg.images.php', 
    563576      array('admin_only'=>true) 
    564577    ); 
     
    575588      '<b>Admin only.</b> Checks if you have updated version of your files for a given photo, the answer can be "missing", "equals" or "differs". 
    576589<br>Don\'t use "thumbnail_sum" and "high_sum", these parameters are here for backward compatibility.', 
    577       null, 
     590      $ws_functions_root . 'pwg.images.php', 
    578591      array('admin_only'=>true) 
    579592    ); 
     
    584597      null, 
    585598      '<b>Admin only.</b> Checks if Piwigo is ready for upload.', 
    586       null, 
     599      $ws_functions_root . 'pwg.images.php', 
    587600      array('admin_only'=>true) 
    588601    ); 
     
    612625(overwrite any existing value) and applies to single values properties like name/author/date_creation/comment. 
    613626<br><b>multiple_value_mode</b> can be "append" (no change on existing values, add the new values) or "replace" and applies to multiple values properties like tag_ids/categories.', 
    614       null, 
     627      $ws_functions_root . 'pwg.images.php', 
    615628      array('admin_only'=>true, 'post_only'=>true) 
    616629    ); 
     
    625638        ), 
    626639      '<b>Admin & POST only.</b> Changes properties of an album.', 
    627       null, 
     640      $ws_functions_root . 'pwg.categories.php', 
    628641      array('admin_only'=>true, 'post_only'=>true) 
    629642    ); 
     
    634647      null, 
    635648      '<b>Admin only.</b> Gets the list of plugins with id, name, version, state and description.', 
    636       null, 
     649      $ws_functions_root . 'pwg.extensions.php', 
    637650      array('admin_only'=>true) 
    638651    ); 
     
    647660        ), 
    648661      '<b>Admin only.</b>', 
    649       null, 
     662      $ws_functions_root . 'pwg.extensions.php', 
    650663      array('admin_only'=>true) 
    651664    ); 
     
    660673        ), 
    661674      '<b>Admin only.</b>', 
    662       null, 
     675      $ws_functions_root . 'pwg.extensions.php', 
    663676      array('admin_only'=>true) 
    664677    ); 
     
    674687        ), 
    675688      '<b>Webmaster only.</b>', 
    676       null, 
     689      $ws_functions_root . 'pwg.extensions.php', 
    677690      array('admin_only'=>true) 
    678691    ); 
     
    691704      ), 
    692705      '<b>Webmaster only.</b> Ignores an extension if it needs update.', 
    693       null, 
     706      $ws_functions_root . 'pwg.extensions.php', 
    694707      array('admin_only'=>true) 
    695708    ); 
     
    700713      null, 
    701714      '<b>Admin only.</b> Checks if piwigo or extensions are up to date.', 
    702       null, 
     715      $ws_functions_root . 'pwg.extensions.php', 
    703716      array('admin_only'=>true) 
    704717    ); 
     
    721734        ), 
    722735      '<b>Admin only.</b> Retrieves a list of all groups. The list can be filtered.', 
    723       null, 
     736      $ws_functions_root . 'pwg.groups.php', 
    724737      array('admin_only'=>true) 
    725738    ); 
     
    734747        ), 
    735748      '<b>Admin & POST only.</b> Creates a group and returns the new group record.', 
    736       null, 
     749      $ws_functions_root . 'pwg.groups.php', 
    737750      array('admin_only'=>true, 'post_only'=>true) 
    738751    ); 
     
    744757        'group_id' => array('flags'=>WS_PARAM_FORCE_ARRAY, 
    745758                            'type'=>WS_TYPE_ID), 
     759        'pwg_token' =>  array(), 
    746760        ), 
    747761      '<b>Admin & POST only.</b> Deletes a or more groups. Users and photos are not deleted.', 
    748       null, 
     762      $ws_functions_root . 'pwg.groups.php', 
    749763      array('admin_only'=>true, 'post_only'=>true) 
    750764    ); 
     
    760774        ), 
    761775      '<b>Admin & POST only.</b> Updates a group. Leave a field blank to keep the current value.', 
    762       null, 
     776      $ws_functions_root . 'pwg.groups.php', 
    763777      array('admin_only'=>true, 'post_only'=>true) 
    764778    ); 
     
    773787        ), 
    774788      '<b>Admin only.</b> Adds one or more users to a group.', 
    775       null, 
     789      $ws_functions_root . 'pwg.groups.php', 
    776790      array('admin_only'=>true) 
    777791    ); 
     
    786800        ), 
    787801      '<b>Admin & POST only.</b> Removes one or more users from a group.', 
    788       null, 
     802      $ws_functions_root . 'pwg.groups.php', 
    789803      array('admin_only'=>true, 'post_only'=>true) 
    790804    ); 
     
    817831      '<b>Admin only.</b> Retrieves a list of all the users. 
    818832<br>"display" controls which data are returned, "basics" stands for "username,email,status,level,groups"', 
    819       null, 
     833      $ws_functions_root . 'pwg.users.php', 
    820834      array('admin_only'=>true) 
    821835    ); 
     
    832846        ), 
    833847      '<b>Admin & POST only.</b> Registers a new user.', 
    834       null, 
     848      $ws_functions_root . 'pwg.users.php', 
    835849      array('admin_only'=>true, 'post_only'=>true) 
    836850    ); 
     
    842856        'user_id' =>  array('flags'=>WS_PARAM_FORCE_ARRAY, 
    843857                            'type'=>WS_TYPE_ID), 
     858        'pwg_token' =>  array(), 
    844859        ), 
    845860      '<b>Admin & POST only.</b> Deletes on or more users. Photos owned by this user are not deleted.', 
    846       null, 
     861      $ws_functions_root . 'pwg.users.php', 
    847862      array('admin_only'=>true, 'post_only'=>true) 
    848863    ); 
     
    880895      '<b>Admin & POST only.</b> Updates a user. Leave a field blank to keep the current value. 
    881896<br>"username", "password" and "email" are ignored if "user_id" is an array.', 
    882       null, 
     897      $ws_functions_root . 'pwg.users.php', 
    883898      array('admin_only'=>true, 'post_only'=>true) 
    884899    ); 
     
    897912      '<b>Admin only.</b> Returns permissions: user ids and group ids having access to each album ; this list can be filtered. 
    898913<br>Provide only one parameter!', 
    899       null, 
     914      $ws_functions_root . 'pwg.permissions.php', 
    900915      array('admin_only'=>true) 
    901916    ); 
     
    915930        ), 
    916931      '<b>Admin only.</b> Adds permissions to an album.', 
    917       null, 
     932      $ws_functions_root . 'pwg.permissions.php', 
    918933      array('admin_only'=>true) 
    919934    ); 
     
    931946        ), 
    932947      '<b>Admin & POST only.</b> Removes permissions from an album.', 
    933       null, 
     948      $ws_functions_root . 'pwg.permissions.php', 
    934949      array('admin_only'=>true, 'post_only'=>true) 
    935950    ); 
Note: See TracChangeset for help on using the changeset viewer.