2011-12-13 12:40:42 +01:00
< ? php
class API extends Handler {
2016-08-27 16:29:25 +02:00
const API_LEVEL = 14 ;
2011-12-13 12:40:42 +01:00
const STATUS_OK = 0 ;
const STATUS_ERR = 1 ;
private $seq ;
function before ( $method ) {
if ( parent :: before ( $method )) {
2013-01-12 09:52:35 +01:00
header ( " Content-Type: text/json " );
2011-12-13 12:40:42 +01:00
if ( ! $_SESSION [ " uid " ] && $method != " login " && $method != " isloggedin " ) {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'NOT_LOGGED_IN' ));
2011-12-13 12:40:42 +01:00
return false ;
}
2013-04-17 16:34:18 +02:00
if ( $_SESSION [ " uid " ] && $method != " logout " && ! get_pref ( 'ENABLE_API_ACCESS' )) {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'API_DISABLED' ));
2011-12-13 12:40:42 +01:00
return false ;
}
$this -> seq = ( int ) $_REQUEST [ 'seq' ];
return true ;
}
return false ;
}
function wrap ( $status , $reply ) {
print json_encode ( array ( " seq " => $this -> seq ,
" status " => $status ,
" content " => $reply ));
}
function getVersion () {
$rv = array ( " version " => VERSION );
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , $rv );
2011-12-13 12:40:42 +01:00
}
function getApiLevel () {
2011-12-13 13:51:49 +01:00
$rv = array ( " level " => self :: API_LEVEL );
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , $rv );
2011-12-13 12:40:42 +01:00
}
function login () {
2013-03-28 05:46:20 +01:00
@ session_destroy ();
2013-03-28 05:06:21 +01:00
@ session_start ();
2013-04-17 18:12:14 +02:00
$login = $this -> dbh -> escape_string ( $_REQUEST [ " user " ]);
2011-12-13 12:40:42 +01:00
$password = $_REQUEST [ " password " ];
$password_base64 = base64_decode ( $_REQUEST [ " password " ]);
if ( SINGLE_USER_MODE ) $login = " admin " ;
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT id FROM ttrss_users WHERE login = ' $login ' " );
2011-12-13 12:40:42 +01:00
2013-04-17 18:12:14 +02:00
if ( $this -> dbh -> num_rows ( $result ) != 0 ) {
$uid = $this -> dbh -> fetch_result ( $result , 0 , " id " );
2011-12-13 12:40:42 +01:00
} else {
$uid = 0 ;
}
if ( ! $uid ) {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => " LOGIN_ERROR " ));
2011-12-13 12:40:42 +01:00
return ;
}
2013-04-17 16:34:18 +02:00
if ( get_pref ( " ENABLE_API_ACCESS " , $uid )) {
if ( authenticate_user ( $login , $password )) { // try login with normal password
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " session_id " => session_id (),
2012-09-29 09:59:50 +02:00
" api_level " => self :: API_LEVEL ));
2013-04-17 16:34:18 +02:00
} else if ( authenticate_user ( $login , $password_base64 )) { // else try with base64_decoded password
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " session_id " => session_id (),
2012-09-29 09:59:50 +02:00
" api_level " => self :: API_LEVEL ));
2011-12-13 12:40:42 +01:00
} else { // else we are not logged in
2014-01-25 01:19:10 +01:00
user_error ( " Failed login attempt for $login from { $_SERVER [ 'REMOTE_ADDR' ] } " , E_USER_WARNING );
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => " LOGIN_ERROR " ));
2011-12-13 12:40:42 +01:00
}
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => " API_DISABLED " ));
2011-12-13 12:40:42 +01:00
}
}
function logout () {
logout_user ();
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => " OK " ));
2011-12-13 12:40:42 +01:00
}
function isLoggedIn () {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => $_SESSION [ " uid " ] != '' ));
2011-12-13 12:40:42 +01:00
}
function getUnread () {
2013-04-17 18:12:14 +02:00
$feed_id = $this -> dbh -> escape_string ( $_REQUEST [ " feed_id " ]);
$is_cat = $this -> dbh -> escape_string ( $_REQUEST [ " is_cat " ]);
2011-12-13 12:40:42 +01:00
if ( $feed_id ) {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " unread " => getFeedUnread ( $feed_id , $is_cat )));
2011-12-13 12:40:42 +01:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " unread " => getGlobalUnread ()));
2011-12-13 12:40:42 +01:00
}
}
/* Method added for ttrss-reader for Android */
function getCounters () {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , getAllCounters ());
2011-12-13 12:40:42 +01:00
}
function getFeeds () {
2013-04-17 18:12:14 +02:00
$cat_id = $this -> dbh -> escape_string ( $_REQUEST [ " cat_id " ]);
2013-03-17 18:04:16 +01:00
$unread_only = sql_bool_to_bool ( $_REQUEST [ " unread_only " ]);
2013-04-17 18:12:14 +02:00
$limit = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " limit " ]);
$offset = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " offset " ]);
2013-03-17 18:04:16 +01:00
$include_nested = sql_bool_to_bool ( $_REQUEST [ " include_nested " ]);
2011-12-13 12:40:42 +01:00
2013-04-17 16:34:18 +02:00
$feeds = $this -> api_get_feeds ( $cat_id , $unread_only , $limit , $offset , $include_nested );
2011-12-13 12:40:42 +01:00
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , $feeds );
2011-12-13 12:40:42 +01:00
}
function getCategories () {
2013-03-17 18:04:16 +01:00
$unread_only = sql_bool_to_bool ( $_REQUEST [ " unread_only " ]);
$enable_nested = sql_bool_to_bool ( $_REQUEST [ " enable_nested " ]);
2013-03-28 12:31:39 +01:00
$include_empty = sql_bool_to_bool ( $_REQUEST [ 'include_empty' ]);
2011-12-13 12:40:42 +01:00
// TODO do not return empty categories, return Uncategorized and standard virtual cats
2012-09-18 07:58:01 +02:00
if ( $enable_nested )
$nested_qpart = " parent_cat IS NULL " ;
else
$nested_qpart = " true " ;
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT
2013-02-10 08:40:03 +01:00
id , title , order_id , ( SELECT COUNT ( id ) FROM
ttrss_feeds WHERE
2013-03-24 11:46:45 +01:00
ttrss_feed_categories . id IS NOT NULL AND cat_id = ttrss_feed_categories . id ) AS num_feeds ,
( SELECT COUNT ( id ) FROM
ttrss_feed_categories AS c2 WHERE
c2 . parent_cat = ttrss_feed_categories . id ) AS num_cats
2013-02-10 08:40:03 +01:00
FROM ttrss_feed_categories
2012-09-18 07:58:01 +02:00
WHERE $nested_qpart AND owner_uid = " .
2011-12-13 12:40:42 +01:00
$_SESSION [ " uid " ]);
$cats = array ();
2013-04-17 18:12:14 +02:00
while ( $line = $this -> dbh -> fetch_assoc ( $result )) {
2013-03-28 12:28:37 +01:00
if ( $include_empty || $line [ " num_feeds " ] > 0 || $line [ " num_cats " ] > 0 ) {
2013-04-17 16:34:18 +02:00
$unread = getFeedUnread ( $line [ " id " ], true );
2013-02-10 08:40:03 +01:00
if ( $enable_nested )
2013-04-17 16:34:18 +02:00
$unread += getCategoryChildrenUnread ( $line [ " id " ]);
2013-02-10 08:40:03 +01:00
if ( $unread || ! $unread_only ) {
array_push ( $cats , array ( " id " => $line [ " id " ],
" title " => $line [ " title " ],
" unread " => $unread ,
" order_id " => ( int ) $line [ " order_id " ],
));
}
2011-12-13 12:40:42 +01:00
}
}
foreach ( array ( - 2 , - 1 , 0 ) as $cat_id ) {
2013-04-01 12:04:56 +02:00
if ( $include_empty || ! $this -> isCategoryEmpty ( $cat_id )) {
2013-04-17 16:34:18 +02:00
$unread = getFeedUnread ( $cat_id , true );
2011-12-13 12:40:42 +01:00
2013-04-01 12:04:56 +02:00
if ( $unread || ! $unread_only ) {
array_push ( $cats , array ( " id " => $cat_id ,
2013-04-17 16:34:18 +02:00
" title " => getCategoryTitle ( $cat_id ),
2013-04-01 12:04:56 +02:00
" unread " => $unread ));
}
2011-12-13 12:40:42 +01:00
}
}
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , $cats );
2011-12-13 12:40:42 +01:00
}
function getHeadlines () {
2013-04-17 18:12:14 +02:00
$feed_id = $this -> dbh -> escape_string ( $_REQUEST [ " feed_id " ]);
2011-12-15 10:13:46 +01:00
if ( $feed_id != " " ) {
2011-12-13 12:40:42 +01:00
2015-07-12 12:18:03 +02:00
if ( is_numeric ( $feed_id )) $feed_id = ( int ) $feed_id ;
2013-04-17 18:12:14 +02:00
$limit = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " limit " ]);
2012-02-06 11:32:30 +01:00
2013-04-18 10:36:27 +02:00
if ( ! $limit || $limit >= 200 ) $limit = 200 ;
2012-02-06 11:32:30 +01:00
2013-04-17 18:12:14 +02:00
$offset = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " skip " ]);
$filter = $this -> dbh -> escape_string ( $_REQUEST [ " filter " ]);
2013-03-17 18:04:16 +01:00
$is_cat = sql_bool_to_bool ( $_REQUEST [ " is_cat " ]);
$show_excerpt = sql_bool_to_bool ( $_REQUEST [ " show_excerpt " ]);
$show_content = sql_bool_to_bool ( $_REQUEST [ " show_content " ]);
2011-12-13 12:40:42 +01:00
/* all_articles, unread, adaptive, marked, updated */
2013-04-17 18:12:14 +02:00
$view_mode = $this -> dbh -> escape_string ( $_REQUEST [ " view_mode " ]);
2013-03-17 18:04:16 +01:00
$include_attachments = sql_bool_to_bool ( $_REQUEST [ " include_attachments " ]);
2013-04-17 18:12:14 +02:00
$since_id = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " since_id " ]);
2013-03-17 18:04:16 +01:00
$include_nested = sql_bool_to_bool ( $_REQUEST [ " include_nested " ]);
2013-05-15 16:07:35 +02:00
$sanitize_content = ! isset ( $_REQUEST [ " sanitize " ]) ||
sql_bool_to_bool ( $_REQUEST [ " sanitize " ]);
2014-10-16 07:53:54 +02:00
$force_update = sql_bool_to_bool ( $_REQUEST [ " force_update " ]);
2014-11-25 11:45:21 +01:00
$has_sandbox = sql_bool_to_bool ( $_REQUEST [ " has_sandbox " ]);
2014-11-29 18:16:09 +01:00
$excerpt_length = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " excerpt_length " ]);
2015-07-12 16:55:35 +02:00
$check_first_id = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " check_first_id " ]);
2015-07-12 11:26:09 +02:00
$include_header = sql_bool_to_bool ( $_REQUEST [ " include_header " ]);
2014-11-25 11:45:21 +01:00
$_SESSION [ 'hasSandbox' ] = $has_sandbox ;
2013-04-02 07:34:32 +02:00
2015-11-21 20:20:00 +01:00
$skip_first_id_check = false ;
2013-04-02 03:21:36 +02:00
$override_order = false ;
switch ( $_REQUEST [ " order_by " ]) {
2013-11-09 13:42:41 +01:00
case " title " :
$override_order = " ttrss_entries.title " ;
break ;
2013-04-02 03:21:36 +02:00
case " date_reverse " :
2013-07-06 10:03:01 +02:00
$override_order = " score DESC, date_entered, updated " ;
2015-11-21 20:20:00 +01:00
$skip_first_id_check = true ;
2013-04-02 03:21:36 +02:00
break ;
case " feed_dates " :
$override_order = " updated DESC " ;
break ;
}
2013-04-02 07:34:32 +02:00
2012-01-19 11:07:59 +01:00
/* do not rely on params below */
2013-04-17 18:12:14 +02:00
$search = $this -> dbh -> escape_string ( $_REQUEST [ " search " ]);
2012-01-19 11:07:59 +01:00
2015-07-12 11:26:09 +02:00
list ( $headlines , $headlines_header ) = $this -> api_get_headlines ( $feed_id , $limit , $offset ,
2013-04-02 03:21:36 +02:00
$filter , $is_cat , $show_excerpt , $show_content , $view_mode , $override_order ,
2015-07-07 14:59:32 +02:00
$include_attachments , $since_id , $search ,
2015-11-21 20:20:00 +01:00
$include_nested , $sanitize_content , $force_update , $excerpt_length , $check_first_id , $skip_first_id_check );
2011-12-13 12:40:42 +01:00
2015-07-12 11:26:09 +02:00
if ( $include_header ) {
$this -> wrap ( self :: STATUS_OK , array ( $headlines_header , $headlines ));
} else {
$this -> wrap ( self :: STATUS_OK , $headlines );
}
2011-12-13 12:40:42 +01:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'INCORRECT_USAGE' ));
2011-12-13 12:40:42 +01:00
}
}
function updateArticle () {
2013-04-17 18:12:14 +02:00
$article_ids = array_filter ( explode ( " , " , $this -> dbh -> escape_string ( $_REQUEST [ " article_ids " ])), is_numeric );
$mode = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " mode " ]);
$data = $this -> dbh -> escape_string ( $_REQUEST [ " data " ]);
$field_raw = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " field " ]);
2011-12-13 12:40:42 +01:00
$field = " " ;
$set_to = " " ;
switch ( $field_raw ) {
case 0 :
$field = " marked " ;
2013-03-17 12:32:44 +01:00
$additional_fields = " ,last_marked = NOW() " ;
2011-12-13 12:40:42 +01:00
break ;
case 1 :
$field = " published " ;
2013-03-17 12:32:44 +01:00
$additional_fields = " ,last_published = NOW() " ;
2011-12-13 12:40:42 +01:00
break ;
case 2 :
$field = " unread " ;
2013-03-17 12:32:44 +01:00
$additional_fields = " ,last_read = NOW() " ;
2011-12-13 12:40:42 +01:00
break ;
case 3 :
$field = " note " ;
};
switch ( $mode ) {
case 1 :
$set_to = " true " ;
break ;
case 0 :
$set_to = " false " ;
break ;
case 2 :
$set_to = " NOT $field " ;
break ;
}
if ( $field == " note " ) $set_to = " ' $data ' " ;
if ( $field && $set_to && count ( $article_ids ) > 0 ) {
$article_ids = join ( " , " , $article_ids );
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " UPDATE ttrss_user_entries SET $field = $set_to $additional_fields WHERE ref_id IN ( $article_ids ) AND owner_uid = " . $_SESSION [ " uid " ]);
2011-12-13 12:40:42 +01:00
2013-04-17 18:12:14 +02:00
$num_updated = $this -> dbh -> affected_rows ( $result );
2011-12-13 12:40:42 +01:00
if ( $num_updated > 0 && $field == " unread " ) {
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT DISTINCT feed_id FROM ttrss_user_entries
2011-12-13 12:40:42 +01:00
WHERE ref_id IN ( $article_ids ) " );
2013-04-17 18:12:14 +02:00
while ( $line = $this -> dbh -> fetch_assoc ( $result )) {
2013-04-17 16:34:18 +02:00
ccache_update ( $line [ " feed_id " ], $_SESSION [ " uid " ]);
2011-12-13 12:40:42 +01:00
}
}
2013-03-17 12:32:44 +01:00
if ( $num_updated > 0 && $field == " published " ) {
if ( PUBSUBHUBBUB_HUB ) {
$rss_link = get_self_url_prefix () .
" /public.php?op=rss&id=-2&key= " .
2013-04-17 16:34:18 +02:00
get_feed_access_key ( - 2 , false );
2013-03-17 12:32:44 +01:00
2017-01-23 06:20:46 +01:00
$p = new pubsubhubbub\publisher\Publisher ( PUBSUBHUBBUB_HUB );
2017-04-26 14:29:22 +02:00
$p -> publish_update ( $rss_link );
2013-03-17 12:32:44 +01:00
}
}
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => " OK " ,
2011-12-13 12:40:42 +01:00
" updated " => $num_updated ));
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'INCORRECT_USAGE' ));
2011-12-13 12:40:42 +01:00
}
}
function getArticle () {
2013-04-17 18:12:14 +02:00
$article_id = join ( " , " , array_filter ( explode ( " , " , $this -> dbh -> escape_string ( $_REQUEST [ " article_id " ])), is_numeric ));
2015-11-23 20:25:04 +01:00
$sanitize_content = ! isset ( $_REQUEST [ " sanitize " ]) ||
sql_bool_to_bool ( $_REQUEST [ " sanitize " ]);
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
if ( $article_id ) {
2011-12-13 12:40:42 +01:00
2016-07-20 14:38:42 +02:00
$query = " SELECT id,guid,title,link,content,feed_id,comments,int_id,
2013-12-03 22:30:54 +01:00
marked , unread , published , score , note , lang ,
2013-05-15 20:29:31 +02:00
" .SUBSTRING_FOR_DATE. " ( updated , 1 , 16 ) as updated ,
2015-11-23 20:25:04 +01:00
author ,( SELECT title FROM ttrss_feeds WHERE id = feed_id ) AS feed_title ,
( SELECT site_url FROM ttrss_feeds WHERE id = feed_id ) AS site_url ,
( SELECT hide_images FROM ttrss_feeds WHERE id = feed_id ) AS hide_images
2013-05-15 20:29:31 +02:00
FROM ttrss_entries , ttrss_user_entries
WHERE id IN ( $article_id ) AND ref_id = id AND owner_uid = " .
$_SESSION [ " uid " ] ;
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
$result = $this -> dbh -> query ( $query );
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
$articles = array ();
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
if ( $this -> dbh -> num_rows ( $result ) != 0 ) {
2013-04-02 21:02:52 +02:00
2013-05-15 20:29:31 +02:00
while ( $line = $this -> dbh -> fetch_assoc ( $result )) {
2013-04-02 21:02:52 +02:00
2013-05-15 20:29:31 +02:00
$attachments = get_article_enclosures ( $line [ 'id' ]);
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
$article = array (
" id " => $line [ " id " ],
2016-07-20 14:38:42 +02:00
" guid " => $line [ " guid " ],
2013-05-15 20:29:31 +02:00
" title " => $line [ " title " ],
" link " => $line [ " link " ],
" labels " => get_article_labels ( $line [ 'id' ]),
" unread " => sql_bool_to_bool ( $line [ " unread " ]),
" marked " => sql_bool_to_bool ( $line [ " marked " ]),
" published " => sql_bool_to_bool ( $line [ " published " ]),
" comments " => $line [ " comments " ],
" author " => $line [ " author " ],
" updated " => ( int ) strtotime ( $line [ " updated " ]),
" feed_id " => $line [ " feed_id " ],
" attachments " => $attachments ,
" score " => ( int ) $line [ " score " ],
2013-11-23 17:22:02 +01:00
" feed_title " => $line [ " feed_title " ],
2013-12-03 22:30:54 +01:00
" note " => $line [ " note " ],
" lang " => $line [ " lang " ]
2013-05-15 20:29:31 +02:00
);
2015-11-23 20:25:04 +01:00
if ( $sanitize_content ) {
$article [ " content " ] = sanitize (
$line [ " content " ],
sql_bool_to_bool ( $line [ 'hide_images' ]),
false , $line [ " site_url " ], false , $line [ " id " ]);
} else {
$article [ " content " ] = $line [ " content " ];
}
2013-05-15 20:29:31 +02:00
foreach ( PluginHost :: getInstance () -> get_hooks ( PluginHost :: HOOK_RENDER_ARTICLE_API ) as $p ) {
$article = $p -> hook_render_article_api ( array ( " article " => $article ));
}
array_push ( $articles , $article );
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
}
}
2011-12-13 12:40:42 +01:00
2013-05-15 20:29:31 +02:00
$this -> wrap ( self :: STATUS_OK , $articles );
} else {
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'INCORRECT_USAGE' ));
}
2011-12-13 12:40:42 +01:00
}
function getConfig () {
$config = array (
" icons_dir " => ICONS_DIR ,
" icons_url " => ICONS_URL );
$config [ " daemon_is_running " ] = file_is_locked ( " update_daemon.lock " );
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT COUNT(*) AS cf FROM
2011-12-13 12:40:42 +01:00
ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"] );
2013-04-17 18:12:14 +02:00
$num_feeds = $this -> dbh -> fetch_result ( $result , 0 , " cf " );
2011-12-13 12:40:42 +01:00
$config [ " num_feeds " ] = ( int ) $num_feeds ;
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , $config );
2011-12-13 12:40:42 +01:00
}
function updateFeed () {
2013-03-25 13:20:45 +01:00
require_once " include/rssfuncs.php " ;
2013-04-17 18:12:14 +02:00
$feed_id = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " feed_id " ]);
2011-12-13 12:40:42 +01:00
2016-01-23 10:13:03 +01:00
if ( ! ini_get ( " open_basedir " )) {
2017-04-26 14:29:22 +02:00
update_rss_feed ( $feed_id );
2016-01-23 10:13:03 +01:00
}
2011-12-13 12:40:42 +01:00
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => " OK " ));
2011-12-13 12:40:42 +01:00
}
function catchupFeed () {
2013-04-17 18:12:14 +02:00
$feed_id = $this -> dbh -> escape_string ( $_REQUEST [ " feed_id " ]);
$is_cat = $this -> dbh -> escape_string ( $_REQUEST [ " is_cat " ]);
2011-12-13 12:40:42 +01:00
2013-04-17 16:34:18 +02:00
catchup_feed ( $feed_id , $is_cat );
2011-12-13 12:40:42 +01:00
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => " OK " ));
2011-12-13 12:40:42 +01:00
}
function getPref () {
2013-04-17 18:12:14 +02:00
$pref_name = $this -> dbh -> escape_string ( $_REQUEST [ " pref_name " ]);
2011-12-13 12:40:42 +01:00
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " value " => get_pref ( $pref_name )));
2011-12-13 12:40:42 +01:00
}
2011-12-17 08:06:55 +01:00
function getLabels () {
2013-04-17 18:12:14 +02:00
//$article_ids = array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_ids"])), is_numeric);
2011-12-17 08:06:55 +01:00
$article_id = ( int ) $_REQUEST [ 'article_id' ];
$rv = array ();
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT id, caption, fg_color, bg_color
2011-12-17 08:06:55 +01:00
FROM ttrss_labels2
WHERE owner_uid = '".$_SESSION[' uid ']."' ORDER BY caption " );
if ( $article_id )
2013-04-17 16:34:18 +02:00
$article_labels = get_article_labels ( $article_id );
2011-12-17 08:06:55 +01:00
else
$article_labels = array ();
2013-04-17 18:12:14 +02:00
while ( $line = $this -> dbh -> fetch_assoc ( $result )) {
2011-12-17 08:06:55 +01:00
$checked = false ;
foreach ( $article_labels as $al ) {
2013-11-27 18:54:27 +01:00
if ( feed_to_label_id ( $al [ 0 ]) == $line [ 'id' ]) {
2011-12-17 08:06:55 +01:00
$checked = true ;
break ;
}
}
array_push ( $rv , array (
2013-07-28 21:37:19 +02:00
" id " => ( int ) label_to_feed_id ( $line [ 'id' ]),
2011-12-17 08:06:55 +01:00
" caption " => $line [ 'caption' ],
" fg_color " => $line [ 'fg_color' ],
" bg_color " => $line [ 'bg_color' ],
" checked " => $checked ));
}
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , $rv );
2011-12-17 08:06:55 +01:00
}
2011-12-17 08:22:50 +01:00
function setArticleLabel () {
2013-04-17 18:12:14 +02:00
$article_ids = array_filter ( explode ( " , " , $this -> dbh -> escape_string ( $_REQUEST [ " article_ids " ])), is_numeric );
$label_id = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ 'label_id' ]);
$assign = ( bool ) $this -> dbh -> escape_string ( $_REQUEST [ 'assign' ]) == " true " ;
2011-12-17 08:22:50 +01:00
2013-04-17 18:12:14 +02:00
$label = $this -> dbh -> escape_string ( label_find_caption (
2013-10-12 07:55:35 +02:00
feed_to_label_id ( $label_id ), $_SESSION [ " uid " ]));
2011-12-17 08:22:50 +01:00
$num_updated = 0 ;
if ( $label ) {
foreach ( $article_ids as $id ) {
if ( $assign )
2013-04-17 16:34:18 +02:00
label_add_article ( $id , $label , $_SESSION [ " uid " ]);
2011-12-17 08:22:50 +01:00
else
2013-04-17 16:34:18 +02:00
label_remove_article ( $id , $label , $_SESSION [ " uid " ]);
2011-12-17 08:22:50 +01:00
++ $num_updated ;
}
}
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => " OK " ,
2011-12-17 08:22:50 +01:00
" updated " => $num_updated ));
}
2013-04-12 06:18:43 +02:00
function index ( $method ) {
2013-04-18 10:27:34 +02:00
$plugin = PluginHost :: getInstance () -> get_api_method ( strtolower ( $method ));
2013-04-12 06:18:43 +02:00
if ( $plugin && method_exists ( $plugin , $method )) {
$reply = $plugin -> $method ();
2013-05-07 09:35:10 +02:00
$this -> wrap ( $reply [ 0 ], $reply [ 1 ]);
2013-04-12 06:18:43 +02:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'UNKNOWN_METHOD' , " method " => $method ));
2013-04-12 06:18:43 +02:00
}
2011-12-13 12:40:42 +01:00
}
2012-09-09 14:05:59 +02:00
function shareToPublished () {
2013-04-17 18:12:14 +02:00
$title = $this -> dbh -> escape_string ( strip_tags ( $_REQUEST [ " title " ]));
$url = $this -> dbh -> escape_string ( strip_tags ( $_REQUEST [ " url " ]));
$content = $this -> dbh -> escape_string ( strip_tags ( $_REQUEST [ " content " ]));
2012-09-09 14:05:59 +02:00
2013-04-17 16:34:18 +02:00
if ( Article :: create_published_article ( $title , $url , $content , " " , $_SESSION [ " uid " ])) {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => 'OK' ));
2012-09-09 14:05:59 +02:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'Publishing failed' ));
2012-09-09 14:05:59 +02:00
}
}
2013-01-22 19:15:56 +01:00
2013-04-17 16:34:18 +02:00
static function api_get_feeds ( $cat_id , $unread_only , $limit , $offset , $include_nested = false ) {
2013-01-22 19:15:56 +01:00
$feeds = array ();
/* Labels */
if ( $cat_id == - 4 || $cat_id == - 2 ) {
2013-04-17 16:34:18 +02:00
$counters = getLabelCounters ( true );
2013-01-22 19:15:56 +01:00
foreach ( array_values ( $counters ) as $cv ) {
$unread = $cv [ " counter " ];
if ( $unread || ! $unread_only ) {
$row = array (
2014-01-24 12:33:16 +01:00
" id " => ( int ) $cv [ " id " ],
2013-01-22 19:15:56 +01:00
" title " => $cv [ " description " ],
" unread " => $cv [ " counter " ],
" cat_id " => - 2 ,
);
array_push ( $feeds , $row );
}
}
}
/* Virtual feeds */
if ( $cat_id == - 4 || $cat_id == - 1 ) {
foreach ( array ( - 1 , - 2 , - 3 , - 4 , - 6 , 0 ) as $i ) {
2013-04-17 16:34:18 +02:00
$unread = getFeedUnread ( $i );
2013-01-22 19:15:56 +01:00
if ( $unread || ! $unread_only ) {
2013-04-17 16:34:18 +02:00
$title = getFeedTitle ( $i );
2013-01-22 19:15:56 +01:00
$row = array (
" id " => $i ,
" title " => $title ,
" unread " => $unread ,
" cat_id " => - 1 ,
);
array_push ( $feeds , $row );
}
}
}
/* Child cats */
if ( $include_nested && $cat_id ) {
2013-04-17 16:34:18 +02:00
$result = db_query ( " SELECT
2013-01-22 19:15:56 +01:00
id , title FROM ttrss_feed_categories
WHERE parent_cat = '$cat_id' AND owner_uid = " . $_SESSION["uid"] .
" ORDER BY id, title " );
while ( $line = db_fetch_assoc ( $result )) {
2013-04-17 16:34:18 +02:00
$unread = getFeedUnread ( $line [ " id " ], true ) +
getCategoryChildrenUnread ( $line [ " id " ]);
2013-01-22 19:15:56 +01:00
if ( $unread || ! $unread_only ) {
$row = array (
2014-01-24 12:33:16 +01:00
" id " => ( int ) $line [ " id " ],
2013-01-22 19:15:56 +01:00
" title " => $line [ " title " ],
" unread " => $unread ,
" is_cat " => true ,
);
array_push ( $feeds , $row );
}
}
}
/* Real feeds */
if ( $limit ) {
$limit_qpart = " LIMIT $limit OFFSET $offset " ;
} else {
$limit_qpart = " " ;
}
if ( $cat_id == - 4 || $cat_id == - 3 ) {
2013-04-17 16:34:18 +02:00
$result = db_query ( " SELECT
2013-01-22 19:15:56 +01:00
id , feed_url , cat_id , title , order_id , " .
SUBSTRING_FOR_DATE . " (last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"] .
" ORDER BY cat_id, title " . $limit_qpart );
} else {
if ( $cat_id )
$cat_qpart = " cat_id = ' $cat_id ' " ;
else
$cat_qpart = " cat_id IS NULL " ;
2013-04-17 16:34:18 +02:00
$result = db_query ( " SELECT
2013-01-22 19:15:56 +01:00
id , feed_url , cat_id , title , order_id , " .
SUBSTRING_FOR_DATE . " (last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE
$cat_qpart AND owner_uid = " . $_SESSION["uid"] .
" ORDER BY cat_id, title " . $limit_qpart );
}
while ( $line = db_fetch_assoc ( $result )) {
2013-04-17 16:34:18 +02:00
$unread = getFeedUnread ( $line [ " id " ]);
2013-01-22 19:15:56 +01:00
$has_icon = feed_has_icon ( $line [ 'id' ]);
if ( $unread || ! $unread_only ) {
$row = array (
" feed_url " => $line [ " feed_url " ],
" title " => $line [ " title " ],
" id " => ( int ) $line [ " id " ],
" unread " => ( int ) $unread ,
" has_icon " => $has_icon ,
" cat_id " => ( int ) $line [ " cat_id " ],
2013-03-15 06:40:31 +01:00
" last_updated " => ( int ) strtotime ( $line [ " last_updated " ]),
2013-01-22 19:15:56 +01:00
" order_id " => ( int ) $line [ " order_id " ],
);
array_push ( $feeds , $row );
}
}
return $feeds ;
}
2017-04-26 14:29:22 +02:00
/**
* @ SuppressWarnings ( PHPMD . UnusedFormalParameter )
*/
2013-04-17 16:34:18 +02:00
static function api_get_headlines ( $feed_id , $limit , $offset ,
2013-01-22 19:15:56 +01:00
$filter , $is_cat , $show_excerpt , $show_content , $view_mode , $order ,
$include_attachments , $since_id ,
2015-07-12 11:26:09 +02:00
$search = " " , $include_nested = false , $sanitize_content = true ,
2015-11-21 20:20:00 +01:00
$force_update = false , $excerpt_length = 100 , $check_first_id = false , $skip_first_id_check = false ) {
2014-10-16 07:53:54 +02:00
if ( $force_update && $feed_id > 0 && is_numeric ( $feed_id )) {
// Update the feed if required with some basic flood control
$result = db_query (
" SELECT cache_images, " . SUBSTRING_FOR_DATE . " (last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE id = '$feed_id' " );
if ( db_num_rows ( $result ) != 0 ) {
$last_updated = strtotime ( db_fetch_result ( $result , 0 , " last_updated " ));
$cache_images = sql_bool_to_bool ( db_fetch_result ( $result , 0 , " cache_images " ));
if ( ! $cache_images && time () - $last_updated > 120 ) {
include " rssfuncs.php " ;
2017-04-26 14:29:22 +02:00
update_rss_feed ( $feed_id , true );
2014-10-16 07:53:54 +02:00
} else {
db_query ( " UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
WHERE id = '$feed_id' " );
}
}
}
2013-01-22 19:15:56 +01:00
2015-07-12 00:29:36 +02:00
/* $qfh_ret = queryFeedHeadlines ( $feed_id , $limit ,
2015-07-07 14:59:32 +02:00
$view_mode , $is_cat , $search , false ,
2015-07-12 00:29:36 +02:00
$order , $offset , 0 , false , $since_id , $include_nested ); */
//function queryFeedHeadlines($feed, $limit,
// $view_mode, $cat_view, $search, $search_mode,
// $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0, $include_children = false,
// $ignore_vfeed_group = false, $override_strategy = false, $override_vfeed = false, $start_ts = false, $check_top_id = false) {
$params = array (
" feed " => $feed_id ,
" limit " => $limit ,
" view_mode " => $view_mode ,
" cat_view " => $is_cat ,
" search " => $search ,
" override_order " => $order ,
" offset " => $offset ,
" since_id " => $since_id ,
" include_children " => $include_nested ,
2015-11-21 20:20:00 +01:00
" check_first_id " => $check_first_id ,
" skip_first_id_check " => $skip_first_id_check
2015-07-12 00:29:36 +02:00
);
$qfh_ret = queryFeedHeadlines ( $params );
2015-07-12 11:01:34 +02:00
$result = $qfh_ret [ 0 ];
2013-01-22 19:15:56 +01:00
$feed_title = $qfh_ret [ 1 ];
2015-07-12 16:55:35 +02:00
$first_id = $qfh_ret [ 6 ];
2013-01-22 19:15:56 +01:00
$headlines = array ();
2015-07-12 11:37:19 +02:00
$headlines_header = array (
'id' => $feed_id ,
2015-07-12 16:55:35 +02:00
'first_id' => $first_id ,
2015-07-12 11:37:19 +02:00
'is_cat' => $is_cat );
2013-07-10 14:44:36 +02:00
2015-07-12 13:23:32 +02:00
if ( ! is_numeric ( $result )) {
2015-07-12 11:01:34 +02:00
while ( $line = db_fetch_assoc ( $result )) {
$line [ " content_preview " ] = truncate_string ( strip_tags ( $line [ " content " ]), $excerpt_length );
foreach ( PluginHost :: getInstance () -> get_hooks ( PluginHost :: HOOK_QUERY_HEADLINES ) as $p ) {
$line = $p -> hook_query_headlines ( $line , $excerpt_length , true );
}
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$is_updated = ( $line [ " last_read " ] == " " &&
( $line [ " unread " ] != " t " && $line [ " unread " ] != " 1 " ));
2014-10-27 20:07:20 +01:00
2015-07-12 11:01:34 +02:00
$tags = explode ( " , " , $line [ " tag_cache " ]);
2014-10-27 20:07:20 +01:00
2015-07-12 11:01:34 +02:00
$label_cache = $line [ " label_cache " ];
$labels = false ;
2014-10-27 20:07:20 +01:00
if ( $label_cache ) {
2015-07-12 11:01:34 +02:00
$label_cache = json_decode ( $label_cache , true );
if ( $label_cache ) {
if ( $label_cache [ " no-labels " ] == 1 )
$labels = array ();
else
$labels = $label_cache ;
}
2014-10-27 20:07:20 +01:00
}
2015-07-12 11:01:34 +02:00
if ( ! is_array ( $labels )) $labels = get_article_labels ( $line [ " id " ]);
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
//if (!$tags) $tags = get_article_tags($line["id"]);
//if (!$labels) $labels = get_article_labels($line["id"]);
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$headline_row = array (
2013-01-22 19:15:56 +01:00
" id " => ( int ) $line [ " id " ],
2016-07-20 14:38:42 +02:00
" guid " => $line [ " guid " ],
2013-01-22 19:15:56 +01:00
" unread " => sql_bool_to_bool ( $line [ " unread " ]),
" marked " => sql_bool_to_bool ( $line [ " marked " ]),
" published " => sql_bool_to_bool ( $line [ " published " ]),
2015-07-12 11:01:34 +02:00
" updated " => ( int ) strtotime ( $line [ " updated " ]),
2013-01-22 19:15:56 +01:00
" is_updated " => $is_updated ,
" title " => $line [ " title " ],
" link " => $line [ " link " ],
" feed_id " => $line [ " feed_id " ],
" tags " => $tags ,
);
2015-07-12 11:01:34 +02:00
if ( $include_attachments )
$headline_row [ 'attachments' ] = get_article_enclosures (
$line [ 'id' ]);
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
if ( $show_excerpt )
$headline_row [ " excerpt " ] = $line [ " content_preview " ];
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
if ( $show_content ) {
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
if ( $sanitize_content ) {
$headline_row [ " content " ] = sanitize (
$line [ " content " ],
sql_bool_to_bool ( $line [ 'hide_images' ]),
false , $line [ " site_url " ], false , $line [ " id " ]);
} else {
$headline_row [ " content " ] = $line [ " content " ];
}
2013-01-22 19:15:56 +01:00
}
2015-07-12 11:01:34 +02:00
// unify label output to ease parsing
if ( $labels [ " no-labels " ] == 1 ) $labels = array ();
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$headline_row [ " labels " ] = $labels ;
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$headline_row [ " feed_title " ] = $line [ " feed_title " ] ? $line [ " feed_title " ] :
$feed_title ;
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$headline_row [ " comments_count " ] = ( int ) $line [ " num_comments " ];
$headline_row [ " comments_link " ] = $line [ " comments " ];
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$headline_row [ " always_display_attachments " ] = sql_bool_to_bool ( $line [ " always_display_enclosures " ]);
2013-01-22 19:15:56 +01:00
2015-07-12 11:01:34 +02:00
$headline_row [ " author " ] = $line [ " author " ];
2013-07-10 14:44:36 +02:00
2015-07-12 11:01:34 +02:00
$headline_row [ " score " ] = ( int ) $line [ " score " ];
$headline_row [ " note " ] = $line [ " note " ];
$headline_row [ " lang " ] = $line [ " lang " ];
2013-03-30 15:24:32 +01:00
2015-07-12 11:01:34 +02:00
foreach ( PluginHost :: getInstance () -> get_hooks ( PluginHost :: HOOK_RENDER_ARTICLE_API ) as $p ) {
$headline_row = $p -> hook_render_article_api ( array ( " headline " => $headline_row ));
}
2013-03-21 15:19:23 +01:00
2015-07-12 11:01:34 +02:00
array_push ( $headlines , $headline_row );
}
2015-07-12 11:26:09 +02:00
} else if ( is_numeric ( $result ) && $result == - 1 ) {
2015-07-12 16:55:35 +02:00
$headlines_header [ 'first_id_changed' ] = true ;
2013-01-22 19:15:56 +01:00
}
2015-07-12 11:26:09 +02:00
return array ( $headlines , $headlines_header );
2013-01-22 19:15:56 +01:00
}
2013-03-24 11:28:43 +01:00
function unsubscribeFeed () {
2013-04-17 18:12:14 +02:00
$feed_id = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " feed_id " ]);
2013-03-24 11:28:43 +01:00
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT id FROM ttrss_feeds WHERE
2013-03-24 11:28:43 +01:00
id = '$feed_id' AND owner_uid = " . $_SESSION["uid"] );
2013-04-17 18:12:14 +02:00
if ( $this -> dbh -> num_rows ( $result ) != 0 ) {
2013-04-17 16:34:18 +02:00
Pref_Feeds :: remove_feed ( $feed_id , $_SESSION [ " uid " ]);
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => " OK " ));
2013-03-24 11:28:43 +01:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => " FEED_NOT_FOUND " ));
2013-03-24 11:28:43 +01:00
}
}
function subscribeToFeed () {
2013-04-17 18:12:14 +02:00
$feed_url = $this -> dbh -> escape_string ( $_REQUEST [ " feed_url " ]);
$category_id = ( int ) $this -> dbh -> escape_string ( $_REQUEST [ " category_id " ]);
$login = $this -> dbh -> escape_string ( $_REQUEST [ " login " ]);
$password = $this -> dbh -> escape_string ( $_REQUEST [ " password " ]);
2013-03-24 11:28:43 +01:00
if ( $feed_url ) {
2013-05-07 09:35:10 +02:00
$rc = subscribe_to_feed ( $feed_url , $category_id , $login , $password );
2013-03-24 11:28:43 +01:00
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " status " => $rc ));
2013-03-24 11:28:43 +01:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " => 'INCORRECT_USAGE' ));
2013-03-24 11:28:43 +01:00
}
}
2013-03-28 08:04:15 +01:00
function getFeedTree () {
2013-03-28 12:31:39 +01:00
$include_empty = sql_bool_to_bool ( $_REQUEST [ 'include_empty' ]);
2013-03-28 12:28:37 +01:00
2013-04-17 16:34:18 +02:00
$pf = new Pref_Feeds ( $_REQUEST );
2013-03-28 08:04:15 +01:00
$_REQUEST [ 'mode' ] = 2 ;
2013-03-28 12:28:37 +01:00
$_REQUEST [ 'force_show_empty' ] = $include_empty ;
2013-03-28 08:04:15 +01:00
if ( $pf ){
$data = $pf -> makefeedtree ();
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_OK , array ( " categories " => $data ));
2013-03-28 08:04:15 +01:00
} else {
2013-05-07 09:35:10 +02:00
$this -> wrap ( self :: STATUS_ERR , array ( " error " =>
2013-03-28 08:04:15 +01:00
'UNABLE_TO_INSTANTIATE_OBJECT' ));
}
}
2013-04-01 12:04:56 +02:00
2013-04-01 12:08:17 +02:00
// only works for labels or uncategorized for the time being
2013-04-01 12:04:56 +02:00
private function isCategoryEmpty ( $id ) {
if ( $id == - 2 ) {
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT COUNT(*) AS count FROM ttrss_labels2
2013-04-01 12:04:56 +02:00
WHERE owner_uid = " . $_SESSION["uid"] );
2013-04-17 18:12:14 +02:00
return $this -> dbh -> fetch_result ( $result , 0 , " count " ) == 0 ;
2013-04-01 12:04:56 +02:00
2013-04-01 12:08:17 +02:00
} else if ( $id == 0 ) {
2013-04-17 18:12:14 +02:00
$result = $this -> dbh -> query ( " SELECT COUNT(*) AS count FROM ttrss_feeds
2013-04-01 12:08:17 +02:00
WHERE cat_id IS NULL AND owner_uid = " . $_SESSION["uid"] );
2013-04-17 18:12:14 +02:00
return $this -> dbh -> fetch_result ( $result , 0 , " count " ) == 0 ;
2013-04-01 12:08:17 +02:00
2013-04-01 12:04:56 +02:00
}
return false ;
}
2011-12-13 12:40:42 +01:00
}
?>