summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/.htaccess3
-rw-r--r--cli/README.md58
-rw-r--r--cli/_cli.php49
-rwxr-xr-xcli/actualize-user.php23
-rwxr-xr-xcli/create-user.php48
-rwxr-xr-xcli/delete-user.php32
-rwxr-xr-xcli/do-install.php101
-rwxr-xr-xcli/export-opml-for-user.php24
-rwxr-xr-xcli/export-zip-for-user.php30
-rwxr-xr-xcli/import-for-user.php35
-rw-r--r--cli/index.html13
-rwxr-xr-xcli/list-users.php14
12 files changed, 430 insertions, 0 deletions
diff --git a/cli/.htaccess b/cli/.htaccess
new file mode 100644
index 000000000..9e768397d
--- /dev/null
+++ b/cli/.htaccess
@@ -0,0 +1,3 @@
+Order Allow,Deny
+Deny from all
+Satisfy all
diff --git a/cli/README.md b/cli/README.md
new file mode 100644
index 000000000..444606b50
--- /dev/null
+++ b/cli/README.md
@@ -0,0 +1,58 @@
+* Back to [main read-me](../README.md)
+
+# FreshRSS Command-Line Interface (CLI)
+
+## Note on access rights
+
+When using the command-line interface, remember that your user might not be the same as the one used by your Web server.
+This might create some access right problems.
+
+It is recommended to invoke commands using the same user as your Web server:
+
+```sh
+cd /usr/share/FreshRSS
+sudo -u www-data sh -c './cli/list-users.php'
+```
+
+In any case, when you are done with a series of commands, you should re-apply the access rights:
+
+```sh
+cd /usr/share/FreshRSS
+sudo chown -R :www-data .
+sudo chmod -R g+r .
+sudo chmod -R g+w ./data/
+```
+
+
+## Commands
+
+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)
+# --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
+# 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 )
+# --language can be: 'en' (default), 'fr', or one of the [supported languages](../app/i18n/)
+
+./cli/delete-user.php --user username
+
+./cli/list-users.php
+# Return a list of users, with the default/admin user first
+
+./cli/actualize-user.php --user username
+
+./cli/import-for-user.php --user username --filename /path/to/file.ext
+# The extension of the file { .json, .opml, .xml, .zip } is used to detect the type of import
+
+./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
+```
diff --git a/cli/_cli.php b/cli/_cli.php
new file mode 100644
index 000000000..7d1a7c6b2
--- /dev/null
+++ b/cli/_cli.php
@@ -0,0 +1,49 @@
+<?php
+if (php_sapi_name() !== 'cli') {
+ die('FreshRSS error: This PHP script may only be invoked from command line!');
+}
+
+require(dirname(__FILE__) . '/../constants.php');
+require(LIB_PATH . '/lib_rss.php');
+
+Minz_Configuration::register('system',
+ DATA_PATH . '/config.php',
+ DATA_PATH . '/config.default.php');
+FreshRSS_Context::$system_conf = Minz_Configuration::get('system');
+Minz_Translate::init('en');
+
+FreshRSS_Context::$isCli = true;
+
+function fail($message) {
+ fwrite(STDERR, $message . "\n");
+ die(1);
+}
+
+function cliInitUser($username) {
+ if (!ctype_alnum($username)) {
+ fail('FreshRSS error: invalid username: ' . $username . "\n");
+ }
+
+ $usernames = listUsers();
+ if (!in_array($username, $usernames)) {
+ fail('FreshRSS error: user not found: ' . $username . "\n");
+ }
+
+ FreshRSS_Context::$user_conf = get_user_configuration($username);
+ if (FreshRSS_Context::$user_conf == null) {
+ fail('FreshRSS error: invalid configuration for user: ' . $username . "\n");
+ }
+ new Minz_ModelPdo($username);
+
+ return $username;
+}
+
+function accessRights() {
+ echo '• Remember to re-apply the appropriate access rights, such as:' , "\n",
+ "\t", 'sudo chown -R :www-data . && sudo chmod -R g+r . && sudo chmod -R g+w ./data/', "\n";
+}
+
+function done($ok = true) {
+ fwrite(STDERR, 'Result: ' . ($ok ? 'success' : 'fail') . "\n");
+ exit($ok ? 0 : 1);
+}
diff --git a/cli/actualize-user.php b/cli/actualize-user.php
new file mode 100755
index 000000000..29d51753a
--- /dev/null
+++ b/cli/actualize-user.php
@@ -0,0 +1,23 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('', array(
+ 'user:',
+ ));
+
+if (empty($options['user'])) {
+ fail('Usage: ' . basename(__FILE__) . " --user username");
+}
+
+$username = cliInitUser($options['user']);
+
+fwrite(STDERR, 'FreshRSS actualizing user “' . $username . "”…\n");
+
+list($nbUpdatedFeeds, $feed) = FreshRSS_feed_Controller::actualizeFeed(0, '', true);
+
+echo "FreshRSS actualized $nbUpdatedFeeds feeds for $username\n";
+
+invalidateHttpCache($username);
+
+done($nbUpdatedFeeds > 0);
diff --git a/cli/create-user.php b/cli/create-user.php
new file mode 100755
index 000000000..008b82ce3
--- /dev/null
+++ b/cli/create-user.php
@@ -0,0 +1,48 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('', array(
+ 'user:',
+ 'password:',
+ 'api-password:',
+ 'language:',
+ 'email:',
+ 'token:',
+ 'no-default-feeds',
+ ));
+
+if (empty($options['user'])) {
+ fail('Usage: ' . basename(__FILE__) . " --user username ( --password 'password' --api-password 'api_password'" .
+ " --language en --email user@example.net --token 'longRandomString --no-default-feeds' )");
+}
+$username = $options['user'];
+if (!ctype_alnum($username)) {
+ fail('FreshRSS error: invalid username “' . $username . '”');
+}
+
+$usernames = listUsers();
+if (preg_grep("/^$username$/i", $usernames)) {
+ fail('FreshRSS error: username already taken “' . $username . '”');
+}
+
+echo 'FreshRSS creating user “', $username, "”…\n";
+
+$ok = FreshRSS_user_Controller::createUser($username,
+ empty($options['password']) ? '' : $options['password'],
+ empty($options['api-password']) ? '' : $options['api-password'],
+ array(
+ 'language' => empty($options['language']) ? '' : $options['language'],
+ 'token' => empty($options['token']) ? '' : $options['token'],
+ ),
+ !isset($options['no-default-feeds']));
+
+if (!$ok) {
+ fail('FreshRSS could not create user!');
+}
+
+invalidateHttpCache(FreshRSS_Context::$system_conf->default_user);
+
+accessRights();
+
+done($ok);
diff --git a/cli/delete-user.php b/cli/delete-user.php
new file mode 100755
index 000000000..6f0e86e17
--- /dev/null
+++ b/cli/delete-user.php
@@ -0,0 +1,32 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('', array(
+ 'user:',
+ ));
+
+if (empty($options['user'])) {
+ fail('Usage: ' . basename(__FILE__) . " --user username");
+}
+$username = $options['user'];
+if (!ctype_alnum($username)) {
+ fail('FreshRSS error: invalid username “' . $username . '”');
+}
+
+$usernames = listUsers();
+if (!preg_grep("/^$username$/i", $usernames)) {
+ fail('FreshRSS error: username not found “' . $username . '”');
+}
+
+if (strcasecmp($username, FreshRSS_Context::$system_conf->default_user) === 0) {
+ fail('FreshRSS error: default user must not be deleted: “' . $username . '”');
+}
+
+echo 'FreshRSS deleting user “', $username, "”…\n";
+
+$ok = FreshRSS_user_Controller::deleteUser($username);
+
+invalidateHttpCache(FreshRSS_Context::$system_conf->default_user);
+
+done($ok);
diff --git a/cli/do-install.php b/cli/do-install.php
new file mode 100755
index 000000000..667191680
--- /dev/null
+++ b/cli/do-install.php
@@ -0,0 +1,101 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+require(LIB_PATH . '/lib_install.php');
+
+$params = array(
+ 'environment:',
+ 'base_url:',
+ 'title:',
+ 'default_user:',
+ 'allow_anonymous',
+ 'allow_anonymous_refresh',
+ 'auth_type:',
+ 'api_enabled',
+ 'allow_robots',
+ );
+
+$dBparams = array(
+ 'db-type:',
+ 'db-host:',
+ 'db-user:',
+ 'db-password:',
+ 'db-base:',
+ 'db-prefix:',
+ );
+
+$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/" .
+ " --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 )");
+}
+
+fwrite(STDERR, 'FreshRSS install…' . "\n");
+
+$requirements = checkRequirements();
+if ($requirements['all'] !== 'ok') {
+ $message = 'FreshRSS install failed requirements:' . "\n";
+ foreach ($requirements as $requirement => $check) {
+ if ($check !== 'ok' && $requirement !== 'all') {
+ $message .= '• ' . $requirement . "\n";
+ }
+ }
+ fail($message);
+}
+
+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'))) {
+ fail('FreshRSS invalid authentication method (auth_type must be one of { form, http_auth, none }: ' . $options['auth_type']);
+}
+
+$config = array(
+ 'salt' => generateSalt(),
+ 'db' => FreshRSS_Context::$system_conf->db,
+ );
+
+foreach ($params as $param) {
+ $param = rtrim($param, ':');
+ if (isset($options[$param])) {
+ $config[$param] = $options[$param] === false ? true : $options[$param];
+ }
+}
+
+if ((!empty($config['base_url'])) && server_is_public($config['base_url'])) {
+ $config['pubsubhubbub_enabled'] = true;
+}
+
+foreach ($dBparams as $dBparam) {
+ $dBparam = rtrim($dBparam, ':');
+ if (!empty($options[$dBparam])) {
+ $param = substr($dBparam, strlen('db-'));
+ $config['db'][$param] = $options[$dBparam];
+ }
+}
+
+if (file_put_contents(join_path(DATA_PATH, 'config.php'), "<?php\n return " . var_export($config, true) . ";\n") === false) {
+ fail('FreshRSS could not write configuration file!: ' . join_path(DATA_PATH, 'config.php'));
+}
+
+$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']));
+}
+
+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";
+
+accessRights();
+
+if (!deleteInstall()) {
+ fail('FreshRSS access right problem while deleting install file!');
+}
+
+done();
diff --git a/cli/export-opml-for-user.php b/cli/export-opml-for-user.php
new file mode 100755
index 000000000..95b12281f
--- /dev/null
+++ b/cli/export-opml-for-user.php
@@ -0,0 +1,24 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('', array(
+ 'user:',
+ ));
+
+if (empty($options['user'])) {
+ fail('Usage: ' . basename(__FILE__) . " --user username > /path/to/file.opml.xml");
+}
+
+$username = cliInitUser($options['user']);
+
+fwrite(STDERR, 'FreshRSS exporting OPML for user “' . $username . "”…\n");
+
+$importController = new FreshRSS_importExport_Controller();
+
+$ok = false;
+$ok = $importController->exportFile(true, false, array(), 0, $username);
+
+invalidateHttpCache($username);
+
+done($ok);
diff --git a/cli/export-zip-for-user.php b/cli/export-zip-for-user.php
new file mode 100755
index 000000000..92fe9bf9a
--- /dev/null
+++ b/cli/export-zip-for-user.php
@@ -0,0 +1,30 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('', array(
+ 'user:',
+ 'max-feed-entries:',
+ ));
+
+if (empty($options['user'])) {
+ fail('Usage: ' . basename(__FILE__) . " --user username ( --max-feed-entries 100 ) > /path/to/file.zip");
+}
+
+$username = cliInitUser($options['user']);
+
+fwrite(STDERR, 'FreshRSS exporting ZIP for user “' . $username . "”…\n");
+
+$importController = new FreshRSS_importExport_Controller();
+
+$ok = false;
+try {
+ $ok = $importController->exportFile(true, true, true,
+ empty($options['max-feed-entries']) ? 100 : intval($options['max-feed-entries']),
+ $username);
+} catch (FreshRSS_ZipMissing_Exception $zme) {
+ fail('FreshRSS error: Lacking php-zip extension!');
+}
+invalidateHttpCache($username);
+
+done($ok);
diff --git a/cli/import-for-user.php b/cli/import-for-user.php
new file mode 100755
index 000000000..29084f062
--- /dev/null
+++ b/cli/import-for-user.php
@@ -0,0 +1,35 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$options = getopt('', array(
+ 'user:',
+ 'filename:',
+ ));
+
+if (empty($options['user']) || empty($options['filename'])) {
+ fail('Usage: ' . basename(__FILE__) . " --user username --filename /path/to/file.ext");
+}
+
+$username = cliInitUser($options['user']);
+
+$filename = $options['filename'];
+if (!is_readable($filename)) {
+ fail('FreshRSS error: file is not readable “' . $filename . '”');
+}
+
+echo 'FreshRSS importing ZIP/OPML/JSON for user “', $username, "”…\n";
+
+$importController = new FreshRSS_importExport_Controller();
+
+$ok = false;
+try {
+ $ok = $importController->importFile($filename, $filename, $username);
+} catch (FreshRSS_ZipMissing_Exception $zme) {
+ fail('FreshRSS error: Lacking php-zip extension!');
+} catch (FreshRSS_Zip_Exception $ze) {
+ fail('FreshRSS error: ZIP archive cannot be imported! Error code: ' . $ze->zipErrorCode());
+}
+invalidateHttpCache($username);
+
+done($ok);
diff --git a/cli/index.html b/cli/index.html
new file mode 100644
index 000000000..85faaa37e
--- /dev/null
+++ b/cli/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB">
+<head>
+<meta charset="UTF-8" />
+<meta http-equiv="Refresh" content="0; url=/" />
+<title>Redirection</title>
+<meta name="robots" content="noindex" />
+</head>
+
+<body>
+<p><a href="/">Redirection</a></p>
+</body>
+</html>
diff --git a/cli/list-users.php b/cli/list-users.php
new file mode 100755
index 000000000..e690ff451
--- /dev/null
+++ b/cli/list-users.php
@@ -0,0 +1,14 @@
+#!/usr/bin/php
+<?php
+require('_cli.php');
+
+$users = listUsers();
+sort($users);
+if (FreshRSS_Context::$system_conf->default_user !== '') {
+ array_unshift($users, FreshRSS_Context::$system_conf->default_user);
+ $users = array_unique($users);
+}
+
+foreach ($users as $user) {
+ echo $user, "\n";
+}