diff options
author | rvelices <rv-github@modusoptimus.com> | 2007-02-22 01:12:32 +0000 |
---|---|---|
committer | rvelices <rv-github@modusoptimus.com> | 2007-02-22 01:12:32 +0000 |
commit | cea58b64ee31c3b34887845bef6761edee3c6fc7 (patch) | |
tree | 66e631cdcad99b2189f57627fc77806fc3ca644f | |
parent | 64108c075b87b5b4815f451909dd9d9b3a7f545a (diff) |
- user comments are not saved in the database with htmlspecialchars anymore
- web service: added the possibility to enter a user comment using the service...
- new comment functions from picture_comment.inc.php
git-svn-id: http://piwigo.org/svn/trunk@1849 68402e56-0260-453c-a942-63ccdbb3a9ee
-rw-r--r-- | comments.php | 4 | ||||
-rw-r--r-- | include/common.inc.php | 1 | ||||
-rw-r--r-- | include/functions_comment.inc.php | 228 | ||||
-rw-r--r-- | include/picture_comment.inc.php | 212 | ||||
-rw-r--r-- | include/ws_functions.inc.php | 196 | ||||
-rw-r--r-- | install/db/53-database.php | 60 | ||||
-rw-r--r-- | tools/ws.htm | 186 | ||||
-rw-r--r-- | ws.php | 21 |
8 files changed, 608 insertions, 300 deletions
diff --git a/comments.php b/comments.php index 432dad08a..0c0735447 100644 --- a/comments.php +++ b/comments.php @@ -109,10 +109,6 @@ if (isset($_GET['author']) and !empty($_GET['author'])) // search a substring among comments content if (isset($_GET['keyword']) and !empty($_GET['keyword'])) { - // fors some odd reason comment content is htmlspecialchars in the database - $keyword = addslashes( - htmlspecialchars( stripslashes($_GET['keyword']), ENT_QUOTES) - ); $page['where_clauses'][] = '('. implode(' AND ', diff --git a/include/common.inc.php b/include/common.inc.php index d65b69641..a691f6cb5 100644 --- a/include/common.inc.php +++ b/include/common.inc.php @@ -254,6 +254,7 @@ if (isset($conf['header_notes'])) } // default event handlers +add_event_handler('render_comment_content', 'htmlspecialchars'); add_event_handler('render_comment_content', 'parse_comment_content'); trigger_action('init'); ?> diff --git a/include/functions_comment.inc.php b/include/functions_comment.inc.php new file mode 100644 index 000000000..c5ff60fc7 --- /dev/null +++ b/include/functions_comment.inc.php @@ -0,0 +1,228 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | file : $Id$ +// | last update : $Date$ +// | last modifier : $Author$ +// | revision : $Revision$ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +/** + * returns a "secret key" that is to be sent back when a user enters a comment + */ +function get_comment_post_key($image_id) +{ + global $conf; + $time = time(); + return $time.':'.hash_hmac('md5', $time.':'.$image_id, $conf['secret_key'] ); +} + +//returns string action to perform on a new comment: validate, moderate, reject +function user_comment_check($action, $comment) +{ + global $conf,$user; + + if ($action=='reject') + return $action; + + $my_action = $conf['comment_spam_reject'] ? 'reject':'moderate'; + + if ($action==$my_action) + return $action; + + // we do here only BASIC spam check (plugins can do more) + if ( !$user['is_the_guest'] ) + return $action; + + $link_count = preg_match_all( '/https?:\/\//', + $comment['content'], $matches); + + if ( strpos($comment['author'], 'http://')!==false ) + { + $link_count++; + } + + if ( $link_count>$conf['comment_spam_max_links'] ) + return $my_action; + + if ( isset($comment['ip']) and $conf['comment_spam_check_ip'] + and $_SERVER["SERVER_ADDR"] != $comment['ip'] + ) + { + $rev_ip = implode( '.', array_reverse( explode('.',$comment['ip']) ) ); + $lookup = $rev_ip . '.sbl-xbl.spamhaus.org.'; + $res = gethostbyname( $lookup ); + if ( $lookup != $res ) + return $my_action; + } + + return $action; +} + + +add_event_handler('user_comment_check', 'user_comment_check', + EVENT_HANDLER_PRIORITY_NEUTRAL, 2); + +/** + * Tries to insert a user comment in the database and returns one of : + * validate, moderate, reject + * @param array comm contains author, content, image_id + * @param string key secret key sent back to the browser + * @param array infos out array of messages + */ +function insert_user_comment( &$comm, $key, &$infos ) +{ + global $conf, $user; + + $comm = array_merge( $comm, + array( + 'ip' => $_SERVER['REMOTE_ADDR'], + 'agent' => $_SERVER['HTTP_USER_AGENT'] + ) + ); + + $infos = array(); + if (!$conf['comments_validation'] or is_admin()) + { + $comment_action='validate'; //one of validate, moderate, reject + } + else + { + $comment_action='moderate'; //one of validate, moderate, reject + } + + if ( $user['is_the_guest'] ) + { + if ( empty($comm['author']) ) + { + $comm['author'] = 'guest'; + } + // if a guest try to use the name of an already existing user, he must be + // rejected + if ( $comm['author'] != 'guest' ) + { + $query = ' +SELECT COUNT(*) AS user_exists + FROM '.USERS_TABLE.' + WHERE '.$conf['user_fields']['username']." = '".addslashes($comm['author'])."'"; + $row = mysql_fetch_assoc( pwg_query( $query ) ); + if ( $row['user_exists'] == 1 ) + { + array_push($infos, l10n('comment_user_exists') ); + $comment_action='reject'; + } + } + } + else + { + $comm['author'] = $user['username']; + } + if ( empty($comm['content']) ) + { // empty comment content + $comment_action='reject'; + } + + $key = explode( ':', @$key ); + if ( count($key)!=2 + or $key[0]>time()-2 // page must have been retrieved more than 2 sec ago + or $key[0]<time()-3600 // 60 minutes expiration + or hash_hmac( + 'md5', $key[0].':'.$comm['image_id'], $conf['secret_key'] + ) != $key[1] + ) + { + $comment_action='reject'; + } + + if ($comment_action!='reject' and $conf['anti-flood_time']>0 ) + { // anti-flood system + $reference_date = time() - $conf['anti-flood_time']; + $query = ' +SELECT id FROM '.COMMENTS_TABLE.' + WHERE date > FROM_UNIXTIME('.$reference_date.') + AND author = "'.addslashes($comm['author']).'"'; + if ( mysql_num_rows( pwg_query( $query ) ) > 0 ) + { + array_push( $infos, l10n('comment_anti-flood') ); + $comment_action='reject'; + } + } + + // perform more spam check + $comment_action = trigger_event('user_comment_check', + $comment_action, $comm + ); + + if ( $comment_action!='reject' ) + { + $query = ' +INSERT INTO '.COMMENTS_TABLE.' + (author, content, date, validated, validation_date, image_id) + VALUES ( + "'.addslashes($comm['author']).'", + "'.addslashes($comm['content']).'", + NOW(), + "'.($comment_action=='validate' ? 'true':'false').'", + '.($comment_action=='validate' ? 'NOW()':'NULL').', + '.$comm['image_id'].' + ) +'; + + pwg_query($query); + + $comm['id'] = mysql_insert_id(); + + if ( ($comment_action=='validate' and $conf['email_admin_on_comment']) + or $conf['email_admin_on_comment_validation'] ) + { + include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php'); + + $del_url = get_absolute_root_url().'comments.php?delete='.$comm['id']; + + $content = + 'Author: '.$comm['author']."\n" + .'Comment: '.$comm['content']."\n" + .'IP: '.$comm['ip']."\n" + .'Browser: '.$comm['agent']."\n\n" + .'Delete: '.$del_url."\n"; + + if ($comment_action!='validate') + { + $content .= + 'Validate: '.get_absolute_root_url() + .'comments.php?validate='.$comm['id']; + } + + pwg_mail + ( + format_email('administrators', get_webmaster_mail_address()), + array + ( + 'subject' => 'PWG comment by '.$comm['author'], + 'content' => $content, + 'Bcc' => get_administrators_email() + ) + ); + } + } + return $comment_action; +} + +?>
\ No newline at end of file diff --git a/include/picture_comment.inc.php b/include/picture_comment.inc.php index 0c3e3a6a2..424fd3fd3 100644 --- a/include/picture_comment.inc.php +++ b/include/picture_comment.inc.php @@ -4,7 +4,6 @@ // | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | // | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | // +-----------------------------------------------------------------------+ -// | branch : BSF (Best So Far) // | file : $Id$ // | last update : $Date$ // | last modifier : $Author$ @@ -30,46 +29,6 @@ * */ -//returns string action to perform on a new comment: validate, moderate, reject -function user_comment_check($action, $comment, $picture) -{ - global $conf,$user; - - if ($action=='reject') - return $action; - - $my_action = $conf['comment_spam_reject'] ? 'reject':'moderate'; - if ($action==$my_action) - return $action; - - // we do here only BASIC spam check (plugins can do more) - if ( !$user['is_the_guest'] ) - return $action; - - $link_count = preg_match_all( '/https?:\/\//', - $comment['content'], $matches); - - if ( $link_count>$conf['comment_spam_max_links'] ) - return $my_action; - - if ( isset($comment['ip']) and $conf['comment_spam_check_ip'] ) - { - $rev_ip = implode( '.', array_reverse( explode('.',$comment['ip']) ) ); - $lookup = $rev_ip . '.sbl-xbl.spamhaus.org.'; - $res = gethostbyname( $lookup ); - if ( $lookup != $res ) - return $my_action; - } - - return $action; -} - - - -add_event_handler('user_comment_check', 'user_comment_check', - EVENT_HANDLER_PRIORITY_NEUTRAL, 3); - - // the picture is commentable if it belongs at least to one category which // is commentable $page['show_comments'] = false; @@ -88,161 +47,40 @@ if ( $page['show_comments'] and isset( $_POST['content'] ) ) { die ('Session expired'); } - if (!$conf['comments_validation'] or is_admin()) - { - $comment_action='validate'; //one of validate, moderate, reject - } - else - { - $comment_action='moderate'; //one of validate, moderate, reject - } - - $_POST['content'] = trim( stripslashes($_POST['content']) ); - - if ( $user['is_the_guest'] ) - { - $author = empty($_POST['author'])?'guest':$_POST['author']; - // if a guest try to use the name of an already existing user, he must be - // rejected - if ( $author != 'guest' ) - { - $query = 'SELECT COUNT(*) AS user_exists'; - $query.= ' FROM '.USERS_TABLE; - $query.= ' WHERE '.$conf['user_fields']['username']." = '".$author."'"; - $query.= ';'; - $row = mysql_fetch_assoc( pwg_query( $query ) ); - if ( $row['user_exists'] == 1 ) - { - $template->assign_block_vars( - 'information', - array('INFORMATION'=>$lang['comment_user_exists'])); - $comment_action='reject'; - } - } - } - else - { - $author = $user['username']; - } $comm = array( - 'author' => $author, - 'content' => $_POST['content'], + 'author' => trim( stripslashes(@$_POST['author']) ), + 'content' => trim( stripslashes($_POST['content']) ), 'image_id' => $page['image_id'], - 'ip' => $_SERVER['REMOTE_ADDR'], - 'agent' => $_SERVER['HTTP_USER_AGENT'] ); - if ($comment_action!='reject' and empty($comm['content']) ) - { // empty comment content - $comment_action='reject'; - } - - $key = explode(':', @$_POST['key']); - if ( count($key)!=2 - or $key[0]>time()-2 // page must have been retrieved more than 2 sec ago - or $key[0]<time()-3600 // 60 minutes expiration - or hash_hmac('md5', $key[0], $conf['secret_key'])!=$key[1] - ) - { - $comment_action='reject'; - } + include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); - if ($comment_action!='reject' and $conf['anti-flood_time']>0 ) - { // anti-flood system - $reference_date = time() - $conf['anti-flood_time']; - $query = 'SELECT id FROM '.COMMENTS_TABLE; - $query.= ' WHERE date > FROM_UNIXTIME('.$reference_date.')'; - $query.= " AND author = '".$comm['author']."'"; - $query.= ';'; - if ( mysql_num_rows( pwg_query( $query ) ) > 0 ) - { - $template->assign_block_vars( - 'information', - array('INFORMATION'=>$lang['comment_anti-flood'])); - $comment_action='reject'; - } - } - - // perform more spam check - $comment_action = trigger_event('user_comment_check', - $comment_action, $comm, $picture['current'] + $comment_action = insert_user_comment( + $comm, @$_POST['key'], $page['image_id'], $infos ); - if ( $comment_action!='reject' ) + switch ($comment_action) { - list($dbnow) = mysql_fetch_row(pwg_query('SELECT NOW();')); - - $data = $comm; - $data['date'] = $dbnow; - $data['content'] = addslashes( - // this htmlpsecialchars is not good here - htmlspecialchars($comm['content'],ENT_QUOTES) - ); - - if ($comment_action=='validate') - { - $data['validated'] = 'true'; - $data['validation_date'] = $dbnow; - } - else - { - $data['validated'] = 'false'; - } - - include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); - $fields = array('author', 'date', 'image_id', 'content', 'validated', - 'validation_date'); - mass_inserts(COMMENTS_TABLE, $fields, array($data)); - $comm['id'] = mysql_insert_id(); - - // information message - $message = $lang['comment_added']; - if ($comment_action!='validate') - { - $message.= '<br />'.$lang['comment_to_validate']; - } - $template->assign_block_vars('information', - array('INFORMATION'=>$message)); - if ( ($comment_action=='validate' and $conf['email_admin_on_comment']) - or $conf['email_admin_on_comment_validation'] ) - { - include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php'); - - $del_url = get_absolute_root_url().'comments.php?delete='.$comm['id']; - - $content = - 'Author: '.$comm['author']."\n" - .'Comment: '.$comm['content']."\n" - .'IP: '.$comm['ip']."\n" - .'Browser: '.$comm['agent']."\n\n" - .'Delete: '.$del_url."\n"; - - if ($comment_action!='validate') - { - $content .= - 'Validate: '.get_absolute_root_url() - .'comments.php?validate='.$comm['id']; - } - - pwg_mail - ( - format_email('administrators', get_webmaster_mail_address()), - array - ( - 'subject' => 'PWG comment by '.$comm['author'], - 'content' => $content, - 'Bcc' => get_administrators_email() - ) - ); - } + case 'moderate': + array_push( $infos, $lang['comment_to_validate'] ); + case 'validate': + array_push( $infos, $lang['comment_added']); + break; + case 'reject': + set_status_header(403); + array_push($infos, l10n('comment_not_added') ); + break; + default: + trigger_error('Invalid comment action '.$comment_action, E_USER_WARNING); } - else + + foreach ($infos as $info) { - set_status_header(403); - $template->assign_block_vars('information', - array('INFORMATION'=>l10n('comment_not_added') ) - ); + $template->assign_block_vars( + 'information', + array( 'INFORMATION'=>$info ) + ); } // allow plugins to notify what's going on @@ -335,8 +173,8 @@ SELECT id,author,date,image_id,content if (!$user['is_the_guest'] or ($user['is_the_guest'] and $conf['comments_forall'])) { - $key = time(); - $key .= ':'.hash_hmac('md5', $key, $conf['secret_key']); + include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); + $key = get_comment_post_key($page['image_id']); $content = ''; if ('reject'===@$comment_action) { diff --git a/include/ws_functions.inc.php b/include/ws_functions.inc.php index 494b3596f..8af08204c 100644 --- a/include/ws_functions.inc.php +++ b/include/ws_functions.inc.php @@ -32,8 +32,19 @@ function ws_isInvokeAllowed($res, $methodName, $params) { global $conf, $calling_partner_id; - if ( !$conf['ws_access_control'] - or strpos($methodName,'reflection.')===0 ) + + if ( strpos($methodName,'reflection.')===0 ) + { // OK for reflection + return $res; + } + + if ( !is_autorize_status(ACCESS_GUEST) and + strpos($methodName,'pwg.session.')!==0 ) + { + return new PwgError(401, 'Access denied'); + } + + if ( !$conf['ws_access_control'] ) { return $res; // No controls are requested } @@ -486,10 +497,69 @@ ORDER BY global_rank'; /** * returns detailed information for an element (web service method) */ +function ws_images_addComment($params, &$service) +{ + $params['image_id'] = (int)$params['image_id']; + $query = ' +SELECT DISTINCT image_id + FROM '.IMAGE_CATEGORY_TABLE.' INNER JOIN '.CATEGORIES_TABLE.' ON category_id=id + WHERE commentable="true" + AND image_id='.$params['image_id']. + get_sql_condition_FandF( + array( + 'forbidden_categories' => 'id', + 'visible_categories' => 'id', + 'visible_images' => 'image_id' + ), + ' AND' + ); + if ( !mysql_num_rows( pwg_query( $query ) ) ) + { + return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id"); + } + + include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); + + $comm = array( + 'author' => trim( stripslashes($params['author']) ), + 'content' => trim( stripslashes($params['content']) ), + 'image_id' => $params['image_id'], + ); + + include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); + + $comment_action = insert_user_comment( + $comm, $params['key'], $infos + ); + + switch ($comment_action) + { + case 'reject': + array_push($infos, l10n('comment_not_added') ); + return new PwgError(403, implode("\n", $infos) ); + case 'validate': + case 'moderate': + $ret = array( + 'id' => $comm['id'], + 'validation' => $comment_action=='validate', + ); + return new PwgNamedStruct( + 'comment', + $ret, + null, array() + ); + default: + return new PwgError(500, "Unknown comment action ".$comment_action ); + } +} + +/** + * returns detailed information for an element (web service method) + */ function ws_images_getInfo($params, &$service) { @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php'); - global $user; + global $user, $conf; $params['image_id'] = (int)$params['image_id']; if ( $params['image_id']<=0 ) { @@ -515,16 +585,22 @@ LIMIT 1;'; //-------------------------------------------------------- related categories $query = ' -SELECT c.id,c.name,c.uppercats,c.global_rank +SELECT id,name,uppercats,global_rank,commentable FROM '.IMAGE_CATEGORY_TABLE.' - INNER JOIN '.CATEGORIES_TABLE.' c ON category_id = id + INNER JOIN '.CATEGORIES_TABLE.' ON category_id = id WHERE image_id = '.$image_row['id'].' AND category_id NOT IN ('.$user['forbidden_categories'].') ;'; $result = pwg_query($query); + $is_commentable = false; $related_categories = array(); while ($row = mysql_fetch_assoc($result)) { + if ($row['commentable']=='true') + { + $is_commentable = true; + } + unset($row['commentable']); $row['url'] = make_index_url( array( 'category' => $row['id'], @@ -540,6 +616,7 @@ SELECT c.id,c.name,c.uppercats,c.global_rank 'cat_name' => $row['name'], ) ); + $row['id']=(int)$row['id']; array_push($related_categories, $row); } usort($related_categories, 'global_rank_compare'); @@ -565,51 +642,97 @@ SELECT c.id,c.name,c.uppercats,c.global_rank ) ); unset($tag['counter']); + $tag['id']=(int)$tag['id']; $related_tags[$i]=$tag; } + //------------------------------------------------------------- related rates + $query = ' +SELECT COUNT(rate) AS count + , ROUND(AVG(rate),2) AS average + , ROUND(STD(rate),2) AS stdev + FROM '.RATE_TABLE.' + WHERE element_id = '.$image_row['id'].' +;'; + $rating = mysql_fetch_assoc(pwg_query($query)); + $rating['count'] = (int)$rating['count']; + //---------------------------------------------------------- related comments + $related_comments = array(); + + $where_comments = 'image_id = '.$image_row['id']; + if ( !is_admin() ) + { + $where_comments .= ' + AND validated="true"'; + } + $query = ' SELECT COUNT(id) nb_comments FROM '.COMMENTS_TABLE.' - WHERE image_id = '.$image_row['id']; + WHERE '.$where_comments; list($nb_comments) = array_from_query($query, 'nb_comments'); + $nb_comments = (int)$nb_comments; - $query = ' + if ( $nb_comments>0 and $params['comments_per_page']>0 ) + { + $query = ' SELECT id, date, author, content FROM '.COMMENTS_TABLE.' - WHERE image_id = '.$image_row['id'].' - AND validated="true"'; - $query .= ' - ORDER BY date DESC - LIMIT 0, 5'; + WHERE '.$where_comments.' + ORDER BY date + LIMIT '.$params['comments_per_page']*(int)$params['comments_page']. + ','.$params['comments_per_page']; - $result = pwg_query($query); - $related_comments = array(); - while ($row = mysql_fetch_assoc($result)) + $result = pwg_query($query); + while ($row = mysql_fetch_assoc($result)) + { + $row['id']=(int)$row['id']; + array_push($related_comments, $row); + } + } + + $comment_post_data = null; + if ($is_commentable and + (!$user['is_the_guest'] + or ($user['is_the_guest'] and $conf['comments_forall'] ) + ) + ) { - array_push($related_comments, $row); + include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); + $comment_post_data['author'] = $user['username']; + $comment_post_data['key'] = get_comment_post_key($params['image_id']); } - //------------------------------------------------------------- related rates - $query = ' -SELECT COUNT(rate) AS count - , ROUND(AVG(rate),2) AS average - , ROUND(STD(rate),2) AS stdev - FROM '.RATE_TABLE.' - WHERE element_id = '.$image_row['id'].' -;'; - $row = mysql_fetch_assoc(pwg_query($query)); - $ret = $image_row; - $ret['rates'] = array( WS_XML_ATTRIBUTES => $row ); + foreach ( array('id','width','height','hit','filesize') as $k ) + { + if (isset($ret[$k])) + { + $ret[$k] = (int)$ret[$k]; + } + } + foreach ( array('path', 'storage_category_id') as $k ) + { + unset($ret[$k]); + } + + $ret['rates'] = array( WS_XML_ATTRIBUTES => $rating ); $ret['categories'] = new PwgNamedArray($related_categories, 'category', array('id','url', 'page_url') ); $ret['tags'] = new PwgNamedArray($related_tags, 'tag', array('id','url_name','url','page_url') ); + if ( isset($comment_post_data) ) + { + $ret['comment_post'] = array( WS_XML_ATTRIBUTES => $comment_post_data ); + } $ret['comments'] = array( - WS_XML_ATTRIBUTES => array('nb_comments' => $nb_comments), - WS_XML_CONTENT => new PwgNamedArray($related_comments, 'comment', array('id') ) + WS_XML_ATTRIBUTES => + array( + 'page' => $params['comments_page'], + 'per_page' => $params['comments_per_page'], + 'count' => count($related_comments), + 'nb_comments' => $nb_comments, + ), + WS_XML_CONTENT => new PwgNamedArray($related_comments, 'comment', array('id','date') ) ); - unset($ret['path']); - unset($ret['storage_category_id']); return new PwgNamedStruct('image',$ret, null, array('name','comment') ); } @@ -768,10 +891,17 @@ function ws_session_logout($params, &$service) function ws_session_getStatus($params, &$service) { - global $user; + global $user, $lang_info; $res = array(); $res['username'] = $user['is_the_guest'] ? 'guest' : $user['username']; - $res['status'] = $user['status']; + foreach ( array('status', 'template', 'theme', 'language') as $k ) + { + $res[$k] = $user[$k]; + } + foreach ( array('charset') as $k ) + { + $res[$k] = $lang_info[$k]; + } return $res; } diff --git a/install/db/53-database.php b/install/db/53-database.php new file mode 100644 index 000000000..020096401 --- /dev/null +++ b/install/db/53-database.php @@ -0,0 +1,60 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | file : $Id$ +// | last update : $Date$ +// | last modifier : $Author$ +// | revision : $Revision$ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +if (!defined('PHPWG_ROOT_PATH')) +{ + die('Hacking attempt!'); +} + +$upgrade_description = '#comments.content is not html escaped anymore'; + +include_once(PHPWG_ROOT_PATH.'include/constants.php'); + + +$replacements = array( + array(''', '\''), + array('"', '"'), + array('<', '<'), + array('>', '>'), + array('&', '&') // <- this must be the last one + ); + +foreach ($replacements as $replacement) +{ + $query = ' +UPDATE '.COMMENTS_TABLE.' + SET content = REPLACE(content, "'.addslashes($replacement[0]).'", "'.addslashes($replacement[1]).'") +;'; + pwg_query($query); +} + +echo +"\n" +.'"'.$upgrade_description.'"'.', ended' +."\n" +; + +?> diff --git a/tools/ws.htm b/tools/ws.htm index fdbd6a502..ac525ab1d 100644 --- a/tools/ws.htm +++ b/tools/ws.htm @@ -1,3 +1,4 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>PWG web service explorer</title> @@ -40,6 +41,7 @@ function dumpError(err) } var gServiceUrl; +var gCurrentMethodParams; Ajax.Responders.register({ @@ -104,6 +106,7 @@ function pwgChangeUrl() setVisibility("methodWrapper", "hidden"); gServiceUrl = $F('ws_url'); + gCurrentMethodParams = null; try { var ajaxReq = new Ajax.Request( @@ -137,6 +140,7 @@ function pwgSelectMethod(method) setElementText("methodName", method); setVisibility("methodDetailWrapper", "hidden"); setVisibility("methodWrapper", "visible"); + gCurrentMethodParams = null; try { @@ -160,26 +164,29 @@ function onSuccess_getMethodDetails(transport) while (methodParamsElt.tBodies[0].rows.length) methodParamsElt.tBodies[0].deleteRow(methodParamsElt.tBodies[0].rows.length-1); - if (result.params && result.params.length>0) - { - for (var i=0; i<result.params.length; i++) - { - var row = methodParamsElt.tBodies[0].insertRow(-1); - var isOptional = result.params[i].optional; - var defaultValue = result.params[i].defaultValue == null ? '' : result.params[i].defaultValue; - - row.insertCell(0).innerHTML = result.params[i].name; - row.insertCell(1).innerHTML = (isOptional ? 'optional':'required'); - row.insertCell(2).innerHTML = '<input id="methodParameterSend_'+i+'" type="checkbox" '+(isOptional ? '':'checked="checked"')+'/>'; - row.insertCell(3).innerHTML = '<input id="methodParameterName_'+i+'" type="hidden" value="'+result.params[i].name+'"/>' - +'<input id="methodParameterValue_'+i+'"" value="'+defaultValue+'" style="width:99%" onchange="$(\'methodParameterSend_'+i+'\').checked=true;"/>'; - } + if (result.params) + { + gCurrentMethodParams = result.params; + if (result.params.length>0) + { + for (var i=0; i<result.params.length; i++) + { + var row = methodParamsElt.tBodies[0].insertRow(-1); + var isOptional = result.params[i].optional; + var defaultValue = result.params[i].defaultValue == null ? '' : result.params[i].defaultValue; + + row.insertCell(0).innerHTML = result.params[i].name; + row.insertCell(1).innerHTML = (isOptional ? 'optional':'required'); + row.insertCell(2).innerHTML = '<input id="methodParameterSend_'+i+'" type="checkbox" '+(isOptional ? '':'checked="checked"')+'/>'; + row.insertCell(3).innerHTML = '<input id="methodParameterValue_'+i+'"" value="'+defaultValue+'" style="width:99%" onchange="$(\'methodParameterSend_'+i+'\').checked=true;"/>'; + } + } } setElementText("methodDescription", result.description); setVisibility("methodDetailWrapper", "visible"); } -function pwgInvokeMethod() +function pwgInvokeMethod( newWindow ) { var method = document.getElementById('methodName').innerHTML; @@ -189,34 +196,31 @@ function pwgInvokeMethod() if (document.getElementById('requestFormat').value == 'get') { reqUrl += "&method="+method; - var i=0; - do + for ( var i=0; i<gCurrentMethodParams.length; i++) { - var elt = document.getElementById('methodParameterName_'+i); - if (!elt) break; if (document.getElementById('methodParameterSend_'+i).checked) - reqUrl += '&'+elt.value+'='+$F('methodParameterValue_'+i); - i++; + reqUrl += '&'+gCurrentMethodParams[i].name+'='+$F('methodParameterValue_'+i); } - while (1); - document.getElementById("invokeFrame").src = reqUrl; + if ( !newWindow ) + document.getElementById("invokeFrame").src = reqUrl; + else + window.open(reqUrl); } else { var form = document.getElementById("invokeForm"); form.action = reqUrl; var t = '<input type="hidden" name="'+'method'+'" value="'+method+'"/>'; - var i=0; - do + for ( var i=0; i<gCurrentMethodParams.length; i++) { - var elt = document.getElementById('methodParameterName_'+i); - if (!elt) break; if (document.getElementById('methodParameterSend_'+i).checked) - t += '<input type="hidden" name="'+elt.value+'" value="'+$F('methodParameterValue_'+i)+'"/>'; - i++; + t += '<input type="hidden" name="'+gCurrentMethodParams[i].name+'" value="'+$F('methodParameterValue_'+i)+'"/>'; } - while (1); form.innerHTML = t; + if ( !newWindow ) + form.target = "invokeFrame"; + else + form.target = "_blank"; form.submit(); } return false; @@ -226,18 +230,19 @@ function pwgInvokeMethod() <style> #methodListWrapper { - width: 16em; + width: 13em; float: left; display: inline; visibility: hidden; } #methodList { - padding-left: 15px; + padding-left: 10px; + margin-left: 15px; } #methodWrapper { - margin-left: 16.5em; + margin-left: 14em; visibility: hidden; } @@ -255,7 +260,29 @@ function pwgInvokeMethod() #methodParams { border-collapse: collapse; + font-size: small; +} + +#methodParams input { + font-size: 90%; + border: 1px solid black; + text-indent: 2px; +} + + +a { + color: #02f; + background-color: white; + text-decoration: underline; } + +a:hover { + color: white; + background-color: #02f; + text-decoration: none; + cursor:pointer; +} + </style> </head> @@ -279,7 +306,7 @@ function pwgInvokeMethod() <div> -<div id="methodListWrapper">Methods +<div id="methodListWrapper"><h2>Methods</h2> <ul id="methodList"> <li><a href="#" onclick="return pwgSelectMethod(this.innerHTML)">getVersion</a></li> </ul> @@ -288,55 +315,68 @@ function pwgInvokeMethod() <div id="methodWrapper"> <h2 id="methodName"></h2> <div id="methodDetailWrapper"> - <div id="methodDescription"></div> - <table> - <tr> - <td>Request format:</td> - <td> - <select id="requestFormat"> - <option value="get" selected="selected">GET</option> - <option value="post">POST</option> - </select> - </td> - </tr> - - <tr> - <td>Response format:</td> - <td> - <select id="responseFormat"> - <option value="rest" selected="selected">REST (xml)</option> - <option value="json">JSON</option> - <option value="php">PHP serial</option> - <option value="xmlrpc">XML RPC</option> - </select> - </td> - </tr> - </table> - <div id="methodParamsWrapper"> - <table id="methodParams" border="1" cellspacing="0" cellpadding="2px"> - <thead> + <table> + <tr style="vertical-align:top"> + + <td> + <div id="methodDescription"></div> + <table> + <tr> + <td>Request format:</td> + <td> + <select id="requestFormat"> + <option value="get" selected="selected">GET</option> + <option value="post">POST</option> + </select> + </td> + </tr> + <tr> - <td style="width:150px">Parameter</td> - <td>Optional</td> - <td>Send</td> - <td style="width:160px">Value</td> + <td>Response format:</td> + <td> + <select id="responseFormat"> + <option value="rest" selected="selected">REST (xml)</option> + <option value="json">JSON</option> + <option value="php">PHP serial</option> + <option value="xmlrpc">XML RPC</option> + </select> + </td> </tr> - </thead> - <tbody> - </tbody> + </table> + <p> + <a href="#" onclick="return pwgInvokeMethod(false)">Invoke</a> + <a href="#" onclick="return pwgInvokeMethod(true)">Invoke (new Window)</a> + </p> + </td> + + + <td> + <table id="methodParams" border="1" cellspacing="0" cellpadding="2px"> + <thead> + <tr> + <td style="width:150px">Parameter</td> + <td>Optional</td> + <td>Send</td> + <td style="width:160px">Value</td> + </tr> + </thead> + <tbody> + </tbody> + </table> + </td> + + </tr> </table> - </div> - <a href="#" onclick="return pwgInvokeMethod()">Invoke</a> - - <div style="display:none"> + + <div style="display:none;"> <!-- hiddenForm for POST --> <form method="post" action="" target="invokeFrame" id="invokeForm"> <input type="submit" value="submit"/> </form> </div> - <iframe width="100%" height="400px" id="invokeFrame" name="invokeFrame"></iframe> + <iframe width="100%" height="400px" id="invokeFrame" name="invokeFrame" style="clear:both"></iframe> </div> <!-- methodDetailWrapper --> </div> <!-- methodWrapper --> @@ -3,7 +3,6 @@ // | PhpWebGallery - a PHP based picture gallery | // | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | // +-----------------------------------------------------------------------+ -// | branch : BSF (Best So Far) // | file : $Id$ // | last update : $Date$ // | last modifier : $Author$ @@ -40,7 +39,7 @@ if ( !$conf['allow_web_services'] ) function ws_addDefaultMethods( $arr ) { include_once(PHPWG_ROOT_PATH.'include/ws_functions.inc.php'); - global $conf; + global $conf, $user; $service = &$arr[0]; $service->addMethod('pwg.getVersion', 'ws_getVersion', null, 'retrieves the PWG version'); @@ -77,8 +76,24 @@ function ws_addDefaultMethods( $arr ) ), 'retrieves a list of categories' ); + $service->addMethod('pwg.images.addComment', 'ws_images_addComment', + array( + 'image_id' => array(), + 'author' => array( 'default' => $user['is_the_guest']? 'guest':$user['username']), + 'content' => array(), + 'key' => array(), + ), + 'add a comment to an image' ); + $service->addMethod('pwg.images.getInfo', 'ws_images_getInfo', - array('image_id'), + array( + 'image_id' => array(), + 'comments_page' => array('default'=>0 ), + 'comments_per_page' => array( + 'default' => $conf['nb_comment_page'], + 'maxValue' => 2*$conf['nb_comment_page'], + ), + ), 'retrieves information about the given photo' ); $service->addMethod('pwg.images.search', 'ws_images_search', |