summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md23
-rw-r--r--CREDITS.md6
-rw-r--r--README.fr.md13
-rw-r--r--README.md11
-rw-r--r--app/Controllers/authController.php4
-rwxr-xr-xapp/Controllers/feedController.php4
-rw-r--r--app/Controllers/importExportController.php6
-rw-r--r--app/Controllers/updateController.php159
-rw-r--r--app/Models/Auth.php15
-rw-r--r--app/Models/EntryDAO.php47
-rw-r--r--app/Models/Factory.php1
-rw-r--r--app/Models/UserDAO.php5
-rw-r--r--app/i18n/cz/admin.php4
-rw-r--r--app/i18n/cz/gen.php2
-rw-r--r--app/i18n/cz/install.php4
-rw-r--r--app/i18n/de/admin.php4
-rw-r--r--app/i18n/de/gen.php2
-rw-r--r--app/i18n/de/install.php4
-rw-r--r--app/i18n/en/admin.php4
-rw-r--r--app/i18n/en/gen.php2
-rw-r--r--app/i18n/en/install.php4
-rw-r--r--app/i18n/fr/admin.php4
-rw-r--r--app/i18n/fr/gen.php2
-rw-r--r--app/i18n/fr/install.php4
-rw-r--r--app/i18n/it/admin.php4
-rw-r--r--app/i18n/it/gen.php2
-rw-r--r--app/i18n/it/install.php4
-rw-r--r--app/i18n/nl/admin.php4
-rw-r--r--app/i18n/nl/gen.php2
-rw-r--r--app/i18n/nl/install.php4
-rw-r--r--app/i18n/ru/admin.php4
-rw-r--r--app/i18n/ru/gen.php2
-rw-r--r--app/i18n/ru/install.php4
-rw-r--r--app/i18n/tr/admin.php4
-rw-r--r--app/i18n/tr/gen.php2
-rw-r--r--app/i18n/tr/install.php4
-rw-r--r--app/install.php12
-rw-r--r--app/views/auth/formLogin.phtml2
-rw-r--r--app/views/helpers/export/articles.phtml101
-rw-r--r--cli/README.md28
-rwxr-xr-xcli/create-user.php3
-rwxr-xr-xcli/do-install.php14
-rwxr-xr-xcli/user-info.php35
-rw-r--r--constants.php2
-rw-r--r--data/config.default.php5
-rw-r--r--extensions/README.md4
-rw-r--r--lib/Minz/ModelPdo.php6
-rw-r--r--lib/favicons.php7
-rw-r--r--lib/lib_install.php10
-rw-r--r--lib/lib_rss.php3
-rw-r--r--p/scripts/main.js2
51 files changed, 460 insertions, 148 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4be6d74bd..da73c285e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,26 @@
# Changelog
+## 2016-12-26 FreshRSS 1.6.2
+
+* Features
+ * Add git compatibility in Web update system [#1357](https://github.com/FreshRSS/FreshRSS/issues/1357)
+ * Requires that the initial installation is done with git
+ * New option `limits.cookie_duration` in `data/config.php` to set the login cookie duration [#1384](https://github.com/FreshRSS/FreshRSS/issues/1384)
+* SQL
+ * More robust export function in the case of large datasets [#1372](https://github.com/FreshRSS/FreshRSS/issues/1372)
+* CLI
+ * New command `./cli/user-info.php` to get some user information [#1345](https://github.com/FreshRSS/FreshRSS/issues/1345)
+* Bug fixing
+ * Fix bug in estimating last user activity [#1358](https://github.com/FreshRSS/FreshRSS/issues/1358)
+ * PostgreSQL: fix bug when updating cached values [#1360](https://github.com/FreshRSS/FreshRSS/issues/1360)
+ * Fix bug in confirmation before marking as read [#1348](https://github.com/FreshRSS/FreshRSS/issues/1348)
+ * Fix small bugs in installer [#1363](https://github.com/FreshRSS/FreshRSS/pull/1363)
+ * Allow slash in database hostname, when using sockets [#1364](https://github.com/FreshRSS/FreshRSS/issues/1364)
+ * Add curl user-agent to retrieve favicons [#1380](https://github.com/FreshRSS/FreshRSS/issues/1380)
+ * Send login cookie only once [#1398](https://github.com/FreshRSS/FreshRSS/pull/1398)
+ * Add a check for PHP extension fileinfo [#1375](https://github.com/FreshRSS/FreshRSS/issues/1375)
+
+
## 2016-11-02 FreshRSS 1.6.1
* Bug fixing
@@ -53,7 +74,7 @@
* Download icon 💾 for podcasts [#1236](https://github.com/FreshRSS/FreshRSS/issues/1236)
* SimplePie
* Fix auto-discovery of RSS feeds in Web pages served as `text/xml` [#1264](https://github.com/FreshRSS/FreshRSS/issues/1264)
-* Mics.
+* Misc.
* Removed *resource-priorities* attributes (`defer`, `lazyload`), deprecated by W3C [#1222](https://github.com/FreshRSS/FreshRSS/pull/1222)
diff --git a/CREDITS.md b/CREDITS.md
index 65c1318b3..827a8cfd3 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -1,5 +1,5 @@
This is a credit file of people who have [contributed to FreshRSS](https://github.com/FreshRSS/FreshRSS/graphs/contributors) with, at least,
-one commit on the FreshRSS repository (at https://github.com/FreshRSS/FreshRSS).
+one commit on one of the FreshRSS repositories (at https://github.com/FreshRSS).
Please note a commit on THIS specific file is not considered as a contribution
(too easy!). Its purpose is to show that even the smallest contribution is important.
People are sorted by name so please keep this order.
@@ -19,15 +19,19 @@ People are sorted by name so please keep this order.
* [hckweb](https://github.com/hckweb): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=hckweb)
* [Jaussoin Timothée](https://github.com/edhelas): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=edhelas), [Web](http://edhelas.movim.eu/)
* [Julien Reichardt](https://github.com/j8r): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=j8r), [Web](https://blog.jrei.ch/)
+* [Kevin Papst](https://github.com/kevinpapst): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=kevinpapst), [Web](http://www.kevinpapst.de/)
* [Luc Didry](https://github.com/ldidry): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=ldidry), [Web](https://www.fiat-tux.fr/)
* [marcomrc](https://github.com/marcomrc): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=marcomrc)
* [Marcus Rohrmoser](https://github.com/mro): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=mro), [Web](http://mro.name/~me)
* [Marien Fressinaud](https://github.com/marienfressinaud): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=marienfressinaud), [Web](http://marienfressinaud.fr/)
* [Melvyn Laïly](https://github.com/yaurthek): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=yaurthek), [Web](http://x2a.yt/)
* [Nicolas Elie](https://github.com/nicolaselie): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=nicolaselie)
+* [Nicolas Lœuillet](https://github.com/nicosomb): [contributions](https://github.com/FreshRSS/documentation/commits?author=nicosomb), [Web](http://www.loeuillet.org/)
* [plopoyop](https://github.com/plopoyop): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=plopoyop)
* [purexo](https://github.com/purexo): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:purexo), [Web](https://purexo.mom/)
+* [Quentin Dufour](https://github.com/superboum): [contributions](https://github.com/FreshRSS/documentation/commits?author=superboum), [Web](http://quentin.dufour.io/)
* [romibi](https://github.com/romibi): [contributions](https://github.com/FreshRSS/FreshRSS/commits/dev?author=romibi)
+* [subic](https://github.com/subic): [contributions](https://github.com/FreshRSS/documentation/commits?author=subic)
* [Tets42](https://github.com/Tets42): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=Tets42)
* [tomgue](https://github.com/tomgue): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=tomgue)
* [Wanabo](https://github.com/Wanabo): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=Wanabo)
diff --git a/README.fr.md b/README.fr.md
index 8efa983e3..b0b46bf65 100644
--- a/README.fr.md
+++ b/README.fr.md
@@ -8,6 +8,7 @@ Il se veut léger et facile à prendre en main tout en étant un outil puissant
Il permet de gérer plusieurs utilisateurs, et dispose d’un mode de lecture anonyme.
Il supporte [PubSubHubbub](https://code.google.com/p/pubsubhubbub/) pour des notifications instantanées depuis les sites compatibles.
Il y a une API pour les clients (mobiles), ainsi qu’une [interface en ligne de commande](./cli/README.md).
+Enfin, il permet l’ajout d’[extensions](#extensions) pour encore plus de personnalisation.
* Site officiel : http://freshrss.org
* Démo : http://demo.freshrss.org/
@@ -23,7 +24,7 @@ Voir la [liste des versions](../../releases).
* Pour ceux qui veulent bien aider à tester ou déveloper les dernières fonctionnalités, [la branche dev](https://github.com/FreshRSS/FreshRSS/tree/dev) vous ouvre les bras !
# Avertissements
-Cette application a été développée pour s’adapter principalement à des besoins personnels, et aucune garantie n'est fournie.
+Cette application a été développée pour s’adapter principalement à des besoins personnels, et aucune garantie n’est fournie.
Les demandes de fonctionnalités, rapports de bugs, et autres contributions sont les bienvenues. Privilégiez pour cela des [demandes sur GitHub](https://github.com/FreshRSS/FreshRSS/issues).
Nous sommes une communauté amicale.
@@ -85,13 +86,16 @@ sudo git checkout -b dev origin/dev
# Mettre les droits d’accès pour le serveur Web
sudo chown -R :www-data . && sudo chmod -R g+r . && sudo chmod -R g+w ./data/
+# Si vous souhaitez permettre les mises à jour par l’interface Web
+sudo chmod -R g+w .
+
# Publier FreshRSS dans votre répertoire HTML public
sudo ln -s /usr/share/FreshRSS/p /var/www/html/FreshRSS
# Naviguez vers http://example.net/FreshRSS pour terminer l’installation
# (Si vous le faite depuis localhost, vous pourrez avoir à ajuster le réglage de votre adresse publique)
# ou utilisez l’interface en ligne de commande
-# Mettre à jour FreshRSS vers une nouvelle version
+# Mettre à jour FreshRSS vers une nouvelle version par git
cd /usr/share/FreshRSS
sudo git pull
sudo chown -R :www-data . && sudo chmod -R g+r . && sudo chmod -R g+w ./data/
@@ -140,6 +144,11 @@ mysqldump -u utilisateur -p --databases freshrss > freshrss.sql
```
+# Extensions
+FreshRSS permet l’ajout d’extensions en plus des fonctionnalités natives.
+Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensions).
+
+
# Bibliothèques incluses
* [SimplePie](http://simplepie.org/)
* [MINZ](https://github.com/marienfressinaud/MINZ)
diff --git a/README.md b/README.md
index ecdd19376..64ced52c9 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@ It is at the same time lightweight, easy to work with, powerful and customizable
It is a multi-user application with an anonymous reading mode.
It supports [PubSubHubbub](https://code.google.com/p/pubsubhubbub/) for instant notifications from compatible Web sites.
There is an API for (mobile) clients, and a [Command-Line Interface](./cli/README.md).
+Finally, it supports [extensions](#extensions) for further tuning.
* Official website: http://freshrss.org
* Demo: http://demo.freshrss.org/
@@ -85,13 +86,16 @@ sudo git checkout -b dev origin/dev
# Set the rights so that your Web server can access the files
sudo chown -R :www-data . && sudo chmod -R g+r . && sudo chmod -R g+w ./data/
+# If you would like to allow updates from the Web interface
+sudo chmod -R g+w .
+
# Publish FreshRSS in your public HTML directory
sudo ln -s /usr/share/FreshRSS/p /var/www/html/FreshRSS
# Navigate to http://example.net/FreshRSS to complete the installation
# (If you do it from localhost, you may have to adjust the setting of your public address later)
# or use the Command-Line Interface
-# Update to a newer version of FreshRSS
+# Update to a newer version of FreshRSS with git
cd /usr/share/FreshRSS
sudo git pull
sudo chown -R :www-data . && sudo chmod -R g+r . && sudo chmod -R g+w ./data/
@@ -140,6 +144,11 @@ mysqldump -u user -p --databases freshrss > freshrss.sql
```
+# Extensions
+FreshRSS supports further customizations by adding extensions on top of its core functionality.
+See the [repository dedicated to those extensions](https://github.com/FreshRSS/Extensions).
+
+
# Included libraries
* [SimplePie](http://simplepie.org/)
* [MINZ](https://github.com/marienfressinaud/MINZ)
diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php
index 9decba431..1398e4e49 100644
--- a/app/Controllers/authController.php
+++ b/app/Controllers/authController.php
@@ -113,6 +113,10 @@ class FreshRSS_auth_Controller extends Minz_ActionController {
$file_mtime = @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js');
Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . $file_mtime));
+ $conf = Minz_Configuration::get('system');
+ $limits = $conf->limits;
+ $this->view->cookie_days = round($limits['cookie_duration'] / 86400, 1);
+
if (Minz_Request::isPost()) {
$nonce = Minz_Session::param('nonce');
$username = Minz_Request::param('username', '');
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index c4115584a..f71f26a4e 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -27,6 +27,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
}
public static function addFeed($url, $title = '', $cat_id = 0, $new_cat_name = '', $http_auth = '') {
+ FreshRSS_UserDAO::touch();
@set_time_limit(300);
$catDAO = new FreshRSS_CategoryDAO();
@@ -484,6 +485,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
if ($feed_id <= 0 || $feed_name == '') {
return false;
}
+ FreshRSS_UserDAO::touch();
$feedDAO = FreshRSS_Factory::createFeedDao();
return $feedDAO->updateFeed($feed_id, array('name' => $feed_name));
}
@@ -492,6 +494,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
if ($feed_id <= 0 || ($cat_id <= 0 && $new_cat_name == '')) {
return false;
}
+ FreshRSS_UserDAO::touch();
$catDAO = new FreshRSS_CategoryDAO();
if ($cat_id > 0) {
@@ -540,6 +543,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
}
public static function deleteFeed($feed_id) {
+ FreshRSS_UserDAO::touch();
$feedDAO = FreshRSS_Factory::createFeedDao();
if ($feedDAO->deleteFeed($feed_id)) {
// TODO: Delete old favicon
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 3ba91a243..6ae89defb 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -531,6 +531,8 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$this->entryDAO = FreshRSS_Factory::createEntryDao($username);
$this->feedDAO = FreshRSS_Factory::createFeedDao($username);
+ $this->entryDAO->disableBuffering();
+
if ($export_feeds === true) {
//All feeds
$export_feeds = $this->feedDAO->listFeedsIds();
@@ -641,13 +643,13 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$this->view->list_title = _t('sub.import_export.starred_list');
$this->view->type = 'starred';
$unread_fav = $this->entryDAO->countUnreadReadFavorites();
- $this->view->entries = $this->entryDAO->listWhere(
+ $this->view->entriesRaw = $this->entryDAO->listWhereRaw(
's', '', FreshRSS_Entry::STATE_ALL, 'ASC', $unread_fav['all']
);
} elseif ($type === 'feed' && $feed != null) {
$this->view->list_title = _t('sub.import_export.feed_list', $feed->name());
$this->view->type = 'feed/' . $feed->id();
- $this->view->entries = $this->entryDAO->listWhere(
+ $this->view->entriesRaw = $this->entryDAO->listWhereRaw(
'f', $feed->id(), FreshRSS_Entry::STATE_ALL, 'ASC',
$maxFeedEntries
);
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 64c984b04..8f939dbdb 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -2,6 +2,45 @@
class FreshRSS_update_Controller extends Minz_ActionController {
+ public static function isGit() {
+ return is_dir(FRESHRSS_PATH . '/.git/');
+ }
+
+ public static function hasGitUpdate() {
+ $cwd = getcwd();
+ chdir(FRESHRSS_PATH);
+ $output = array();
+ try {
+ exec('git fetch', $output, $return);
+ if ($return == 0) {
+ exec('git status -sb --porcelain remote', $output, $return);
+ } else {
+ $line = is_array($output) ? implode('; ', $output) : '' . $output;
+ Minz_Log::warning('git fetch warning:' . $line);
+ }
+ } catch (Exception $e) {
+ Minz_Log::warning('git fetch error:' . $e->getMessage());
+ }
+ chdir($cwd);
+ $line = is_array($output) ? implode('; ', $output) : '' . $output;
+ return strpos($line, '[behind') !== false;
+ }
+
+ public static function gitPull() {
+ $cwd = getcwd();
+ chdir(FRESHRSS_PATH);
+ $output = array();
+ $return = 1;
+ try {
+ exec('git pull --ff-only', $output, $return);
+ } catch (Exception $e) {
+ Minz_Log::warning('git pull error:' . $e->getMessage());
+ }
+ chdir($cwd);
+ $line = is_array($output) ? implode('; ', $output) : '' . $output;
+ return $return == 0 ? true : 'Git error: ' . $line;
+ }
+
public function firstAction() {
if (!FreshRSS_Auth::hasAccess('admin')) {
Minz_Error::error(403);
@@ -20,7 +59,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
public function indexAction() {
Minz_View::prependTitle(_t('admin.update.title') . ' · ');
- if (file_exists(UPDATE_FILENAME) && !is_writable(FRESHRSS_PATH)) {
+ if (!is_writable(FRESHRSS_PATH)) {
$this->view->message = array(
'status' => 'bad',
'title' => _t('gen.short.damn'),
@@ -53,49 +92,65 @@ class FreshRSS_update_Controller extends Minz_ActionController {
return;
}
- $auto_update_url = FreshRSS_Context::$system_conf->auto_update_url . '?v=' . FRESHRSS_VERSION;
- $c = curl_init($auto_update_url);
- curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
- curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
- $result = curl_exec($c);
- $c_status = curl_getinfo($c, CURLINFO_HTTP_CODE);
- $c_error = curl_error($c);
- curl_close($c);
-
- if ($c_status !== 200) {
- Minz_Log::warning(
- 'Error during update (HTTP code ' . $c_status . '): ' . $c_error
- );
+ $script = '';
+ $version = '';
- $this->view->message = array(
- 'status' => 'bad',
- 'title' => _t('gen.short.damn'),
- 'body' => _t('feedback.update.server_not_found', $auto_update_url)
- );
- return;
- }
-
- $res_array = explode("\n", $result, 2);
- $status = $res_array[0];
- if (strpos($status, 'UPDATE') !== 0) {
- $this->view->message = array(
- 'status' => 'bad',
- 'title' => _t('gen.short.damn'),
- 'body' => _t('feedback.update.none')
- );
+ if (self::isGit()) {
+ if (self::hasGitUpdate()) {
+ $version = 'git';
+ } else {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('gen.short.damn'),
+ 'body' => _t('feedback.update.none')
+ );
+ @touch(join_path(DATA_PATH, 'last_update.txt'));
+ return;
+ }
+ } else {
+ $auto_update_url = FreshRSS_Context::$system_conf->auto_update_url . '?v=' . FRESHRSS_VERSION;
+ Minz_Log::debug('HTTP GET ' . $auto_update_url);
+ $c = curl_init($auto_update_url);
+ curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
+ $result = curl_exec($c);
+ $c_status = curl_getinfo($c, CURLINFO_HTTP_CODE);
+ $c_error = curl_error($c);
+ curl_close($c);
+
+ if ($c_status !== 200) {
+ Minz_Log::warning(
+ 'Error during update (HTTP code ' . $c_status . '): ' . $c_error
+ );
+
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('gen.short.damn'),
+ 'body' => _t('feedback.update.server_not_found', $auto_update_url)
+ );
+ return;
+ }
- @touch(join_path(DATA_PATH, 'last_update.txt'));
+ $res_array = explode("\n", $result, 2);
+ $status = $res_array[0];
+ if (strpos($status, 'UPDATE') !== 0) {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('gen.short.damn'),
+ 'body' => _t('feedback.update.none')
+ );
+ @touch(join_path(DATA_PATH, 'last_update.txt'));
+ return;
+ }
- return;
+ $script = $res_array[1];
+ $version = explode(' ', $status, 2);
+ $version = $version[1];
}
- $script = $res_array[1];
if (file_put_contents(UPDATE_FILENAME, $script) !== false) {
- $version = explode(' ', $status, 2);
- $version = $version[1];
@file_put_contents(join_path(DATA_PATH, 'last_update.txt'), $version);
-
Minz_Request::forward(array('c' => 'update'), true);
} else {
$this->view->message = array(
@@ -111,10 +166,13 @@ class FreshRSS_update_Controller extends Minz_ActionController {
Minz_Request::forward(array('c' => 'update'), true);
}
- require(UPDATE_FILENAME);
-
if (Minz_Request::param('post_conf', false)) {
- $res = do_post_update();
+ if (self::isGit()) {
+ $res = !self::hasGitUpdate();
+ } else {
+ require(UPDATE_FILENAME);
+ $res = do_post_update();
+ }
Minz_ExtensionManager::callHook('post_update');
@@ -126,14 +184,21 @@ class FreshRSS_update_Controller extends Minz_ActionController {
Minz_Request::bad(_t('feedback.update.error', $res),
array('c' => 'update', 'a' => 'index'));
}
- }
-
- if (Minz_Request::isPost()) {
- save_info_update();
- }
+ } else {
+ $res = false;
- if (!need_info_update()) {
- $res = apply_update();
+ if (self::isGit()) {
+ $res = self::gitPull();
+ } else {
+ if (Minz_Request::isPost()) {
+ save_info_update();
+ }
+ if (!need_info_update()) {
+ $res = apply_update();
+ } else {
+ return;
+ }
+ }
if ($res === true) {
Minz_Request::forward(array(
diff --git a/app/Models/Auth.php b/app/Models/Auth.php
index b93942e19..b3255cfbd 100644
--- a/app/Models/Auth.php
+++ b/app/Models/Auth.php
@@ -25,7 +25,7 @@ class FreshRSS_Auth {
self::giveAccess();
} elseif (self::accessControl()) {
self::giveAccess();
- FreshRSS_UserDAO::touch($current_user);
+ FreshRSS_UserDAO::touch();
} else {
// Be sure all accesses are removed!
self::removeAccess();
@@ -219,8 +219,8 @@ class FreshRSS_FormAuth {
}
public static function makeCookie($username, $password_hash) {
+ $conf = Minz_Configuration::get('system');
do {
- $conf = Minz_Configuration::get('system');
$token = sha1($conf->salt . $username . uniqid(mt_rand(), true));
$token_file = DATA_PATH . '/tokens/' . $token . '.txt';
} while (file_exists($token_file));
@@ -229,15 +229,17 @@ class FreshRSS_FormAuth {
return false;
}
- $expire = time() + 2629744; //1 month //TODO: Use a configuration instead
+ $limits = $conf->limits;
+ $cookie_duration = empty($limits['cookie_duration']) ? 2629744 : $limits['cookie_duration'];
+ $expire = time() + $cookie_duration;
Minz_Session::setLongTermCookie('FreshRSS_login', $token, $expire);
return $token;
}
public static function deleteCookie() {
$token = Minz_Session::getLongTermCookie('FreshRSS_login');
- Minz_Session::deleteLongTermCookie('FreshRSS_login');
if (ctype_alnum($token)) {
+ Minz_Session::deleteLongTermCookie('FreshRSS_login');
@unlink(DATA_PATH . '/tokens/' . $token . '.txt');
}
@@ -247,7 +249,10 @@ class FreshRSS_FormAuth {
}
public static function purgeTokens() {
- $oldest = time() - 2629744; // 1 month // TODO: Use a configuration instead
+ $conf = Minz_Configuration::get('system');
+ $limits = $conf->limits;
+ $cookie_duration = empty($limits['cookie_duration']) ? 2629744 : $limits['cookie_duration'];
+ $oldest = time() - $cookie_duration;
foreach (new DirectoryIterator(DATA_PATH . '/tokens/') as $file_info) {
// $extension = $file_info->getExtension(); doesn't work in PHP < 5.3.7
$extension = pathinfo($file_info->getFilename(), PATHINFO_EXTENSION);
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index 58f2c1a79..397471baa 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -241,6 +241,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
if (count($ids) < 1) {
return 0;
}
+ FreshRSS_UserDAO::touch();
$sql = 'UPDATE `' . $this->prefix . 'entry` '
. 'SET is_favorite=? '
. 'WHERE id IN (' . str_repeat('?,', count($ids) - 1). '?)';
@@ -315,6 +316,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
* @return integer affected rows
*/
public function markRead($ids, $is_read = true) {
+ FreshRSS_UserDAO::touch();
if (is_array($ids)) { //Many IDs at once (used by API)
if (count($ids) < 6) { //Speed heuristics
$affected = 0;
@@ -379,6 +381,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
* @return integer affected rows
*/
public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0, $filter = null, $state = 0) {
+ FreshRSS_UserDAO::touch();
if ($idMax == 0) {
$idMax = time() . '000000';
Minz_Log::debug('Calling markReadEntries(0) is deprecated!');
@@ -421,6 +424,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
* @return integer affected rows
*/
public function markReadCat($id, $idMax = 0, $filter = null, $state = 0) {
+ FreshRSS_UserDAO::touch();
if ($idMax == 0) {
$idMax = time() . '000000';
Minz_Log::debug('Calling markReadCat(0) is deprecated!');
@@ -458,6 +462,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
* @return integer affected rows
*/
public function markReadFeed($id_feed, $idMax = 0, $filter = null, $state = 0) {
+ FreshRSS_UserDAO::touch();
if ($idMax == 0) {
$idMax = time() . '000000';
Minz_Log::debug('Calling markReadFeed(0) is deprecated!');
@@ -513,7 +518,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$stm->execute($values);
$res = $stm->fetchAll(PDO::FETCH_ASSOC);
- $entries = self::daoToEntry($res);
+ $entries = self::daoToEntries($res);
return isset($entries[0]) ? $entries[0] : null;
}
@@ -528,7 +533,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$stm->execute($values);
$res = $stm->fetchAll(PDO::FETCH_ASSOC);
- $entries = self::daoToEntry($res);
+ $entries = self::daoToEntries($res);
return isset($entries[0]) ? $entries[0] : null;
}
@@ -661,7 +666,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
. ($limit > 0 ? ' LIMIT ' . $limit : '')); //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/
}
- public function listWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) {
+ public function listWhereRaw($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) {
list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min);
$sql = 'SELECT e0.id, e0.guid, e0.title, e0.author, '
@@ -675,8 +680,12 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$stm = $this->bd->prepare($sql);
$stm->execute($values);
+ return $stm;
+ }
- return self::daoToEntry($stm->fetchAll(PDO::FETCH_ASSOC));
+ public function listWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) {
+ $stm = $this->listWhereRaw($type, $id, $state, $order, $limit, $firstId, $filter, $date_min);
+ return self::daoToEntries($stm->fetchAll(PDO::FETCH_ASSOC));
}
public function listIdsWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) { //For API
@@ -805,15 +814,8 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return $res[0];
}
- public static function daoToEntry($listDAO) {
- $list = array();
-
- if (!is_array($listDAO)) {
- $listDAO = array($listDAO);
- }
-
- foreach ($listDAO as $key => $dao) {
- $entry = new FreshRSS_Entry(
+ public static function daoToEntry($dao) {
+ $entry = new FreshRSS_Entry(
$dao['id_feed'],
$dao['guid'],
$dao['title'],
@@ -825,10 +827,21 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
$dao['is_favorite'],
$dao['tags']
);
- if (isset($dao['id'])) {
- $entry->_id($dao['id']);
- }
- $list[] = $entry;
+ if (isset($dao['id'])) {
+ $entry->_id($dao['id']);
+ }
+ return $entry;
+ }
+
+ private static function daoToEntries($listDAO) {
+ $list = array();
+
+ if (!is_array($listDAO)) {
+ $listDAO = array($listDAO);
+ }
+
+ foreach ($listDAO as $key => $dao) {
+ $list[] = self::daoToEntry($dao);
}
unset($listDAO);
diff --git a/app/Models/Factory.php b/app/Models/Factory.php
index 764987c46..6502c38b7 100644
--- a/app/Models/Factory.php
+++ b/app/Models/Factory.php
@@ -6,6 +6,7 @@ class FreshRSS_Factory {
$conf = Minz_Configuration::get('system');
switch ($conf->db['type']) {
case 'sqlite':
+ case 'pgsql':
return new FreshRSS_FeedDAOSQLite($username);
default:
return new FreshRSS_FeedDAO($username);
diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php
index a95ee6bc4..32bc6de2f 100644
--- a/app/Models/UserDAO.php
+++ b/app/Models/UserDAO.php
@@ -84,7 +84,10 @@ class FreshRSS_UserDAO extends Minz_ModelPdo {
return is_dir(join_path(DATA_PATH , 'users', $username));
}
- public static function touch($username) {
+ public static function touch($username = '') {
+ if (($username == '') || (!ctype_alnum($username))) {
+ $username = Minz_Session::param('currentUser', '_');
+ }
return touch(join_path(DATA_PATH , 'users', $username, 'config.php'));
}
diff --git a/app/i18n/cz/admin.php b/app/i18n/cz/admin.php
index 84bc58a17..63cee3cca 100644
--- a/app/i18n/cz/admin.php
+++ b/app/i18n/cz/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'Tabulka kanálů je nastavena špatně.',
'ok' => 'Tabulka kanálů je v pořádku.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Nemáte PHP fileinfo (balíček fileinfo).',
+ 'ok' => 'Máte rozšíření fileinfo.',
+ ),
'files' => 'Instalace souborů',
'json' => array(
'nok' => 'Nemáte JSON (balíček php5-json).',
diff --git a/app/i18n/cz/gen.php b/app/i18n/cz/gen.php
index e73325c55..3db3a31da 100644
--- a/app/i18n/cz/gen.php
+++ b/app/i18n/cz/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Email',
- 'keep_logged_in' => 'Zapamatovat přihlášení <small>(1 měsíc)</small>',
+ 'keep_logged_in' => 'Zapamatovat přihlášení <small>(%s dny)</small>',
'login' => 'Login',
'logout' => 'Odhlášení',
'password' => array(
diff --git a/app/i18n/cz/install.php b/app/i18n/cz/install.php
index c40ae46e2..ea4812ea5 100644
--- a/app/i18n/cz/install.php
+++ b/app/i18n/cz/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Zkontrolujte oprávnění adresáře <em>./data/favicons</em>. HTTP server musí mít do tohoto adresáře práva zápisu',
'ok' => 'Oprávnění adresáře favicons jsou v pořádku.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Nemáte PHP fileinfo (balíček fileinfo).',
+ 'ok' => 'Máte rozšíření fileinfo.',
+ ),
'http_referer' => array(
'nok' => 'Zkontrolujte prosím že neměníte HTTP REFERER.',
'ok' => 'Váš HTTP REFERER je znám a odpovídá Vašemu serveru.',
diff --git a/app/i18n/de/admin.php b/app/i18n/de/admin.php
index c12f32bc8..8fc43a7bb 100644
--- a/app/i18n/de/admin.php
+++ b/app/i18n/de/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'Die Tabelle <em>feed</em> ist schlecht konfiguriert.',
'ok' => 'Die Tabelle <em>feed</em> ist korrekt konfiguriert.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Ihnen fehlt PHP fileinfo (Paket fileinfo).',
+ 'ok' => 'Sie haben die fileinfo-Erweiterung.',
+ ),
'files' => 'Datei-Installation',
'json' => array(
'nok' => 'Ihnen fehlt die JSON-Erweiterung (Paket php5-json).',
diff --git a/app/i18n/de/gen.php b/app/i18n/de/gen.php
index c6e7f1ef3..c73aedbfe 100644
--- a/app/i18n/de/gen.php
+++ b/app/i18n/de/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'E-Mail-Adresse',
- 'keep_logged_in' => 'Eingeloggt bleiben <small>(1 Monat)</small>',
+ 'keep_logged_in' => 'Eingeloggt bleiben <small>(%s Tage)</small>',
'login' => 'Anmelden',
'logout' => 'Abmelden',
'password' => array(
diff --git a/app/i18n/de/install.php b/app/i18n/de/install.php
index 178e8ea4c..b747d1551 100644
--- a/app/i18n/de/install.php
+++ b/app/i18n/de/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Überprüfen Sie die Berechtigungen des Verzeichnisses <em>./data/favicons</em>. Der HTTP-Server muss Schreibrechte besitzen.',
'ok' => 'Die Berechtigungen des Verzeichnisses <em>./data/favicons</em> sind in Ordnung.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Ihnen fehlt PHP fileinfo (Paket fileinfo).',
+ 'ok' => 'Sie haben die fileinfo-Erweiterung.',
+ ),
'http_referer' => array(
'nok' => 'Bitte stellen Sie sicher, dass Sie Ihren HTTP REFERER nicht abändern.',
'ok' => 'Ihr HTTP REFERER ist bekannt und entspricht Ihrem Server.',
diff --git a/app/i18n/en/admin.php b/app/i18n/en/admin.php
index e5286d948..e94d9fa80 100644
--- a/app/i18n/en/admin.php
+++ b/app/i18n/en/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'Feed table is bad configured.',
'ok' => 'Feed table is ok.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',
+ 'ok' => 'You have the fileinfo library.',
+ ),
'files' => 'File installation',
'json' => array(
'nok' => 'Cannot find JSON (php5-json package).',
diff --git a/app/i18n/en/gen.php b/app/i18n/en/gen.php
index 17b47ba2f..3f86cfd19 100644
--- a/app/i18n/en/gen.php
+++ b/app/i18n/en/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Email address',
- 'keep_logged_in' => 'Keep me logged in <small>(1 month)</small>',
+ 'keep_logged_in' => 'Keep me logged in <small>(%s days)</small>',
'login' => 'Login',
'logout' => 'Logout',
'password' => array(
diff --git a/app/i18n/en/install.php b/app/i18n/en/install.php
index 63d31fe53..40fff37dd 100644
--- a/app/i18n/en/install.php
+++ b/app/i18n/en/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have rights to write into',
'ok' => 'Permissions on favicons directory are good.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',
+ 'ok' => 'You have the fileinfo library.',
+ ),
'http_referer' => array(
'nok' => 'Please check that you are not altering your HTTP REFERER.',
'ok' => 'Your HTTP REFERER is known and corresponds to your server.',
diff --git a/app/i18n/fr/admin.php b/app/i18n/fr/admin.php
index e9263a5e2..9a13ecc21 100644
--- a/app/i18n/fr/admin.php
+++ b/app/i18n/fr/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'La table feed est mal configurée.',
'ok' => 'La table feed est bien configurée.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Impossible de trouver la librairie PHP fileinfo (paquet fileinfo).',
+ 'ok' => 'Vous disposez de la librairie fileinfo.',
+ ),
'files' => 'Installation des fichiers',
'json' => array(
'nok' => 'Vous ne disposez pas de JSON (paquet php5-json).',
diff --git a/app/i18n/fr/gen.php b/app/i18n/fr/gen.php
index d61a716a7..b5dc098ae 100644
--- a/app/i18n/fr/gen.php
+++ b/app/i18n/fr/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Adresse courriel',
- 'keep_logged_in' => 'Rester connecté <small>(1 mois)</small>',
+ 'keep_logged_in' => 'Rester connecté <small>(%s jours)</small>',
'login' => 'Connexion',
'logout' => 'Déconnexion',
'password' => array(
diff --git a/app/i18n/fr/install.php b/app/i18n/fr/install.php
index c50807107..09625de78 100644
--- a/app/i18n/fr/install.php
+++ b/app/i18n/fr/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Veuillez vérifier les droits sur le répertoire <em>./data/favicons</em>. Le serveur HTTP doit être capable d’écrire dedans',
'ok' => 'Les droits sur le répertoire des favicons sont bons.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Vous ne disposez pas de PHP fileinfo (paquet fileinfo).',
+ 'ok' => 'Vous disposez de fileinfo.',
+ ),
'http_referer' => array(
'nok' => 'Veuillez vérifier que vous ne modifiez pas votre HTTP REFERER.',
'ok' => 'Le HTTP REFERER est connu et semble correspondre à votre serveur.',
diff --git a/app/i18n/it/admin.php b/app/i18n/it/admin.php
index c399bc8c8..ae46818ae 100644
--- a/app/i18n/it/admin.php
+++ b/app/i18n/it/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'La tabella Feed ha una configurazione errata.',
'ok' => 'Tabella Feed OK.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Manca il supporto per PHP fileinfo (pacchetto fileinfo).',
+ 'ok' => 'Estensione fileinfo presente.',
+ ),
'files' => 'Installazione files',
'json' => array(
'nok' => 'Manca il supoorto a JSON (pacchetto php5-json).',
diff --git a/app/i18n/it/gen.php b/app/i18n/it/gen.php
index c02ddd13a..a9a8709d3 100644
--- a/app/i18n/it/gen.php
+++ b/app/i18n/it/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Indirizzo email',
- 'keep_logged_in' => 'Ricorda i dati <small>(1 mese)</small>',
+ 'keep_logged_in' => 'Ricorda i dati <small>(%s giorni)</small>',
'login' => 'Accedi',
'logout' => 'Esci',
'password' => array(
diff --git a/app/i18n/it/install.php b/app/i18n/it/install.php
index 2fa298508..18f8cc337 100644
--- a/app/i18n/it/install.php
+++ b/app/i18n/it/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Verifica i permessi sulla cartella <em>./data/favicons</em>. Il server HTTP deve avere i permessi per scriverci dentro',
'ok' => 'I permessi sulla cartella favicons sono corretti.',
),
+ 'fileinfo' => array(
+ 'nok' => 'Manca il supporto per PHP fileinfo (pacchetto fileinfo).',
+ 'ok' => 'Estensione fileinfo presente.',
+ ),
'http_referer' => array(
'nok' => 'Per favore verifica che non stai alterando il tuo HTTP REFERER.',
'ok' => 'Il tuo HTTP REFERER riconosciuto corrisponde al tuo server.',
diff --git a/app/i18n/nl/admin.php b/app/i18n/nl/admin.php
index 59637bfef..607fb1892 100644
--- a/app/i18n/nl/admin.php
+++ b/app/i18n/nl/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'Feed tabel is slecht geconfigureerd.',
'ok' => 'Feed tabel is ok.',
),
+ 'fileinfo' => array(
+ 'nok' => 'U mist de PHP fileinfo (fileinfo package).',
+ 'ok' => 'U hebt de fileinfo uitbreiding.',
+ ),
'files' => 'Bestanden installatie',
'json' => array(
'nok' => 'U mist JSON (php5-json package).',
diff --git a/app/i18n/nl/gen.php b/app/i18n/nl/gen.php
index 7e03229c9..83811ce68 100644
--- a/app/i18n/nl/gen.php
+++ b/app/i18n/nl/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Email adres',
- 'keep_logged_in' => 'Ingelogd blijven voor <small>(1 maand)</small>',
+ 'keep_logged_in' => 'Ingelogd blijven voor <small>(%s dagen)</small>',
'login' => 'Log in',
'logout' => 'Log uit',
'password' => array(
diff --git a/app/i18n/nl/install.php b/app/i18n/nl/install.php
index bd2ba0cce..79db9c794 100644
--- a/app/i18n/nl/install.php
+++ b/app/i18n/nl/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Controleer permissies van de <em>./data/favicons</em> map. HTTP server moet rechten hebben om er in te kunnen schrijven',
'ok' => 'Permissies van de favicons map zijn goed.',
),
+ 'fileinfo' => array(
+ 'nok' => 'U mist PHP fileinfo (fileinfo package).',
+ 'ok' => 'U hebt de fileinfo uitbreiding.',
+ ),
'http_referer' => array(
'nok' => 'Controleer a.u.b. dat u niet uw HTTP REFERER wijzigd.',
'ok' => 'Uw HTTP REFERER is bekend en komt overeen met uw server.',
diff --git a/app/i18n/ru/admin.php b/app/i18n/ru/admin.php
index 355100689..f5da97371 100644
--- a/app/i18n/ru/admin.php
+++ b/app/i18n/ru/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'Таблица подписок (feed) неправильно настроена.',
'ok' => 'Таблица подписок (feed) настроена правильно.',
),
+ 'fileinfo' => array(
+ 'nok' => 'У вас не установлено расширение PHP fileinfo (пакет fileinfo).',
+ 'ok' => 'У вас установлено расширение fileinfo.',
+ ),
'files' => 'Установка файлов',
'json' => array(
'nok' => 'У вас не установлена библиотека для работы с JSON (пакет php5-json).',
diff --git a/app/i18n/ru/gen.php b/app/i18n/ru/gen.php
index eecd72749..bc42afaa8 100644
--- a/app/i18n/ru/gen.php
+++ b/app/i18n/ru/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Email address',
- 'keep_logged_in' => 'Keep me logged in <small>(1 month)</small>',
+ 'keep_logged_in' => 'Keep me logged in <small>(%s дней)</small>',
'login' => 'Login',
'logout' => 'Logout',
'password' => array(
diff --git a/app/i18n/ru/install.php b/app/i18n/ru/install.php
index bad59bbb3..1dea2cd66 100644
--- a/app/i18n/ru/install.php
+++ b/app/i18n/ru/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => 'Проверьте права доступа к папке <em>./data/favicons</em> . Сервер HTTP должен иметь права на запись в эту папку.',
'ok' => 'Права на папку значков в порядке.',
),
+ 'fileinfo' => array(
+ 'nok' => 'У вас нет расширения PHP fileinfo (пакет fileinfo).',
+ 'ok' => 'У вас установлено расширение fileinfo.',
+ ),
'http_referer' => array(
'nok' => 'Убедитесь, что вы не изменяете ваш HTTP REFERER.',
'ok' => 'Ваш HTTP REFERER известен и соотвествует вашему серверу.',
diff --git a/app/i18n/tr/admin.php b/app/i18n/tr/admin.php
index e0dbd288d..9d10ef9dd 100644
--- a/app/i18n/tr/admin.php
+++ b/app/i18n/tr/admin.php
@@ -57,6 +57,10 @@ return array(
'nok' => 'Akış tablosu kötü yapılandırılmış.',
'ok' => 'Akış tablosu sorunsuz.',
),
+ 'fileinfo' => array(
+ 'nok' => 'PHP fileinfo eksik (fileinfo package).',
+ 'ok' => 'fileinfo eklentisi sorunsuz.',
+ ),
'files' => 'Dosya kurulumu',
'json' => array(
'nok' => 'JSON eklentisi eksik (php5-json package).',
diff --git a/app/i18n/tr/gen.php b/app/i18n/tr/gen.php
index 865dbd4e2..bcc839daf 100644
--- a/app/i18n/tr/gen.php
+++ b/app/i18n/tr/gen.php
@@ -22,7 +22,7 @@ return array(
),
'auth' => array(
'email' => 'Email adresleri',
- 'keep_logged_in' => '<small>(1 ay)</small> oturumu açık tut',
+ 'keep_logged_in' => '<small>(%s günler)</small> oturumu açık tut',
'login' => 'Giriş',
'logout' => 'Çıkış',
'password' => array(
diff --git a/app/i18n/tr/install.php b/app/i18n/tr/install.php
index 4daa45099..d5564297b 100644
--- a/app/i18n/tr/install.php
+++ b/app/i18n/tr/install.php
@@ -56,6 +56,10 @@ return array(
'nok' => '<em>./data/favicons</em> klasör yetkisini kontrol edin. HTTP yazma yetkisi olmalı',
'ok' => 'Site ikonu klasörü yetkileri sorunsuz.',
),
+ 'fileinfo' => array(
+ 'nok' => 'PHP fileinfo eksik (fileinfo package).',
+ 'ok' => 'fileinfo eklentisi sorunsuz.',
+ ),
'http_referer' => array(
'nok' => 'Lütfen HTTP REFERER değiştirmediğinize emin olun.',
'ok' => 'HTTP REFERER ve sunucunuz arası iletişim sorunsuz.',
diff --git a/app/install.php b/app/install.php
index fcc901713..986a7dc60 100644
--- a/app/install.php
+++ b/app/install.php
@@ -230,7 +230,7 @@ function saveStep3() {
$_SESSION['bd_error'] = '';
header('Location: index.php?step=4');
} else {
- $_SESSION['bd_error'] = empty($config_array['db']['bd_error']) ? 'Unknown error!' : $config_array['db']['bd_error'];
+ $_SESSION['bd_error'] = empty($config_array['db']['error']) ? 'Unknown error!' : $config_array['db']['error'];
}
}
invalidateHttpCache();
@@ -375,7 +375,7 @@ function checkDbUser(&$dbOptions) {
}
} catch (PDOException $e) {
$ok = false;
- $dbOptions['bd_error'] = $e->getMessage();
+ $dbOptions['error'] = $e->getMessage();
}
return $ok;
}
@@ -478,6 +478,12 @@ function printStep1() {
<p class="alert alert-error"><span class="alert-head"><?php echo _t('gen.short.damn'); ?></span> <?php echo _t('install.check.xml.nok'); ?></p>
<?php } ?>
+ <?php if ($res['fileinfo'] == 'ok') { ?>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('gen.short.ok'); ?></span> <?php echo _t('install.check.fileinfo.ok'); ?></p>
+ <?php } else { ?>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('gen.short.damn'); ?></span> <?php echo _t('install.check.fileinfo.nok'); ?></p>
+ <?php } ?>
+
<?php if ($res['data'] == 'ok') { ?>
<p class="alert alert-success"><span class="alert-head"><?php echo _t('gen.short.ok'); ?></span> <?php echo _t('install.check.data.ok'); ?></p>
<?php } else { ?>
@@ -634,7 +640,7 @@ function printStep3() {
<div class="form-group">
<label class="group-name" for="host"><?php echo _t('install.bdd.host'); ?></label>
<div class="group-controls">
- <input type="text" id="host" name="host" pattern="[0-9A-Za-z_.-]{1,64}(:[0-9]{2,5})?" value="<?php echo isset($_SESSION['bd_host']) ? $_SESSION['bd_host'] : $system_default_config->db['host']; ?>" tabindex="2" />
+ <input type="text" id="host" name="host" pattern="[0-9A-Z/a-z_.-]{1,64}(:[0-9]{2,5})?" value="<?php echo isset($_SESSION['bd_host']) ? $_SESSION['bd_host'] : $system_default_config->db['host']; ?>" tabindex="2" />
</div>
</div>
diff --git a/app/views/auth/formLogin.phtml b/app/views/auth/formLogin.phtml
index 4bbc8ed55..a8213b7ae 100644
--- a/app/views/auth/formLogin.phtml
+++ b/app/views/auth/formLogin.phtml
@@ -20,7 +20,7 @@
<div>
<label class="checkbox" for="keep_logged_in">
<input type="checkbox" name="keep_logged_in" id="keep_logged_in" value="1" />
- <?php echo _t('gen.auth.keep_logged_in'); ?>
+ <?php echo _t('gen.auth.keep_logged_in', $this->cookie_days); ?>
</label>
<br />
</div>
diff --git a/app/views/helpers/export/articles.phtml b/app/views/helpers/export/articles.phtml
index ffdca1daa..49c370023 100644
--- a/app/views/helpers/export/articles.phtml
+++ b/app/views/helpers/export/articles.phtml
@@ -1,47 +1,66 @@
<?php
- $username = Minz_Session::param('currentUser', '_');
+$username = Minz_Session::param('currentUser', '_');
- $articles = array(
- 'id' => 'user/' . str_replace('/', '', $username) . '/state/org.freshrss/' . $this->type,
- 'title' => $this->list_title,
- 'author' => $username,
- 'items' => array()
- );
+$options = 0;
+if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
+ $options = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
+}
- foreach ($this->entries as $entry) {
- if (!isset($this->feed)) {
- $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $entry->feed ());
- } else {
- $feed = $this->feed;
- }
+$articles = array(
+ 'id' => 'user/' . str_replace('/', '', $username) . '/state/org.freshrss/' . $this->type,
+ 'title' => $this->list_title,
+ 'author' => $username,
+ 'items' => array(),
+);
- $articles['items'][] = array(
- 'id' => $entry->guid(),
- 'categories' => array_values($entry->tags()),
- 'title' => $entry->title(),
- 'author' => $entry->author(),
- 'published' => $entry->date(true),
- 'updated' => $entry->date(true),
- 'alternate' => array(array(
- 'href' => $entry->link(),
- 'type' => 'text/html'
- )),
- 'content' => array(
- 'content' => $entry->content()
- ),
- 'origin' => array(
- 'streamId' => $feed->id(),
- 'title' => $feed->name(),
- 'htmlUrl' => $feed->website(),
- 'feedUrl' => $feed->url()
- )
- );
- }
+echo rtrim(json_encode($articles, $options), " ]}\n\r\t"), "\n";
+$first = true;
- $options = 0;
- if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
- $options = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
- }
+foreach ($this->entriesRaw as $entryRaw) {
+ if (empty($entryRaw)) {
+ continue;
+ }
+ $entry = FreshRSS_EntryDAO::daoToEntry($entryRaw);
+ if (!isset($this->feed)) {
+ $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $entry->feed());
+ if ($feed == null) {
+ $feed = $entry->feed(true);
+ }
+ } else {
+ $feed = $this->feed;
+ }
- echo json_encode($articles, $options);
-?>
+ $article = array(
+ 'id' => $entry->guid(),
+ 'categories' => array_values($entry->tags()),
+ 'title' => $entry->title(),
+ 'author' => $entry->author(),
+ 'published' => $entry->date(true),
+ 'updated' => $entry->date(true),
+ 'alternate' => array(array(
+ 'href' => $entry->link(),
+ 'type' => 'text/html',
+ )),
+ 'content' => array(
+ 'content' => $entry->content(),
+ ),
+ 'origin' => array(
+ 'streamId' => $feed == null ? '' : $feed->id(),
+ 'title' => $feed == null ? '' : $feed->name(),
+ 'htmlUrl' => $feed == null ? '' : $feed->website(),
+ 'feedUrl' => $feed == null ? '' : $feed->url(),
+ )
+ );
+
+ $line = json_encode($article, $options);
+ if ($line != '') {
+ if ($first) {
+ $first = false;
+ } else {
+ echo ",\n";
+ }
+ echo $line;
+ }
+}
+
+echo "\n]}\n";
diff --git a/cli/README.md b/cli/README.md
index 444606b50..e4d3409a2 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -32,11 +32,11 @@ Options in parenthesis are optional.
```sh
cd /usr/share/FreshRSS
-./cli/do-install.php --default_user admin --auth_type form ( --environment production --base_url https://rss.example.net/ --title FreshRSS --allow_anonymous --api_enabled --db-type mysql --db-host localhost:3306 --db-user freshrss --db-password dbPassword123 --db-base freshrss --db-prefix freshrss )
-# --auth_type can be: 'form' (recommended), 'http_auth' (using the Web server access control), 'none' (dangerous)
+./cli/do-install.php --default_user admin ( --auth_type form --environment production --base_url https://rss.example.net/ --title FreshRSS --allow_anonymous --api_enabled --db-type mysql --db-host localhost:3306 --db-user freshrss --db-password dbPassword123 --db-base freshrss --db-prefix freshrss )
+# --auth_type can be: 'form' (default), 'http_auth' (using the Web server access control), 'none' (dangerous)
# --db-type can be: 'sqlite' (default), 'mysql' (MySQL or MariaDB), 'pgsql' (PostgreSQL)
# --environment can be: 'production' (default), 'development' (for additional log messages)
-# --db-prefix is an optional prefix in front of the names of the tables
+# --db-prefix is an optional prefix in front of the names of the tables. We suggest using 'freshrss_'
# This command does not create the default user. Do that with ./cli/create-user.php
./cli/create-user.php --user username ( --password 'password' --api-password 'api_password' --language en --email user@example.net --token 'longRandomString' --no-default-feeds )
@@ -55,4 +55,26 @@ cd /usr/share/FreshRSS
./cli/export-opml-for-user.php --user username > /path/to/file.opml.xml
./cli/export-zip-for-user.php --user username ( --max-feed-entries 100 ) > /path/to/file.zip
+
+./cli/user-info.php -h --user username
+# -h is to use a human-readable format
+# --user can be a username, or '*' to loop on all users
+# Returns a * if the user is admin, the name of the user, the date/time of last action, and the size occupied
+```
+
+
+## Unix piping
+
+It is possible to invoke a command multiple times, e.g. with different usernames, thanks to the `xargs -n1` command.
+
+Example showing user information for all users which username starts with 'a':
+
+```sh
+./cli/list-users.php | grep '^a' | xargs -n1 ./cli/user-info.php -h --user
+```
+
+Example showing all users ranked by date of last activity:
+
+```sh
+./cli/user-info.php -h --user '*' | sort -k2 -r
```
diff --git a/cli/create-user.php b/cli/create-user.php
index 008b82ce3..444264cc7 100755
--- a/cli/create-user.php
+++ b/cli/create-user.php
@@ -43,6 +43,9 @@ if (!$ok) {
invalidateHttpCache(FreshRSS_Context::$system_conf->default_user);
+echo '• Remember to refresh the feeds of the user: ', $username , "\n",
+ "\t", './cli/actualize-user.php --user ', $username, "\n";
+
accessRights();
done($ok);
diff --git a/cli/do-install.php b/cli/do-install.php
index 667191680..100d4947f 100755
--- a/cli/do-install.php
+++ b/cli/do-install.php
@@ -26,12 +26,12 @@ $dBparams = array(
$options = getopt('', array_merge($params, $dBparams));
-if (empty($options['default_user']) || empty($options['auth_type'])) {
- fail('Usage: ' . basename(__FILE__) . " --default_user admin --auth_type form" .
- " ( --environment production --base_url https://rss.example.net/" .
+if (empty($options['default_user'])) {
+ fail('Usage: ' . basename(__FILE__) . " --default_user admin ( --auth_type form" .
+ " --environment production --base_url https://rss.example.net/" .
" --title FreshRSS --allow_anonymous --api_enabled" .
" --db-type mysql --db-host localhost:3306 --db-user freshrss --db-password dbPassword123" .
- " --db-base freshrss --db-prefix freshrss )");
+ " --db-base freshrss --db-prefix freshrss_ )");
}
fwrite(STDERR, 'FreshRSS install…' . "\n");
@@ -51,7 +51,7 @@ if (!ctype_alnum($options['default_user'])) {
fail('FreshRSS invalid default username (must be ASCII alphanumeric): ' . $options['default_user']);
}
-if (!in_array($options['auth_type'], array('form', 'http_auth', 'none'))) {
+if (isset($options['auth_type']) && !in_array($options['auth_type'], array('form', 'http_auth', 'none'))) {
fail('FreshRSS invalid authentication method (auth_type must be one of { form, http_auth, none }: ' . $options['auth_type']);
}
@@ -86,11 +86,11 @@ if (file_put_contents(join_path(DATA_PATH, 'config.php'), "<?php\n return " . va
$config['db']['default_user'] = $config['default_user'];
if (!checkDb($config['db'])) {
@unlink(join_path(DATA_PATH, 'config.php'));
- fail('FreshRSS database error: ' . (empty($config['db']['bd_error']) ? 'Unknown error' : $config['db']['bd_error']));
+ fail('FreshRSS database error: ' . (empty($config['db']['error']) ? 'Unknown error' : $config['db']['error']));
}
echo '• Remember to create the default user: ', $config['default_user'] , "\n",
- "\t", './cli/create-user.php --user ', $config['default_user'] , " --password 'password' --more-options\n";
+ "\t", './cli/create-user.php --user ', $config['default_user'], " --password 'password' --more-options\n";
accessRights();
diff --git a/cli/user-info.php b/cli/user-info.php
new file mode 100755
index 000000000..dd38e6c7f
--- /dev/null
+++ b/cli/user-info.php
@@ -0,0 +1,35 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('h', array(
+ 'user:',
+ ));
+
+if (empty($options['user'])) {
+ fail('Usage: ' . basename(__FILE__) . " -h --user username");
+}
+
+$users = $options['user'] === '*' ? listUsers() : array($options['user']);
+
+foreach ($users as $username) {
+ $username = cliInitUser($username);
+
+ $entryDAO = FreshRSS_Factory::createEntryDao($username);
+
+ echo $username === FreshRSS_Context::$system_conf->default_user ? '*' : ' ', "\t";
+
+ if (isset($options['h'])) { //Human format
+ echo
+ $username, "\t",
+ date('c', FreshRSS_UserDAO::mtime($username)), "\t",
+ format_bytes($entryDAO->size()), "\t",
+ "\n";
+ } else {
+ echo
+ $username, "\t",
+ FreshRSS_UserDAO::mtime($username), "\t",
+ $entryDAO->size(), "\t",
+ "\n";
+ }
+}
diff --git a/constants.php b/constants.php
index e5ae3ff00..cb00839e2 100644
--- a/constants.php
+++ b/constants.php
@@ -1,5 +1,5 @@
<?php
-define('FRESHRSS_VERSION', '1.6.1');
+define('FRESHRSS_VERSION', '1.6.2');
define('FRESHRSS_WEBSITE', 'http://freshrss.org');
define('FRESHRSS_WIKI', 'http://doc.freshrss.org');
diff --git a/data/config.default.php b/data/config.default.php
index d3cd3bf22..433207a9c 100644
--- a/data/config.default.php
+++ b/data/config.default.php
@@ -46,7 +46,7 @@ return array(
# `http_auth` is an access controled by the HTTP Web server (e.g. `/FreshRSS/p/i/.htaccess` for Apache)
# if you use `http_auth`, remember to protect only `/FreshRSS/p/i/`,
# and in particular not protect `/FreshRSS/p/api/` if you would like to use the API (different login system).
- 'auth_type' => 'none',
+ 'auth_type' => 'form',
# Allow or not the use of the API, used for mobile apps.
# End-point is http://example.net/FreshRSS/p/api/greader.php
@@ -74,6 +74,9 @@ return array(
'limits' => array(
+ # Duration in seconds of the login cookie.
+ 'cookie_duration' => 2592000,
+
# Duration in seconds of the SimplePie cache,
# during which a query to the RSS feed will return the local cached version.
# Especially important for multi-user setups.
diff --git a/extensions/README.md b/extensions/README.md
index 4c1a81f5c..62766d6f2 100644
--- a/extensions/README.md
+++ b/extensions/README.md
@@ -1,3 +1,5 @@
# FreshRSS extensions
-You may place in this directory some custom extensions for FreshRSS.
+You may place custom extensions for FreshRSS in this directory.
+
+You can find some extensions in our [GitHub repository](https://github.com/FreshRSS/Extensions).
diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php
index 6e8d60bc9..caab1d114 100644
--- a/lib/Minz/ModelPdo.php
+++ b/lib/Minz/ModelPdo.php
@@ -116,6 +116,12 @@ class Minz_ModelPdo {
self::$sharedBd = null;
self::$sharedPrefix = '';
}
+
+ public function disableBuffering() {
+ if ((self::$sharedDbType === 'mysql') && defined('PDO::MYSQL_ATTR_USE_BUFFERED_QUERY')) {
+ $this->bd->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
+ }
+ }
}
class MinzPDO extends PDO {
diff --git a/lib/favicons.php b/lib/favicons.php
index 6709f6745..d8c97964e 100644
--- a/lib/favicons.php
+++ b/lib/favicons.php
@@ -9,7 +9,7 @@ $default_favicon = PUBLIC_PATH . '/themes/icons/default_favicon.ico';
function download_favicon($website, $dest) {
global $favicons_dir, $default_favicon;
- syslog(LOG_DEBUG, 'FreshRSS Favicon discovery GET ' . $website);
+ syslog(LOG_INFO, 'FreshRSS Favicon discovery GET ' . $website);
$favicon_getter = new \Favicon\Favicon();
$favicon_getter->setCacheDir($favicons_dir);
$favicon_url = $favicon_getter->get($website);
@@ -18,11 +18,12 @@ function download_favicon($website, $dest) {
return @copy($default_favicon, $dest);
}
- syslog(LOG_DEBUG, 'FreshRSS Favicon GET ' . $favicon_url);
+ syslog(LOG_INFO, 'FreshRSS Favicon GET ' . $favicon_url);
$c = curl_init($favicon_url);
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_BINARYTRANSFER, true);
+ curl_setopt($c, CURLOPT_USERAGENT, 'FreshRSS/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ')');
$img_raw = curl_exec($c);
$status_code = curl_getinfo($c, CURLINFO_HTTP_CODE);
curl_close($c);
@@ -34,6 +35,8 @@ function download_favicon($website, $dest) {
fclose($file);
return true;
}
+ } else {
+ syslog(LOG_WARNING, 'FreshRSS Favicon GET ' . $favicon_url . ' error ' . $status_code);
}
return false;
diff --git a/lib/lib_install.php b/lib/lib_install.php
index 0e7b7f036..c5cae4293 100644
--- a/lib/lib_install.php
+++ b/lib/lib_install.php
@@ -15,6 +15,7 @@ function checkRequirements() {
$pdo = $pdo_mysql || $pdo_sqlite || $pdo_pgsql;
$pcre = extension_loaded('pcre');
$ctype = extension_loaded('ctype');
+ $fileinfo = extension_loaded('fileinfo');
$dom = class_exists('DOMDocument');
$xml = function_exists('xml_parser_create');
$json = function_exists('json_encode');
@@ -34,6 +35,7 @@ function checkRequirements() {
'pdo' => $pdo ? 'ok' : 'ko',
'pcre' => $pcre ? 'ok' : 'ko',
'ctype' => $ctype ? 'ok' : 'ko',
+ 'fileinfo' => $fileinfo ? 'ok' : 'ko',
'dom' => $dom ? 'ok' : 'ko',
'xml' => $xml ? 'ok' : 'ko',
'json' => $json ? 'ok' : 'ko',
@@ -42,7 +44,7 @@ function checkRequirements() {
'users' => $users ? 'ok' : 'ko',
'favicons' => $favicons ? 'ok' : 'ko',
'http_referer' => $http_referer ? 'ok' : 'ko',
- 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $dom && $xml &&
+ 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $fileinfo && $dom && $xml &&
$data && $cache && $users && $favicons && $http_referer ?
'ok' : 'ko'
);
@@ -54,8 +56,8 @@ function generateSalt() {
function checkDb(&$dbOptions) {
$dsn = '';
+ $driver_options = null;
try {
- $driver_options = null;
switch ($dbOptions['type']) {
case 'mysql':
include_once(APP_PATH . '/SQL/install.sql.mysql.php');
@@ -99,8 +101,12 @@ function checkDb(&$dbOptions) {
default:
return false;
}
+
+ $c = new PDO($dsn, $dbOptions['user'], $dbOptions['password'], $driver_options);
+ $res = $c->query('SELECT 1');
} catch (PDOException $e) {
$dsn = '';
+ syslog(LOG_DEBUG, 'FreshRSS SQL warning: ' . $e->getMessage());
$dbOptions['error'] = $e->getMessage();
}
$dbOptions['dsn'] = $dsn;
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index 143b55bee..560e5b256 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -127,6 +127,8 @@ function format_bytes($bytes, $precision = 2, $system = 'IEC') {
} elseif ($system === 'SI') {
$base = 1000;
$units = array('B', 'KB', 'MB', 'GB', 'TB');
+ } else {
+ return format_number($bytes, $precision);
}
$bytes = max(intval($bytes), 0);
$pow = $bytes === 0 ? 0 : floor(log($bytes) / log($base));
@@ -396,6 +398,7 @@ function check_install_php() {
'pdo' => $pdo_mysql || $pdo_sqlite,
'pcre' => extension_loaded('pcre'),
'ctype' => extension_loaded('ctype'),
+ 'fileinfo' => extension_loaded('fileinfo'),
'dom' => class_exists('DOMDocument'),
'json' => extension_loaded('json'),
'zip' => extension_loaded('zip'),
diff --git a/p/scripts/main.js b/p/scripts/main.js
index 078bec682..14e0c5be5 100644
--- a/p/scripts/main.js
+++ b/p/scripts/main.js
@@ -1354,7 +1354,6 @@ function init_beforeDOM() {
window.setTimeout(init_beforeDOM, 100);
return;
}
- init_confirm_action();
if (['normal', 'reader', 'global'].indexOf(context.current_view) >= 0) {
inject_script('jquery.sticky-kit.min.js');
init_normal();
@@ -1372,6 +1371,7 @@ function init_afterDOM() {
init_notifications();
$stream = $('#stream');
if ($stream.length > 0) {
+ init_confirm_action();
init_load_more($stream);
init_posts();
init_nav_entries();