From c27c9d1d359828a071159995689c9c3b28d99891 Mon Sep 17 00:00:00 2001
From: rdalverny
Date: Sat, 22 Jan 2022 18:54:11 +0100
Subject: Move public resources under public/ directory
Existing setups need to update their server config to point (or link to)
public/ directory instead of the root of the code repo.
Configuration (and password) location also changes from custom/ and
admin/inc to custom/config/.
That way, config and code library move out of the publicly served
file tree.
Apart from the change of the web root, config should be migrated
seamlessly.
---
.gitignore | 9 +-
Makefile | 12 +-
admin/administration.php | 59 ---------
admin/changepassword.php | 12 --
admin/default.css | 232 ------------------------------------
admin/img/button-add.png | Bin 244 -> 0 bytes
admin/img/button-delete.png | Bin 201 -> 0 bytes
admin/img/button-h.png | Bin 212 -> 0 bytes
admin/img/button.png | Bin 212 -> 0 bytes
admin/img/h3.png | Bin 212 -> 0 bytes
admin/img/moonmoon.png | Bin 564 -> 0 bytes
admin/img/nav-admin.png | Bin 1519 -> 0 bytes
admin/img/nav-feed.png | Bin 1090 -> 0 bytes
admin/inc/auth.inc.php | 13 --
admin/index.php | 149 -----------------------
admin/login.php | 51 --------
admin/logout.php | 10 --
admin/purgecache.php | 24 ----
admin/subscriptions.php | 84 -------------
admin/template.php | 54 ---------
app/classes/PlanetConfig.php | 76 ++++++++++--
app/helpers.php | 41 ++++++-
atom.php | 41 -------
cron.php | 13 --
custom/img/feed.png | Bin 484 -> 0 bytes
custom/img/moonmoon.png | Bin 73408 -> 0 bytes
custom/img/moonmoon@128w.png | Bin 8671 -> 0 bytes
custom/img/moonmoon@256w.png | Bin 24255 -> 0 bytes
custom/img/opml.png | Bin 31542 -> 0 bytes
custom/style/dark.css | 125 -------------------
custom/style/default.css | 158 ------------------------
custom/style/green.css | 132 --------------------
custom/style/light.css | 124 -------------------
custom/style/mobile.css | 8 --
index.php | 40 -------
install.php | 100 ----------------
phpcs.xml | 4 +-
phpunit.xml | 4 +-
postload.php | 28 -----
public/admin/administration.php | 59 +++++++++
public/admin/changepassword.php | 12 ++
public/admin/default.css | 232 ++++++++++++++++++++++++++++++++++++
public/admin/img/button-add.png | Bin 0 -> 244 bytes
public/admin/img/button-delete.png | Bin 0 -> 201 bytes
public/admin/img/button-h.png | Bin 0 -> 212 bytes
public/admin/img/button.png | Bin 0 -> 212 bytes
public/admin/img/h3.png | Bin 0 -> 212 bytes
public/admin/img/moonmoon.png | Bin 0 -> 564 bytes
public/admin/img/nav-admin.png | Bin 0 -> 1519 bytes
public/admin/img/nav-feed.png | Bin 0 -> 1090 bytes
public/admin/inc/auth.inc.php | 9 ++
public/admin/index.php | 149 +++++++++++++++++++++++
public/admin/login.php | 51 ++++++++
public/admin/logout.php | 10 ++
public/admin/purgecache.php | 24 ++++
public/admin/subscriptions.php | 84 +++++++++++++
public/admin/template.php | 54 +++++++++
public/atom.php | 4 +
public/cron.php | 13 ++
public/custom/img/feed.png | Bin 0 -> 484 bytes
public/custom/img/moonmoon.png | Bin 0 -> 73408 bytes
public/custom/img/moonmoon@128w.png | Bin 0 -> 8671 bytes
public/custom/img/moonmoon@256w.png | Bin 0 -> 24255 bytes
public/custom/img/opml.png | Bin 0 -> 31542 bytes
public/custom/style/dark.css | 125 +++++++++++++++++++
public/custom/style/default.css | 158 ++++++++++++++++++++++++
public/custom/style/green.css | 132 ++++++++++++++++++++
public/custom/style/light.css | 124 +++++++++++++++++++
public/custom/style/mobile.css | 8 ++
public/feed/index.php | 43 +++++++
public/index.php | 40 +++++++
public/install.php | 98 +++++++++++++++
public/postload.php | 28 +++++
tests/InstallTest.php | 47 +++++++-
74 files changed, 1622 insertions(+), 1485 deletions(-)
delete mode 100755 admin/administration.php
delete mode 100644 admin/changepassword.php
delete mode 100755 admin/default.css
delete mode 100644 admin/img/button-add.png
delete mode 100644 admin/img/button-delete.png
delete mode 100644 admin/img/button-h.png
delete mode 100644 admin/img/button.png
delete mode 100644 admin/img/h3.png
delete mode 100644 admin/img/moonmoon.png
delete mode 100644 admin/img/nav-admin.png
delete mode 100644 admin/img/nav-feed.png
delete mode 100644 admin/inc/auth.inc.php
delete mode 100755 admin/index.php
delete mode 100755 admin/login.php
delete mode 100644 admin/logout.php
delete mode 100644 admin/purgecache.php
delete mode 100755 admin/subscriptions.php
delete mode 100755 admin/template.php
delete mode 100644 atom.php
delete mode 100644 cron.php
delete mode 100644 custom/img/feed.png
delete mode 100644 custom/img/moonmoon.png
delete mode 100644 custom/img/moonmoon@128w.png
delete mode 100644 custom/img/moonmoon@256w.png
delete mode 100644 custom/img/opml.png
delete mode 100644 custom/style/dark.css
delete mode 100644 custom/style/default.css
delete mode 100644 custom/style/green.css
delete mode 100644 custom/style/light.css
delete mode 100644 custom/style/mobile.css
delete mode 100755 index.php
delete mode 100755 install.php
delete mode 100644 postload.php
create mode 100755 public/admin/administration.php
create mode 100644 public/admin/changepassword.php
create mode 100755 public/admin/default.css
create mode 100644 public/admin/img/button-add.png
create mode 100644 public/admin/img/button-delete.png
create mode 100644 public/admin/img/button-h.png
create mode 100644 public/admin/img/button.png
create mode 100644 public/admin/img/h3.png
create mode 100644 public/admin/img/moonmoon.png
create mode 100644 public/admin/img/nav-admin.png
create mode 100644 public/admin/img/nav-feed.png
create mode 100644 public/admin/inc/auth.inc.php
create mode 100755 public/admin/index.php
create mode 100755 public/admin/login.php
create mode 100644 public/admin/logout.php
create mode 100644 public/admin/purgecache.php
create mode 100755 public/admin/subscriptions.php
create mode 100755 public/admin/template.php
create mode 100644 public/atom.php
create mode 100644 public/cron.php
create mode 100644 public/custom/img/feed.png
create mode 100644 public/custom/img/moonmoon.png
create mode 100644 public/custom/img/moonmoon@128w.png
create mode 100644 public/custom/img/moonmoon@256w.png
create mode 100644 public/custom/img/opml.png
create mode 100644 public/custom/style/dark.css
create mode 100644 public/custom/style/default.css
create mode 100644 public/custom/style/green.css
create mode 100644 public/custom/style/light.css
create mode 100644 public/custom/style/mobile.css
create mode 100644 public/feed/index.php
create mode 100755 public/index.php
create mode 100755 public/install.php
create mode 100644 public/postload.php
diff --git a/.gitignore b/.gitignore
index 5101c47..a1813f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,16 @@
+.DS_Store
+.idea
+.phpunit.*
/cache
/custom/config.yml
/custom/people.opml
/custom/people.opml.bak
+/custom/config
/admin/inc/pwd.inc.php
/vendor/
/tests/_output/*
/nbproject/private/
-/.idea/
tmp/
-
-.phpunit.result.cache
-
+public/tests
diff --git a/Makefile b/Makefile
index 00506fa..7548027 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,13 @@ VENDOR=./vendor/bin/
PHPUNIT=php -dxdebug.enabled=1 -dxdebug.mode=coverage ./vendor/bin/phpunit --coverage-text
test:
- { php -S 127.0.0.1:8081 >& /dev/null & }; \
+ rm -f public/tests && ln -s ../tests public/tests
+ { php -S 127.0.0.1:8081 -t public/ >& /dev/null & }; \
PID=$$!; \
$(PHPUNIT); \
RES=$$?; \
kill $$PID; \
+ rm public/tests
exit $$RES
fmt:
@@ -24,9 +26,13 @@ stan:
report:
$(VENDOR)phpmd \
- admin,app,custom,docs,tests,atom.php,cron.php,index.php,install.php,postload.php \
+ app,custom,docs,tests,public \
html \
cleancode,codesize,controversial,design,naming,unusedcode > tmp/report.html
serve:
- php -S localhost:5555 -t .
+ php -S localhost:5555 -t public/
+
+clean:
+ rm -fr ./cache/*
+ rm -fr ./custom/config/*
\ No newline at end of file
diff --git a/admin/administration.php b/admin/administration.php
deleted file mode 100755
index e6236fd..0000000
--- a/admin/administration.php
+++ /dev/null
@@ -1,59 +0,0 @@
-getOpmlFile());
-$opml_people = $opml->getPeople();
-$page_id = 'admin-admin';
-$header_extra = <<<"HTML"
-
-
-HTML;
-
-$repo_url = 'https://github.com/moonmoon/moonmoon';
-$releases_url = "$repo_url/releases";
-$link_url = "$releases_url";
-$version_current = str_replace('%s', $moon_version, $l10n->getString('Your moonmoon instance version is %s.'));
-$version_action = str_replace('%s', $link_url, $l10n->getString('You can check for a more recent version on: %s.'));
-
-$page_content = <<<"FRAGMENT"
-
-
-
-
-
-
-
-FRAGMENT;
-
-$footer_extra = '';
-$admin_access = 1;
-require_once __DIR__ . '/template.php';
diff --git a/admin/changepassword.php b/admin/changepassword.php
deleted file mode 100644
index c1e61ff..0000000
--- a/admin/changepassword.php
+++ /dev/null
@@ -1,12 +0,0 @@
-verify($_POST['_csrf'], 'frmPassword') && isset($_POST['password']) && ('' != $_POST['password'])) {
- $out = sprintf('', hash('sha256', $_POST['password']));
- file_put_contents(__DIR__.'/inc/pwd.inc.php', $out);
- die("Password changed. Login");
-} else {
- die('Can not change password');
-}
diff --git a/admin/default.css b/admin/default.css
deleted file mode 100755
index fcba3f4..0000000
--- a/admin/default.css
+++ /dev/null
@@ -1,232 +0,0 @@
-html, body{
- margin: 0;
- padding: 0;
-}
-html{
- font-size: 62.5%;
-}
-body{
- background: #FFF;
- color: #333;
- font: 1.1em/1.6em "Lucida Grande", Tahoma, Arial, sans-serif;
-}
-
-
-fieldset{
- border: 0;
- padding: 0;
- margin: 1em 0;
-}
-input.text{
- border: 1px solid #BBB;
- padding: 4px;
-}
-input.submit{
- font-size: 1em;
- padding: 4px;
- background: #D1D1D1 url(img/button.png) repeat-x left center;
- border: 1px solid #FFF;
- border-bottom: 1px solid #CECECE;
- border-right: 1px solid #CECECE;
- cursor: pointer;
-}
-input.submit:hover{
- background: #D1D1D1 url(img/button-h.png) repeat-x left center;
- color: #000;
- border: 1px solid #FFF;
- border-bottom: 1px solid #C6C6C6;
- border-right: 1px solid #C6C6C6;
-}
-input.delete{
- margin-left: 1em;
-}
-input.delete:hover{
- background: #ffabab url(img/button-delete.png) repeat-x left center;
- color: #C00;
- border: 1px solid #FCC;
- border-bottom: 1px solid #F99;
- border-right: 1px solid #F99;
-}
-input.add{
- font-weight: bold;
-}
-input.add:hover{
- background: #65a5e1 url(img/button-add.png) repeat-x left center;
- color: #20466a;
- border: 1px solid #a6c7e5;
- border-bottom: 1px solid #4f90cd;
- border-right: 1px solid #4f90cd;
-}
-p.help{
- font-size: 0.8em;
- color: #999;
- margin: 0;
-}
-
-#page{
-}
-
- header{
- background: #E0E0E0 url(img/moonmoon.png) no-repeat right center;
- border-top: 5px solid #D0D0D0;
- margin: 0;
- padding: 10px;
- }
- header h1{
- display: none;
- margin: 0 0 0 20px;
- padding: 0;
- height: 14px;
- width: 95px;
- background: transparent url(img/moonmoon.png) no-repeat left center;
-
- overflow: hidden;
- text-indent: -1000em;
- }
- header p{
- margin: 0 0 0 20px;
- padding: 0;
- }
- header p a{
- color: #AAA;
- }
- header p a:hover{
- color: #111;
- }
-
-
- nav ul{
- margin: 20px 30px;
- padding: 0;
- list-style: none;
- }
- nav ul:after {content: "."; display: block; height: 0; clear: both; visibility: hidden; }
- nav ul {display: inline-table;}
- /* Hides from IE-mac \*/
- * html nav ul {height: 1%;}
- nav ul {display: block;}
- /* End hide from IE-mac */
-
- nav ul li{
- display: block;
- float: left;
- }
- nav ul li a{
- display: block;
- border: 1px solid #DDD;
- padding: 8px 8px 8px 36px;
- margin-right: 8px;
- text-decoration: none;
- color: #666;
- background-repeat: no-repeat;
- background-position: 6px center;
- }
- nav ul li a:hover,
- body#admin-feed #nav-feed a,
- body#admin-admin #nav-admin a {
- background-color: #f0f2f6;
- border-color: #AAA;
- color: #111;
- }
- #nav-feed a{
- background-image: url(img/nav-feed.png);
- }
- #nav-admin a{
- background-image: url(img/nav-admin.png);
- }
-
- #content{
- margin: 20px 30px;
- }
-
- .widget{
- margin: 20px 0;
- }
- .widget h3{
- background: #3e4350 url(img/h3.png) repeat-x left center;
- color: #FFF;
- text-transform: uppercase;
- margin: 0;
- padding: 10px;
- }
- .widget form{
- padding: 10px;
- border: 1px solid #EEE;
- border-top: 0;
- }
-
- #feedmanage p.select{
- margin: 3px 0;
- }
- #feedmanage p.action span.count{
- float: right;
- padding-right: 10px;
- font-size: 1.3em;
- }
- #feedmanage table{
- width: 99%;
- border-collapse: collapse;
- border: 1px solid #f0f2f6;
- }
- #feedmanage thead th{
- background: #f0f2f6;
- text-align: left;
- padding: 6px;
- }
- #feedmanage thead span{
- display: none;
- }
- #feedmanage tr{
- border-bottom: 1px solid #e8ebf1;
- }
- #feedmanage tr.even td{
- background: #f0f2f6;
- width: auto;
- }
- #feedmanage .text{
- background: transparent;
- border: 1px solid #FFF;
- width: 90%;
- }
- #feedmanage tr.even td .text{
- border: 1px solid #f0f2f6;
- }
- #feedmanage tr td input.text:focus{
- background: #FFF;
- border: 1px solid #4392b7;
- }
-
- #feedmanage tr.selected td{
- background: #ffabab;
- background: #4392b7;
- color: #FFF;
- }
- #feedmanage tr.selected td .text{
- color: #FFF;
- border: 1px solid #4392b7;
- }
- #feedmanage tr td input.text:focus{
- background: #FFF;
- color: #000;
- border: 1px solid #4392b7;
- }
-
-/* Login form
-*******************************************************************************/
-form.login {
- width: 400px;
- margin: 0 auto;
-}
-form.login fieldset {
- border: 1px solid #CCC;
- text-align: center;
-}
-
-p.logout {
- float: right;
- margin: 20px 30px 0 0;
-}
- p.logout a {
- padding: 8px;
- display: block;
- }
diff --git a/admin/img/button-add.png b/admin/img/button-add.png
deleted file mode 100644
index 859364a..0000000
Binary files a/admin/img/button-add.png and /dev/null differ
diff --git a/admin/img/button-delete.png b/admin/img/button-delete.png
deleted file mode 100644
index 7bfebc2..0000000
Binary files a/admin/img/button-delete.png and /dev/null differ
diff --git a/admin/img/button-h.png b/admin/img/button-h.png
deleted file mode 100644
index 0a43a6a..0000000
Binary files a/admin/img/button-h.png and /dev/null differ
diff --git a/admin/img/button.png b/admin/img/button.png
deleted file mode 100644
index fad6ccc..0000000
Binary files a/admin/img/button.png and /dev/null differ
diff --git a/admin/img/h3.png b/admin/img/h3.png
deleted file mode 100644
index 0c86748..0000000
Binary files a/admin/img/h3.png and /dev/null differ
diff --git a/admin/img/moonmoon.png b/admin/img/moonmoon.png
deleted file mode 100644
index 26cc8f4..0000000
Binary files a/admin/img/moonmoon.png and /dev/null differ
diff --git a/admin/img/nav-admin.png b/admin/img/nav-admin.png
deleted file mode 100644
index 3077a54..0000000
Binary files a/admin/img/nav-admin.png and /dev/null differ
diff --git a/admin/img/nav-feed.png b/admin/img/nav-feed.png
deleted file mode 100644
index 00c896b..0000000
Binary files a/admin/img/nav-feed.png and /dev/null differ
diff --git a/admin/inc/auth.inc.php b/admin/inc/auth.inc.php
deleted file mode 100644
index 0305b13..0000000
--- a/admin/inc/auth.inc.php
+++ /dev/null
@@ -1,13 +0,0 @@
-' . _g('You might want to install moonmoon.') . '
');
-}
-
-//Instantiate app
-$Planet = new Planet($PlanetConfig);
-
-//Load
-if (0 < $Planet->loadOpml($PlanetConfig->getOpmlFile())) {
- $Planet->loadFeeds();
- $items = $Planet->getItems();
-}
-
-$everyone = $Planet->getPeople();
-$count_feeds = count($everyone);
-$page_id = 'admin-feed';
-$footer_extra = <<
- var allCheckboxes = function(status){
- var form = document.getElementById('feedmanage');
- var selectboxes = form.getElementsByTagName('input');
- for (var i=0; i
-FRAGMENT;
-
-ob_start();
-?>
-
-
-
-
-
-
-
-', $hash_pwd));
- }
-
- setcookie('auth', $hash_pwd);
- header('Location: index.php');
-}
-
-$page_content = <<
-
-
-FRAGMENT;
-
-$footer_extra = <<
-
-
-
-FRAGMENT;
-
-$page_id = 'admin-login';
-$admin_access = 0;
-
-require_once __DIR__ . '/template.php';
diff --git a/admin/logout.php b/admin/logout.php
deleted file mode 100644
index 88c60b3..0000000
--- a/admin/logout.php
+++ /dev/null
@@ -1,10 +0,0 @@
-verify($_POST['_csrf'], 'feedmanage')) {
- die('Invalid CSRF token!');
-}
-
-$opmlFile = $PlanetConfig->getOpmlFile();
-
-if (isset($_POST['upload']) &&
- isset($_FILES['opml']) &&
- is_uploaded_file($_FILES['opml']['tmp_name']) &&
- $_FILES['opml']['size'] > 0) {
- OpmlManager::backup($opmlFile);
- $newOpml = new Opml();
- $newOpml->parse(file_get_contents($_FILES['opml']['tmp_name']));
- OpmlManager::save($newOpml, $opmlFile);
-} elseif (isset($_POST['opml']) || isset($_POST['add'])) {
- // Load old OPML
- $oldOpml = OpmlManager::load($opmlFile);
- if ($PlanetConfig->getName() === '') {
- $PlanetConfig->setName($oldOpml->getTitle());
- }
- $newOpml = new Opml();
- $newOpml->title = $PlanetConfig->getName();
-
- // Remove slashes if needed
- if (isset($_POST['opml'])) {
- array_walk_recursive($_POST['opml'], 'removeSlashes');
- }
- // Delete/Save feeds
- if (isset($_POST['delete']) || isset($_POST['save'])) {
- foreach ($_POST['opml'] as $person) {
- if (isset($_POST['delete'])) {
- //delete mode, check if to be deleted
- if (!isset($person['delete'])) {
- $newOpml->entries[] = $person;
- }
- } else {
- $newOpml->entries[] = $person;
- }
- }
- }
-
- // Add feed
- if (isset($_POST['add'])) {
- if ('http://' != $_POST['url']) {
- //autodiscover feed
- $feed = new SimplePie();
- $feed->enable_cache(false);
- $feed->set_feed_url($_POST['url']);
- if (!$PlanetConfig->checkCertificates()) {
- $feed->set_curl_options([
- CURLOPT_SSL_VERIFYHOST => false,
- CURLOPT_SSL_VERIFYPEER => false
- ]);
- }
- $feed->init();
- $feed->handle_content_type();
- $person['name'] = html_entity_decode($feed->get_title());
- $person['website'] = $feed->get_permalink();
- $person['feed'] = $feed->feed_url;
- $person['isDown'] = '0';
-
- $oldOpml->entries[] = $person;
- }
- $newOpml->entries = $oldOpml->entries;
- }
-
- // Backup old OPML
- OpmlManager::backup($opmlFile);
-
- // Save new OPML
- OpmlManager::save($newOpml, $opmlFile);
-}
-header("Location: index.php");
-die();
diff --git a/admin/template.php b/admin/template.php
deleted file mode 100755
index 964c639..0000000
--- a/admin/template.php
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- =@$header_extra ?: ''; ?>
-
-
-
-
-
-
-
-
-
=_g('Logout')?>
-
-
-
-
-
-
-
-
- =@$page_content ?: ''; ?>
-
-
-
-
-=@$footer_extra ?: ''; ?>
-
-
-
diff --git a/app/classes/PlanetConfig.php b/app/classes/PlanetConfig.php
index b8233e0..6094956 100644
--- a/app/classes/PlanetConfig.php
+++ b/app/classes/PlanetConfig.php
@@ -41,23 +41,31 @@ class PlanetConfig
public static function load(string $dir)
{
$config = new PlanetConfig;
- $configFile = realpath($dir . '/../custom/config.yml');
- if (self::isInstalled()) {
- $conf = Spyc::YAMLLoad($configFile);
-
- // this is a check to upgrade older config file without l10n
- if (!isset($conf['locale'])) {
- $resetPlanetConfig = new PlanetConfig($conf);
- file_put_contents($configFile, $resetPlanetConfig->toYaml());
- $conf = Spyc::YAMLLoad($configFile);
+ if (!self::isInstalled()) {
+ if (!self::isInstalledPre10Version()) {
+ return $config;
+ }
- return $resetPlanetConfig;
+ if (!self::migratePre10Version()) {
+ error_log('Failed to migrate configuration.');
+ return $config;
}
+ }
- $config = new PlanetConfig($conf);
+ $configFile = realpath(config_path('config.yml'));
+ $conf = Spyc::YAMLLoad($configFile);
+
+ // this is a check to upgrade older config file without l10n
+ if (!isset($conf['locale'])) {
+ $resetPlanetConfig = new PlanetConfig($conf);
+ file_put_contents($configFile, $resetPlanetConfig->toYaml());
+ $conf = Spyc::YAMLLoad($configFile);
+ return $resetPlanetConfig;
}
+ $config = new PlanetConfig($conf);
+
return $config;
}
@@ -67,11 +75,55 @@ class PlanetConfig
* @return bool
*/
public static function isInstalled() : bool
+ {
+ return file_exists(config_path('config.yml')) &&
+ file_exists(config_path('people.opml'));
+ }
+
+ /**
+ * Or is it a pre-10 version installed?
+ * (that is, config is stored in custom/config.yml instead of custom/config/config.yml)
+ */
+ public static function isInstalledPre10Version(): bool
{
return file_exists(custom_path('config.yml')) &&
file_exists(custom_path('people.opml'));
}
+ /**
+ * Migrate config files from old to new location.
+ * Purge cache.
+ *
+ * @return bool true if succeeded, false otherwise
+ */
+ public static function migratePre10Version() : bool
+ {
+ if (!is_dir(config_path())) {
+ if (!mkdir(config_path(), 0777, true)) {
+ return false;
+ }
+ }
+
+ return self::migrate_file('config.yml') &&
+ self::migrate_file('people.opml');
+ }
+
+ public static function migrate_file($file) : bool
+ {
+ $source = custom_path($file);
+ $dest = config_path($file);
+ if (!copy($source, $source . '.bak')) {
+ error_log("Failed to make a backup of ${source}");
+ return false;
+ }
+ if (!rename($source, $dest)) {
+ error_log("Failed to move ${source} to ${dest}");
+ return false;
+ }
+
+ return true;
+ }
+
/**
* Merge the configuration of the user in the default one.
*
@@ -115,7 +167,7 @@ class PlanetConfig
public function getOpmlFile()
{
if (is_null($this->opmlFile)) {
- $this->opmlFile = realpath(__DIR__ . '/../../custom/people.opml');
+ $this->opmlFile = realpath(config_path('people.opml'));
}
return $this->opmlFile;
}
diff --git a/app/helpers.php b/app/helpers.php
index a7e68ae..24f9d38 100644
--- a/app/helpers.php
+++ b/app/helpers.php
@@ -18,8 +18,9 @@ register_polyfills();
*
* @param string $file Append this filename to the returned path.
* @return string
+ * @deprecated
*/
-function custom_path($file = '')
+function custom_path($file = '') : string
{
return __DIR__.'/../custom' . (!empty($file) ? '/'.$file : '');
}
@@ -29,8 +30,9 @@ function custom_path($file = '')
*
* @param string $file Append this filename to the returned path.
* @return string
+ * @deprecated
*/
-function views_path($file = '')
+function views_path($file = '') : string
{
return custom_path('views/' . $file);
}
@@ -40,12 +42,37 @@ function views_path($file = '')
*
* @param string $file Append this filename to the returned path.
* @return string
+ * @deprecated
*/
-function admin_path($file = '')
+function admin_path($file = '') : string
{
return __DIR__.'/../admin' . (!empty($file) ? '/'.$file : '');
}
+/**
+ * Path to the _config_ directory.
+ *
+ * @param string $file Append this filename to the returned path
+ * @param string $site Append this site as a sub-directory before the file
+ * @return string
+ */
+function config_path($file = '', $site = '') : string
+{
+ $path = __DIR__ . '/../custom/config';
+ if (!empty($site)) {
+ $path .= '/' . $site;
+ }
+ if (!empty($file)) {
+ $path .= '/' . $file;
+ }
+ return $path;
+}
+
+function cache_path($site = '') : string
+{
+ return __DIR__ . '/../cache';
+}
+
/**
* Shortcut to Simplel10n::getString().
*
@@ -64,10 +91,16 @@ function _g($str, $comment = '')
function removeCustomFiles()
{
$toRemove = [
+ config_path('config.yml'),
+ config_path('people.opml'),
+ config_path('people.opml.bak'),
+ cache_path('cache'),
+
+ // legacy location
custom_path('config.yml'),
+ custom_path('config.yml.bak'),
custom_path('people.opml'),
custom_path('people.opml.bak'),
- custom_path('cache')
];
foreach ($toRemove as $path) {
diff --git a/atom.php b/atom.php
deleted file mode 100644
index ddeebc0..0000000
--- a/atom.php
+++ /dev/null
@@ -1,41 +0,0 @@
-loadOpml($PlanetConfig->getOpmlFile()) == 0) {
- exit;
-}
-
-$Planet->loadFeeds();
-$items = $Planet->getItems();
-$limit = $PlanetConfig->getMaxDisplay();
-$count = 0;
-
-header('Content-Type: text/xml; charset=UTF-8');
-echo '';
-?>
-
- =htmlspecialchars($PlanetConfig->getName())?>
- =htmlspecialchars($PlanetConfig->getName())?>
- =$PlanetConfig->getUrl()?>
-
-
- =gmdate('Y-m-d\TH:i:s\Z')?>
- =htmlspecialchars($PlanetConfig->getName())?>
-
-
-
- =htmlspecialchars($item->get_feed()->getName())?> : =htmlspecialchars($item->get_title())?>
- =htmlspecialchars($item->get_id())?>
-
- =$item->get_gmdate('Y-m-d\TH:i:s\Z')?>
- =$item->get_gmdate('Y-m-d\TH:i:s\Z')?>
- =($item->get_author() ? $item->get_author()->get_name() : 'anonymous')?>
- get_content()?>]]>
-
-
-
-
-
diff --git a/cron.php b/cron.php
deleted file mode 100644
index 688bebe..0000000
--- a/cron.php
+++ /dev/null
@@ -1,13 +0,0 @@
-loadOpml($PlanetConfig->getOpmlFile())) {
- $Planet->download(1.0);
-}
-
-if ($PlanetConfig->getDebug()) {
- foreach ($Planet->errors as $error) {
- echo $error->toString() . "\n";
- }
-}
diff --git a/custom/img/feed.png b/custom/img/feed.png
deleted file mode 100644
index f8cd243..0000000
Binary files a/custom/img/feed.png and /dev/null differ
diff --git a/custom/img/moonmoon.png b/custom/img/moonmoon.png
deleted file mode 100644
index 10f9736..0000000
Binary files a/custom/img/moonmoon.png and /dev/null differ
diff --git a/custom/img/moonmoon@128w.png b/custom/img/moonmoon@128w.png
deleted file mode 100644
index 2a164aa..0000000
Binary files a/custom/img/moonmoon@128w.png and /dev/null differ
diff --git a/custom/img/moonmoon@256w.png b/custom/img/moonmoon@256w.png
deleted file mode 100644
index b52c4bb..0000000
Binary files a/custom/img/moonmoon@256w.png and /dev/null differ
diff --git a/custom/img/opml.png b/custom/img/opml.png
deleted file mode 100644
index 7a9d86f..0000000
Binary files a/custom/img/opml.png and /dev/null differ
diff --git a/custom/style/dark.css b/custom/style/dark.css
deleted file mode 100644
index 1ee004b..0000000
--- a/custom/style/dark.css
+++ /dev/null
@@ -1,125 +0,0 @@
-html{
- font-family: Arial, sans-serif;
- color: #FFF;
- background: #333;
- font-size: 62.5%;
-}
-
-body{
- margin: 0;
- padding: 0;
- font-size: 1.1em;
- line-height: 1.5em;
-}
-
-a{
- color: #CCC;
-}
-
-a:visited{
- color: #AAA;
-}
-
-a:hover{
- color: #FFF;
-}
-
-a img{
- border: none;
-}
-
-pre, code{
- font-size: 1.2em;
-}
-/* Top
-*******************************************************************************/
-#page{
- width: 640px;
- margin: 0 auto;
-}
-/* Top
-*******************************************************************************/
-#top{
- padding: 2%;
- margin: 3em;
- line-height: 2em;
- color: #FFF;
- text-align: center;
-}
-
- #top h1{
- margin: 0;
- letter-spacing: -1px;
- font-family: Georgia, serif;
- }
-
-/* Top
-*******************************************************************************/
-#content{
- width: 66%;
- padding: 0 2%;
- margin: 0;
- float: right;
-}
-
-.post{
- margin-bottom: 3em;
-}
-
-.post-title, .post-title a{
- font-family: Georgia, serif;
- color: #CCC;
- text-decoration: none;
-}
-
-.post-title{
- padding-bottom: 0.5em;
- border-bottom: 1px solid #444;
-}
-
-.post-info{
- color: #999;
- margin-top: -1em;
-}
-
-.post-info a{
- color: #999;
- text-decoration : none;
-}
-
-/* Top
-*******************************************************************************/
-#sidebar{
- width: 26%;
- padding: 0 2%;
- margin: 0;
- float: left;
-}
-
- #sidebar div{
- font-size: 0.8em;
- }
-
- #sidebar h2{
- font-family: Georgia, serif;
- color: #999;
- }
-
- #sidebar a{
- text-decoration: none;
- }
-
- #sidebar ul{
- margin: 0;
- padding: 0;
- list-style: none;
- }
-
-/* Footer
-*******************************************************************************/
-#footer{
- padding: 1ex 1em;
- clear: both;
- border-top: 1px solid #444;
- color: #999;
-}
\ No newline at end of file
diff --git a/custom/style/default.css b/custom/style/default.css
deleted file mode 100644
index 12268ef..0000000
--- a/custom/style/default.css
+++ /dev/null
@@ -1,158 +0,0 @@
-@viewport {
- width: device-width;
- initial-scale: 1.0;
-}
-
-html {
- font-family: "Lucida Grande", "Segoe UI", sans-serif;
- color: #111;
- background: #EEE;
- font-size: 62.5%;
-}
-
-body {
- margin: 0;
- padding: 0;
- font-size: 1.3em;
- line-height: 1.5em;
-}
-
-a {
- color: #669;
-}
-
-a:visited {
- color: #444;
-}
-
-a:hover {
- color: #000;
-}
-
-a img {
- border: none;
-}
-
-pre, code {
- max-height: 100%;
- width: 100%;
- font-size: 1.2em;
- overflow: auto;
-}
-
-h1, h2 {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-
-h2 {
- margin: 0;
-}
-
-#page {
- margin: 0 5em;
-}
-
-/* Header
-*******************************************************************************/
-
-#top {
- color: #FFF;
- padding: 10px 30px;
-}
-
-h1 a, h1 a:visited {
- color: #665;
- text-decoration: none;
-}
-
-h1 a:hover {
- color: #444;
-}
-
-/* Content
-*******************************************************************************/
-
-#content {
- width: 75%;
- float: left;
-}
-
-#content img {
- max-width: 100%;
- height: auto;
-}
-
-/* Sidebar
-*******************************************************************************/
-
-#sidebar {
- width: 18%;
- float: left;
-}
-
-#sidebar div {
- padding: 1em 30px;
-}
-
-#sidebar h2 {
- color: #665;
-}
-
-#sidebar ul {
- list-style: none;
- padding: 0;
- margin: 1em 0;
-}
-
-/* Article
-*******************************************************************************/
-
-.article {
- margin-bottom: 2em;
- padding: 30px;
- background: #FFF;
- border: 1px solid #DDD;
- overflow: hidden;
-}
-
-.article-title, .article-title a {
- color: #111;
- text-decoration: none;
-}
-
-.article-info {
- margin: 0 0 1em 0;
- color: #999;
-}
-
-.article-content {
- font-family: Georgia, serif;
-}
-
-.article img {
- max-width: 440px;
-}
-
-.article .collapsed {
- display: none;
-}
-
-/* Footer
-*******************************************************************************/
-
-#footer {
- clear: both;
- padding: 0 30px;
-}
-
-@media screen and (max-width: 1023px) {
- #page {
- margin: 0px;
- display: flex;
- flex-direction: column;
- }
- #content, #sidebar {
- float: none;
- width: 100%;
- }
-}
\ No newline at end of file
diff --git a/custom/style/green.css b/custom/style/green.css
deleted file mode 100644
index d665bd8..0000000
--- a/custom/style/green.css
+++ /dev/null
@@ -1,132 +0,0 @@
-html{
- font-family: "Lucida Grande", Tahoma, sans-serif;
- color: #333;
- background: #DFC;
- font-size: 62.5%;
-}
-
-body{
- margin: 0;
- padding: 0;
- font-size: 1.1em;
- line-height: 1.5em;
-}
-
-a{
- color: #669;
-}
-
-a:visited{
- color: #444;
-}
-
-a:hover{
- color: #000;
-}
-
-a img{
- border: none;
-}
-
-pre, code{
- font-size: 1.2em;
-}
-/* Top
-*******************************************************************************/
-#page{
- width: 60em;
- margin: 0 auto;
- background: #FFF;
-}
-/* Top
-*******************************************************************************/
-#top{
- padding: 1.5em;
- margin: 0;
- background: #99cc33;
- color: #FFF;
-
- border-top: 3px solid #7A2;
-
- -moz-border-radius-bottomleft: 5px;
- -moz-border-radius-bottomright: 5px;
-}
-
- #top h1{
- margin: 0;
- }
-
- #top h1 a{
- color: #FFF;
- text-decoration: none;
- }
-
-/* Top
-*******************************************************************************/
-#content{
- width: 38em;
- padding: 0 2em;
- margin: 2em 0;
- float: left;
- overflow: hidden;
-}
-
-.post{
- margin-bottom: 3em;
-}
-
-.post-title, .post-title a{
- color: #77AA22;
- text-decoration: none;
-}
-
-.post-info{
- color: #666;
- margin-top: -1em;
-}
-
-.post-info a{
- color: #669;
- text-decoration : none;
-}
-
-/* Top
-*******************************************************************************/
-#sidebar{
- width: 13em;
- padding: 0 2em;
- margin: 2em 0;
- float: right;
-}
-
- #sidebar div{
- font-size: 0.8em;
- }
-
- #sidebar h2{
- color: #99CC33;
- }
-
- #sidebar a{
- text-decoration: none;
- border-bottom: 1px solid #DDD;
- }
-
- #sidebar ul{
- margin: 0;
- padding: 0;
- list-style: none;
- }
-
- #sidebar li{
- margin: 0.5ex 0;
- }
-
-/* Footer
-*******************************************************************************/
-#footer{
- padding: 1ex 1em;
- clear: both;
- border-top: 1px dotted #CCC;
- color: #999;
-}
\ No newline at end of file
diff --git a/custom/style/light.css b/custom/style/light.css
deleted file mode 100644
index 60826e4..0000000
--- a/custom/style/light.css
+++ /dev/null
@@ -1,124 +0,0 @@
-html{
- font-family: Arial, sans-serif;
- color: #333;
- background: #FFF;
- font-size: 62.5%;
-}
-
-body{
- margin: 0;
- padding: 0;
- font-size: 1.1em;
- line-height: 1.5em;
-}
-
-a{
- color: #669;
-}
-
-a:visited{
- color: #444;
-}
-
-a:hover{
- color: #000;
-}
-
-a img{
- border: none;
-}
-
-pre, code{
- font-size: 1.2em;
-}
-/* Top
-*******************************************************************************/
-#page{
- margin: 0;
- background: #FFF;
-}
-/* Top
-*******************************************************************************/
-#top{
- padding: 2%;
- margin: 0;
- background: #CCC;
- color: #FFF;
-
- border-top: 5px solid #999;
-}
-
- #top h1{
- margin: 0;
- letter-spacing: -1px;
- }
-
-/* Top
-*******************************************************************************/
-#content{
- width: 66%;
- padding: 0 2%;
- margin: 0;
- float: left;
-}
-
-.post{
- margin-bottom: 3em;
-}
-
-.post-title, .post-title a{
- color: #666;
- text-decoration: none;
-}
-
-.post-title{
- padding-bottom: 0.5em;
- border-bottom: 1px dotted #CCC;
-}
-
-.post-info{
- color: #666;
- margin-top: -1em;
-}
-
-.post-info a{
- color: #666;
- text-decoration : none;
-}
-
-/* Top
-*******************************************************************************/
-#sidebar{
- width: 26%;
- padding: 0 2%;
- margin: 0;
- float: right;
-}
-
- #sidebar div{
- font-size: 0.8em;
- }
-
- #sidebar h2{
- color: #999;
- }
-
- #sidebar a{
- text-decoration: none;
- border-bottom: 1px solid #DDD;
- }
-
- #sidebar ul{
- margin: 0;
- padding: 0;
- list-style: none;
- }
-
-/* Footer
-*******************************************************************************/
-#footer{
- padding: 1ex 1em;
- clear: both;
- border-top: 1px dotted #CCC;
- color: #999;
-}
\ No newline at end of file
diff --git a/custom/style/mobile.css b/custom/style/mobile.css
deleted file mode 100644
index 38b3cd2..0000000
--- a/custom/style/mobile.css
+++ /dev/null
@@ -1,8 +0,0 @@
-body {
-margin:0;
-padding:0;
-background-color:#fff;
-color:#111;
-font:.6em/1.2em normal arial,helvetica,sans-serif;
-}
-h1{font-size: 1em;text-align:center;}
\ No newline at end of file
diff --git a/index.php b/index.php
deleted file mode 100755
index 0d149bd..0000000
--- a/index.php
+++ /dev/null
@@ -1,40 +0,0 @@
-' . _g('You might want to install moonmoon.') . '');
-}
-
-$pageRole = $_GET['type'] ?? 'index';
-$pageTheme = 'default';
-if (!in_array($pageRole, ['index', 'archive', 'atom10'])) {
- $pageRole = 'index';
-}
-
-if ($pageRole == 'atom10') {
- /* XXX: Redirect old ATOM feeds to new url to make sure our users don't
- * loose subscribers upon upgrading their moonmoon installation.
- * Remove this check in a more distant future.
- */
- header('Status: 301 Moved Permanently', false, 301);
- header('Location: atom.php');
- exit;
-}
-
-$cache_duration = $PlanetConfig->getOutputTimeout();
-Cache::$enabled = ($cache_duration > 0);
-Cache::setStore($PlanetConfig->getCacheDir() . '/');
-
-if (!OutputCache::Start('html', $pageRole, $cache_duration)) {
- $items = $Planet->getFeedsItems();
- $last_modified = (count($items)) ? $items[0]->get_date() : '';
- include_once(__DIR__.'/custom/views/'.$pageTheme.'/'.$pageRole.'.tpl.php');
- OutputCache::End();
-}
-
-if ($PlanetConfig->getDebug()) {
- echo "";
-}
diff --git a/install.php b/install.php
deleted file mode 100755
index 5aaaef9..0000000
--- a/install.php
+++ /dev/null
@@ -1,100 +0,0 @@
-' . $str . ' | ' . $msg . ' | ';
-}
-
-// If the config file exists and the auth variables are set, moonmoon is already installed
-if ($PlanetConfig::isInstalled()) {
- $status = 'installed';
-} elseif (isset($_POST['url'])) {
- // Do no try to use the file of an invalid locale
- if (strstr($_POST['locale'], '..') !== false
- || !file_exists(__DIR__ . "/app/l10n/${_REQUEST['locale']}.lang")) {
- $_POST['locale'] = 'en';
- }
-
- $save = array();
- //Save config file
- $config = array_merge(PlanetConfig::$defaultConfig, [
- 'url' => $_POST['url'],
- 'name' => filter_var($_POST['title'], FILTER_SANITIZE_SPECIAL_CHARS),
- 'locale' => $_POST['locale'],
- ]);
-
- $CreatePlanetConfig = new PlanetConfig($config);
- $save['config'] = file_put_contents(custom_path('config.yml'), $CreatePlanetConfig->toYaml());
-
- OpmlManager::save(new Opml(), custom_path('people.opml'));
-
- //Save password
- $save['password'] = file_put_contents(
- admin_path('inc/pwd.inc.php'),
- sprintf('', hash('sha256', $_POST['password']))
- );
-
- if (0 != ($save['config'] + $save['password'])) {
- $status = 'installed';
- }
-} else {
- // We start by malking sure we have PHP5 as a base requirement
- if (version_compare(PHP_VERSION, '7.2.0') >= 0) {
- $strInstall = installStatus('Server is running at least PHP 7.2', 'OK', true);
- $strRecommendation = '';
- } else {
- $strInstall = installStatus('Server is running at least PHP 7.2', 'FAIL', false);
- $strRecommendation = 'Check your server documentation to activate at least PHP 7.2';
- }
-
- $required_extensions = [
- 'dom', // moonmoon, simplepie
- 'curl', // simplepie
- 'iconv', // simplepie
- 'libxml', // moonmoon, simplepie
- 'mbstring', // simplepie
- 'pcre', // moonmoon
- 'xml', // moonmoon, simplepie
- 'xmlreader', // moonmoon, simplepie
- 'zlib' // simplepie
- ];
- foreach ($required_extensions as $ext) {
- if (extension_loaded($ext) === true) {
- $strInstall .= installStatus("PHP extension $ext
is present", 'OK', true);
- } else {
- $strInstall .= installStatus("PHP extension $ext
is present", 'FAIL', false);
- $strRecommendation .= "Install PHP extension $ext
on your server";
- }
- }
-
- // Writable file requirements
- $tests = array(
- '/custom',
- '/custom/people.opml',
- '/admin/inc/pwd.inc.php',
- '/cache',
- );
-
- // We now test that all required files and directories are writable.
- foreach ($tests as $v) {
- $filename = __DIR__ . $v;
- if (touch($filename)) {
- $strInstall .= installStatus("$v
is writable", 'OK', true);
- if (is_file($filename)) {
- unlink($filename);
- }
- } else {
- $strInstall .= installStatus("$v
is writable", 'FAIL', false);
- $strRecommendation .= "Make $v
writable with CHMOD";
- }
- }
-
- // We can now decide if we install moonmoon or not
- $status = ($strRecommendation != '') ? 'error' : 'install';
-}
-
-require_once views_path('install.tpl.php');
diff --git a/phpcs.xml b/phpcs.xml
index e741e42..343f8b0 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -5,7 +5,9 @@
.
-
+
+ cache/
+ tmp/
vendor/
\ No newline at end of file
diff --git a/phpunit.xml b/phpunit.xml
index 8d463d4..2a0713a 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -17,7 +17,9 @@
- .
+ app
+ public
+ custom/views
vendor
diff --git a/postload.php b/postload.php
deleted file mode 100644
index 0dff886..0000000
--- a/postload.php
+++ /dev/null
@@ -1,28 +0,0 @@
-getOpmlFile()));
-
-foreach ($xml->xpath('/opml/body/outline[@xmlUrl]') as $element) {
- if ($element->attributes()->xmlUrl == $_GET['url']) {
- $person = new PlanetFeed(
- '',
- $_GET['url'],
- '',
- false
- );
- $Planet->addPerson($person);
-
- $Planet->download(1);
- header('Content-type: image/png');
- readfile(custom_path('img/feed.png'));
- die();
- }
-}
-
-echo 'Updating this URL is not allowed.';
diff --git a/public/admin/administration.php b/public/admin/administration.php
new file mode 100755
index 0000000..09b5f85
--- /dev/null
+++ b/public/admin/administration.php
@@ -0,0 +1,59 @@
+getOpmlFile());
+$opml_people = $opml->getPeople();
+$page_id = 'admin-admin';
+$header_extra = <<<"HTML"
+
+
+HTML;
+
+$repo_url = 'https://github.com/moonmoon/moonmoon';
+$releases_url = "$repo_url/releases";
+$link_url = "$releases_url";
+$version_current = str_replace('%s', $moon_version, $l10n->getString('Your moonmoon instance version is %s.'));
+$version_action = str_replace('%s', $link_url, $l10n->getString('You can check for a more recent version on: %s.'));
+
+$page_content = <<<"FRAGMENT"
+
+
+
+
+
+
+
+FRAGMENT;
+
+$footer_extra = '';
+$admin_access = 1;
+require_once __DIR__ . '/template.php';
diff --git a/public/admin/changepassword.php b/public/admin/changepassword.php
new file mode 100644
index 0000000..c1e61ff
--- /dev/null
+++ b/public/admin/changepassword.php
@@ -0,0 +1,12 @@
+verify($_POST['_csrf'], 'frmPassword') && isset($_POST['password']) && ('' != $_POST['password'])) {
+ $out = sprintf('', hash('sha256', $_POST['password']));
+ file_put_contents(__DIR__.'/inc/pwd.inc.php', $out);
+ die("Password changed. Login");
+} else {
+ die('Can not change password');
+}
diff --git a/public/admin/default.css b/public/admin/default.css
new file mode 100755
index 0000000..fcba3f4
--- /dev/null
+++ b/public/admin/default.css
@@ -0,0 +1,232 @@
+html, body{
+ margin: 0;
+ padding: 0;
+}
+html{
+ font-size: 62.5%;
+}
+body{
+ background: #FFF;
+ color: #333;
+ font: 1.1em/1.6em "Lucida Grande", Tahoma, Arial, sans-serif;
+}
+
+
+fieldset{
+ border: 0;
+ padding: 0;
+ margin: 1em 0;
+}
+input.text{
+ border: 1px solid #BBB;
+ padding: 4px;
+}
+input.submit{
+ font-size: 1em;
+ padding: 4px;
+ background: #D1D1D1 url(img/button.png) repeat-x left center;
+ border: 1px solid #FFF;
+ border-bottom: 1px solid #CECECE;
+ border-right: 1px solid #CECECE;
+ cursor: pointer;
+}
+input.submit:hover{
+ background: #D1D1D1 url(img/button-h.png) repeat-x left center;
+ color: #000;
+ border: 1px solid #FFF;
+ border-bottom: 1px solid #C6C6C6;
+ border-right: 1px solid #C6C6C6;
+}
+input.delete{
+ margin-left: 1em;
+}
+input.delete:hover{
+ background: #ffabab url(img/button-delete.png) repeat-x left center;
+ color: #C00;
+ border: 1px solid #FCC;
+ border-bottom: 1px solid #F99;
+ border-right: 1px solid #F99;
+}
+input.add{
+ font-weight: bold;
+}
+input.add:hover{
+ background: #65a5e1 url(img/button-add.png) repeat-x left center;
+ color: #20466a;
+ border: 1px solid #a6c7e5;
+ border-bottom: 1px solid #4f90cd;
+ border-right: 1px solid #4f90cd;
+}
+p.help{
+ font-size: 0.8em;
+ color: #999;
+ margin: 0;
+}
+
+#page{
+}
+
+ header{
+ background: #E0E0E0 url(img/moonmoon.png) no-repeat right center;
+ border-top: 5px solid #D0D0D0;
+ margin: 0;
+ padding: 10px;
+ }
+ header h1{
+ display: none;
+ margin: 0 0 0 20px;
+ padding: 0;
+ height: 14px;
+ width: 95px;
+ background: transparent url(img/moonmoon.png) no-repeat left center;
+
+ overflow: hidden;
+ text-indent: -1000em;
+ }
+ header p{
+ margin: 0 0 0 20px;
+ padding: 0;
+ }
+ header p a{
+ color: #AAA;
+ }
+ header p a:hover{
+ color: #111;
+ }
+
+
+ nav ul{
+ margin: 20px 30px;
+ padding: 0;
+ list-style: none;
+ }
+ nav ul:after {content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+ nav ul {display: inline-table;}
+ /* Hides from IE-mac \*/
+ * html nav ul {height: 1%;}
+ nav ul {display: block;}
+ /* End hide from IE-mac */
+
+ nav ul li{
+ display: block;
+ float: left;
+ }
+ nav ul li a{
+ display: block;
+ border: 1px solid #DDD;
+ padding: 8px 8px 8px 36px;
+ margin-right: 8px;
+ text-decoration: none;
+ color: #666;
+ background-repeat: no-repeat;
+ background-position: 6px center;
+ }
+ nav ul li a:hover,
+ body#admin-feed #nav-feed a,
+ body#admin-admin #nav-admin a {
+ background-color: #f0f2f6;
+ border-color: #AAA;
+ color: #111;
+ }
+ #nav-feed a{
+ background-image: url(img/nav-feed.png);
+ }
+ #nav-admin a{
+ background-image: url(img/nav-admin.png);
+ }
+
+ #content{
+ margin: 20px 30px;
+ }
+
+ .widget{
+ margin: 20px 0;
+ }
+ .widget h3{
+ background: #3e4350 url(img/h3.png) repeat-x left center;
+ color: #FFF;
+ text-transform: uppercase;
+ margin: 0;
+ padding: 10px;
+ }
+ .widget form{
+ padding: 10px;
+ border: 1px solid #EEE;
+ border-top: 0;
+ }
+
+ #feedmanage p.select{
+ margin: 3px 0;
+ }
+ #feedmanage p.action span.count{
+ float: right;
+ padding-right: 10px;
+ font-size: 1.3em;
+ }
+ #feedmanage table{
+ width: 99%;
+ border-collapse: collapse;
+ border: 1px solid #f0f2f6;
+ }
+ #feedmanage thead th{
+ background: #f0f2f6;
+ text-align: left;
+ padding: 6px;
+ }
+ #feedmanage thead span{
+ display: none;
+ }
+ #feedmanage tr{
+ border-bottom: 1px solid #e8ebf1;
+ }
+ #feedmanage tr.even td{
+ background: #f0f2f6;
+ width: auto;
+ }
+ #feedmanage .text{
+ background: transparent;
+ border: 1px solid #FFF;
+ width: 90%;
+ }
+ #feedmanage tr.even td .text{
+ border: 1px solid #f0f2f6;
+ }
+ #feedmanage tr td input.text:focus{
+ background: #FFF;
+ border: 1px solid #4392b7;
+ }
+
+ #feedmanage tr.selected td{
+ background: #ffabab;
+ background: #4392b7;
+ color: #FFF;
+ }
+ #feedmanage tr.selected td .text{
+ color: #FFF;
+ border: 1px solid #4392b7;
+ }
+ #feedmanage tr td input.text:focus{
+ background: #FFF;
+ color: #000;
+ border: 1px solid #4392b7;
+ }
+
+/* Login form
+*******************************************************************************/
+form.login {
+ width: 400px;
+ margin: 0 auto;
+}
+form.login fieldset {
+ border: 1px solid #CCC;
+ text-align: center;
+}
+
+p.logout {
+ float: right;
+ margin: 20px 30px 0 0;
+}
+ p.logout a {
+ padding: 8px;
+ display: block;
+ }
diff --git a/public/admin/img/button-add.png b/public/admin/img/button-add.png
new file mode 100644
index 0000000..859364a
Binary files /dev/null and b/public/admin/img/button-add.png differ
diff --git a/public/admin/img/button-delete.png b/public/admin/img/button-delete.png
new file mode 100644
index 0000000..7bfebc2
Binary files /dev/null and b/public/admin/img/button-delete.png differ
diff --git a/public/admin/img/button-h.png b/public/admin/img/button-h.png
new file mode 100644
index 0000000..0a43a6a
Binary files /dev/null and b/public/admin/img/button-h.png differ
diff --git a/public/admin/img/button.png b/public/admin/img/button.png
new file mode 100644
index 0000000..fad6ccc
Binary files /dev/null and b/public/admin/img/button.png differ
diff --git a/public/admin/img/h3.png b/public/admin/img/h3.png
new file mode 100644
index 0000000..0c86748
Binary files /dev/null and b/public/admin/img/h3.png differ
diff --git a/public/admin/img/moonmoon.png b/public/admin/img/moonmoon.png
new file mode 100644
index 0000000..26cc8f4
Binary files /dev/null and b/public/admin/img/moonmoon.png differ
diff --git a/public/admin/img/nav-admin.png b/public/admin/img/nav-admin.png
new file mode 100644
index 0000000..3077a54
Binary files /dev/null and b/public/admin/img/nav-admin.png differ
diff --git a/public/admin/img/nav-feed.png b/public/admin/img/nav-feed.png
new file mode 100644
index 0000000..00c896b
Binary files /dev/null and b/public/admin/img/nav-feed.png differ
diff --git a/public/admin/inc/auth.inc.php b/public/admin/inc/auth.inc.php
new file mode 100644
index 0000000..32615e7
--- /dev/null
+++ b/public/admin/inc/auth.inc.php
@@ -0,0 +1,9 @@
+' . _g('You might want to install moonmoon.') . '');
+}
+
+//Instantiate app
+$Planet = new Planet($PlanetConfig);
+
+//Load
+if (0 < $Planet->loadOpml($PlanetConfig->getOpmlFile())) {
+ $Planet->loadFeeds();
+ $items = $Planet->getItems();
+}
+
+$everyone = $Planet->getPeople();
+$count_feeds = count($everyone);
+$page_id = 'admin-feed';
+$footer_extra = <<
+ var allCheckboxes = function(status){
+ var form = document.getElementById('feedmanage');
+ var selectboxes = form.getElementsByTagName('input');
+ for (var i=0; i
+FRAGMENT;
+
+ob_start();
+?>
+
+
+
+
+
+
+
+', $hash_pwd));
+ }
+
+ setcookie('auth', $hash_pwd);
+ header('Location: index.php');
+}
+
+$page_content = <<
+
+
+FRAGMENT;
+
+$footer_extra = <<
+
+
+
+FRAGMENT;
+
+$page_id = 'admin-login';
+$admin_access = 0;
+
+require_once __DIR__ . '/template.php';
diff --git a/public/admin/logout.php b/public/admin/logout.php
new file mode 100644
index 0000000..25a3e4c
--- /dev/null
+++ b/public/admin/logout.php
@@ -0,0 +1,10 @@
+verify($_POST['_csrf'], 'feedmanage')) {
+ die('Invalid CSRF token!');
+}
+
+$opmlFile = $PlanetConfig->getOpmlFile();
+
+if (isset($_POST['upload']) &&
+ isset($_FILES['opml']) &&
+ is_uploaded_file($_FILES['opml']['tmp_name']) &&
+ $_FILES['opml']['size'] > 0) {
+ OpmlManager::backup($opmlFile);
+ $newOpml = new Opml();
+ $newOpml->parse(file_get_contents($_FILES['opml']['tmp_name']));
+ OpmlManager::save($newOpml, $opmlFile);
+} elseif (isset($_POST['opml']) || isset($_POST['add'])) {
+ // Load old OPML
+ $oldOpml = OpmlManager::load($opmlFile);
+ if ($PlanetConfig->getName() === '') {
+ $PlanetConfig->setName($oldOpml->getTitle());
+ }
+ $newOpml = new Opml();
+ $newOpml->title = $PlanetConfig->getName();
+
+ // Remove slashes if needed
+ if (isset($_POST['opml'])) {
+ array_walk_recursive($_POST['opml'], 'removeSlashes');
+ }
+ // Delete/Save feeds
+ if (isset($_POST['delete']) || isset($_POST['save'])) {
+ foreach ($_POST['opml'] as $person) {
+ if (isset($_POST['delete'])) {
+ //delete mode, check if to be deleted
+ if (!isset($person['delete'])) {
+ $newOpml->entries[] = $person;
+ }
+ } else {
+ $newOpml->entries[] = $person;
+ }
+ }
+ }
+
+ // Add feed
+ if (isset($_POST['add'])) {
+ if ('http://' != $_POST['url']) {
+ //autodiscover feed
+ $feed = new SimplePie();
+ $feed->enable_cache(false);
+ $feed->set_feed_url($_POST['url']);
+ if (!$PlanetConfig->checkCertificates()) {
+ $feed->set_curl_options([
+ CURLOPT_SSL_VERIFYHOST => false,
+ CURLOPT_SSL_VERIFYPEER => false
+ ]);
+ }
+ $feed->init();
+ $feed->handle_content_type();
+ $person['name'] = html_entity_decode($feed->get_title());
+ $person['website'] = $feed->get_permalink();
+ $person['feed'] = $feed->feed_url;
+ $person['isDown'] = '0';
+
+ $oldOpml->entries[] = $person;
+ }
+ $newOpml->entries = $oldOpml->entries;
+ }
+
+ // Backup old OPML
+ OpmlManager::backup($opmlFile);
+
+ // Save new OPML
+ OpmlManager::save($newOpml, $opmlFile);
+}
+header("Location: index.php");
+die();
diff --git a/public/admin/template.php b/public/admin/template.php
new file mode 100755
index 0000000..964c639
--- /dev/null
+++ b/public/admin/template.php
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ =@$header_extra ?: ''; ?>
+
+
+
+
+
+
+
+
+
=_g('Logout')?>
+
+
+
+
+
+
+
+
+ =@$page_content ?: ''; ?>
+
+
+
+
+=@$footer_extra ?: ''; ?>
+
+
+
diff --git a/public/atom.php b/public/atom.php
new file mode 100644
index 0000000..26abeb6
--- /dev/null
+++ b/public/atom.php
@@ -0,0 +1,4 @@
+loadOpml($PlanetConfig->getOpmlFile())) {
+ $Planet->download(1.0);
+}
+
+if ($PlanetConfig->getDebug()) {
+ foreach ($Planet->errors as $error) {
+ echo $error->toString() . "\n";
+ }
+}
diff --git a/public/custom/img/feed.png b/public/custom/img/feed.png
new file mode 100644
index 0000000..f8cd243
Binary files /dev/null and b/public/custom/img/feed.png differ
diff --git a/public/custom/img/moonmoon.png b/public/custom/img/moonmoon.png
new file mode 100644
index 0000000..10f9736
Binary files /dev/null and b/public/custom/img/moonmoon.png differ
diff --git a/public/custom/img/moonmoon@128w.png b/public/custom/img/moonmoon@128w.png
new file mode 100644
index 0000000..2a164aa
Binary files /dev/null and b/public/custom/img/moonmoon@128w.png differ
diff --git a/public/custom/img/moonmoon@256w.png b/public/custom/img/moonmoon@256w.png
new file mode 100644
index 0000000..b52c4bb
Binary files /dev/null and b/public/custom/img/moonmoon@256w.png differ
diff --git a/public/custom/img/opml.png b/public/custom/img/opml.png
new file mode 100644
index 0000000..7a9d86f
Binary files /dev/null and b/public/custom/img/opml.png differ
diff --git a/public/custom/style/dark.css b/public/custom/style/dark.css
new file mode 100644
index 0000000..1ee004b
--- /dev/null
+++ b/public/custom/style/dark.css
@@ -0,0 +1,125 @@
+html{
+ font-family: Arial, sans-serif;
+ color: #FFF;
+ background: #333;
+ font-size: 62.5%;
+}
+
+body{
+ margin: 0;
+ padding: 0;
+ font-size: 1.1em;
+ line-height: 1.5em;
+}
+
+a{
+ color: #CCC;
+}
+
+a:visited{
+ color: #AAA;
+}
+
+a:hover{
+ color: #FFF;
+}
+
+a img{
+ border: none;
+}
+
+pre, code{
+ font-size: 1.2em;
+}
+/* Top
+*******************************************************************************/
+#page{
+ width: 640px;
+ margin: 0 auto;
+}
+/* Top
+*******************************************************************************/
+#top{
+ padding: 2%;
+ margin: 3em;
+ line-height: 2em;
+ color: #FFF;
+ text-align: center;
+}
+
+ #top h1{
+ margin: 0;
+ letter-spacing: -1px;
+ font-family: Georgia, serif;
+ }
+
+/* Top
+*******************************************************************************/
+#content{
+ width: 66%;
+ padding: 0 2%;
+ margin: 0;
+ float: right;
+}
+
+.post{
+ margin-bottom: 3em;
+}
+
+.post-title, .post-title a{
+ font-family: Georgia, serif;
+ color: #CCC;
+ text-decoration: none;
+}
+
+.post-title{
+ padding-bottom: 0.5em;
+ border-bottom: 1px solid #444;
+}
+
+.post-info{
+ color: #999;
+ margin-top: -1em;
+}
+
+.post-info a{
+ color: #999;
+ text-decoration : none;
+}
+
+/* Top
+*******************************************************************************/
+#sidebar{
+ width: 26%;
+ padding: 0 2%;
+ margin: 0;
+ float: left;
+}
+
+ #sidebar div{
+ font-size: 0.8em;
+ }
+
+ #sidebar h2{
+ font-family: Georgia, serif;
+ color: #999;
+ }
+
+ #sidebar a{
+ text-decoration: none;
+ }
+
+ #sidebar ul{
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+
+/* Footer
+*******************************************************************************/
+#footer{
+ padding: 1ex 1em;
+ clear: both;
+ border-top: 1px solid #444;
+ color: #999;
+}
\ No newline at end of file
diff --git a/public/custom/style/default.css b/public/custom/style/default.css
new file mode 100644
index 0000000..12268ef
--- /dev/null
+++ b/public/custom/style/default.css
@@ -0,0 +1,158 @@
+@viewport {
+ width: device-width;
+ initial-scale: 1.0;
+}
+
+html {
+ font-family: "Lucida Grande", "Segoe UI", sans-serif;
+ color: #111;
+ background: #EEE;
+ font-size: 62.5%;
+}
+
+body {
+ margin: 0;
+ padding: 0;
+ font-size: 1.3em;
+ line-height: 1.5em;
+}
+
+a {
+ color: #669;
+}
+
+a:visited {
+ color: #444;
+}
+
+a:hover {
+ color: #000;
+}
+
+a img {
+ border: none;
+}
+
+pre, code {
+ max-height: 100%;
+ width: 100%;
+ font-size: 1.2em;
+ overflow: auto;
+}
+
+h1, h2 {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+h2 {
+ margin: 0;
+}
+
+#page {
+ margin: 0 5em;
+}
+
+/* Header
+*******************************************************************************/
+
+#top {
+ color: #FFF;
+ padding: 10px 30px;
+}
+
+h1 a, h1 a:visited {
+ color: #665;
+ text-decoration: none;
+}
+
+h1 a:hover {
+ color: #444;
+}
+
+/* Content
+*******************************************************************************/
+
+#content {
+ width: 75%;
+ float: left;
+}
+
+#content img {
+ max-width: 100%;
+ height: auto;
+}
+
+/* Sidebar
+*******************************************************************************/
+
+#sidebar {
+ width: 18%;
+ float: left;
+}
+
+#sidebar div {
+ padding: 1em 30px;
+}
+
+#sidebar h2 {
+ color: #665;
+}
+
+#sidebar ul {
+ list-style: none;
+ padding: 0;
+ margin: 1em 0;
+}
+
+/* Article
+*******************************************************************************/
+
+.article {
+ margin-bottom: 2em;
+ padding: 30px;
+ background: #FFF;
+ border: 1px solid #DDD;
+ overflow: hidden;
+}
+
+.article-title, .article-title a {
+ color: #111;
+ text-decoration: none;
+}
+
+.article-info {
+ margin: 0 0 1em 0;
+ color: #999;
+}
+
+.article-content {
+ font-family: Georgia, serif;
+}
+
+.article img {
+ max-width: 440px;
+}
+
+.article .collapsed {
+ display: none;
+}
+
+/* Footer
+*******************************************************************************/
+
+#footer {
+ clear: both;
+ padding: 0 30px;
+}
+
+@media screen and (max-width: 1023px) {
+ #page {
+ margin: 0px;
+ display: flex;
+ flex-direction: column;
+ }
+ #content, #sidebar {
+ float: none;
+ width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/public/custom/style/green.css b/public/custom/style/green.css
new file mode 100644
index 0000000..d665bd8
--- /dev/null
+++ b/public/custom/style/green.css
@@ -0,0 +1,132 @@
+html{
+ font-family: "Lucida Grande", Tahoma, sans-serif;
+ color: #333;
+ background: #DFC;
+ font-size: 62.5%;
+}
+
+body{
+ margin: 0;
+ padding: 0;
+ font-size: 1.1em;
+ line-height: 1.5em;
+}
+
+a{
+ color: #669;
+}
+
+a:visited{
+ color: #444;
+}
+
+a:hover{
+ color: #000;
+}
+
+a img{
+ border: none;
+}
+
+pre, code{
+ font-size: 1.2em;
+}
+/* Top
+*******************************************************************************/
+#page{
+ width: 60em;
+ margin: 0 auto;
+ background: #FFF;
+}
+/* Top
+*******************************************************************************/
+#top{
+ padding: 1.5em;
+ margin: 0;
+ background: #99cc33;
+ color: #FFF;
+
+ border-top: 3px solid #7A2;
+
+ -moz-border-radius-bottomleft: 5px;
+ -moz-border-radius-bottomright: 5px;
+}
+
+ #top h1{
+ margin: 0;
+ }
+
+ #top h1 a{
+ color: #FFF;
+ text-decoration: none;
+ }
+
+/* Top
+*******************************************************************************/
+#content{
+ width: 38em;
+ padding: 0 2em;
+ margin: 2em 0;
+ float: left;
+ overflow: hidden;
+}
+
+.post{
+ margin-bottom: 3em;
+}
+
+.post-title, .post-title a{
+ color: #77AA22;
+ text-decoration: none;
+}
+
+.post-info{
+ color: #666;
+ margin-top: -1em;
+}
+
+.post-info a{
+ color: #669;
+ text-decoration : none;
+}
+
+/* Top
+*******************************************************************************/
+#sidebar{
+ width: 13em;
+ padding: 0 2em;
+ margin: 2em 0;
+ float: right;
+}
+
+ #sidebar div{
+ font-size: 0.8em;
+ }
+
+ #sidebar h2{
+ color: #99CC33;
+ }
+
+ #sidebar a{
+ text-decoration: none;
+ border-bottom: 1px solid #DDD;
+ }
+
+ #sidebar ul{
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+
+ #sidebar li{
+ margin: 0.5ex 0;
+ }
+
+/* Footer
+*******************************************************************************/
+#footer{
+ padding: 1ex 1em;
+ clear: both;
+ border-top: 1px dotted #CCC;
+ color: #999;
+}
\ No newline at end of file
diff --git a/public/custom/style/light.css b/public/custom/style/light.css
new file mode 100644
index 0000000..60826e4
--- /dev/null
+++ b/public/custom/style/light.css
@@ -0,0 +1,124 @@
+html{
+ font-family: Arial, sans-serif;
+ color: #333;
+ background: #FFF;
+ font-size: 62.5%;
+}
+
+body{
+ margin: 0;
+ padding: 0;
+ font-size: 1.1em;
+ line-height: 1.5em;
+}
+
+a{
+ color: #669;
+}
+
+a:visited{
+ color: #444;
+}
+
+a:hover{
+ color: #000;
+}
+
+a img{
+ border: none;
+}
+
+pre, code{
+ font-size: 1.2em;
+}
+/* Top
+*******************************************************************************/
+#page{
+ margin: 0;
+ background: #FFF;
+}
+/* Top
+*******************************************************************************/
+#top{
+ padding: 2%;
+ margin: 0;
+ background: #CCC;
+ color: #FFF;
+
+ border-top: 5px solid #999;
+}
+
+ #top h1{
+ margin: 0;
+ letter-spacing: -1px;
+ }
+
+/* Top
+*******************************************************************************/
+#content{
+ width: 66%;
+ padding: 0 2%;
+ margin: 0;
+ float: left;
+}
+
+.post{
+ margin-bottom: 3em;
+}
+
+.post-title, .post-title a{
+ color: #666;
+ text-decoration: none;
+}
+
+.post-title{
+ padding-bottom: 0.5em;
+ border-bottom: 1px dotted #CCC;
+}
+
+.post-info{
+ color: #666;
+ margin-top: -1em;
+}
+
+.post-info a{
+ color: #666;
+ text-decoration : none;
+}
+
+/* Top
+*******************************************************************************/
+#sidebar{
+ width: 26%;
+ padding: 0 2%;
+ margin: 0;
+ float: right;
+}
+
+ #sidebar div{
+ font-size: 0.8em;
+ }
+
+ #sidebar h2{
+ color: #999;
+ }
+
+ #sidebar a{
+ text-decoration: none;
+ border-bottom: 1px solid #DDD;
+ }
+
+ #sidebar ul{
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+
+/* Footer
+*******************************************************************************/
+#footer{
+ padding: 1ex 1em;
+ clear: both;
+ border-top: 1px dotted #CCC;
+ color: #999;
+}
\ No newline at end of file
diff --git a/public/custom/style/mobile.css b/public/custom/style/mobile.css
new file mode 100644
index 0000000..38b3cd2
--- /dev/null
+++ b/public/custom/style/mobile.css
@@ -0,0 +1,8 @@
+body {
+margin:0;
+padding:0;
+background-color:#fff;
+color:#111;
+font:.6em/1.2em normal arial,helvetica,sans-serif;
+}
+h1{font-size: 1em;text-align:center;}
\ No newline at end of file
diff --git a/public/feed/index.php b/public/feed/index.php
new file mode 100644
index 0000000..90ce907
--- /dev/null
+++ b/public/feed/index.php
@@ -0,0 +1,43 @@
+loadOpml($PlanetConfig->getOpmlFile()) == 0) {
+ header('Content-Type: text/xml; charset=utf-8');
+ header('HTTP/1.1 404 Not Found');
+ exit;
+}
+
+$Planet->loadFeeds();
+$items = $Planet->getItems();
+$limit = $PlanetConfig->getMaxDisplay();
+$count = 0;
+
+header('Content-Type: text/xml; charset=UTF-8');
+echo '';
+?>
+
+ =htmlspecialchars($PlanetConfig->getName())?>
+ =htmlspecialchars($PlanetConfig->getName())?>
+ =$PlanetConfig->getUrl()?>
+
+
+ =gmdate('Y-m-d\TH:i:s\Z')?>
+ =htmlspecialchars($PlanetConfig->getName())?>
+
+
+
+ =htmlspecialchars($item->get_feed()->getName())?> : =htmlspecialchars($item->get_title())?>
+ =htmlspecialchars($item->get_id())?>
+
+ =$item->get_gmdate('Y-m-d\TH:i:s\Z')?>
+ =$item->get_gmdate('Y-m-d\TH:i:s\Z')?>
+ =($item->get_author() ? $item->get_author()->get_name() : 'anonymous')?>
+ get_content()?>]]>
+
+
+
+
+
diff --git a/public/index.php b/public/index.php
new file mode 100755
index 0000000..0a0de38
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,40 @@
+' . _g('You might want to install moonmoon.') . '');
+}
+
+$pageRole = $_GET['type'] ?? 'index';
+$pageTheme = 'default';
+if (!in_array($pageRole, ['index', 'archive', 'atom10'])) {
+ $pageRole = 'index';
+}
+
+if ($pageRole == 'atom10') {
+ /* XXX: Redirect old ATOM feeds to new url to make sure our users don't
+ * loose subscribers upon upgrading their moonmoon installation.
+ * Remove this check in a more distant future.
+ */
+ header('Status: 301 Moved Permanently', false, 301);
+ header('Location: feed/');
+ exit;
+}
+
+$cache_duration = $PlanetConfig->getOutputTimeout();
+Cache::$enabled = ($cache_duration > 0);
+Cache::setStore($PlanetConfig->getCacheDir() . '/');
+
+if (!OutputCache::Start('html', $pageRole, $cache_duration)) {
+ $items = $Planet->getFeedsItems();
+ $last_modified = (count($items)) ? $items[0]->get_date() : '';
+ include_once '../custom/views/'.$pageTheme.'/'.$pageRole.'.tpl.php';
+ OutputCache::End();
+}
+
+if ($PlanetConfig->getDebug()) {
+ echo "";
+}
diff --git a/public/install.php b/public/install.php
new file mode 100755
index 0000000..09cbe63
--- /dev/null
+++ b/public/install.php
@@ -0,0 +1,98 @@
+' . $str . ' | ' . $msg . ' | ';
+}
+
+// If the config file exists and the auth variables are set, moonmoon is already installed
+if ($PlanetConfig::isInstalled()) {
+ $status = 'installed';
+} elseif (isset($_POST['url'])) {
+ // Do no try to use the file of an invalid locale
+ if (strstr($_POST['locale'], '..') !== false
+ || !file_exists(__DIR__ . "/app/l10n/${_REQUEST['locale']}.lang")) {
+ $_POST['locale'] = 'en';
+ }
+
+ $save = array();
+ //Save config file
+ $config = array_merge(PlanetConfig::$defaultConfig, [
+ 'url' => $_POST['url'],
+ 'name' => filter_var($_POST['title'], FILTER_SANITIZE_SPECIAL_CHARS),
+ 'locale' => $_POST['locale'],
+ ]);
+
+ $CreatePlanetConfig = new PlanetConfig($config);
+ $save['config'] = file_put_contents(config_path('config.yml'), $CreatePlanetConfig->toYaml());
+
+ OpmlManager::save(new Opml(), config_path('people.opml'));
+
+ //Save password
+ $save['password'] = file_put_contents(
+ config_path('pwd.inc.php'),
+ sprintf('', hash('sha256', $_POST['password']))
+ );
+
+ if (0 != ($save['config'] + $save['password'])) {
+ $status = 'installed';
+ }
+} else {
+ // We start by malking sure we have PHP5 as a base requirement
+ if (version_compare(PHP_VERSION, '7.2.0') >= 0) {
+ $strInstall = installStatus('Server is running at least PHP 7.2', 'OK', true);
+ $strRecommendation = '';
+ } else {
+ $strInstall = installStatus('Server is running at least PHP 7.2', 'FAIL', false);
+ $strRecommendation = 'Check your server documentation to activate at least PHP 7.2';
+ }
+
+ $required_extensions = [
+ 'dom', // moonmoon, simplepie
+ 'curl', // simplepie
+ 'iconv', // simplepie
+ 'libxml', // moonmoon, simplepie
+ 'mbstring', // simplepie
+ 'pcre', // moonmoon
+ 'xml', // moonmoon, simplepie
+ 'xmlreader', // moonmoon, simplepie
+ 'zlib' // simplepie
+ ];
+ foreach ($required_extensions as $ext) {
+ if (extension_loaded($ext) === true) {
+ $strInstall .= installStatus("PHP extension $ext
is present", 'OK', true);
+ } else {
+ $strInstall .= installStatus("PHP extension $ext
is present", 'FAIL', false);
+ $strRecommendation .= "Install PHP extension $ext
on your server";
+ }
+ }
+
+ // Writable file requirements
+ $tests = array(
+ config_path('config.yml'),
+ config_path('people.opml'),
+ config_path('pwd.inc.php'),
+ cache_path('test_cache'),
+ );
+
+ // We now test that all required files and directories are writable.
+ foreach ($tests as $filename) {
+ if (touch($filename)) {
+ $strInstall .= installStatus("$filename
is writable", 'OK', true);
+ if (is_file($filename)) {
+ unlink($filename);
+ }
+ } else {
+ $strInstall .= installStatus("$filename
is writable", 'FAIL', false);
+ $strRecommendation .= "Make $filename
writable with CHMOD";
+ }
+ }
+
+ // We can now decide if we install moonmoon or not
+ $status = ($strRecommendation != '') ? 'error' : 'install';
+}
+
+require_once views_path('install.tpl.php');
diff --git a/public/postload.php b/public/postload.php
new file mode 100644
index 0000000..69d6571
--- /dev/null
+++ b/public/postload.php
@@ -0,0 +1,28 @@
+getOpmlFile()));
+
+foreach ($xml->xpath('/opml/body/outline[@xmlUrl]') as $element) {
+ if ($element->attributes()->xmlUrl == $_GET['url']) {
+ $person = new PlanetFeed(
+ '',
+ $_GET['url'],
+ '',
+ false
+ );
+ $Planet->addPerson($person);
+
+ $Planet->download(1);
+ header('Content-type: image/png');
+ readfile(__DIR__ . '/custom/img/feed.png');
+ die();
+ }
+}
+
+echo 'Updating this URL is not allowed.';
diff --git a/tests/InstallTest.php b/tests/InstallTest.php
index b230d74..5433c56 100644
--- a/tests/InstallTest.php
+++ b/tests/InstallTest.php
@@ -39,9 +39,9 @@ class InstallTest extends GuzzleHarness
public function test_get_install_page_should_not_create_custom_files()
{
$this->client->get('/install.php');
- $this->assertFalse(file_exists(custom_path('people.opml')));
- $this->assertFalse(file_exists(custom_path('config.yml')));
- $this->assertFalse(file_exists(custom_path('inc/pwc.inc.php')));
+ $this->assertFalse(file_exists(config_path('people.opml')));
+ $this->assertFalse(file_exists(config_path('config.yml')));
+ $this->assertFalse(file_exists(config_path('pwc.inc.php')));
}
public function test_install_button()
@@ -59,4 +59,45 @@ class InstallTest extends GuzzleHarness
$this->assertEquals(200, $res->getStatusCode());
$this->assertStringContainsString('Your moonmoon is ready.', (string) $res->getBody());
}
+
+
+ public function testMigratePre10SetupAuto()
+ {
+ $this->assertEquals(false, PlanetConfig::isInstalledPre10Version(), "Planet is not installed /old config");
+ $this->assertEquals(false, PlanetConfig::isInstalled(), "Planet is not installed /new config");
+
+ $config = new PlanetConfig();
+ file_put_contents(custom_path('config.yml'), $config->toYaml());
+ OpmlManager::save(new Opml(), custom_path('people.opml'));
+
+ $this->assertEquals(true, PlanetConfig::isInstalledPre10Version(), "Planet is installed /old config");
+ $this->assertEquals(false, PlanetConfig::isInstalled(), "Planet is not installed /new config");
+
+ // explicitly migrate
+ $this->assertEquals(true, PlanetConfig::migratePre10Version(), "Migration succeeded");
+
+ $this->assertEquals(true, PlanetConfig::isInstalled(), "Planet is installed /new config");
+ $this->assertFileExists(custom_path('config.yml.bak'), "Backup config is kept");
+ $this->assertFileExists(custom_path('people.opml.bak'), "Backup OPML is kept");
+ }
+
+ public function testMigratePre10SetupIndex()
+ {
+ $this->assertEquals(false, PlanetConfig::isInstalledPre10Version(), "Planet is not installed /old config");
+ $this->assertEquals(false, PlanetConfig::isInstalled(), "Planet is not installed /new config");
+
+ $config = new PlanetConfig();
+ file_put_contents(custom_path('config.yml'), $config->toYaml());
+ OpmlManager::save(new Opml(), custom_path('people.opml'));
+
+ $this->assertEquals(true, PlanetConfig::isInstalledPre10Version(), "Planet is installed /old config");
+ $this->assertEquals(false, PlanetConfig::isInstalled(), "Planet is not installed /new config");
+
+ // call through web interface
+ $this->client->get('/');
+
+ $this->assertEquals(true, PlanetConfig::isInstalled(), "Planet is installed /new config");
+ $this->assertFileExists(custom_path('config.yml.bak'), "Backup config is kept");
+ $this->assertFileExists(custom_path('people.opml.bak'), "Backup OPML is kept");
+ }
}
--
cgit v1.2.1