aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrvelices <rv-github@modusoptimus.com>2007-02-22 01:12:32 +0000
committerrvelices <rv-github@modusoptimus.com>2007-02-22 01:12:32 +0000
commitcea58b64ee31c3b34887845bef6761edee3c6fc7 (patch)
tree66e631cdcad99b2189f57627fc77806fc3ca644f
parent64108c075b87b5b4815f451909dd9d9b3a7f545a (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.php4
-rw-r--r--include/common.inc.php1
-rw-r--r--include/functions_comment.inc.php228
-rw-r--r--include/picture_comment.inc.php212
-rw-r--r--include/ws_functions.inc.php196
-rw-r--r--install/db/53-database.php60
-rw-r--r--tools/ws.htm186
-rw-r--r--ws.php21
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('&#039;', '\''),
+ array('&quot;', '"'),
+ array('&lt;', '<'),
+ array('&gt;', '>'),
+ array('&amp;', '&') // <- 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 -->
diff --git a/ws.php b/ws.php
index 740f5b03e..ca3832a44 100644
--- a/ws.php
+++ b/ws.php
@@ -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',