Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
9330 lines (8208 sloc) 336 KB
<?php
// KrISS feed: a simple and smart (or stupid) feed reader
// Copyleft (ɔ) - Tontof - http://tontof.net
// use KrISS feed at your own risk
define('FEED_VERSION', 8.8);
define('DATA_DIR', 'data');
define('INC_DIR', 'inc');
define('CACHE_DIR', DATA_DIR.'/cache');
define('FAVICON_DIR', INC_DIR.'/favicon');
define('DATA_FILE', DATA_DIR.'/data.php');
define('STAR_FILE', DATA_DIR.'/star.php');
define('ITEM_FILE', DATA_DIR.'/item.php');
define('CONFIG_FILE', DATA_DIR.'/config.php');
define('OPML_FILE', DATA_DIR.'/feeds.opml');
define('OPML_FILE_SAVE', DATA_DIR.'/feeds.bak.opml');
define('BAN_FILE', DATA_DIR.'/ipbans.php');
define('PHPPREFIX', '<?php /* '); // Prefix to encapsulate data in php code.
define('PHPSUFFIX', ' */ ?>'); // Suffix to encapsulate data in php code.
define('MIN_TIME_UPDATE', 5); // Minimum accepted time for update
// Updates check frequency. 86400 seconds = 24 hours
define('UPDATECHECK_INTERVAL', 86400);
// fix some warning
date_default_timezone_set('Europe/Paris');
class Feed
{
public $dataFile = '';
public $cacheDir = '';
public $kfc;
private $_data = array();
public function __construct($dataFile, $cacheDir, $kfc)
{
$this->kfc = $kfc;
$this->dataFile = $dataFile;
$this->cacheDir = $cacheDir;
}
public function getData()
{
return $this->_data;
}
public function setData($data)
{
$this->_data = $data;
}
public function initData()
{
$this->_data['feeds'] = array(
MyTool::smallHash('http://tontof.net/?rss') => array(
'title' => 'Tontof',
'foldersHash' => array(),
'timeUpdate' => 'auto',
'lastUpdate' => 0,
'nbUnread' => 0,
'nbAll' => 0,
'htmlUrl' => 'http://tontof.net',
'xmlUrl' => 'http://tontof.net/?rss',
'description' => 'A simple and smart (or stupid) blog'));
$this->_data['folders'] = array();
$this->_data['items'] = array();
$this->_data['newItems'] = array();
}
public function loadData()
{
if (empty($this->_data)) {
if (file_exists($this->dataFile)) {
$this->_data = unserialize(
gzinflate(
base64_decode(
substr(
file_get_contents($this->dataFile),
strlen(PHPPREFIX),
-strlen(PHPSUFFIX)
)
)
)
);
return true;
} else {
$this->initData();
$this->writeData();
return false;
}
}
// data already loaded
return true;
}
public function writeData()
{
if ($this->kfc->isLogged()) {
$write = @file_put_contents(
$this->dataFile,
PHPPREFIX
. base64_encode(gzdeflate(serialize($this->_data)))
. PHPSUFFIX,
LOCK_EX
);
if (!$write) {
die("Can't write to " . $this->dataFile);
}
}
}
public function setFeeds($feeds) {
$this->_data['feeds'] = $feeds;
}
public function getFeeds()
{
return $this->_data['feeds'];
}
public function sortFeeds()
{
uasort(
$this->_data['feeds'],
'Feed::sortByTitle'
);
}
public function sortFolders()
{
uasort(
$this->_data['folders'],
'Feed::sortByOrder'
);
}
public function getFeedsView()
{
$feedsView = array('all' => array('title' => Intl::msg('All feeds'), 'nbUnread' => 0, 'nbAll' => 0, 'feeds' => array()), 'folders' => array());
foreach ($this->_data['feeds'] as $feedHash => $feed) {
if (isset($feed['error'])) {
$feed['error'] = $feed['error'];
}
if (isset($feed['nbUnread'])) {
$feedsView['all']['nbUnread'] += $feed['nbUnread'];
} else {
$feedsView['all']['nbUnread'] += $feed['nbAll'];
}
$feedsView['all']['nbAll'] += $feed['nbAll'];
if (empty($feed['foldersHash'])) {
$feedsView['all']['feeds'][$feedHash] = $feed;
if (!isset($feed['nbUnread'])) {
$feedsView['all']['feeds'][$feedHash]['nbUnread'] = $feed['nbAll'];
}
} else {
foreach ($feed['foldersHash'] as $folderHash) {
$folder = $this->getFolder($folderHash);
if ($folder !== false) {
if (!isset($feedsView['folders'][$folderHash]['title'])) {
$feedsView['folders'][$folderHash]['title'] = $folder['title'];
$feedsView['folders'][$folderHash]['isOpen'] = $folder['isOpen'];
$feedsView['folders'][$folderHash]['nbUnread'] = 0;
$feedsView['folders'][$folderHash]['nbAll'] = 0;
if (isset($folder['order'])) {
$feedsView['folders'][$folderHash]['order'] = $folder['order'];
} else {
$feedsView['folders'][$folderHash]['order'] = 0;
}
}
$feedsView['folders'][$folderHash]['feeds'][$feedHash] = $feed;
$feedsView['folders'][$folderHash]['nbUnread'] += $feed['nbUnread'];
$feedsView['folders'][$folderHash]['nbAll'] += $feed['nbAll'];
}
}
}
}
uasort($feedsView['folders'], 'Feed::sortByOrder');
return $feedsView;
}
public function getFeed($feedHash)
{
if (isset($this->_data['feeds'][$feedHash])) {
// FIX: problem of version 6 &amp;amp;
$this->_data['feeds'][$feedHash]['xmlUrl'] = preg_replace('/&(amp;)*/', '&', $this->_data['feeds'][$feedHash]['xmlUrl']);
$this->_data['feeds'][$feedHash]['htmlUrl'] = preg_replace('/&(amp;)*/', '&', $this->_data['feeds'][$feedHash]['htmlUrl']);
return $this->_data['feeds'][$feedHash];
}
return false;
}
public function getFaviconFeed($feedHash)
{
$htmlUrl = $this->_data['feeds'][$feedHash]['htmlUrl'];
$url = 'http://www.google.com/s2/favicons?domain='.$htmlUrl;
$file = FAVICON_DIR.'/favicon.'.$feedHash.'.ico';
if ($this->kfc->isLogged() && $this->kfc->addFavicon) {
MyTool::grabToLocal($url, $file);
}
if (file_exists($file)) {
return $file;
} else {
return $url;
}
}
public function getFeedHtmlUrl($feedHash)
{
if (isset($this->_data['feeds'][$feedHash]['htmlUrl'])) {
return $this->_data['feeds'][$feedHash]['htmlUrl'];
}
return false;
}
public function getFeedTitle($feedHash)
{
if (isset($this->_data['feeds'][$feedHash]['title'])) {
return $this->_data['feeds'][$feedHash]['title'];
}
return false;
}
public function loadFeed($feedHash)
{
if (!isset($this->_data['feeds'][$feedHash]['items'])) {
$this->_data['feeds'][$feedHash]['items'] = array();
if (file_exists($this->cacheDir.'/'.$feedHash.'.php')) {
$items = unserialize(
gzinflate(
base64_decode(
substr(
file_get_contents($this->cacheDir.'/'.$feedHash.'.php'),
strlen(PHPPREFIX),
-strlen(PHPSUFFIX)
)
)
)
);
$this->_data['feeds'][$feedHash]['items'] = $items;
}
}
}
public function editFeed(
$feedHash,
$title,
$description,
$foldersHash,
$timeUpdate,
$htmlUrl)
{
if (isset($this->_data['feeds'][$feedHash])) {
if (!empty($title)) {
$this->_data['feeds'][$feedHash]['title'] = $title;
}
if (!empty($description)) {
$this->_data['feeds'][$feedHash]['description'] = $description;
}
if (!empty($htmlUrl)) {
$this->_data['feeds'][$feedHash]['htmlUrl'] = $htmlUrl;
}
$this->_data['feeds'][$feedHash]['foldersHash'] = $foldersHash;
$this->_data['feeds'][$feedHash]['timeUpdate'] = 'auto';
if (!empty($timeUpdate)) {
if ($timeUpdate == 'max') {
$this->_data['feeds'][$feedHash]['timeUpdate'] = $timeUpdate;
} else {
$this->_data['feeds'][$feedHash]['timeUpdate'] = (int) $timeUpdate;
$maxUpdate = $this->kfc->maxUpdate;
if ($this->_data['feeds'][$feedHash]['timeUpdate'] < MIN_TIME_UPDATE
|| $this->_data['feeds'][$feedHash]['timeUpdate'] > $maxUpdate
) {
$this->_data['feeds'][$feedHash]['timeUpdate'] = 'auto';
}
}
}
}
}
public function removeFeed($feedHash)
{
if (isset($this->_data['feeds'][$feedHash])) {
unset($this->_data['feeds'][$feedHash]);
unlink($this->cacheDir. '/' .$feedHash.'.php' );
foreach (array_keys($this->_data['items']) as $itemHash) {
if (substr($itemHash, 0, 6) === $feedHash) {
unset($this->_data['items'][$itemHash]);
}
}
foreach (array_keys($this->_data['newItems']) as $itemHash) {
if (substr($itemHash, 0, 6) === $feedHash) {
unset($this->_data['newItems'][$itemHash]);
}
}
}
}
public function writeFeed($feedHash, $feed)
{
if ($this->kfc->isLogged() || (isset($_GET['cron']) && $_GET['cron'] === sha1($this->kfc->salt.$this->kfc->hash))) {
if (!is_dir($this->cacheDir)) {
if (!@mkdir($this->cacheDir, 0755)) {
die("Can not create cache dir: ".$this->cacheDir);
}
@chmod($this->cacheDir, 0755);
if (!is_file($this->cacheDir.'/.htaccess')) {
if (!@file_put_contents(
$this->cacheDir.'/.htaccess',
"Allow from none\nDeny from all\n"
)) {
die("Can not protect cache dir: ".$this->cacheDir);
}
}
}
$write = @file_put_contents(
$this->cacheDir.'/'.$feedHash.'.php',
PHPPREFIX
. base64_encode(gzdeflate(serialize($feed)))
. PHPSUFFIX,
LOCK_EX
);
if (!$write) {
die("Can't write to " . $this->cacheDir.'/'.$feedHash.'.php');
}
}
}
public function orderFeedsForUpdate($feedsHash)
{
$newFeedsHash = array();
foreach(array_keys($this->_data['items']) as $itemHash) {
$feedHash = substr($itemHash, 0, 6);
if (in_array($feedHash, $feedsHash) and !in_array($feedHash, $newFeedsHash)) {
$newFeedsHash[] = $feedHash;
}
}
if ($this->kfc->order !== 'newerFirst') {
$newFeedsHash = array_reverse($newFeedsHash);
}
foreach($feedsHash as $feedHash) {
if (!in_array($feedHash, $newFeedsHash)) {
$newFeedsHash[] = $feedHash;
}
}
return $newFeedsHash;
}
public function getFeedsHashFromFolderHash($folderHash)
{
$list = array();
$folders = $this->getFolders();
if (isset($folders[$folderHash])) {
foreach ($this->_data['feeds'] as $feedHash => $feed) {
if (in_array($folderHash, $feed['foldersHash'])) {
$list[] = $feedHash;
}
}
}
return $list;
}
public function getFolders()
{
return $this->_data['folders'];
}
public function getFolder($folderHash)
{
if (isset($this->_data['folders'][$folderHash])) {
return $this->_data['folders'][$folderHash];
}
return false;
}
public function addFolder($folderTitle, $newFolderHash = '')
{
if (empty($newFolderHash)) {
$newFolderHash = MyTool::smallHash($newFolderTitle);
}
$this->_data['folders'][$newFolderHash] = array(
'title' => $folderTitle,
'isOpen' => 1
);
}
public function renameFolder($oldFolderHash, $newFolderTitle)
{
$newFolderHash = '';
if (!empty($newFolderTitle)) {
$newFolderHash = MyTool::smallHash($newFolderTitle);
$this->addFolder($newFolderTitle, $newFolderHash);
$this->_data['folders'][$newFolderHash]['isOpen'] = $this->_data['folders'][$oldFolderHash]['isOpen'];
}
unset($this->_data['folders'][$oldFolderHash]);
foreach ($this->_data['feeds'] as $feedHash => $feed) {
$i = array_search($oldFolderHash, $feed['foldersHash']);
if ($i !== false) {
unset($this->_data['feeds'][$feedHash]['foldersHash'][$i]);
if (!empty($newFolderTitle)) {
$this->_data['feeds'][$feedHash]['foldersHash'][] = $newFolderHash;
}
}
}
}
public function orderFolder(
$folderHash,
$order)
{
if (isset($this->_data['folders'][$folderHash])) {
$this->_data['folders'][$folderHash]['order'] = $order;
}
}
public function toggleFolder($hash)
{
if ($this->_data['folders'][$hash]) {
$isOpen = $this->_data['folders'][$hash]['isOpen'];
if ($isOpen) {
$this->_data['folders'][$hash]['isOpen'] = 0;
} else {
$this->_data['folders'][$hash]['isOpen'] = 1;
}
}
return true;
}
public function getFolderTitle($folderHash)
{
if (isset($this->_data['folders'][$folderHash])) {
return $this->_data['folders'][$folderHash]['title'];
}
return false;
}
public function getItems($hash = 'all', $filter = 'all')
{
if (empty($hash) or $hash == 'all' and $filter == 'all') {
if (isset($this->_data['newItems'])) {
return $this->_data['items']+$this->_data['newItems'];
} else {
return $this->_data['items'];
}
}
if (empty($hash) or $hash == 'all' and $filter == 'old') {
return $this->_data['items'];
}
if (empty($hash) or $hash == 'all' and $filter == 'new') {
if (isset($this->_data['newItems'])) {
return $this->_data['newItems'];
} else {
return array();
}
}
$list = array();
$isRead = 1;
if ($filter === 'unread') {
$isRead = 0;
}
if (empty($hash) || $hash == 'all') {
// all items
foreach ($this->_data['items'] as $itemHash => $item) {
if ($item[1] === $isRead) {
$list[$itemHash] = $item;
}
}
if (isset($this->_data['newItems'])) {
foreach ($this->_data['newItems'] as $itemHash => $item) {
if ($item[1] === $isRead) {
$list[$itemHash] = $item;
}
}
}
} else {
if (strlen($hash) === 12) {
// an item
if (isset($this->_data['items'][$hash])) {
$list[$hash] = $this->_data['items'][$hash];
} else if (isset($this->_data['newItems']) && isset($this->_data['newItems'][$hash])) {
$list[$hash] = $this->_data['newItems'][$hash];
}
} else {
$feedsHash = array();
if (isset($this->_data['feeds'][$hash])) {
// a feed
$feedsHash[] = $hash;
} else if (isset($this->_data['folders'][$hash])) {
// a folder
foreach ($this->_data['feeds'] as $feedHash => $feed) {
if (in_array($hash, $feed['foldersHash'])) {
$feedsHash[] = $feedHash;
}
}
}
// get items from a list of feeds
if (!empty($feedsHash)) {
$flipFeedsHash = array_flip($feedsHash);
foreach ($this->_data['items'] as $itemHash => $item) {
if (isset($flipFeedsHash[substr($itemHash, 0, 6)])) {
if ($filter === 'all' or $item[1] === $isRead) {
$list[$itemHash] = $item;
}
}
}
if (isset($this->_data['newItems'])) {
foreach ($this->_data['newItems'] as $itemHash => $item) {
if (isset($flipFeedsHash[substr($itemHash, 0, 6)])) {
if ($filter === 'all' or $item[1] === $isRead) {
$list[$itemHash] = $item;
}
}
}
}
}
}
}
return $list;
}
public function setItems($items)
{
$this->_data['items'] = $items;
}
public function loadItem($itemHash, $keep)
{
$feedHash = substr($itemHash, 0, 6);
$item = array();
if (isset($this->_data['feeds'][$feedHash]['items'])) {
if (isset($this->_data['feeds'][$feedHash]['items'][$itemHash])) {
$item = $this->_data['feeds'][$feedHash]['items'][$itemHash];
}
} else {
$this->loadFeed($feedHash);
return $this->loadItem($itemHash, $keep);
}
if (!$keep) {
unset($this->_data['feeds'][$feedHash]['items']);
}
return $item;
}
public function getItem($itemHash, $keep = true)
{
$item = $this->loadItem($itemHash, $keep);
if (!empty($item)) {
$item['itemHash'] = $itemHash;
$time = $item['time'];
if (strftime('%Y%m%d', $time) == strftime('%Y%m%d', time())) {
// Today
$item['time'] = array('time' => $time, 'list' => utf8_encode(strftime('%H:%M', $time)), 'expanded' => utf8_encode(strftime('%A %d %B %Y - %H:%M', $time)));
} else {
if (strftime('%Y', $time) == strftime('%Y', time())) {
$item['time'] = array('time' => $time, 'list' => utf8_encode(strftime('%b %d', $time)), 'expanded' => utf8_encode(strftime('%A %d %B %Y - %H:%M', $time)));
} else {
$item['time'] = array('time' => $time, 'list' => utf8_encode(strftime('%b %d, %Y', $time)), 'expanded' => utf8_encode(strftime('%A %d %B %Y - %H:%M', $time)));
}
}
if (isset($this->_data['items'][$itemHash])) {
$item['read'] = $this->_data['items'][$itemHash][1];
} else if (isset($this->_data['newItems'][$itemHash])) {
$item['read'] = $this->_data['newItems'][$itemHash][1];
$currentNewItemIndex = array_search($itemHash, array_keys($this->_data['newItems']));
if (isset($_SESSION['lastNewItemsHash'])) {
$lastNewItemIndex = array_search($_SESSION['lastNewItemsHash'], array_keys($this->_data['newItems']));
if ($lastNewItemIndex < $currentNewItemIndex) {
$_SESSION['lastNewItemsHash'] = $itemHash;
}
} else {
$_SESSION['lastNewItemsHash'] = $itemHash;
}
} else {
// FIX: data may be corrupted
return false;
}
$item['author'] = htmlspecialchars(html_entity_decode(strip_tags($item['author']), ENT_QUOTES, 'utf-8'), ENT_NOQUOTES);
$item['title'] = htmlspecialchars(html_entity_decode(strip_tags($item['title']), ENT_QUOTES, 'utf-8'), ENT_NOQUOTES);
$item['link'] = htmlspecialchars($item['link']);
if (empty($item['title'])) {
$item['title'] = $item['link'];
}
$item['via'] = htmlspecialchars($item['via']);
$item['favicon'] = $this->getFaviconFeed(substr($itemHash, 0, 6));
$item['xmlUrl'] = htmlspecialchars($item['xmlUrl']);
if (isset($GLOBALS['starredItems'][$itemHash])) {
$item['starred'] = 1 ;
} else {
$item['starred'] = 0 ;
}
return $item;
}
return false;
}
public function updateItems()
{
if (isset($this->_data['needSort']) or (isset($this->_data['order']) and $this->_data['order'] != $this->kfc->order)) {
unset($this->_data['needSort']);
$this->_data['items'] = $this->_data['items']+$this->_data['newItems'];
$this->_data['newItems'] = array();
// sort items
if ($this->kfc->order === 'newerFirst') {
arsort($this->_data['items']);
} else {
asort($this->_data['items']);
}
$this->_data['order'] = $this->kfc->order;
return true;
}
return false;
}
public function initFeedCache($feed, $force)
{
if (!empty($feed)) {
if ($force) {
$feed['etag'] = '';
$feed['lastModified'] = '';
}
MyTool::$opts['http']['headers'] = array();
if (!empty($feed['lastModified'])) {
MyTool::$opts['http']['headers'][] = 'If-Modified-Since: ' . $feed['lastModified'];
}
if (!empty($feed['etag'])) {
MyTool::$opts['http']['headers'][] = 'If-None-Match: ' . $feed['etag'];
}
}
return $feed;
}
public function updateFeedCache($feed, $outputUrl)
{
// really new (2XX) and errors (4XX and 5XX) are considered new
if ($outputUrl['code'] != 304) {
if (preg_match('/^ETag: ([^\r\n]*)[\r\n]*$/im', $outputUrl['header'], $matches)) {
$feed['etag'] = $matches[1];
}
if (preg_match('/^Last-Modified: ([^\r\n]*)[\r\n]*$/im', $outputUrl['header'], $matches)) {
$feed['lastModified'] = $matches[1];
}
}
if (empty($feed['etag'])) {
unset($feed['etag']);
}
if (empty($feed['lastModified'])) {
unset($feed['lastModified']);
}
return $feed;
}
public function updateFeedFromDom($feed, $dom) {
if (empty($feed)) {
// addFeed
$feed = Rss::getFeed($dom);
if (!MyTool::isUrl($feed['htmlUrl'])) {
$feed['htmlUrl'] = ' ';
}
if (empty($feed['description'])) {
$feed['description'] = ' ';
}
$feed['foldersHash'] = array();
$feed['timeUpdate'] = 'auto';
} else if (empty($feed['description']) || empty($feed['htmlUrl'])) {
// if feed description/htmlUrl is empty try to update
// (after opml import, description/htmlUrl are often empty)
$rssFeed = Rss::getFeed($dom);
if (empty($feed['description'])) {
if (empty($rssFeed['description'])) {
$rssFeed['description'] = ' ';
}
$feed['description'] = $rssFeed['description'];
}
if (empty($feed['htmlUrl'])) {
if (empty($rssFeed['htmlUrl'])) {
$rssFeed['htmlUrl'] = ' ';
}
$feed['htmlUrl'] = $rssFeed['htmlUrl'];
}
}
return $feed;
}
private function showEnclosure($enclosure) {
$path = parse_url($enclosure, PHP_URL_PATH);
$ext = pathinfo($path, PATHINFO_EXTENSION);
$link = '<a href="'.$enclosure.'">'.$enclosure.'</a>';
switch(strtolower($ext)) {
case '':
if (strpos($enclosure, 'https://www.youtube.com') === 0) {
$link = '<iframe src="'.str_replace('/v/','/embed/', $enclosure).'" width="640" height="360" allowfullscreen></iframe>';
}
break;
case 'jpg':
case 'jpeg':
case 'png':
case 'gif':
$link = '<img src="'.$enclosure.'">';
break;
case 'mp3':
case 'oga':
case 'wav':
$link = '<audio controls><source src="'.$enclosure.'">'.$link.'</audio>';
break;
case 'mp4':
case 'ogg':
case 'webm':
$link = '<video controls><source src="'.$enclosure.'">'.$link.'</video>';
break;
}
return $link;
}
public function updateItemsFromDom($dom) {
$items = Rss::getItems($dom);
$newItems = array();
foreach($items as $item) {
if (!empty($item['link'])) {
$hashUrl = MyTool::smallHash($item['link']);
$newItems[$hashUrl] = array();
$newItems[$hashUrl]['title'] = empty($item['title'])?$item['link']:$item['title'];
$newItems[$hashUrl]['time'] = strtotime($item['time'])
? strtotime($item['time'])
: time();
if (MyTool::isUrl($item['via']) &&
parse_url($item['via'], PHP_URL_HOST)
!= parse_url($item['link'], PHP_URL_HOST)) {
$newItems[$hashUrl]['via'] = $item['via'];
} else {
$newItems[$hashUrl]['via'] = '';
}
$newItems[$hashUrl]['link'] = $item['link'];
$newItems[$hashUrl]['author'] = $item['author'];
mb_internal_encoding("UTF-8");
$newItems[$hashUrl]['description'] = mb_substr(
strip_tags($item['description']), 0, 500
);
if(!empty($item['enclosure'])) {
foreach($item['enclosure'] as $enclosure) {
$item['content'] .= '<br>'.$this->showEnclosure($enclosure);
}
}
$newItems[$hashUrl]['content'] = $item['content'];
}
}
return $newItems;
}
public function loadRss($xmlUrl, $feed = array(), $force = false)
{
$items = array();
$feed = $this->initFeedCache($feed, $force);
if( !ini_get('safe_mode') && isset(MyTool::$opts['http']['timeout'])){
set_time_limit(MyTool::$opts['http']['timeout']+1);
}
$outputUrl = MyTool::loadUrl($xmlUrl);
if (!empty($outputUrl['error'])) {
$feed['error'] = $outputUrl['error'];
} else if (empty($outputUrl['data'])) {
if ($outputUrl['code'] != 304) { // 304 Not modified
$feed['error'] = Intl::msg('Empty output data');;
}
} else {
$outputDom = Rss::loadDom($outputUrl['data']);
if (!empty($outputDom['error'])) {
$feed['error'] = $outputDom['error'];
} else {
unset($feed['error']);
$feed = $this->updateFeedFromDom($feed, $outputDom['dom']);
$feed = $this->updateFeedCache($feed, $outputUrl);
$items = $this->updateItemsFromDom($outputDom['dom']);
}
}
$feed['lastUpdate'] = time();
return array(
'feed' => $feed,
'items' => $items,
);
}
public function addChannel($xmlUrl)
{
$feedHash = MyTool::smallHash($xmlUrl);
$error = '';
if (!isset($this->_data['feeds'][$feedHash])) {
$output = $this->loadRss($xmlUrl);
if (empty($output['feed']['error'])) {
$output['feed']['xmlUrl'] = $xmlUrl;
$output['feed']['nbUnread'] = count($output['items']);
$output['feed']['nbAll'] = count($output['items']);
$this->_data['feeds'][$feedHash] = $output['feed'];
$this->_data['needSort'] = true;
$items = $output['items'];
foreach (array_keys($items) as $itemHash) {
if (empty($items[$itemHash]['via'])) {
$items[$itemHash]['via'] = $output['feed']['htmlUrl'];
}
if (empty($items[$itemHash]['author'])) {
$items[$itemHash]['author'] = $output['feed']['title'];
} else {
$items[$itemHash]['author']
= $output['feed']['title'] . ' ('
. $items[$itemHash]['author'] . ')';
}
$items[$itemHash]['xmlUrl'] = $xmlUrl;
$this->_data['newItems'][$feedHash . $itemHash] = array(
$items[$itemHash]['time'],
0
);
$items[$feedHash . $itemHash] = $items[$itemHash];
unset($items[$itemHash]);
}
$this->writeFeed($feedHash, $items);
} else {
$error = $output['feed']['error'];
}
} else {
$error = Intl::msg('Duplicated feed');
}
return array('error' => $error);
}
public function getTimeUpdate($feed)
{
$max = $feed['timeUpdate'];
if ($max == 'auto') {
$max = $this->kfc->maxUpdate;
} elseif ($max == 'max') {
$max = $this->kfc->maxUpdate;
} elseif ((int) $max < MIN_TIME_UPDATE
|| (int) $max > $this->kfc->maxUpdate) {
$max = $this->kfc->maxUpdate;
}
return (int) $max;
}
public function needUpdate($feed)
{
$diff = (int) (time()-$feed['lastUpdate']);
if ($diff > $this->getTimeUpdate($feed) * 60) {
return true;
}
return false;
}
public function updateChannel($feedHash, $force = false)
{
$error = '';
$newItems = array();
if (!isset($this->_data['feeds'][$feedHash])) {
return array(
'error' => Intl::msg('Unknown feedhash'),
'newItems' => $newItems
);
}
$xmlUrl = $this->_data['feeds'][$feedHash]['xmlUrl'];
$output = $this->loadRss($xmlUrl, $this->_data['feeds'][$feedHash], $force);
// Update feed information
$this->_data['feeds'][$feedHash] = $output['feed'];
if (empty($output['feed']['error'])) {
$this->loadFeed($feedHash);
$oldItems = array();
if (!empty($this->_data['feeds'][$feedHash]['items']) && is_array($this->_data['feeds'][$feedHash]['items'])) {
$oldItems = $this->_data['feeds'][$feedHash]['items'];
}
$lastTime = 0;
if (isset($this->_data['feeds'][$feedHash]['lastTime'])) {
$lastTime = $this->_data['feeds'][$feedHash]['lastTime'];
}
if (!empty($oldItems)) {
$lastTime = current($oldItems);
$lastTime = $lastTime['time'];
}
$newLastTime = $lastTime;
$rssItems = $output['items'];
$rssItems = array_slice($rssItems, 0, $this->kfc->maxItems, true);
$rssItemsHash = array_keys($rssItems);
if (count($rssItemsHash) !== 0) {
// Look for new items
foreach ($rssItemsHash as $itemHash) {
// itemHash is smallHash of link. To compare to item
// hashes into data, we need to concatenate to feedHash.
if (!isset($oldItems[$feedHash.$itemHash])) {
if (empty($rssItems[$itemHash]['via'])) {
$rssItems[$itemHash]['via']
= $this->_data['feeds'][$feedHash]['htmlUrl'];
}
if (empty($rssItems[$itemHash]['author'])) {
$rssItems[$itemHash]['author']
= $this->_data['feeds'][$feedHash]['title'];
} else {
$rssItems[$itemHash]['author']
= $this->_data['feeds'][$feedHash]['title'] . ' ('
. $rssItems[$itemHash]['author'] . ')';
}
$rssItems[$itemHash]['xmlUrl'] = $xmlUrl;
if ($rssItems[$itemHash]['time'] > $lastTime) {
if ($rssItems[$itemHash]['time'] > $newLastTime) {
$newLastTime = $rssItems[$itemHash]['time'];
}
$newItems[$feedHash . $itemHash] = $rssItems[$itemHash];
}
}
}
$newItemsHash = array_keys($newItems);
$this->_data['feeds'][$feedHash]['items']
= $newItems+$oldItems;
// Check if items may have been missed
if (count($oldItems) !== 0 and count($rssItemsHash) === count($newItemsHash)) {
$error = Intl::msg('Items may have been missed since last update');
}
// Remove from cache already read items not any more in the feed
$listOfOldItems = $this->getItems($feedHash);
foreach ($listOfOldItems as $itemHash => $item) {
$itemRssHash = substr($itemHash, 6, 6);
if (!isset($rssItems[$itemRssHash]) and $item[1] == 1) {
unset($this->_data['feeds'][$feedHash]['items'][$itemHash]);
}
}
// Check if quota exceeded
$nbAll = count($this->_data['feeds'][$feedHash]['items']);
if ($nbAll > $this->kfc->maxItems) {
$this->_data['feeds'][$feedHash]['items']
= array_slice(
$this->_data['feeds'][$feedHash]['items'],
0,
$this->kfc->maxItems, true
);
$nbAll = $this->kfc->maxItems;
}
// Remove items not any more in the cache
foreach (array_keys($listOfOldItems) as $itemHash) {
if (!isset($this->_data['feeds'][$feedHash]['items'][$itemHash])) {
// Remove items not any more in the cache
unset($this->_data['items'][$itemHash]);
unset($this->_data['newItems'][$itemHash]);
}
}
// Update items list and feed information (nbUnread, nbAll)
$this->_data['feeds'][$feedHash]['nbAll'] = $nbAll;
$nbUnread = 0;
foreach ($this->_data['feeds'][$feedHash]['items'] as $itemHash => $item) {
if (isset($this->_data['items'][$itemHash])) {
if ($this->_data['items'][$itemHash][1] === 0) {
$nbUnread++;
}
} else if (isset($this->_data['newItems'][$itemHash])) {
if ($this->_data['newItems'][$itemHash][1] === 0) {
$nbUnread++;
}
} else {
// TODO: Check if itemHash is appended at the end ??
$this->_data['newItems'][$itemHash] = array(
$item['time'],
0
);
$nbUnread++;
}
}
$this->_data['feeds'][$feedHash]['nbUnread'] = $nbUnread;
}
if (empty($this->_data['feeds'][$feedHash]['items'])) {
$this->_data['feeds'][$feedHash]['lastTime'] = $newLastTime;
} else {
unset($this->_data['feeds'][$feedHash]['lastTime']);
}
$this->writeFeed($feedHash, $this->_data['feeds'][$feedHash]['items']);
unset($this->_data['feeds'][$feedHash]['items']);
} else {
$error = $output['feed']['error'];
}
if (!empty($error)) {
$this->_data['feeds'][$feedHash]['error'] = $error;
}
if (empty($newItems)) {
$this->writeData();
} else {
$this->_data['needSort'] = true;
if (isset($_SESSION['lastNewItemsHash'])) {
$lastNewItemIndex = array_search($_SESSION['lastNewItemsHash'], array_keys($this->_data['newItems']));
$this->_data['items'] = $this->_data['items']+array_slice($this->_data['newItems'], 0, $lastNewItemIndex + 1, true);
$this->_data['newItems'] = array_slice($this->_data['newItems'], $lastNewItemIndex + 1, count($this->_data['newItems']) - $lastNewItemIndex, true);
unset($_SESSION['lastNewItemsHash']);
}
if ($this->kfc->order === 'newerFirst') {
arsort($this->_data['newItems']);
} else {
asort($this->_data['newItems']);
}
$this->_data['order'] = $this->kfc->order;
$this->writeData();
}
return array(
'error' => $error,
'newItems' => $newItems
);
}
public function updateFeedsHash($feedsHash, $force, $format = '')
{
$i = 0;
$errorCount = 0;
$noUpdateCount = 0;
$successCount = 0;
$nbItemsAdded = 0;
$feedsHash = $this->orderFeedsForUpdate($feedsHash);
$nbFeeds = count($feedsHash);
ob_end_flush();
if (ob_get_level() == 0) ob_start();
if ($format === 'html') {
echo '<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>'.Intl::msg('Feed').'</th>
<th>'.Intl::msg('New items').'</th>
<th>'.Intl::msg('Time').'</th>
<th>'.Intl::msg('Status').'</th>
</tr>
</thead>
<tbody>';
}
$start = microtime(true);
$lastTime = $start;
foreach ($feedsHash as $feedHash) {
$i++;
$feed = $this->getFeed($feedHash);
$strBegin = "\n".'<tr><td>'.str_pad($i.'/'.$nbFeeds, 7, ' ', STR_PAD_LEFT).'</td><td> <a href="?currentHash='.$feedHash.'">'.substr(str_pad($feed['title'], 50), 0, 50).'</a> </td><td>';
if ($format === 'html') {
echo str_pad($strBegin, 4096);
ob_flush();
flush();
}
$strEnd = '';
$time = microtime(true) - $lastTime;
$lastTime += $time;
if ($force or $this->needUpdate($feed)) {
$info = $this->updateChannel($feedHash, $force);
$countItems = count($info['newItems']);
$strEnd .= '<span class="text-success">'.str_pad($countItems, 3, ' ', STR_PAD_LEFT).'</span> </td><td>'.str_pad(number_format($time, 1), 6, ' ', STR_PAD_LEFT).'s </td><td>';
if (empty($info['error'])) {
$strEnd .= Intl::msg('Successfully updated').'</td></tr>';
$successCount++;
$nbItemsAdded += $countItems;
} else {
$strEnd .= '<span class="text-error">'.$info['error'].'</span></td></tr>';
$errorCount++;
}
} else {
$strEnd .= str_pad('0', 3, ' ', STR_PAD_LEFT).' </td><td>'.str_pad(number_format($time, 1), 6, ' ', STR_PAD_LEFT).'s </td><td><span class="text-warning">'.Intl::msg('Already up-to-date').'</span></td></tr>';
$noUpdateCount++;
}
if ($format==='html') {
echo str_pad($strEnd, 4096);
ob_flush();
flush();
} else {
echo strip_tags($strBegin.$strEnd);
}
}
// summary
$strBegin = "\n".'<tr><td></td><td> '.Intl::msg('Total:').' '.$nbFeeds.' '.($nbFeeds > 1 ? Intl::msg('items') : Intl::msg('item')).'</td><td>';
if ($format === 'html') {
echo str_pad($strBegin, 4096);
ob_flush();
flush();
}
$strEnd = str_pad($nbItemsAdded, 3, ' ', STR_PAD_LEFT).' </td><td>'.str_pad(number_format(microtime(true) - $start, 1), 6, ' ', STR_PAD_LEFT).'s </td><td>'
.'<span class="text-success">'.$successCount.' '.($successCount > 1 ? Intl::msg('Successes') : Intl::msg('Success')).' </span><br />'
.'<span class="text-warning">'.$noUpdateCount.' '.Intl::msg('Up-to-date').' </span><br />'
.'<span class="text-error">'.$errorCount.' '.($errorCount > 1 ? Intl::msg('Errors') : Intl::msg('Error')).' </span></td></tr>';
if ($format === 'html') {
echo str_pad($strEnd, 4096);
ob_flush();
flush();
} else {
echo strip_tags($strBegin.$strEnd);
}
if ($format === 'html') {
echo '</tbody></table>';
}
return '';
}
public function markAll($read) {
$save = false;
foreach (array_keys($this->_data['items']) as $itemHash) {
if (!$save and $this->_data['items'][$itemHash][1] != $read) {
$save = true;
}
$this->_data['items'][$itemHash][1] = $read;
}
foreach (array_keys($this->_data['newItems']) as $itemHash) {
if (!$save and $this->_data['newItems'][$itemHash][1] != $read) {
$save = true;
}
$this->_data['newItems'][$itemHash][1] = $read;
}
if ($save) {
foreach ($this->_data['feeds'] as $feedHash => $feed) {
if ($read == 1) {
$this->_data['feeds'][$feedHash]['nbUnread'] = 0;
} else {
$this->_data['feeds'][$feedHash]['nbUnread'] = $this->_data['feeds'][$feedHash]['nbAll'];
}
}
}
return $save;
}
public function markItem($itemHash, $read) {
$save = false;
if (isset($this->_data['items'][$itemHash])) {
if ($this->_data['items'][$itemHash][1] != $read) {
$save = true;
$this->_data['items'][$itemHash][1] = $read;
}
} else if (isset($this->_data['newItems'][$itemHash])) {
if ($this->_data['newItems'][$itemHash][1] != $read) {
$save = true;
$this->_data['newItems'][$itemHash][1] = $read;
}
}
if ($save) {
$feedHash = substr($itemHash, 0, 6);
if ($read == 1) {
$this->_data['feeds'][$feedHash]['nbUnread']--;
} else {
$this->_data['feeds'][$feedHash]['nbUnread']++;
}
}
return $save;
}
public function markFeeds($feedsHash, $read) {
$save = false;
// get items from a list of feeds
$flipFeedsHash = array_flip($feedsHash);
foreach ($this->_data['items'] as $itemHash => $item) {
if (isset($flipFeedsHash[substr($itemHash, 0, 6)])) {
if ($this->_data['items'][$itemHash][1] != $read) {
$save = true;
$this->_data['items'][$itemHash][1] = $read;
}
}
}
foreach ($this->_data['newItems'] as $itemHash => $item) {
if (isset($flipFeedsHash[substr($itemHash, 0, 6)])) {
if ($this->_data['newItems'][$itemHash][1] != $read) {
$save = true;
$this->_data['newItems'][$itemHash][1] = $read;
}
}
}
if ($save) {
foreach (array_values($feedsHash) as $feedHash) {
if ($read == 1) {
$this->_data['feeds'][$feedHash]['nbUnread'] = 0;
} else {
$this->_data['feeds'][$feedHash]['nbUnread'] = $this->_data['feeds'][$feedHash]['nbAll'];
}
}
}
return $save;
}
public function mark($hash, $read)
{
if (empty($hash) || $hash == 'all') {
// all items
return $this->markAll($read);
} else {
if (strlen($hash) === 12) {
// an item
return $this->markItem($hash, $read);
} else {
$feedsHash = array();
if (isset($this->_data['feeds'][$hash])) {
// a feed
$feedsHash[] = $hash;
} else if (isset($this->_data['folders'][$hash])) {
// a folder
foreach ($this->_data['feeds'] as $feedHash => $feed) {
if (in_array($hash, $feed['foldersHash'])) {
$feedsHash[] = $feedHash;
}
}
}
return $this->markFeeds($feedsHash, $read);
}
}
return false;
}
public function hashType($hash)
{
$type = '';
if (empty($hash) || $hash=='all') {
$type = 'all';
} else {
if (strlen($hash) === 12) {
// should be an item
$type = 'item';
} else {
if (isset($this->_data['folders'][$hash])) {
// a folder
$type = 'folder';
} else {
if (isset($this->_data['feeds'][$hash])) {
// a feed
$type = 'feed';
} else {
$type = 'unknown';
}
}
}
}
return $type;
}
public static function sortByOrder($a, $b) {
return strnatcasecmp($a['order'], $b['order']);
}
public static function sortByTitle($a, $b) {
return strnatcasecmp($a['title'], $b['title']);
}
}
class FeedConf
{
private $_file = '';
public $login = '';
public $hash = '';
public $disableSessionProtection = false;
public $salt = '';
public $title = "Kriss feed";
public $redirector = '';
public $locale = 'en_GB';
public $shaarli = '';
public $maxItems = 100;
public $maxUpdate = 60;
public $order = 'newerFirst';
public $autoreadItem = false;
public $autoreadPage = false;
public $autoUpdate = false;
public $autohide = false;
public $autofocus = true;
public $addFavicon = false;
public $preload = false;
public $blank = false;
public $visibility = 'private';
public $version;
public $view = 'list';
public $filter = 'unread';
public $listFeeds = 'show';
public $byPage = 10;
public $currentHash = 'all';
public $currentPage = 1;
public $lang = '';
public $menuView = 1;
public $menuListFeeds = 2;
public $menuFilter = 3;
public $menuOrder = 4;
public $menuUpdate = 5;
public $menuRead = 6;
public $menuUnread = 7;
public $menuEdit = 8;
public $menuAdd = 9;
public $menuHelp = 10;
public $menuStars = 11;
public $pagingItem = 1;
public $pagingPage = 2;
public $pagingByPage = 3;
public $pagingMarkAs = 4;
public function __construct($configFile, $version)
{
$this->_file = $configFile;
$this->version = $version;
$this->lang = Intl::$lang;
// Loading user config
if (file_exists($this->_file)) {
include_once $this->_file;
} else {
$this->_install();
}
Session::$disableSessionProtection = $this->disableSessionProtection;
if ($this->addFavicon) {
/* favicon dir */
if (!is_dir(INC_DIR)) {
if (!@mkdir(INC_DIR, 0755)) {
FeedPage::$pb->assign('message', sprintf(Intl::msg('Can not create %s directory, check permissions'), INC_DIR));
FeedPage::$pb->renderPage('message');
}
}
if (!is_dir(FAVICON_DIR)) {
if (!@mkdir(FAVICON_DIR, 0755)) {
FeedPage::$pb->assign('message', sprintf(Intl::msg('Can not create %s directory, check permissions'), FAVICON_DIR));
FeedPage::$pb->renderPage('message');
}
}
}
if ($this->isLogged()) {
unset($_SESSION['view']);
unset($_SESSION['listFeeds']);
unset($_SESSION['filter']);
unset($_SESSION['order']);
unset($_SESSION['byPage']);
unset($_SESSION['lang']);
}
$view = $this->getView();
$listFeeds = $this->getListFeeds();
$filter = $this->getFilter();
$order = $this->getOrder();
$byPage = $this->getByPage();
$lang = $this->getLang();
if ($this->view != $view
|| $this->listFeeds != $listFeeds
|| $this->filter != $filter
|| $this->order != $order
|| $this->byPage != $byPage
|| $this->lang != $lang
) {
$this->view = $view;
$this->listFeeds = $listFeeds;
$this->filter = $filter;
$this->order = $order;
$this->byPage = $byPage;
$this->lang = $lang;
$this->write();
}
if (!$this->isLogged()) {
$_SESSION['view'] = $view;
$_SESSION['listFeeds'] = $listFeeds;
$_SESSION['filter'] = $filter;
$_SESSION['order'] = $order;
$_SESSION['byPage'] = $byPage;
$_SESSION['lang'] = $lang;
}
Intl::$lang = $this->lang;
}
private function _install()
{
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) {
$this->setSalt(sha1(uniqid('', true).'_'.mt_rand()));
$this->setLogin($_POST['setlogin']);
$this->setHash($_POST['setpassword']);
$this->write();
FeedPage::$pb->assign('pagetitle', 'KrISS feed installation');
FeedPage::$pb->assign('class', 'text-success');
FeedPage::$pb->assign('message', Intl::msg('Your simple and smart (or stupid) feed reader is now configured.'));
FeedPage::$pb->assign('referer', MyTool::getUrl().'?import');
FeedPage::$pb->assign('button', Intl::msg('Continue'));
FeedPage::$pb->renderPage('message');
} else {
FeedPage::$pb->assign('pagetitle', Intl::msg('KrISS feed installation'));
FeedPage::$pb->assign('token', Session::getToken());
FeedPage::$pb->renderPage('install');
}
exit();
}
public function hydrate(array $data)
{
foreach ($data as $key => $value) {
// get setter
$method = 'set'.ucfirst($key);
// if setter exists just call it
// (php is not case-sensitive with functions)
if (method_exists($this, $method)) {
$this->$method($value);
}
}
$this->write();
}
public function getLang()
{
$lang = $this->lang;
if (isset($_GET['lang'])) {
$lang = $_GET['lang'];
} else if (isset($_SESSION['lang'])) {
$lang = $_SESSION['lang'];
}
if (!in_array($lang, array_keys(Intl::$langList))) {
$lang = $this->lang;
}
return $lang;
}
public function getView()
{
$view = $this->view;
if (isset($_GET['view'])) {
if ($_GET['view'] == 'expanded') {
$view = 'expanded';
}
if ($_GET['view'] == 'list') {
$view = 'list';
}
} else if (isset($_SESSION['view'])) {
$view = $_SESSION['view'];
}
return $view;
}
public function getFilter()
{
$filter = $this->filter;
if (isset($_GET['filter'])) {
if ($_GET['filter'] == 'unread') {
$filter = 'unread';
}
if ($_GET['filter'] == 'all') {
$filter = 'all';
}
} else if (isset($_SESSION['filter'])) {
$filter = $_SESSION['filter'];
}
return $filter;
}
public function getListFeeds()
{
$listFeeds = $this->listFeeds;
if (isset($_GET['listFeeds'])) {
if ($_GET['listFeeds'] == 'show') {
$listFeeds = 'show';
}
if ($_GET['listFeeds'] == 'hide') {
$listFeeds = 'hide';
}
} else if (isset($_SESSION['listFeeds'])) {
$listFeeds = $_SESSION['listFeeds'];
}
return $listFeeds;
}
public function getByPage()
{
$byPage = $this->byPage;
if (isset($_GET['byPage']) && is_numeric($_GET['byPage']) && $_GET['byPage'] > 0) {
$byPage = $_GET['byPage'];
} else if (isset($_SESSION['byPage'])) {
$byPage = $_SESSION['byPage'];
}
return $byPage;
}
public function getOrder()
{
$order = $this->order;
if (isset($_GET['order'])) {
if ($_GET['order'] === 'newerFirst') {
$order = 'newerFirst';
}
if ($_GET['order'] === 'olderFirst') {
$order = 'olderFirst';
}
} else if (isset($_SESSION['order'])) {
$order = $_SESSION['order'];
}
return $order;
}
public function getCurrentHash()
{
$currentHash = $this->currentHash;
if (isset($_GET['currentHash'])) {
$currentHash = preg_replace('/[^a-zA-Z0-9-_@]/', '', substr(trim($_GET['currentHash'], '/'), 0, 6));
}
if (empty($currentHash)) {
$currentHash = 'all';
}
return $currentHash;
}
public function getCurrentPage()
{
$currentPage = $this->currentPage;
if (isset($_GET['page']) && !empty($_GET['page'])) {
$currentPage = (int) $_GET['page'];
} else if (isset($_GET['previousPage']) && !empty($_GET['previousPage'])) {
$currentPage = (int) $_GET['previousPage'] - 1;
if ($currentPage < 1) {
$currentPage = 1;
}
} else if (isset($_GET['nextPage']) && !empty($_GET['nextPage'])) {
$currentPage = (int) $_GET['nextPage'] + 1;
}
return $currentPage;
}
public function setDisableSessionProtection($disableSessionProtection)
{
$this->disableSessionProtection = $disableSessionProtection;
}
public function setLogin($login)
{
$this->login = $login;
}
public function setVisibility($visibility)
{
$this->visibility = $visibility;
}
public function setHash($pass)
{
$this->hash = sha1($pass.$this->login.$this->salt);
}
public function setSalt($salt)
{
$this->salt = $salt;
}
public function setTitle($title)
{
$this->title = $title;
}
public function setLocale($locale)
{
$this->locale = $locale;
}
public function setRedirector($redirector)
{
$this->redirector = $redirector;
}
public function setAutoreadPage($autoreadPage)
{
$this->autoreadPage = $autoreadPage;
}
public function setAutoUpdate($autoUpdate)
{
$this->autoUpdate = $autoUpdate;
}
public function setAutoreadItem($autoreadItem)
{
$this->autoreadItem = $autoreadItem;
}
public function setAutohide($autohide)
{
$this->autohide = $autohide;
}
public function setAutofocus($autofocus)
{
$this->autofocus = $autofocus;
}
public function setAddFavicon($addFavicon)
{
$this->addFavicon = $addFavicon;
}
public function setPreload($preload)
{
$this->preload = $preload;
}
public function setShaarli($url)
{
$this->shaarli = $url;
}
public function setMaxUpdate($max)
{
$this->maxUpdate = $max;
}
public function setMaxItems($max)
{
$this->maxItems = $max;
}
public function setOrder($order)
{
$this->order = $order;
}
public function setBlank($blank)
{
$this->blank = $blank;
}
public function getMenu()
{
$menu = array();
if ($this->menuView != 0) {
$menu['menuView'] = $this->menuView;
}
if ($this->menuListFeeds != 0) {
$menu['menuListFeeds'] = $this->menuListFeeds;
}
if ($this->menuFilter != 0) {
$menu['menuFilter'] = $this->menuFilter;
}
if ($this->menuOrder != 0) {
$menu['menuOrder'] = $this->menuOrder;
}
if ($this->menuUpdate != 0) {
$menu['menuUpdate'] = $this->menuUpdate;
}
if ($this->menuRead != 0) {
$menu['menuRead'] = $this->menuRead;
}
if ($this->menuUnread != 0) {
$menu['menuUnread'] = $this->menuUnread;
}
if ($this->menuEdit != 0) {
$menu['menuEdit'] = $this->menuEdit;
}
if ($this->menuAdd != 0) {
$menu['menuAdd'] = $this->menuAdd;
}
if ($this->menuHelp != 0) {
$menu['menuHelp'] = $this->menuHelp;
}
if ($this->menuStars != 0) {
$menu['menuStars'] = $this->menuStars;
}
asort($menu);
return $menu;
}
public function getPaging()
{
$paging = array();
if ($this->pagingItem != 0) {
$paging['pagingItem'] = $this->pagingItem;
}
if ($this->pagingPage != 0) {
$paging['pagingPage'] = $this->pagingPage;
}
if ($this->pagingByPage != 0) {
$paging['pagingByPage'] = $this->pagingByPage;
}
if ($this->pagingMarkAs != 0) {
$paging['pagingMarkAs'] = $this->pagingMarkAs;
}
asort($paging);
return $paging;
}
public function setMenuView($menuView)
{
$this->menuView = $menuView;
}
public function setMenuListFeeds($menuListFeeds)
{
$this->menuListFeeds = $menuListFeeds;
}
public function setMenuFilter($menuFilter)
{
$this->menuFilter = $menuFilter;
}
public function setMenuOrder($menuOrder)
{
$this->menuOrder = $menuOrder;
}
public function setMenuUpdate($menuUpdate)
{
$this->menuUpdate = $menuUpdate;
}
public function setMenuRead($menuRead)
{
$this->menuRead = $menuRead;
}
public function setMenuUnread($menuUnread)
{
$this->menuUnread = $menuUnread;
}
public function setMenuEdit($menuEdit)
{
$this->menuEdit = $menuEdit;
}
public function setMenuAdd($menuAdd)
{
$this->menuAdd = $menuAdd;
}
public function setMenuHelp($menuHelp)
{
$this->menuHelp = $menuHelp;
}
public function setMenuStars($menuStars)
{
$this->menuStars = $menuStars;
}
public function setPagingItem($pagingItem)
{
$this->pagingItem = $pagingItem;
}
public function setPagingPage($pagingPage)
{
$this->pagingPage = $pagingPage;
}
public function setPagingByPage($pagingByPage)
{
$this->pagingByPage = $pagingByPage;
}
public function setPagingMarkAs($pagingMarkAs)
{
$this->pagingMarkAs = $pagingMarkAs;
}
public function isLogged()
{
global $argv;
if (Session::isLogged()
|| $this->visibility === 'public'
|| (isset($_GET['cron'])
&& $_GET['cron'] === sha1($this->salt.$this->hash))
|| (isset($argv)
&& count($argv) >= 3
&& $argv[1] == 'update'
&& $argv[2] == sha1($this->salt.$this->hash))) {
return true;
}
return false;
}
public function write()
{
if ($this->isLogged() || !is_file($this->_file)) {
$data = array('login', 'hash', 'salt', 'title', 'redirector', 'shaarli',
'byPage', 'order', 'visibility', 'filter', 'view','locale',
'maxItems', 'autoreadItem', 'autoreadPage', 'maxUpdate',
'autohide', 'autofocus', 'listFeeds', 'autoUpdate', 'menuView',
'menuListFeeds', 'menuFilter', 'menuOrder', 'menuUpdate',
'menuRead', 'menuUnread', 'menuEdit', 'menuAdd', 'menuHelp', 'menuStars',
'pagingItem', 'pagingPage', 'pagingByPage', 'addFavicon', 'preload',
'pagingMarkAs', 'disableSessionProtection', 'blank', 'lang');
$out = '<?php';
$out .= "\n";
foreach ($data as $key) {
$out .= '$this->'.$key.' = '.var_export($this->$key, true).";\n";
}
$out .= '?>';
if (!@file_put_contents($this->_file, $out)) {
die("Can't write to ".CONFIG_FILE." check permissions");
}
}
}
}
class FeedPage
{
public static $pb; // PageBuilder
public static $var = array();
public static function init($var)
{
FeedPage::$var = $var;
}
public static function add_feedTpl()
{
extract(FeedPage::$var);
?>
<!DOCTYPE html>
<html>
<head>
<?php FeedPage::includesTpl(); ?>
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="edit-all" class="span6 offset3">
<?php FeedPage::statusTpl(); ?>
<?php FeedPage::navTpl(); ?>
<form class="form-horizontal" action="?add" method="POST">
<fieldset>
<legend><?php echo Intl::msg( 'Add a new feed' );?></legend>
<div class="control-group">
<label class="control-label" ><?php echo Intl::msg( 'Feed URL' );?></label>
<div class="controls">
<input type="text" id="newfeed" name="newfeed" value="<?php echo $newfeed;?>">
</div>
</div>
</fieldset>
<fieldset>
<legend><?php echo Intl::msg( 'Add selected folders to feed' );?></legend>
<div class="control-group">
<div class="controls">
<?php $counter1=-1; if( isset($folders) && is_array($folders) && sizeof($folders) ) foreach( $folders as $key1 => $value1 ){ $counter1++; ?>
<label for="add-folder-<?php echo $key1;?>">
<input type="checkbox" id="add-folder-<?php echo $key1;?>" name="folders[]" value="<?php echo $key1;?>"> <?php echo htmlspecialchars( $value1["title"] );?> (<a href="?edit=<?php echo $key1;?>"><?php echo Intl::msg( 'Edit feed' );?></a>)
</label>
<?php } ?>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Add a new folder' );?></label>
<div class="controls">
<input type="text" name="newfolder" value="">
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="add" value="<?php echo Intl::msg( 'Add new feed' );?>"/>
</div>
</div>
</fieldset>
<fieldset>
<legend><?php echo Intl::msg( 'Use bookmarklet to add a new feed' );?></legend>
<div id="add-feed-bookmarklet" class="text-center">
<a onclick="alert('<?php echo Intl::msg( 'Drag this link to your bookmarks toolbar, or right-click it and choose Bookmark This Link...' );?>');return false;" href="javascript:(function(){var%20url%20=%20location.href;window.open('<?php echo $base;?>?add&amp;newfeed='+encodeURIComponent(url),'_blank','menubar=no,height=390,width=600,toolbar=no,scrollbars=yes,status=no,dialog=1');})();"><b>KF+</b></a>
</div>
</fieldset>
<input type="hidden" name="token" value="<?php echo $token;?>">
<input type="hidden" name="returnurl" value="<?php echo $referer;?>" />
</form>
</div>
</div>
</div>
</body>
</html>
<?php
}
public static function change_passwordTpl()
{
extract(FeedPage::$var);
?>
<!DOCTYPE html>
<html>
<?php FeedPage::includesTpl(); ?>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div class="span6 offset3">
<div id="config">
<?php FeedPage::statusTpl(); ?>
<?php FeedPage::navTpl(); ?>
<div id="section">
<form class="form-horizontal" method="post" action="">
<input type="hidden" name="token" value="<?php echo $token;?>">
<input type="hidden" name="returnurl" value="<?php echo $referer;?>" />
<fieldset>
<legend><?php echo Intl::msg( 'Change your password' );?></legend>
<div class="control-group">
<label class="control-label" for="oldpassword"><?php echo Intl::msg( 'Old password' );?></label>
<div class="controls">
<input type="password" id="oldpassword" name="oldpassword">
</div>
</div>
<div class="control-group">
<label class="control-label" for="newpassword"><?php echo Intl::msg( 'New password' );?></label>
<div class="controls">
<input type="password" id="newpassword" name="newpassword">
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save new password' );?>" />
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
<?php
}
public static function configTpl()
{
extract(FeedPage::$var);
?>
<!DOCTYPE html>
<html>
<?php FeedPage::includesTpl(); ?>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div class="span6 offset3">
<div id="config">
<?php FeedPage::statusTpl(); ?>
<?php FeedPage::navTpl(); ?>
<div id="section">
<form class="form-horizontal" method="post" action="">
<input type="hidden" name="token" value="<?php echo $token;?>"/>
<input type="hidden" name="returnurl" value="<?php echo $referer;?>"/>
<fieldset>
<legend><?php echo Intl::msg( 'KrISS feed main information' );?></legend>
<div class="control-group">
<label class="control-label" for="title"><?php echo Intl::msg( 'KrISS feed title' );?></label>
<div class="controls">
<input type="text" id="title" name="title" value="<?php echo $kfctitle;?>">
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'KrISS feed visibility' );?></label>
<div class="controls">
<label for="publicReader">
<input type="radio" id="publicReader" name="visibility" value="public" <?php if( $kfcvisibility==='public' ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Public KrISS feed' );?>
</label>
<span class="help-block">
<?php echo Intl::msg( 'No restriction. Anyone can modify configuration, mark as read items, update feeds...' );?>
</span>
<label for="protectedReader">
<input type="radio" id="protectedReader" name="visibility" value="protected" <?php if( $kfcvisibility==='protected' ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Protected KrISS feed' );?>
</label>
<span class="help-block">
<?php echo Intl::msg( 'Anyone can access feeds and items but only you can modify configuration, mark as read items, update feeds...' );?>
</span>
<label for="privateReader">
<input type="radio" id="privateReader" name="visibility" value="private" <?php if( $kfcvisibility==='private' ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Private KrISS feed' );?>
</label>
<span class="help-block">
<?php echo Intl::msg( 'Only you can access feeds and items and only you can modify configuration, mark as read items, update feeds...' );?>
</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="shaarli"><?php echo Intl::msg( 'Shaarli URL' );?></label>
<div class="controls">
<input type="text" id="shaarli" name="shaarli" value="<?php echo $kfcshaarli;?>">
<span class="help-block"><?php echo Intl::msg( 'Options:' );?><br>
- <?php echo Intl::msg( '${url}: item link' );?><br>
- <?php echo Intl::msg( '${title}: item title' );?><br>
- <?php echo Intl::msg( '${via}: if domain of &lt;link&gt; and &lt;guid&gt; are different ${via} is equals to: <code>via &lt;guid&gt;</code>' );?><br>
- <?php echo Intl::msg( '${sel}: <strong>Only available</strong> with javascript: <code>selected text</code>' );?><br>
- <?php echo Intl::msg( 'example with shaarli:' );?> <code>http://your-shaarli/?post=${url}&title=${title}&description=${sel}%0A%0A${via}&source=bookmarklet</code>
</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="redirector"><?php echo Intl::msg( 'KrISS feed redirector (only for links, media are not considered, <strong>item content is anonymize only with javascript</strong>)' );?></label>
<div class="controls">
<input type="text" id="redirector" name="redirector" value="<?php echo $kfcredirector;?>">
<span class="help-block"><?php echo Intl::msg( '<strong>http://anonym.to/?</strong> will mask the HTTP_REFERER, you can also use <strong>noreferrer</strong> to use HTML5 property' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="disablesessionprotection">Session protection</label>
<div class="controls">
<label><input type="checkbox" id="disablesessionprotection" name="disableSessionProtection" <?php if( $kfcdisablesessionprotection ){ ?>checked="checked"<?php } ?>><?php echo Intl::msg( 'Disable session cookie hijacking protection' );?></label>
<span class="help-block"><?php echo Intl::msg( 'Check this if you get disconnected often or if your IP address changes often.' );?></span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
</div>
</div>
</fieldset>
<fieldset>
<legend><?php echo Intl::msg( 'KrISS feed preferences' );?></legend>
<div class="control-group">
<label class="control-label" for="maxItems"><?php echo Intl::msg( 'Maximum number of items by feed' );?></label>
<div class="controls">
<input type="text" maxlength="3" id="maxItems" name="maxItems" value="<?php echo $kfcmaxitems;?>">
<span class="help-block"><?php echo Intl::msg( 'Need update to be taken into consideration' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="maxUpdate"><?php echo Intl::msg( 'Maximum delay between feed update (in minutes)' );?></label>
<div class="controls">
<input type="number" id="maxUpdate" name="maxUpdate" value="<?php echo $kfcmaxupdate;?>">
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Auto read next item option' );?></label>
<div class="controls">
<label for="donotautoreaditem">
<input type="radio" id="donotautoreaditem" name="autoreadItem" value="0" <?php if( !$kfcautoreaditem ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not mark as read when next item' );?>
</label>
<label for="autoread">
<input type="radio" id="autoread" name="autoreadItem" value="1" <?php if( $kfcautoreaditem ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Auto mark current as read when next item' );?>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Auto read next page option' );?></label>
<div class="controls">
<label for="donotautoreadpage">
<input type="radio" id="donotautoreadpage" name="autoreadPage" value="0" <?php if( !$kfcautoreadpage ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not mark as read when next page' );?>
</label>
<label for="autoreadpage">
<input type="radio" id="autoreadpage" name="autoreadPage" value="1" <?php if( $kfcautoreadpage ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Auto mark current as read when next page' );?>
</label>
<span class="help-block"><strong><?php echo Intl::msg( 'Not implemented yet' );?></strong></span>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Auto hide option' );?></label>
<div class="controls">
<label for="donotautohide">
<input type="radio" id="donotautohide" name="autohide" value="0" <?php if( !$kfcautohide ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Always show feed in feeds list' );?>
</label>
<label for="autohide">
<input type="radio" id="autohide" name="autohide" value="1" <?php if( $kfcautohide ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Automatically hide feed when 0 unread item' );?>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Auto focus option' );?></label>
<div class="controls">
<label for="donotautofocus">
<input type="radio" id="donotautofocus" name="autofocus" value="0" <?php if( !$kfcautofocus ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not automatically jump to current item when it changes' );?>
</label>
<label for="autofocus">
<input type="radio" id="autofocus" name="autofocus" value="1" <?php if( $kfcautofocus ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Automatically jump to the current item position' );?>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Add favicon option' );?></label>
<div class="controls">
<label for="donotaddfavicon">
<input type="radio" id="donotaddfavicon" name="addFavicon" value="0" <?php if( !$kfcaddfavicon ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not add favicon next to feed on list of feeds/items' );?>
</label>
<label for="addfavicon">
<input type="radio" id="addfavicon" name="addFavicon" value="1" <?php if( $kfcaddfavicon ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Add favicon next to feed on list of feeds/items' );?><br><strong><?php echo Intl::msg( 'Warning: It depends on http://getfavicon.appspot.com/' );?><?php if( in_array('curl', get_loaded_extensions()) ){ ?><?php echo Intl::msg( 'but it will cache favicon on your server' );?><?php } ?></strong>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Preload option' );?></label>
<div class="controls">
<label for="donotpreload">
<input type="radio" id="donotpreload" name="preload" value="0" <?php if( !$kfcpreload ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not preload items.' );?>
</label>
<label for="preload">
<input type="radio" id="preload" name="preload" value="1" <?php if( $kfcpreload ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Preload current page items in background. This greatly enhance speed sensation when opening a new item. Note: It uses your bandwith more than needed if you do not read all the page items.' );?>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label">Auto target="_blank"</label>
<div class="controls">
<label for="donotblank">
<input type="radio" id="donotblank" name="blank" value="0" <?php if( !$kfcblank ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not open link in new tab' );?>
</label>
<label for="doblank">
<input type="radio" id="doblank" name="blank" value="1" <?php if( $kfcblank ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Automatically open link in new tab' );?>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label"><?php echo Intl::msg( 'Auto update with javascript' );?></label>
<div class="controls">
<label for="donotautoupdate">
<input type="radio" id="donotautoupdate" name="autoUpdate" value="0" <?php if( !$kfcautoupdate ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Do not auto update with javascript' );?>
</label>
<label for="autoupdate">
<input type="radio" id="autoupdate" name="autoUpdate" value="1" <?php if( $kfcautoupdate ){ ?>checked="checked"<?php } ?>/>
<?php echo Intl::msg( 'Auto update with javascript' );?>
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
</div>
</div>
</fieldset>
<?php $zero=FeedPage::$var['zero']=0;?>
<fieldset>
<legend><?php echo Intl::msg( 'KrISS feed menu preferences' );?></legend>
<?php echo Intl::msg( 'You can order or remove elements in the menu. Set a position or leave empty if you do not want the element to appear in the menu.' );?>
<div class="control-group">
<label class="control-label" for="menuView"><?php echo Intl::msg( 'View' );?></label>
<div class="controls">
<input type="text" id="menuView" name="menuView" value="<?php if( empty($kfcmenu['menuView']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuView"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'View as list' );?>/<?php echo Intl::msg( 'View as expanded' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuListFeeds"><?php echo Intl::msg( 'Feeds' );?></label>
<div class="controls">
<input type="text" id="menuListFeeds" name="menuListFeeds" value="<?php if( empty($kfcmenu['menuListFeeds']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuListFeeds"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Hide feeds list' );?>/<?php echo Intl::msg( 'Show feeds list' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuFilter"><?php echo Intl::msg( 'Filter' );?></label>
<div class="controls">
<input type="text" id="menuFilter" name="menuFilter" value="<?php if( empty($kfcmenu['menuFilter']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuFilter"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Show all items' );?>/<?php echo Intl::msg( 'Show unread items' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuOrder"><?php echo Intl::msg( 'Order' );?></label>
<div class="controls">
<input type="text" id="menuOrder" name="menuOrder" value="<?php if( empty($kfcmenu['menuOrder']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuOrder"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Show older first' );?>/<?php echo Intl::msg( 'Show newer first' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuUpdate"><?php echo Intl::msg( 'Update' );?></label>
<div class="controls">
<input type="text" id="menuUpdate" name="menuUpdate" value="<?php if( empty($kfcmenu['menuUpdate']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuUpdate"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Update all' );?>/<?php echo Intl::msg( 'Update folder' );?>/<?php echo Intl::msg( 'Update feed' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuRead"><?php echo Intl::msg( 'Mark as read' );?></label>
<div class="controls">
<input type="text" id="menuRead" name="menuRead" value="<?php if( empty($kfcmenu['menuRead']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuRead"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Mark all as read' );?>/<?php echo Intl::msg( 'Mark folder as read' );?>/<?php echo Intl::msg( 'Mark feed as read' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuUnread"><?php echo Intl::msg( 'Mark as unread' );?></label>
<div class="controls">
<input type="text" id="menuUnread" name="menuUnread" value="<?php if( empty($kfcmenu['menuUnread']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuUnread"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Mark all as unread' );?>/<?php echo Intl::msg( 'Mark folder as unread' );?>/<?php echo Intl::msg( 'Mark feed as unread' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuEdit"><?php echo Intl::msg( 'Edit' );?></label>
<div class="controls">
<input type="text" id="menuEdit" name="menuEdit" value="<?php if( empty($kfcmenu['menuEdit']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuEdit"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Edit all' );?>/<?php echo Intl::msg( 'Edit folder' );?>/<?php echo Intl::msg( 'Edit feed' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuAdd"><?php echo Intl::msg( 'Add a new feed' );?></label>
<div class="controls">
<input type="text" id="menuAdd" name="menuAdd" value="<?php if( empty($kfcmenu['menuAdd']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuAdd"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Add a new feed' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuHelp"><?php echo Intl::msg( 'Help' );?></label>
<div class="controls">
<input type="text" id="menuHelp" name="menuHelp" value="<?php if( empty($kfcmenu['menuHelp']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuHelp"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Help' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="menuStars"><?php echo Intl::msg( 'Starred items' );?></label>
<div class="controls">
<input type="text" id="menuStars" name="menuStars" value="<?php if( empty($kfcmenu['menuStars']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcmenu["menuStars"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'Starred items' );?></span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
</div>
</div>
</fieldset>
<fieldset>
<legend><?php echo Intl::msg( 'KrISS feed paging menu preferences' );?></legend>
<div class="control-group">
<label class="control-label" for="pagingItem"><?php echo Intl::msg( 'Item' );?></label>
<div class="controls">
<input type="text" id="pagingItem" name="pagingItem" value="<?php if( empty($kfcpaging['pagingItem']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcpaging["pagingItem"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'If you want to go previous and next item' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="pagingPage"><?php echo Intl::msg( 'Page' );?></label>
<div class="controls">
<input type="text" id="pagingPage" name="pagingPage" value="<?php if( empty($kfcpaging['pagingPage']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcpaging["pagingPage"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'If you want to go previous and next page' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="pagingByPage"><?php echo Intl::msg( 'Items by page' );?></label>
<div class="controls">
<input type="text" id="pagingByPage" name="pagingByPage" value="<?php if( empty($kfcpaging['pagingByPage']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcpaging["pagingByPage"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'If you want to modify number of items by page' );?></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="pagingMarkAs"><?php echo Intl::msg( 'Mark as read' );?></label>
<div class="controls">
<input type="text" id="pagingMarkAs" name="pagingMarkAs" value="<?php if( empty($kfcpaging['pagingMarkAs']) ){ ?><?php echo $zero;?><?php }else{ ?><?php echo $kfcpaging["pagingMarkAs"];?><?php } ?>">
<span class="help-block"><?php echo Intl::msg( 'If you want to add a mark as read button into paging' );?></span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
</div>
</div>
</fieldset>
<fieldset>
<legend><?php echo Intl::msg( 'Cron configuration' );?></legend>
<code><?php echo $base;?>?update&cron=<?php echo $kfccron;?></code>
<?php echo Intl::msg( 'You can use <code>&force</code> to force update.' );?><br>
<?php echo Intl::msg( 'To update every hour:' );?><br>
<code>0 * * * * wget "<?php echo $base;?>?update&cron=<?php echo $kfccron;?>" -O /tmp/kf.cron</code><br>
<?php echo Intl::msg( 'If you can not use wget, you may try php command line:' );?><br>
<code>0 * * * * php -f <?php echo $scriptfilename;?> update <?php echo $kfccron;?> > /tmp/kf.cron</code><br>
<?php echo Intl::msg( 'If previous solutions do not work, try to create an update.php file into data directory containing:' );?><br>
<code>
&lt;?php<br>
$url = "<?php echo $base;?>?update&cron=<?php echo $kfccron;?>";<br>
$options = array('http'=>array('method'=>'GET'));<br>
$context = stream_context_create($options);<br>
$data=file_get_contents($url,false,$context);<br>
print($data);
</code><br>
<?php echo Intl::msg( 'Then set up your cron with:' );?><br>
<code>0 * * * * php -f <?php echo dirname( $scriptfilename );?>/data/update.php > /tmp/kf.cron</code><br>
<?php echo Intl::msg( 'Do not forget to check permissions' );?><br>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
</div>
</div>
</fieldset>
</form><br>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
<?php
}
public static function edit_allTpl()
{
extract(FeedPage::$var);
?>
<!DOCTYPE html>
<html>
<head>
<?php FeedPage::includesTpl(); ?>
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="edit-all" class="span6 offset3">
<?php FeedPage::statusTpl(); ?>
<?php FeedPage::navTpl(); ?>
<form class="form-horizontal" method="post" action="">
<fieldset>
<legend><?php echo Intl::msg( 'Reorder folders' );?></legend>
<div class="control-group">
<div class="controls">
<?php $counter1=-1; if( isset($folders) && is_array($folders) && sizeof($folders) ) foreach( $folders as $key1 => $value1 ){ $counter1++; ?>
<label for="order-folder-<?php echo $key1;?>">
<?php echo htmlspecialchars( $value1["title"] );?> (<a href="?edit=<?php echo $key1;?>"><?php echo Intl::msg( 'Edit folder' );?></a>) <br>
<input type="text" id="order-folder-<?php echo $key1;?>" name="order-folder-<?php echo $key1;?>" value="<?php echo $counter1;?>">
</label>
<?php } ?>
</div>
</div>
</fieldset>
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
<fieldset>
<legend><?php echo Intl::msg( 'Add selected folders to selected feeds' );?></legend>
<div class="control-group">
<div class="controls">
<?php $counter1=-1; if( isset($folders) && is_array($folders) && sizeof($folders) ) foreach( $folders as $key1 => $value1 ){ $counter1++; ?>
<label for="add-folder-<?php echo $key1;?>">
<input type="checkbox" id="add-folder-<?php echo $key1;?>" name="addfolders[]" value="<?php echo $key1;?>"> <?php echo htmlspecialchars( $value1["title"] );?> (<a href="?edit=<?php echo $key1;?>"><?php echo Intl::msg( 'Edit folder' );?></a>)
</label>
<?php } ?>
</div>
<div class="controls">
<input type="text" name="addnewfolder" value="" placeholder="New folder">
</div>
</div>
</fieldset>
<input class="btn" type="submit" name="cancel" value="<?php echo Intl::msg( 'Cancel' );?>"/>
<input class="btn" type="submit" name="save" value="<?php echo Intl::msg( 'Save modifications' );?>" />
<fieldset>
<legend><?php echo Intl::msg( 'Remove selected folders to selected feeds' );?></legend>
<div class="control-group">
<div class="controls">
<?php $counter1=-1; if( isset($folders) && is_array($folders) && sizeof($folders) ) foreach( $folders as $key1 => $value1 ){ $counter1++; ?>
<label for="remove-folder-<?php echo $key1;?>">
<input type="checkbox" id="remove-folder-<?php echo