- 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
This commit is contained in:
rvelices 2007-02-22 01:12:32 +00:00
parent 64108c075b
commit cea58b64ee
8 changed files with 611 additions and 303 deletions

View file

@ -109,10 +109,6 @@ if (isset($_GET['author']) and !empty($_GET['author']))
// search a substring among comments content // search a substring among comments content
if (isset($_GET['keyword']) and !empty($_GET['keyword'])) 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'][] = $page['where_clauses'][] =
'('. '('.
implode(' AND ', implode(' AND ',

View file

@ -254,6 +254,7 @@ if (isset($conf['header_notes']))
} }
// default event handlers // default event handlers
add_event_handler('render_comment_content', 'htmlspecialchars');
add_event_handler('render_comment_content', 'parse_comment_content'); add_event_handler('render_comment_content', 'parse_comment_content');
trigger_action('init'); trigger_action('init');
?> ?>

View file

@ -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;
}
?>

View file

@ -4,7 +4,6 @@
// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | // | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | // | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
// +-----------------------------------------------------------------------+ // +-----------------------------------------------------------------------+
// | branch : BSF (Best So Far)
// | file : $Id$ // | file : $Id$
// | last update : $Date$ // | last update : $Date$
// | last modifier : $Author$ // | 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 // the picture is commentable if it belongs at least to one category which
// is commentable // is commentable
$page['show_comments'] = false; $page['show_comments'] = false;
@ -88,161 +47,40 @@ if ( $page['show_comments'] and isset( $_POST['content'] ) )
{ {
die ('Session expired'); 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( $comm = array(
'author' => $author, 'author' => trim( stripslashes(@$_POST['author']) ),
'content' => $_POST['content'], 'content' => trim( stripslashes($_POST['content']) ),
'image_id' => $page['image_id'], 'image_id' => $page['image_id'],
'ip' => $_SERVER['REMOTE_ADDR'],
'agent' => $_SERVER['HTTP_USER_AGENT']
); );
if ($comment_action!='reject' and empty($comm['content']) ) include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
{ // 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';
}
if ($comment_action!='reject' and $conf['anti-flood_time']>0 ) $comment_action = insert_user_comment(
{ // anti-flood system $comm, @$_POST['key'], $page['image_id'], $infos
$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']
); );
if ( $comment_action!='reject' ) switch ($comment_action)
{ {
list($dbnow) = mysql_fetch_row(pwg_query('SELECT NOW();')); case 'moderate':
array_push( $infos, $lang['comment_to_validate'] );
$data = $comm; case 'validate':
$data['date'] = $dbnow; array_push( $infos, $lang['comment_added']);
$data['content'] = addslashes( break;
// this htmlpsecialchars is not good here case 'reject':
htmlspecialchars($comm['content'],ENT_QUOTES) set_status_header(403);
); array_push($infos, l10n('comment_not_added') );
break;
if ($comment_action=='validate') default:
{ trigger_error('Invalid comment action '.$comment_action, E_USER_WARNING);
$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()
)
);
}
} }
else
foreach ($infos as $info)
{ {
set_status_header(403); $template->assign_block_vars(
$template->assign_block_vars('information', 'information',
array('INFORMATION'=>l10n('comment_not_added') ) array( 'INFORMATION'=>$info )
); );
} }
// allow plugins to notify what's going on // allow plugins to notify what's going on
@ -335,8 +173,8 @@ SELECT id,author,date,image_id,content
if (!$user['is_the_guest'] if (!$user['is_the_guest']
or ($user['is_the_guest'] and $conf['comments_forall'])) or ($user['is_the_guest'] and $conf['comments_forall']))
{ {
$key = time(); include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
$key .= ':'.hash_hmac('md5', $key, $conf['secret_key']); $key = get_comment_post_key($page['image_id']);
$content = ''; $content = '';
if ('reject'===@$comment_action) if ('reject'===@$comment_action)
{ {

View file

@ -32,8 +32,19 @@
function ws_isInvokeAllowed($res, $methodName, $params) function ws_isInvokeAllowed($res, $methodName, $params)
{ {
global $conf, $calling_partner_id; 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 return $res; // No controls are requested
} }
@ -483,13 +494,72 @@ 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) * returns detailed information for an element (web service method)
*/ */
function ws_images_getInfo($params, &$service) function ws_images_getInfo($params, &$service)
{ {
@include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php'); @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
global $user; global $user, $conf;
$params['image_id'] = (int)$params['image_id']; $params['image_id'] = (int)$params['image_id'];
if ( $params['image_id']<=0 ) if ( $params['image_id']<=0 )
{ {
@ -515,16 +585,22 @@ LIMIT 1;';
//-------------------------------------------------------- related categories //-------------------------------------------------------- related categories
$query = ' $query = '
SELECT c.id,c.name,c.uppercats,c.global_rank SELECT id,name,uppercats,global_rank,commentable
FROM '.IMAGE_CATEGORY_TABLE.' 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'].' WHERE image_id = '.$image_row['id'].'
AND category_id NOT IN ('.$user['forbidden_categories'].') AND category_id NOT IN ('.$user['forbidden_categories'].')
;'; ;';
$result = pwg_query($query); $result = pwg_query($query);
$is_commentable = false;
$related_categories = array(); $related_categories = array();
while ($row = mysql_fetch_assoc($result)) while ($row = mysql_fetch_assoc($result))
{ {
if ($row['commentable']=='true')
{
$is_commentable = true;
}
unset($row['commentable']);
$row['url'] = make_index_url( $row['url'] = make_index_url(
array( array(
'category' => $row['id'], 'category' => $row['id'],
@ -540,6 +616,7 @@ SELECT c.id,c.name,c.uppercats,c.global_rank
'cat_name' => $row['name'], 'cat_name' => $row['name'],
) )
); );
$row['id']=(int)$row['id'];
array_push($related_categories, $row); array_push($related_categories, $row);
} }
usort($related_categories, 'global_rank_compare'); usort($related_categories, 'global_rank_compare');
@ -565,31 +642,9 @@ SELECT c.id,c.name,c.uppercats,c.global_rank
) )
); );
unset($tag['counter']); unset($tag['counter']);
$tag['id']=(int)$tag['id'];
$related_tags[$i]=$tag; $related_tags[$i]=$tag;
} }
//---------------------------------------------------------- related comments
$query = '
SELECT COUNT(id) nb_comments
FROM '.COMMENTS_TABLE.'
WHERE image_id = '.$image_row['id'];
list($nb_comments) = array_from_query($query, 'nb_comments');
$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';
$result = pwg_query($query);
$related_comments = array();
while ($row = mysql_fetch_assoc($result))
{
array_push($related_comments, $row);
}
//------------------------------------------------------------- related rates //------------------------------------------------------------- related rates
$query = ' $query = '
SELECT COUNT(rate) AS count SELECT COUNT(rate) AS count
@ -598,18 +653,86 @@ SELECT COUNT(rate) AS count
FROM '.RATE_TABLE.' FROM '.RATE_TABLE.'
WHERE element_id = '.$image_row['id'].' WHERE element_id = '.$image_row['id'].'
;'; ;';
$row = mysql_fetch_assoc(pwg_query($query)); $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 '.$where_comments;
list($nb_comments) = array_from_query($query, 'nb_comments');
$nb_comments = (int)$nb_comments;
if ( $nb_comments>0 and $params['comments_per_page']>0 )
{
$query = '
SELECT id, date, author, content
FROM '.COMMENTS_TABLE.'
WHERE '.$where_comments.'
ORDER BY date
LIMIT '.$params['comments_per_page']*(int)$params['comments_page'].
','.$params['comments_per_page'];
$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'] )
)
)
{
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']);
}
$ret = $image_row; $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['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') ); $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( $ret['comments'] = array(
WS_XML_ATTRIBUTES => array('nb_comments' => $nb_comments), WS_XML_ATTRIBUTES =>
WS_XML_CONTENT => new PwgNamedArray($related_comments, 'comment', array('id') ) 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') ); 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) function ws_session_getStatus($params, &$service)
{ {
global $user; global $user, $lang_info;
$res = array(); $res = array();
$res['username'] = $user['is_the_guest'] ? 'guest' : $user['username']; $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; return $res;
} }

View file

@ -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"
;
?>

View file

@ -1,3 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html> <html>
<head> <head>
<title>PWG web service explorer</title> <title>PWG web service explorer</title>
@ -40,6 +41,7 @@ function dumpError(err)
} }
var gServiceUrl; var gServiceUrl;
var gCurrentMethodParams;
Ajax.Responders.register({ Ajax.Responders.register({
@ -104,6 +106,7 @@ function pwgChangeUrl()
setVisibility("methodWrapper", "hidden"); setVisibility("methodWrapper", "hidden");
gServiceUrl = $F('ws_url'); gServiceUrl = $F('ws_url');
gCurrentMethodParams = null;
try { try {
var ajaxReq = new Ajax.Request( var ajaxReq = new Ajax.Request(
@ -137,6 +140,7 @@ function pwgSelectMethod(method)
setElementText("methodName", method); setElementText("methodName", method);
setVisibility("methodDetailWrapper", "hidden"); setVisibility("methodDetailWrapper", "hidden");
setVisibility("methodWrapper", "visible"); setVisibility("methodWrapper", "visible");
gCurrentMethodParams = null;
try { try {
@ -160,26 +164,29 @@ function onSuccess_getMethodDetails(transport)
while (methodParamsElt.tBodies[0].rows.length) while (methodParamsElt.tBodies[0].rows.length)
methodParamsElt.tBodies[0].deleteRow(methodParamsElt.tBodies[0].rows.length-1); methodParamsElt.tBodies[0].deleteRow(methodParamsElt.tBodies[0].rows.length-1);
if (result.params && result.params.length>0) if (result.params)
{ {
for (var i=0; i<result.params.length; i++) gCurrentMethodParams = result.params;
{ if (result.params.length>0)
var row = methodParamsElt.tBodies[0].insertRow(-1); {
var isOptional = result.params[i].optional; for (var i=0; i<result.params.length; i++)
var defaultValue = result.params[i].defaultValue == null ? '' : result.params[i].defaultValue; {
var row = methodParamsElt.tBodies[0].insertRow(-1);
row.insertCell(0).innerHTML = result.params[i].name; var isOptional = result.params[i].optional;
row.insertCell(1).innerHTML = (isOptional ? 'optional':'required'); var defaultValue = result.params[i].defaultValue == null ? '' : result.params[i].defaultValue;
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+'"/>' row.insertCell(0).innerHTML = result.params[i].name;
+'<input id="methodParameterValue_'+i+'"" value="'+defaultValue+'" style="width:99%" onchange="$(\'methodParameterSend_'+i+'\').checked=true;"/>'; 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); setElementText("methodDescription", result.description);
setVisibility("methodDetailWrapper", "visible"); setVisibility("methodDetailWrapper", "visible");
} }
function pwgInvokeMethod() function pwgInvokeMethod( newWindow )
{ {
var method = document.getElementById('methodName').innerHTML; var method = document.getElementById('methodName').innerHTML;
@ -189,34 +196,31 @@ function pwgInvokeMethod()
if (document.getElementById('requestFormat').value == 'get') if (document.getElementById('requestFormat').value == 'get')
{ {
reqUrl += "&method="+method; reqUrl += "&method="+method;
var i=0; for ( var i=0; i<gCurrentMethodParams.length; i++)
do
{ {
var elt = document.getElementById('methodParameterName_'+i);
if (!elt) break;
if (document.getElementById('methodParameterSend_'+i).checked) if (document.getElementById('methodParameterSend_'+i).checked)
reqUrl += '&'+elt.value+'='+$F('methodParameterValue_'+i); reqUrl += '&'+gCurrentMethodParams[i].name+'='+$F('methodParameterValue_'+i);
i++;
} }
while (1); if ( !newWindow )
document.getElementById("invokeFrame").src = reqUrl; document.getElementById("invokeFrame").src = reqUrl;
else
window.open(reqUrl);
} }
else else
{ {
var form = document.getElementById("invokeForm"); var form = document.getElementById("invokeForm");
form.action = reqUrl; form.action = reqUrl;
var t = '<input type="hidden" name="'+'method'+'" value="'+method+'"/>'; var t = '<input type="hidden" name="'+'method'+'" value="'+method+'"/>';
var i=0; for ( var i=0; i<gCurrentMethodParams.length; i++)
do
{ {
var elt = document.getElementById('methodParameterName_'+i);
if (!elt) break;
if (document.getElementById('methodParameterSend_'+i).checked) if (document.getElementById('methodParameterSend_'+i).checked)
t += '<input type="hidden" name="'+elt.value+'" value="'+$F('methodParameterValue_'+i)+'"/>'; t += '<input type="hidden" name="'+gCurrentMethodParams[i].name+'" value="'+$F('methodParameterValue_'+i)+'"/>';
i++;
} }
while (1);
form.innerHTML = t; form.innerHTML = t;
if ( !newWindow )
form.target = "invokeFrame";
else
form.target = "_blank";
form.submit(); form.submit();
} }
return false; return false;
@ -226,18 +230,19 @@ function pwgInvokeMethod()
<style> <style>
#methodListWrapper { #methodListWrapper {
width: 16em; width: 13em;
float: left; float: left;
display: inline; display: inline;
visibility: hidden; visibility: hidden;
} }
#methodList { #methodList {
padding-left: 15px; padding-left: 10px;
margin-left: 15px;
} }
#methodWrapper { #methodWrapper {
margin-left: 16.5em; margin-left: 14em;
visibility: hidden; visibility: hidden;
} }
@ -255,7 +260,29 @@ function pwgInvokeMethod()
#methodParams { #methodParams {
border-collapse: collapse; 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> </style>
</head> </head>
@ -279,7 +306,7 @@ function pwgInvokeMethod()
<div> <div>
<div id="methodListWrapper">Methods <div id="methodListWrapper"><h2>Methods</h2>
<ul id="methodList"> <ul id="methodList">
<li><a href="#" onclick="return pwgSelectMethod(this.innerHTML)">getVersion</a></li> <li><a href="#" onclick="return pwgSelectMethod(this.innerHTML)">getVersion</a></li>
</ul> </ul>
@ -288,55 +315,68 @@ function pwgInvokeMethod()
<div id="methodWrapper"> <div id="methodWrapper">
<h2 id="methodName"></h2> <h2 id="methodName"></h2>
<div id="methodDetailWrapper"> <div id="methodDetailWrapper">
<div id="methodDescription"></div>
<table> <table>
<tr> <tr style="vertical-align:top">
<td>Request format:</td>
<td> <td>
<select id="requestFormat"> <div id="methodDescription"></div>
<option value="get" selected="selected">GET</option> <table>
<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>
<tr> <tr>
<td style="width:150px">Parameter</td> <td>Request format:</td>
<td>Optional</td> <td>
<td>Send</td> <select id="requestFormat">
<td style="width:160px">Value</td> <option value="get" selected="selected">GET</option>
<option value="post">POST</option>
</select>
</td>
</tr> </tr>
</thead>
<tbody> <tr>
</tbody> <td>Response format:</td>
</table> <td>
</div> <select id="responseFormat">
<a href="#" onclick="return pwgInvokeMethod()">Invoke</a> <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>
<p>
<a href="#" onclick="return pwgInvokeMethod(false)">Invoke</a>
<a href="#" onclick="return pwgInvokeMethod(true)">Invoke (new Window)</a>
</p>
</td>
<div style="display:none"> <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 style="display:none;">
<!-- hiddenForm for POST --> <!-- hiddenForm for POST -->
<form method="post" action="" target="invokeFrame" id="invokeForm"> <form method="post" action="" target="invokeFrame" id="invokeForm">
<input type="submit" value="submit"/> <input type="submit" value="submit"/>
</form> </form>
</div> </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> <!-- methodDetailWrapper -->
</div> <!-- methodWrapper --> </div> <!-- methodWrapper -->

21
ws.php
View file

@ -3,7 +3,6 @@
// | PhpWebGallery - a PHP based picture gallery | // | PhpWebGallery - a PHP based picture gallery |
// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | // | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
// +-----------------------------------------------------------------------+ // +-----------------------------------------------------------------------+
// | branch : BSF (Best So Far)
// | file : $Id$ // | file : $Id$
// | last update : $Date$ // | last update : $Date$
// | last modifier : $Author$ // | last modifier : $Author$
@ -40,7 +39,7 @@ if ( !$conf['allow_web_services'] )
function ws_addDefaultMethods( $arr ) function ws_addDefaultMethods( $arr )
{ {
include_once(PHPWG_ROOT_PATH.'include/ws_functions.inc.php'); include_once(PHPWG_ROOT_PATH.'include/ws_functions.inc.php');
global $conf; global $conf, $user;
$service = &$arr[0]; $service = &$arr[0];
$service->addMethod('pwg.getVersion', 'ws_getVersion', null, $service->addMethod('pwg.getVersion', 'ws_getVersion', null,
'retrieves the PWG version'); 'retrieves the PWG version');
@ -77,8 +76,24 @@ function ws_addDefaultMethods( $arr )
), ),
'retrieves a list of categories' ); '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', $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' ); 'retrieves information about the given photo' );
$service->addMethod('pwg.images.search', 'ws_images_search', $service->addMethod('pwg.images.search', 'ws_images_search',