summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dockerignore3
-rw-r--r--CHANGELOG.md20
-rw-r--r--CREDITS.md1
-rw-r--r--Docker/Dockerfile22
-rw-r--r--Docker/FreshRSS.Apache.conf27
-rw-r--r--Docker/README.md119
-rw-r--r--README.fr.md4
-rw-r--r--README.md6
-rwxr-xr-xapp/Controllers/entryController.php3
-rwxr-xr-xapp/Controllers/feedController.php2
-rw-r--r--app/FreshRSS.php2
-rw-r--r--app/Models/Auth.php3
-rw-r--r--app/Models/EntryDAO.php27
-rw-r--r--app/Models/Feed.php2
-rw-r--r--app/Models/FeedDAO.php24
-rw-r--r--app/i18n/cz/conf.php2
-rw-r--r--app/i18n/de/conf.php2
-rw-r--r--app/i18n/en/conf.php2
-rwxr-xr-xapp/i18n/es/conf.php2
-rw-r--r--app/i18n/fr/conf.php2
-rw-r--r--app/i18n/he/conf.php2
-rw-r--r--app/i18n/it/conf.php2
-rw-r--r--app/i18n/kr/conf.php2
-rw-r--r--app/i18n/nl/conf.php2
-rw-r--r--app/i18n/pt-br/conf.php2
-rw-r--r--app/i18n/ru/conf.php2
-rw-r--r--app/i18n/tr/conf.php2
-rw-r--r--app/i18n/zh-cn/conf.php2
-rw-r--r--app/shares.php (renamed from data/shares.php)0
-rw-r--r--app/views/configure/sharing.phtml6
-rw-r--r--cli/README.md3
-rw-r--r--cli/i18n/I18nData.php24
-rw-r--r--cli/i18n/I18nFile.php31
-rw-r--r--cli/manipulate.translation.php19
-rwxr-xr-xcli/prepare.php37
-rw-r--r--constants.php2
-rw-r--r--docs/en/admins/02_Installation.md2
-rw-r--r--docs/en/users/07_Frequently_Asked_Questions.md11
-rw-r--r--docs/fr/users/01_Installation.md2
-rw-r--r--docs/fr/users/07_Frequently_Asked_Questions.md11
-rw-r--r--lib/Minz/Request.php3
-rw-r--r--p/api/greader.php6
42 files changed, 401 insertions, 47 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..ab223517d
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+*/.git
+*/data
+*/docs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88f6fa129..e855e1acb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# FreshRSS changelog
+## 2018-03-04 FreshRSS 1.10.1
+
+* Deployment
+ * New Docker image, smaller (based on Alpine Linux) and newer (with PHP 7.1) [#1813](https://github.com/FreshRSS/FreshRSS/pull/1813)
+ * with [automated build](https://hub.docker.com/r/freshrss/freshrss/) for x86-64 (AMD64) architectures
+* CLI
+ * New command `./cli/prepare.php` to make the needed sub-directories of the `./data/` directory [#1813](https://github.com/FreshRSS/FreshRSS/pull/1813)
+* Bug fixing
+ * Fix API bug for EasyRSS [#1799](https://github.com/FreshRSS/FreshRSS/issues/1799)
+ * Fix login bug when using double authentication (HTTP + Web form) [#1807](https://github.com/FreshRSS/FreshRSS/issues/1807)
+ * Fix database upgrade for FreshRSS versions older than 1.1.1 [#1803](https://github.com/FreshRSS/FreshRSS/issues/1803)
+ * Fix cases of double port in FreshRSS public URL [#1815](https://github.com/FreshRSS/FreshRSS/pull/1815)
+* UI
+ * Add tooltips on share configuration buttons [#1805](https://github.com/FreshRSS/FreshRSS/pull/1805)
+* Misc.
+ * Move `./data/shares.php` to `./app/shares.php` to facilitate updates [#1812](https://github.com/FreshRSS/FreshRSS/pull/1812)
+ * Show article author email when there is no author name [#1801](https://github.com/FreshRSS/FreshRSS/pull/1801)
+ * Improve translation tools [#1808](https://github.com/FreshRSS/FreshRSS/pull/1808)
+
+
## 2018-02-24 FreshRSS 1.10.0
* API
diff --git a/CREDITS.md b/CREDITS.md
index e7e7c97a8..5307061db 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -44,6 +44,7 @@ People are sorted by name so please keep this order.
* [Nicolas Lœuillet](https://github.com/nicosomb): [contributions](https://github.com/FreshRSS/documentation/commits?author=nicosomb), [Web](http://www.loeuillet.org/)
* [Nicola Spanti](https://github.com/RyDroid): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:RyDroid), [Web](http://www.nicola-spanti.info/)
* [Olivier Dossmann](https://github.com/blankoworld): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=blankoworld), [Web](https://olivier.dossmann.net)
+* [perrinjerome](https://github.com/perrinjerome): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:perrinjerome)
* [plopoyop](https://github.com/plopoyop): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=plopoyop)
* [Paulius Šukys](https://github.com/psukys): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:psukys), [Web](http://sukys.eu)
* [purexo](https://github.com/purexo): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:purexo), [Web](https://purexo.mom/)
diff --git a/Docker/Dockerfile b/Docker/Dockerfile
new file mode 100644
index 000000000..993dcea31
--- /dev/null
+++ b/Docker/Dockerfile
@@ -0,0 +1,22 @@
+FROM alpine:3.7
+
+RUN apk add --no-cache \
+ apache2 php7-apache2 \
+ php7 php7-curl php7-gmp php7-intl php7-mbstring php7-xml php7-zip \
+ php7-ctype php7-dom php7-fileinfo php7-json php7-session \
+ php7-pdo_sqlite \
+ php7-pdo_mysql \
+ php7-pdo_pgsql
+
+ENV FRESHRSS_ROOT /var/www/FreshRSS
+RUN mkdir -p ${FRESHRSS_ROOT} /run/apache2/
+WORKDIR ${FRESHRSS_ROOT}
+
+COPY . ${FRESHRSS_ROOT}
+COPY ./Docker/*.Apache.conf /etc/apache2/conf.d/
+
+EXPOSE 80
+CMD php -f ./cli/prepare.php > /dev/null && \
+ chown -R :www-data ${FRESHRSS_ROOT} && \
+ chmod -R g+r ${FRESHRSS_ROOT} && chmod -R g+w ${FRESHRSS_ROOT}/data/ && \
+ exec httpd -D FOREGROUND
diff --git a/Docker/FreshRSS.Apache.conf b/Docker/FreshRSS.Apache.conf
new file mode 100644
index 000000000..59151d749
--- /dev/null
+++ b/Docker/FreshRSS.Apache.conf
@@ -0,0 +1,27 @@
+<IfModule !deflate_module>
+ LoadModule deflate_module modules/mod_deflate.so
+</IfModule>
+<IfModule !expires_module>
+ LoadModule expires_module modules/mod_expires.so
+</IfModule>
+<IfModule !headers_module>
+ LoadModule headers_module modules/mod_headers.so
+</IfModule>
+<IfModule !mime_module>
+ LoadModule mime_module modules/mod_mime.so
+</IfModule>
+<IfModule !rewrite_module>
+ LoadModule rewrite_module modules/mod_rewrite.so
+</IfModule>
+
+ServerName freshrss.localhost
+Listen 0.0.0.0:80
+DocumentRoot /var/www/FreshRSS/p/
+ErrorLog /dev/stderr
+TransferLog /dev/stdout
+AllowEncodedSlashes On
+
+<Directory /var/www/FreshRSS/p>
+ AllowOverride AuthConfig FileInfo Indexes Limit
+ Require all granted
+</Directory>
diff --git a/Docker/README.md b/Docker/README.md
new file mode 100644
index 000000000..ccf4ab3f0
--- /dev/null
+++ b/Docker/README.md
@@ -0,0 +1,119 @@
+# Deploy FreshRSS with Docker
+* See also:
+ * https://hub.docker.com/r/freshrss/freshrss/
+ * https://cloud.docker.com/app/freshrss/repository/docker/freshrss/freshrss
+
+## Install Docker
+
+```sh
+curl -fsSL https://get.docker.com/ -o get-docker.sh
+sh get-docker.sh
+```
+
+## Optional: Build Docker image of FreshRSS
+Optional, as a *less recent* online image can be automatically fetched during the next step (run),
+but online images are not available for as many platforms as if you build yourself.
+
+```sh
+# First time only
+git clone https://github.com/FreshRSS/FreshRSS.git
+
+cd ./FreshRSS/
+git pull
+sudo docker pull alpine:3.7
+sudo docker build --tag freshrss/freshrss -f Docker/Dockerfile .
+```
+
+## Run FreshRSS
+
+Example using SQLite, and exposing FreshRSS on port 8080. You may have to adapt the network parameters to fit your needs.
+
+```sh
+# You can optionally run from the directory containing the FreshRSS source code:
+cd ./FreshRSS/
+
+# The data will be saved on the host in `./data/`
+mkdir -p ./data/
+
+sudo docker run -dit --restart unless-stopped --log-opt max-size=10m \
+ -v $(pwd)/data:/var/www/FreshRSS/data \
+ -p 8080:80 \
+ --name freshrss freshrss/freshrss
+```
+
+### Examples with external databases
+
+You may want to use other link methods such as Docker bridges, and use Docker volumes for the data, but here are some simple examples:
+
+#### MySQL
+See https://hub.docker.com/_/mysql/
+
+```sh
+sudo docker run -d -v /path/to/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=rootpass -e MYSQL_DATABASE=freshrss -e MYSQL_USER=freshrss -e MYSQL_PASSWORD=pass --name mysql mysql
+sudo docker run -dit --restart unless-stopped --log-opt max-size=10m \
+ -v $(pwd)/data:/var/www/FreshRSS/data \
+ --link mysql -p 8080:80 \
+ --name freshrss freshrss/freshrss
+```
+
+#### PostgreSQL
+See https://hub.docker.com/_/postgres/
+
+```sh
+sudo docker run -d -v /path/to/pgsql-data:/var/lib/postgresql/data -e POSTGRES_DB=freshrss -e POSTGRES_USER=freshrss -e POSTGRES_PASSWORD=pass --name postgres postgres
+sudo docker run -dit --restart unless-stopped --log-opt max-size=10m \
+ -v $(pwd)/data:/var/www/FreshRSS/data \
+ --link postgres -p 8080:80 \
+ --name freshrss freshrss/freshrss
+```
+
+## Update
+
+```sh
+# Rebuild an image (see build section above) or get a new online version:
+sudo docker pull freshrss/freshrss
+# And then
+sudo docker stop freshrss
+sudo docker rename freshrss freshrss_old
+# See the run section above for the full command
+sudo docker run ...
+# If everything is working, delete the old container
+sudo docker rm freshrss_old
+```
+
+## Command line
+
+```sh
+sudo docker exec --user apache -it freshrss php ./cli/list-users.php
+```
+
+See the [CLI documentation](../cli/) for all the other commands.
+
+### Cron job to refresh feeds
+Set a cron job up on your host machine, calling the `actualize_script.php` inside the FreshRSS Docker instance.
+
+#### Example on Debian / Ubuntu
+Create `/etc/cron.d/FreshRSS` with:
+
+```
+7,37 * * * * root docker exec --user apache -it freshrss php ./app/actualize_script.php > /tmp/FreshRSS.log 2>&1
+```
+
+## Debugging
+
+```sh
+# See FreshRSS data (it is on the host)
+cd ./data/
+# See Web server logs
+sudo docker logs -f freshrss
+
+# Enter inside FreshRSS docker container
+sudo docker exec -it freshrss sh
+## See FreshRSS root inside the container
+ls /var/www/FreshRSS/
+```
+
+## Deployment in production
+
+Use a reverse proxy on your host server, such as [Træfik](https://traefik.io/) or [nginx](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/),
+with HTTPS, for instance using [Let’s Encrypt](https://letsencrypt.org/).
diff --git a/README.fr.md b/README.fr.md
index 4421f92f0..97ffafb56 100644
--- a/README.fr.md
+++ b/README.fr.md
@@ -55,6 +55,8 @@ Nous sommes une communauté amicale.
7. Avec Apache, activer [`AllowEncodedSlashes`](https://httpd.apache.org/docs/trunk/mod/core.html#allowencodedslashes) pour une meilleure compatibilité avec les clients mobiles.
## Installation automatisée
+* [Docker](./Docker/)
+* [![Cloudron](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=org.freshrss.cloudronapp)
* [![DP deploy](https://raw.githubusercontent.com/DFabric/DPlatform-ShellCore/gh-pages/img/deploy.png)](https://dfabric.github.io/DPlatform-ShellCore)
* [YunoHost](https://github.com/YunoHost-Apps/freshrss_ynh)
@@ -172,7 +174,7 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio
* [password_compat](https://github.com/ircmaxell/password_compat)
-# [Clients compatibles](https://freshrss.github.io/FreshRSS/en/users/06_Mobile_access.html)
+# [Clients compatibles](https://freshrss.github.io/FreshRSS/fr/users/06_Mobile_access.html)
Tout client supportant une API de type Google Reader. Sélection :
* Android
diff --git a/README.md b/README.md
index a95593651..cacf61fa9 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
[![Build Status][travis-badge]][travis-link]
+* Read this document on [github.com/FreshRSS/FreshRSS/](https://github.com/FreshRSS/FreshRSS/blob/master/README.md) to get the correct links and pictures.
* [Version française](README.fr.md)
# FreshRSS
@@ -46,7 +47,7 @@ We are a friendly community.
# Documentation
* https://freshrss.github.io/FreshRSS/en/
-# [Installation](https://freshrss.github.io/FreshRSS/en/users/01_Installation.html)
+# [Installation](https://freshrss.github.io/FreshRSS/en/admins/02_Installation.html)
1. Get FreshRSS with git or [by downloading the archive](https://github.com/FreshRSS/FreshRSS/archive/master.zip)
2. Dump the application on your server (expose only the `./p/` folder)
3. Add write access on `./data/` folder to the webserver user
@@ -59,7 +60,8 @@ We are a friendly community.
More information about installation and server configuration can be found in [our documentation](https://freshrss.github.io/FreshRSS/en/admins/02_Installation.html).
## Automated install
-* [![Install on Cloudron](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=org.freshrss.cloudronapp)
+* [Docker](./Docker/)
+* [![Cloudron](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=org.freshrss.cloudronapp)
* [![DP deploy](https://raw.githubusercontent.com/DFabric/DPlatform-ShellCore/gh-pages/img/deploy.png)](https://dfabric.github.io/DPlatform-ShellCore)
* [YunoHost](https://github.com/YunoHost-Apps/freshrss_ynh)
diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php
index 9c6b248a9..28f0cb745 100755
--- a/app/Controllers/entryController.php
+++ b/app/Controllers/entryController.php
@@ -169,6 +169,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
$nb_month_old = max(FreshRSS_Context::$user_conf->old_entries, 1);
$date_min = time() - (3600 * 24 * 30 * $nb_month_old);
+ $entryDAO = FreshRSS_Factory::createEntryDao();
$feedDAO = FreshRSS_Factory::createFeedDao();
$feeds = $feedDAO->listFeeds();
$nb_total = 0;
@@ -182,7 +183,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
}
if ($feed_history >= 0) {
- $nb = $feedDAO->cleanOldEntries($feed->id(), $date_min, $feed_history);
+ $nb = $entryDAO->cleanOldEntries($feed->id(), $date_min, $feed_history);
if ($nb > 0) {
$nb_total += $nb;
Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url() . ']');
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index 7f66b10db..af732951f 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -408,7 +408,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
$entryDAO->beginTransaction();
}
- $nb = $feedDAO->cleanOldEntries($feed->id(),
+ $nb = $entryDAO->cleanOldEntries($feed->id(),
$date_min,
max($feed_history, count($entries) + 10));
if ($nb > 0) {
diff --git a/app/FreshRSS.php b/app/FreshRSS.php
index f53c85bfb..25fd429a2 100644
--- a/app/FreshRSS.php
+++ b/app/FreshRSS.php
@@ -128,7 +128,7 @@ class FreshRSS extends Minz_FrontController {
}
header("X-Content-Type-Options: nosniff");
- FreshRSS_Share::load(join_path(DATA_PATH, 'shares.php'));
+ FreshRSS_Share::load(join_path(APP_PATH, 'shares.php'));
self::loadStylesAndScripts();
}
}
diff --git a/app/Models/Auth.php b/app/Models/Auth.php
index 32b673b6d..8c711308c 100644
--- a/app/Models/Auth.php
+++ b/app/Models/Auth.php
@@ -63,7 +63,6 @@ class FreshRSS_Auth {
$login_ok = $current_user != '';
if ($login_ok) {
Minz_Session::_param('currentUser', $current_user);
- Minz_Session::_param('REMOTE_USER', $current_user);
}
return $login_ok;
case 'none':
@@ -102,6 +101,7 @@ class FreshRSS_Auth {
}
Minz_Session::_param('loginOk', self::$login_ok);
+ Minz_Session::_param('REMOTE_USER', httpAuthUser());
}
/**
@@ -133,6 +133,7 @@ class FreshRSS_Auth {
self::$login_ok = false;
Minz_Session::_param('loginOk');
Minz_Session::_param('csrf');
+ Minz_Session::_param('REMOTE_USER');
$system_conf = Minz_Configuration::get('system');
$username = '';
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index 70135e7a0..8cdebedc5 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -560,6 +560,33 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return $affected;
}
+ public function cleanOldEntries($id_feed, $date_min, $keep = 15) { //Remember to call updateCachedValue($id_feed) or updateCachedValues() just after
+ $sql = 'DELETE FROM `' . $this->prefix . 'entry` '
+ . 'WHERE id_feed=:id_feed AND id<=:id_max '
+ . 'AND is_favorite=0 ' //Do not remove favourites
+ . 'AND `lastSeen` < (SELECT maxLastSeen FROM (SELECT (MAX(e3.`lastSeen`)-99) AS maxLastSeen FROM `' . $this->prefix . 'entry` e3 WHERE e3.id_feed=:id_feed) recent) ' //Do not remove the most newly seen articles, plus a few seconds of tolerance
+ . 'AND id NOT IN (SELECT id FROM (SELECT e2.id FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=:id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select: MySQL doesn't support 'LIMIT & IN/ALL/ANY/SOME subquery'
+ $stm = $this->bd->prepare($sql);
+
+ if ($stm) {
+ $id_max = intval($date_min) . '000000';
+ $stm->bindParam(':id_feed', $id_feed, PDO::PARAM_INT);
+ $stm->bindParam(':id_max', $id_max, PDO::PARAM_STR);
+ $stm->bindParam(':keep', $keep, PDO::PARAM_INT);
+ }
+
+ if ($stm && $stm->execute()) {
+ return $stm->rowCount();
+ } else {
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
+ if ($this->autoUpdateDb($info)) {
+ return $this->cleanOldEntries($id_feed, $date_min, $keep);
+ }
+ Minz_Log::error('SQL error cleanOldEntries: ' . $info[2]);
+ return false;
+ }
+ }
+
public function searchByGuid($id_feed, $guid) {
// un guid est unique pour un flux donné
$sql = 'SELECT id, guid, title, author, '
diff --git a/app/Models/Feed.php b/app/Models/Feed.php
index 13ab13df9..196d94931 100644
--- a/app/Models/Feed.php
+++ b/app/Models/Feed.php
@@ -355,7 +355,7 @@ class FreshRSS_Feed extends Minz_Model {
$this->id(),
$item->get_id(false, false),
$title === null ? '' : $title,
- $author === null ? '' : html_only_entity_decode(strip_tags($author->name)),
+ $author === null ? '' : html_only_entity_decode(strip_tags($author->name == null ? $author->email : $author->name)),
$content === null ? '' : $content,
$link === null ? '' : $link,
$date ? $date : time()
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php
index 011b3d112..0c25ab0ba 100644
--- a/app/Models/FeedDAO.php
+++ b/app/Models/FeedDAO.php
@@ -353,30 +353,6 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return $affected;
}
- public function cleanOldEntries($id, $date_min, $keep = 15) { //Remember to call updateCachedValue($id) or updateCachedValues() just after
- $sql = 'DELETE FROM `' . $this->prefix . 'entry` '
- . 'WHERE id_feed=:id_feed AND id<=:id_max '
- . 'AND is_favorite=0 ' //Do not remove favourites
- . 'AND `lastSeen` < (SELECT maxLastSeen FROM (SELECT (MAX(e3.`lastSeen`)-99) AS maxLastSeen FROM `' . $this->prefix . 'entry` e3 WHERE e3.id_feed=:id_feed) recent) ' //Do not remove the most newly seen articles, plus a few seconds of tolerance
- . 'AND id NOT IN (SELECT id FROM (SELECT e2.id FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=:id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select: MySQL doesn't support 'LIMIT & IN/ALL/ANY/SOME subquery'
- $stm = $this->bd->prepare($sql);
-
- if ($stm) {
- $id_max = intval($date_min) . '000000';
- $stm->bindParam(':id_feed', $id, PDO::PARAM_INT);
- $stm->bindParam(':id_max', $id_max, PDO::PARAM_STR);
- $stm->bindParam(':keep', $keep, PDO::PARAM_INT);
- }
-
- if ($stm && $stm->execute()) {
- return $stm->rowCount();
- } else {
- $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
- Minz_Log::error('SQL error cleanOldEntries: ' . $info[2]);
- return false;
- }
- }
-
public static function daoToFeed($listDAO, $catID = null) {
$list = array();
diff --git a/app/i18n/cz/conf.php b/app/i18n/cz/conf.php
index 649724e80..a7bcf6c08 100644
--- a/app/i18n/cz/conf.php
+++ b/app/i18n/cz/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Sdílení',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Více informací',
'print' => 'Tisk',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Jméno pro zobrazení',
'share_url' => 'Jakou URL použít pro sdílení',
diff --git a/app/i18n/de/conf.php b/app/i18n/de/conf.php
index 9f1edffb9..6b0d7c7f9 100644
--- a/app/i18n/de/conf.php
+++ b/app/i18n/de/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Teilen',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'E-Mail',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Weitere Informationen',
'print' => 'Drucken',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Anzuzeigender Teilen-Name',
'share_url' => 'Zu verwendende Teilen-URL',
diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php
index 60231b825..a1c3fc949 100644
--- a/app/i18n/en/conf.php
+++ b/app/i18n/en/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Sharing',
+ 'add' => 'Add a sharing method',
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'More information',
'print' => 'Print',
+ 'remove' => 'Remove sharing method',
'shaarli' => 'Shaarli',
'share_name' => 'Share name to display',
'share_url' => 'Share URL to use',
diff --git a/app/i18n/es/conf.php b/app/i18n/es/conf.php
index 65858fefe..464bebc4f 100755
--- a/app/i18n/es/conf.php
+++ b/app/i18n/es/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Compartir',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Más información',
'print' => 'Print',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Compartir nombre a mostrar',
'share_url' => 'Compatir URL a usar',
diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php
index b4c39e1ca..402a97b1c 100644
--- a/app/i18n/fr/conf.php
+++ b/app/i18n/fr/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Partage',
+ 'add' => 'Ajouter une méthode de partage',
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Courriel',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Plus d’informations',
'print' => 'Print',
+ 'remove' => 'Supprimer la méthode de partage',
'shaarli' => 'Shaarli',
'share_name' => 'Nom du partage à afficher',
'share_url' => 'URL du partage à utiliser',
diff --git a/app/i18n/he/conf.php b/app/i18n/he/conf.php
index 50d1936a8..3d0534fdc 100644
--- a/app/i18n/he/conf.php
+++ b/app/i18n/he/conf.php
@@ -123,6 +123,7 @@ return array(
),
'sharing' => array(
'_' => 'שיתוף',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'דואר אלקטרוני',
@@ -130,6 +131,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'מידע נוסף',
'print' => 'הדפסה',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'שיתוף שם לתצוגה',
'share_url' => 'לשימוש שתפו URL',
diff --git a/app/i18n/it/conf.php b/app/i18n/it/conf.php
index 9e20236f1..5ab343c4d 100644
--- a/app/i18n/it/conf.php
+++ b/app/i18n/it/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Condivisione',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Ulteriori informazioni',
'print' => 'Stampa',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Nome condivisione',
'share_url' => 'URL condivisione',
diff --git a/app/i18n/kr/conf.php b/app/i18n/kr/conf.php
index 31b042f57..c9e91a804 100644
--- a/app/i18n/kr/conf.php
+++ b/app/i18n/kr/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => '공유',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => '메일',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => '자세한 정보',
'print' => '인쇄',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => '표시할 이름',
'share_url' => '사용할 공유 URL',
diff --git a/app/i18n/nl/conf.php b/app/i18n/nl/conf.php
index 360e1c5e7..847c735d1 100644
--- a/app/i18n/nl/conf.php
+++ b/app/i18n/nl/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Delen',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Meer informatie',
'print' => 'Afdrukken',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Gedeelde naam om weer te geven',
'share_url' => 'Deel URL voor gebruik',
diff --git a/app/i18n/pt-br/conf.php b/app/i18n/pt-br/conf.php
index 71b6afb20..864c80e61 100644
--- a/app/i18n/pt-br/conf.php
+++ b/app/i18n/pt-br/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Compartilhando',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Mais informação',
'print' => 'Imprimir',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Nome de visualização para compartilhar',
'share_url' => 'URL utilizada para compartilhar',
diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php
index 15109dd15..1b5cd8085 100644
--- a/app/i18n/ru/conf.php
+++ b/app/i18n/ru/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Sharing',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'More information',
'print' => 'Print',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Share name to display',
'share_url' => 'Share URL to use',
diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php
index 596adaf9a..0671da79e 100644
--- a/app/i18n/tr/conf.php
+++ b/app/i18n/tr/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => 'Paylaşım',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => 'Daha fazla bilgi',
'print' => 'Yazdır',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => 'Paylaşım ismi',
'share_url' => 'Paylaşım URL si',
diff --git a/app/i18n/zh-cn/conf.php b/app/i18n/zh-cn/conf.php
index 2e068be42..c57738c5b 100644
--- a/app/i18n/zh-cn/conf.php
+++ b/app/i18n/zh-cn/conf.php
@@ -126,6 +126,7 @@ return array(
),
'sharing' => array(
'_' => '分享',
+ 'add' => 'Add a sharing method', // TODO
'blogotext' => 'Blogotext',
'diaspora' => 'Diaspora*',
'email' => 'Email',
@@ -133,6 +134,7 @@ return array(
'g+' => 'Google+',
'more_information' => '更多信息',
'print' => '打印',
+ 'remove' => 'Remove sharing method', // TODO
'shaarli' => 'Shaarli',
'share_name' => '名称',
'share_url' => '地址',
diff --git a/data/shares.php b/app/shares.php
index 5403fd48c..5403fd48c 100644
--- a/data/shares.php
+++ b/app/shares.php
diff --git a/app/views/configure/sharing.phtml b/app/views/configure/sharing.phtml
index b0e6618fa..026659007 100644
--- a/app/views/configure/sharing.phtml
+++ b/app/views/configure/sharing.phtml
@@ -14,7 +14,7 @@
<div class="stick">
<input type="text" id="share_##key##_name" name="share[##key##][name]" class="extend" value="" placeholder="<?php echo _t('conf.sharing.share_name'); ?>" size="64" />
<input type="url" id="share_##key##_url" name="share[##key##][url]" class="extend" value="" placeholder="<?php echo _t('conf.sharing.share_url'); ?>" size="64" />
- <a href="#" class="remove btn btn-attention" data-remove="group-share-##key##"><?php echo _i('close'); ?></a></div>
+ <a href="#" class="remove btn btn-attention" data-remove="group-share-##key##" title="<?php echo _t('conf.sharing.remove'); ?>"><?php echo _i('close'); ?></a></div>
<a target="_blank" rel="noreferrer" class="btn" title="<?php echo _t('conf.sharing.more_information'); ?>" href="##help##"><?php echo _i('help'); ?></a>
</div></div>'>
<input type="hidden" name="_csrf" value="<?php echo FreshRSS_Auth::csrfToken(); ?>" />
@@ -39,7 +39,7 @@
<?php } else { ?>
<input type="url" id="share_<?php echo $key; ?>_url" name="share[<?php echo $key; ?>][url]" class="extend" value="<?php echo $share->baseUrl(); ?>" placeholder="<?php echo _t('gen.short.not_applicable'); ?>" size="64" disabled/>
<?php } ?>
- <a href='#' class='remove btn btn-attention' data-remove="group-share-<?php echo $key; ?>"><?php echo _i('close'); ?></a>
+ <a href='#' class='remove btn btn-attention' data-remove="group-share-<?php echo $key; ?>" title="<?php echo _t('conf.sharing.remove'); ?>"><?php echo _i('close'); ?></a>
</div>
<?php if ($share->formType() === 'advanced') { ?>
<a target="_blank" rel="noreferrer" class="btn" title="<?php echo _t('conf.sharing.more_information'); ?>" href="<?php echo $share->help(); ?>"><?php echo _i('help'); ?></a>
@@ -57,7 +57,7 @@
</option>
<?php } ?>
</select>
- <a href='#' class='share add btn'><?php echo _i('add'); ?></a>
+ <a href='#' class='share add btn' title="<?php echo _t('conf.sharing.add'); ?>"><?php echo _i('add'); ?></a>
</div>
</div>
diff --git a/cli/README.md b/cli/README.md
index a496aab58..d531b8c3d 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -32,6 +32,9 @@ Options in parenthesis are optional.
```sh
cd /usr/share/FreshRSS
+./cli/prepare.php
+# Ensure the needed directories in ./data/
+
./cli/do-install.php --default_user admin ( --auth_type form --environment production --base_url https://rss.example.net/ --language en --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)
diff --git a/cli/i18n/I18nData.php b/cli/i18n/I18nData.php
index cd8ba0765..b8f958288 100644
--- a/cli/i18n/I18nData.php
+++ b/cli/i18n/I18nData.php
@@ -32,6 +32,7 @@ class I18nData {
* Add a new language. It's a copy of the reference language.
*
* @param string $language
+ * @throws Exception
*/
public function addLanguage($language) {
if (array_key_exists($language, $this->data)) {
@@ -45,6 +46,7 @@ class I18nData {
*
* @param string $key
* @param string $value
+ * @throws Exception
*/
public function addKey($key, $value) {
if (array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
@@ -54,9 +56,28 @@ class I18nData {
}
/**
+ * Add a value for a key for the selected language.
+ *
+ * @param string $key
+ * @param string $value
+ * @param string $language
+ * @throws Exception
+ */
+ public function addValue($key, $value, $language) {
+ if (!in_array($language, $this->getAvailableLanguages())) {
+ throw new Exception('The selected language does not exist.');
+ }
+ if (!array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
+ throw new Exception('The selected key does not exist for the selected language.');
+ }
+ $this->data[$language][$this->getFilenamePrefix($key)][$key] = $value;
+ }
+
+ /**
* Duplicate a key from the reference language to all other languages
*
* @param string $key
+ * @throws Exception
*/
public function duplicateKey($key) {
if (!array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
@@ -68,7 +89,7 @@ class I18nData {
continue;
}
if (array_key_exists($key, $this->data[$language][$this->getFilenamePrefix($key)])) {
- throw new Exception(sprintf('The selected key already exist in %s.', $language));
+ continue;
}
$this->data[$language][$this->getFilenamePrefix($key)][$key] = $value;
}
@@ -78,6 +99,7 @@ class I18nData {
* Remove a key in all languages
*
* @param string $key
+ * @throws Exception
*/
public function removeKey($key) {
if (!array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
diff --git a/cli/i18n/I18nFile.php b/cli/i18n/I18nFile.php
index d6489ee21..a07efdf88 100644
--- a/cli/i18n/I18nFile.php
+++ b/cli/i18n/I18nFile.php
@@ -36,8 +36,7 @@ class i18nFile {
}
foreach ($file as $name => $content) {
$filename = $dir . DIRECTORY_SEPARATOR . $name;
- $fullContent = var_export($this->unflatten($content), true);
- file_put_contents($filename, sprintf('<?php return %s;', $fullContent));
+ file_put_contents($filename, $this->format($content));
}
}
}
@@ -89,4 +88,32 @@ class i18nFile {
return $a;
}
+ /**
+ * Format an array of translation
+ *
+ * It takes an array of translation and format it to be dumped in a
+ * translation file. The array is first converted to a string then some
+ * formatting regexes are applied to match the original content.
+ *
+ * @param array $translation
+ * @return string
+ */
+ private function format($translation) {
+ $translation = var_export($this->unflatten($translation), true);
+ $patterns = array(
+ '/array \(/',
+ '/=>\s*array/',
+ '/ {2}/',
+ );
+ $replacements = array(
+ 'array(',
+ '=> array',
+ "\t", // Double quoting is mandatory to have a tab instead of the \t string
+ );
+ $translation = preg_replace($patterns, $replacements, $translation);
+
+ // Double quoting is mandatory to have new lines instead of \n strings
+ return sprintf("<?php\n\nreturn %s;\n", $translation);
+ }
+
}
diff --git a/cli/manipulate.translation.php b/cli/manipulate.translation.php
index aace5723a..0e06993ef 100644
--- a/cli/manipulate.translation.php
+++ b/cli/manipulate.translation.php
@@ -6,7 +6,7 @@ if (array_key_exists('h', $options)) {
help();
}
-if (1 === $argc || 4 < $argc) {
+if (1 === $argc || 5 < $argc) {
help();
}
@@ -25,12 +25,21 @@ switch ($argv[1]) {
}
$i18nData->addKey($argv[2], $argv[3]);
break;
+ case 'add_value':
+ if (4 === $argc) {
+ help();
+ }
+ $i18nData->addValue($argv[2], $argv[3], $argv[4]);
+ break;
case 'duplicate_key' :
$i18nData->duplicateKey($argv[2]);
break;
case 'delete_key' :
$i18nData->removeKey($argv[2]);
break;
+ case 'format' :
+ $i18nFile->dump($i18nData);
+ break;
default :
help();
}
@@ -48,7 +57,7 @@ NAME
%s
SYNOPSIS
- php %s [OPTION] [OPERATION] [KEY] [VALUE]
+ php %s [OPTION] [OPERATION] [KEY] [VALUE] [LANGUAGE]
DESCRIPTION
Manipulate translation files. Available operations are
@@ -64,6 +73,10 @@ OPERATION
add_key add a new key in the referential. This operation needs a KEY and
a VALUE.
+ add_value
+ add a value in the referential. This operation needs a KEY, a
+ VALUE, and a LANGUAGE.
+
duplicate_key
duplicate a referential key in other languages. This operation
needs only a KEY.
@@ -72,6 +85,8 @@ OPERATION
delete a referential key from all languages. This operation needs
only a KEY.
+ format format i18n files.
+
HELP;
$file = str_replace(__DIR__ . '/', '', __FILE__);
echo sprintf($help, $file, $file);
diff --git a/cli/prepare.php b/cli/prepare.php
new file mode 100755
index 000000000..2db2da555
--- /dev/null
+++ b/cli/prepare.php
@@ -0,0 +1,37 @@
+#!/usr/bin/php
+<?php
+require(__DIR__ . '/_cli.php');
+
+$dirs = array(
+ '/',
+ '/cache',
+ '/extensions-data',
+ '/favicons',
+ '/PubSubHubbub',
+ '/PubSubHubbub/feeds',
+ '/PubSubHubbub/keys',
+ '/tokens',
+ '/users',
+ '/users/_',
+);
+
+$ok = true;
+
+foreach ($dirs as $dir) {
+ @mkdir(DATA_PATH . $dir, 0770, true);
+ $ok &= touch(DATA_PATH . $dir . '/index.html');
+}
+
+if (!is_file(DATA_PATH . '/config.php')) {
+ $ok &= touch(DATA_PATH . '/do-install.txt');
+}
+
+file_put_contents(DATA_PATH . '/.htaccess',
+"Order Allow,Deny\n" .
+"Deny from all\n" .
+"Satisfy all\n"
+);
+
+accessRights();
+
+done($ok);
diff --git a/constants.php b/constants.php
index f33e2d63e..e0a271ee8 100644
--- a/constants.php
+++ b/constants.php
@@ -2,7 +2,7 @@
//NB: Do not edit; use ./constants.local.php instead.
//<Not customisable>
-define('FRESHRSS_VERSION', '1.10.0');
+define('FRESHRSS_VERSION', '1.10.1');
define('FRESHRSS_WEBSITE', 'https://freshrss.org');
define('FRESHRSS_WIKI', 'https://freshrss.github.io/FreshRSS/');
diff --git a/docs/en/admins/02_Installation.md b/docs/en/admins/02_Installation.md
index ef6531bd0..9bf800969 100644
--- a/docs/en/admins/02_Installation.md
+++ b/docs/en/admins/02_Installation.md
@@ -9,7 +9,7 @@ You need to verify that your server can run FreshRSS before installing it. If yo
| Web server | **Apache 2** | Nginx |
| PHP | **PHP 5.5+** | PHP 5.3.8+ |
| PHP modules | Required: libxml, cURL, PDO_MySQL, PCRE and ctype. \\ Required (32-bit only): GMP \\Recommanded: JSON, Zlib, mbstring, iconv, ZipArchive | |
-| Database | **MySQL 5.0.3+** | SQLite 3.7.4+ |
+| Database | **MySQL 5.5.3+** | SQLite 3.7.4+ |
| Browser | **Firefox** | Chrome, Opera, Safari, or IE11+ |
## Important notice
diff --git a/docs/en/users/07_Frequently_Asked_Questions.md b/docs/en/users/07_Frequently_Asked_Questions.md
index 427da7bd9..132b2e7ec 100644
--- a/docs/en/users/07_Frequently_Asked_Questions.md
+++ b/docs/en/users/07_Frequently_Asked_Questions.md
@@ -33,3 +33,14 @@ Here is a list of feeds which don't work:
* http://foulab.org/fr/rss/Foulab_News: is not a W3C valid feed (November 2014)
* http://eu.battle.net/hearthstone/fr/feed/news: is not a W3C valid feed (Novembre 2014)
* http://webseriesmag.blogs.liberation.fr/we/atom.xml: is not working for the user but succeed on all the described validations (November 2014)
+
+## How to change a forgotten password?
+
+Since [1.10.0](https://github.com/FreshRSS/FreshRSS/releases/tag/1.10.0) release, admins are able to change user passwords directly from the interface. This interface is available under ```Administration → Manage users```.
+Select a user, enter a password, and validate.
+
+Since [1.8.0](https://github.com/FreshRSS/FreshRSS/releases/tag/1.8.0) release, admins are able to change user passwords using a terminal. It worth mentioning that it must have access to PHP CLI. Open a terminal, and type the following command:
+```sh
+./cli/update_user.php --user <username> --password <password>
+```
+For more information on that matter, there is a [dedicated documentation](../../cli/README.md). \ No newline at end of file
diff --git a/docs/fr/users/01_Installation.md b/docs/fr/users/01_Installation.md
index dd1bacd00..de4e687b7 100644
--- a/docs/fr/users/01_Installation.md
+++ b/docs/fr/users/01_Installation.md
@@ -9,7 +9,7 @@ Il est toutefois de votre responsabilité de vérifier que votre hébergement pe
| Serveur web | **Apache 2** | Nginx |
| PHP | **PHP 5.5+** | PHP 5.3.8+ |
| Modules PHP | Requis : libxml, cURL, PDO_MySQL, PCRE et ctype \\ Requis (32 bits seulement) : GMP \\ Recommandé : JSON, Zlib, mbstring et iconv, ZipArchive | |
- | Base de données | **MySQL 5.0.3+** | SQLite 3.7.4+ |
+ | Base de données | **MySQL 5.5.3+** | SQLite 3.7.4+ |
| Navigateur | **Firefox** | Chrome, Opera, Safari, or IE 11+ |
## Note importante
diff --git a/docs/fr/users/07_Frequently_Asked_Questions.md b/docs/fr/users/07_Frequently_Asked_Questions.md
index 1f4d059ce..f27c92579 100644
--- a/docs/fr/users/07_Frequently_Asked_Questions.md
+++ b/docs/fr/users/07_Frequently_Asked_Questions.md
@@ -33,3 +33,14 @@ Voici une liste des flux qui ne fonctionnent pas :
* http://foulab.org/fr/rss/Foulab_News : ne passe pas la validation W3C (novembre 2014)
* http://eu.battle.net/hearthstone/fr/feed/news : ne passe pas la validation W3C (novembre 2014)
* http://webseriesmag.blogs.liberation.fr/we/atom.xml : ne fonctionne pas chez l'utilisateur mais passe l'ensemble des validations ci-dessus (novembre 2014)
+
+## Comment changer un mot de passe oublié ?
+
+Depuis la version [1.10.0](https://github.com/FreshRSS/FreshRSS/releases/tag/1.10.0), l'administrateur peut modifier le mot de passe d'un utilisateur depuis l'interface. Cette interface est disponible dans le menu ```Administration → Gestion des utilisateurs```.
+Il suffit de sélectionner l'utilisateur, de saisir un mot de passe et de valider.
+
+Depuis la version [1.8.0](https://github.com/FreshRSS/FreshRSS/releases/tag/1.8.0), l'administrateur peut modifier le mot de passe d'un utilisateur depuis un terminal. Il est bon de noter que celui-ci doit avoir un accès à PHP en ligne de commande. Pour cela, il suffit d'ouvrir son terminal et de saisir la commande suivante :
+```sh
+./cli/update_user.php --user <username> --password <password>
+```
+Pour plus d'information à ce sujet, il existe la [documentation dédiée](../../cli/README.md).
diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php
index f80b707d6..a43509ded 100644
--- a/lib/Minz/Request.php
+++ b/lib/Minz/Request.php
@@ -106,7 +106,8 @@ class Minz_Request {
$https = self::isHttps();
if (!empty($_SERVER['HTTP_HOST'])) {
- $host = $_SERVER['HTTP_HOST'];
+ //Might contain a port number, and mind IPv6 addresses
+ $host = parse_url('http://' . $_SERVER['HTTP_HOST'], PHP_URL_HOST);
} elseif (!empty($_SERVER['SERVER_NAME'])) {
$host = $_SERVER['SERVER_NAME'];
} else {
diff --git a/p/api/greader.php b/p/api/greader.php
index b1546192e..9778aecf5 100644
--- a/p/api/greader.php
+++ b/p/api/greader.php
@@ -445,6 +445,9 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl
}
function entriesToArray($entries) {
+ $feedDAO = FreshRSS_Factory::createFeedDao();
+ $arrayFeedCategoryNames = $feedDAO->arrayFeedCategoryNames();
+
$items = array();
foreach ($entries as $entry) {
$f_id = $entry->feed();
@@ -494,9 +497,6 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex
//http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#feed
header('Content-Type: application/json; charset=UTF-8');
- $feedDAO = FreshRSS_Factory::createFeedDao();
- $arrayFeedCategoryNames = $feedDAO->arrayFeedCategoryNames();
-
switch ($path) {
case 'reading-list':
$type = 'A';