diff --git a/action.php b/action.php index 58658f5..9a0b18c 100644 --- a/action.php +++ b/action.php @@ -113,4 +113,8 @@ switch ($VARS['action']) { returnToSender("invalid_parameters#notifications"); } break; + case "resetfeedkey": + $database->delete('userkeys', ['AND' => ['uid' => $_SESSION['uid'], 'typeid' => 1]]); + returnToSender("feed_key_reset"); + break; } \ No newline at end of file diff --git a/composer.json b/composer.json index 8e5ce8b..4252b03 100644 --- a/composer.json +++ b/composer.json @@ -6,10 +6,10 @@ "catfan/medoo": "^1.5", "spomky-labs/otphp": "^8.3", "endroid/qr-code": "^3.2", - "ldaptools/ldaptools": "^0.24.0", "guzzlehttp/guzzle": "^6.2", "phpmailer/phpmailer": "^5.2", - "christian-riesen/base32": "^1.3" + "christian-riesen/base32": "^1.3", + "mibe/feedwriter": "^1.1" }, "license": "MPL-2.0", "authors": [ diff --git a/composer.lock b/composer.lock index e6d8b5a..40cef4a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "872ba5f8bcf571aca66346a439e5b40d", - "content-hash": "49c0c56036b215998ff212564e9c2fd3", + "content-hash": "eca0497dbaf6b15cbe0ced496dec0712", "packages": [ { "name": "bacon/bacon-qr-code", @@ -51,7 +50,7 @@ ], "description": "BaconQrCode is a QR code generator for PHP.", "homepage": "https://github.com/Bacon/BaconQrCode", - "time": "2017-10-17 09:59:25" + "time": "2017-10-17T09:59:25+00:00" }, { "name": "beberlei/assert", @@ -106,7 +105,7 @@ "assertion", "validation" ], - "time": "2018-04-09 14:40:28" + "time": "2018-04-09T14:40:28+00:00" }, { "name": "catfan/medoo", @@ -165,7 +164,7 @@ "sql", "sqlite" ], - "time": "2018-03-26 17:54:24" + "time": "2018-03-26T17:54:24+00:00" }, { "name": "christian-riesen/base32", @@ -219,7 +218,7 @@ "encode", "rfc4648" ], - "time": "2016-05-05 11:49:03" + "time": "2016-05-05T11:49:03+00:00" }, { "name": "endroid/qr-code", @@ -279,7 +278,7 @@ "qr", "qrcode" ], - "time": "2018-02-27 21:35:30" + "time": "2018-02-27T21:35:30+00:00" }, { "name": "guzzlehttp/guzzle", @@ -344,7 +343,7 @@ "rest", "web service" ], - "time": "2018-03-26 16:33:04" + "time": "2018-03-26T16:33:04+00:00" }, { "name": "guzzlehttp/promises", @@ -395,7 +394,7 @@ "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "time": "2016-12-20T10:07:11+00:00" }, { "name": "guzzlehttp/psr7", @@ -460,7 +459,7 @@ "uri", "url" ], - "time": "2017-03-20 17:10:46" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "khanamiryan/qrcode-detector-decoder", @@ -510,67 +509,104 @@ "qr", "zxing" ], - "time": "2018-04-01 20:25:53" + "time": "2018-04-01T20:25:53+00:00" }, { - "name": "ldaptools/ldaptools", - "version": "v0.24.0", + "name": "mibe/feedwriter", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/ldaptools/ldaptools.git", - "reference": "31e05ae6082fc7e61afc666e2c773ee8cb0e47b5" + "url": "https://github.com/mibe/FeedWriter.git", + "reference": "f4cc748ad8700e36663f08cfeebe7fd39b00eea2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ldaptools/ldaptools/zipball/31e05ae6082fc7e61afc666e2c773ee8cb0e47b5", - "reference": "31e05ae6082fc7e61afc666e2c773ee8cb0e47b5", + "url": "https://api.github.com/repos/mibe/FeedWriter/zipball/f4cc748ad8700e36663f08cfeebe7fd39b00eea2", + "reference": "f4cc748ad8700e36663f08cfeebe7fd39b00eea2", "shasum": "" }, "require": { - "ext-ldap": "*", - "php": ">=5.6", - "ramsey/uuid": ">=3.0", - "symfony/event-dispatcher": ">=2.0", - "symfony/yaml": ">=2.0" - }, - "require-dev": { - "doctrine/cache": "~1.0", - "friendsofphp/php-cs-fixer": "~1.0", - "phpspec/phpspec": "~3.0", - "tedivm/stash": ">=0.14.1" - }, - "suggest": { - "doctrine/cache": "Provides the cache_type 'doctrine' to help increase performance.", - "ext-intl": "Better UTF-8 handling.", - "ext-mbstring": "Better UTF-8 handling.", - "tedivm/stash": "Provides the cache_type 'stash' to help increase performance." + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, "autoload": { "psr-4": { - "LdapTools\\": "src/LdapTools" + "FeedWriter\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "GPL-3.0" ], "authors": [ { - "name": "Chad Sikorra", - "email": "Chad.Sikorra@gmail.com", - "homepage": "http://www.chadsikorra.com" + "name": "Michael Bemmerl", + "email": "mail@mx-server.de" + }, + { + "name": "Phil Freo" + }, + { + "name": "Paul Ferrett" + }, + { + "name": "Brennen Bearnes" + }, + { + "name": "Michael Robinson", + "email": "mike@pagesofinterest.net" + }, + { + "name": "Baptiste Fontaine" + }, + { + "name": "Kristián Valentín" + }, + { + "name": "Brandtley McMinn" + }, + { + "name": "Julian Bogdani" + }, + { + "name": "Anis Uddin Ahmad", + "email": "anis.programmer@gmail.com" + }, + { + "name": "Cedric Gampert" + }, + { + "name": "Yamek" + }, + { + "name": "thielj" + }, + { + "name": "Pavel Khakhlou" + }, + { + "name": "Daniel" + }, + { + "name": "Tino Goratsch" } ], - "description": "LdapTools is a feature-rich LDAP library for PHP 5.6+.", - "homepage": "http://www.phpldaptools.com", + "description": "Generate feeds in either RSS 1.0, RSS 2.0 or ATOM formats", + "homepage": "https://github.com/mibe/FeedWriter", "keywords": [ - "Microsoft Exchange", - "active directory", - "ldap", - "openldap" - ], - "time": "2017-04-09 23:39:51" + "RSS 1.0", + "atom", + "feed", + "rss", + "rss 2.0", + "rss2" + ], + "time": "2016-11-19T20:47:44+00:00" }, { "name": "myclabs/php-enum", @@ -614,7 +650,7 @@ "keywords": [ "enum" ], - "time": "2017-06-28 16:24:08" + "time": "2017-06-28T16:24:08+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -676,20 +712,20 @@ "hex2bin", "rfc4648" ], - "time": "2018-03-10 19:47:49" + "time": "2018-03-10T19:47:49+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.12", + "version": "v2.0.17", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", "shasum": "" }, "require": { @@ -721,10 +757,11 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2018-04-04 21:24:14" + "time": "2018-07-04T16:31:37+00:00" }, { "name": "phpmailer/phpmailer", @@ -801,7 +838,7 @@ } ], "description": "PHPMailer is a full-featured email creation and transfer class for PHP", - "time": "2017-11-04 09:26:05" + "time": "2017-11-04T09:26:05+00:00" }, { "name": "psr/http-message", @@ -851,87 +888,7 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" - }, - { - "name": "ramsey/uuid", - "version": "3.7.3", - "source": { - "type": "git", - "url": "https://github.com/ramsey/uuid.git", - "reference": "44abcdad877d9a46685a3a4d221e3b2c4b87cb76" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/44abcdad877d9a46685a3a4d221e3b2c4b87cb76", - "reference": "44abcdad877d9a46685a3a4d221e3b2c4b87cb76", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "^1.0|^2.0", - "php": "^5.4 || ^7.0" - }, - "replace": { - "rhumsaa/uuid": "self.version" - }, - "require-dev": { - "codeception/aspect-mock": "^1.0 | ~2.0.0", - "doctrine/annotations": "~1.2.0", - "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ^2.1", - "ircmaxell/random-lib": "^1.1", - "jakub-onderka/php-parallel-lint": "^0.9.0", - "mockery/mockery": "^0.9.9", - "moontoast/math": "^1.1", - "php-mock/php-mock-phpunit": "^0.3|^1.1", - "phpunit/phpunit": "^4.7|^5.0", - "squizlabs/php_codesniffer": "^2.3" - }, - "suggest": { - "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", - "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", - "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", - "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", - "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", - "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Ramsey\\Uuid\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marijn Huizendveld", - "email": "marijn.huizendveld@gmail.com" - }, - { - "name": "Thibaud Fabre", - "email": "thibaud@aztech.io" - }, - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - } - ], - "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", - "homepage": "https://github.com/ramsey/uuid", - "keywords": [ - "guid", - "identifier", - "uuid" - ], - "time": "2018-01-20 00:28:24" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "spomky-labs/otphp", @@ -995,70 +952,7 @@ "otp", "totp" ], - "time": "2017-07-24 10:27:40" - }, - { - "name": "symfony/event-dispatcher", - "version": "v4.0.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "63353a71073faf08f62caab4e6889b06a787f07b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/63353a71073faf08f62caab4e6889b06a787f07b", - "reference": "63353a71073faf08f62caab4e6889b06a787f07b", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "conflict": { - "symfony/dependency-injection": "<3.4" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/expression-language": "~3.4|~4.0", - "symfony/stopwatch": "~3.4|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2018-04-06 07:35:43" + "time": "2017-07-24T10:27:40+00:00" }, { "name": "symfony/inflector", @@ -1115,7 +1009,7 @@ "symfony", "words" ], - "time": "2018-01-03 17:15:19" + "time": "2018-01-03T17:15:19+00:00" }, { "name": "symfony/options-resolver", @@ -1169,7 +1063,7 @@ "configuration", "options" ], - "time": "2018-01-18 22:19:33" + "time": "2018-01-18T22:19:33+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -1228,7 +1122,7 @@ "portable", "shim" ], - "time": "2018-01-30 19:27:44" + "time": "2018-01-30T19:27:44+00:00" }, { "name": "symfony/polyfill-php56", @@ -1284,7 +1178,7 @@ "portable", "shim" ], - "time": "2018-01-30 19:27:44" + "time": "2018-01-30T19:27:44+00:00" }, { "name": "symfony/polyfill-util", @@ -1336,7 +1230,7 @@ "polyfill", "shim" ], - "time": "2018-01-31 18:08:44" + "time": "2018-01-31T18:08:44+00:00" }, { "name": "symfony/property-access", @@ -1403,65 +1297,7 @@ "property path", "reflection" ], - "time": "2018-01-03 07:38:00" - }, - { - "name": "symfony/yaml", - "version": "v4.0.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "8b34ebb5989df61cbd77eff29a02c4db9ac1069c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/8b34ebb5989df61cbd77eff29a02c4db9ac1069c", - "reference": "8b34ebb5989df61cbd77eff29a02c4db9ac1069c", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2018-04-03 05:24:00" + "time": "2018-01-03T07:38:00+00:00" } ], "packages-dev": [], diff --git a/database.mwb b/database.mwb index e514b55..9fbac86 100644 Binary files a/database.mwb and b/database.mwb differ diff --git a/database_upgrade/2.0_2.1.sql b/database_upgrade/2.0_2.1.sql new file mode 100644 index 0000000..cafa74b --- /dev/null +++ b/database_upgrade/2.0_2.1.sql @@ -0,0 +1,35 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +CREATE TABLE IF NOT EXISTS `userkeys` ( + `uid` INT(11) NOT NULL, + `key` VARCHAR(100) NOT NULL, + `created` DATETIME NULL DEFAULT NULL, + `typeid` INT(11) NOT NULL, + PRIMARY KEY (`uid`), + INDEX `fk_userkeys_userkeytypes1_idx` (`typeid` ASC), + CONSTRAINT `fk_userkeys_accounts1` + FOREIGN KEY (`uid`) + REFERENCES `accounthub`.`accounts` (`uid`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_userkeys_userkeytypes1` + FOREIGN KEY (`typeid`) + REFERENCES `accounthub`.`userkeytypes` (`typeid`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB +DEFAULT CHARACTER SET = utf8; + +CREATE TABLE IF NOT EXISTS `userkeytypes` ( + `typeid` INT(11) NOT NULL, + `typename` VARCHAR(45) NOT NULL, + PRIMARY KEY (`typeid`, `typename`)) +ENGINE = InnoDB +DEFAULT CHARACTER SET = utf8; + +INSERT INTO `userkeytypes` (`typeid`, `typename`) VALUES (1, 'RSSAtomFeed'); +INSERT INTO `userkeytypes` (`typeid`, `typename`) VALUES (2, 'Other'); \ No newline at end of file diff --git a/feed.php b/feed.php new file mode 100644 index 0000000..65d5dd3 --- /dev/null +++ b/feed.php @@ -0,0 +1,89 @@ +has('userkeys', ['key' => $_GET['key']])) { + http_response_code(403); + die("403 Forbidden: provide valid key"); +} + +$uid = $database->get('userkeys', 'uid', ['key' => $_GET['key']]); +$user = new User($uid); +switch ($user->getStatus()->get()) { + case AccountStatus::NORMAL: + case AccountStatus::CHANGE_PASSWORD: + case AccountStatus::ALERT_ON_ACCESS: + break; + default: + http_response_code(403); + die("403 Forbidden: user account not active"); +} + +$notifications = Notifications::get($user); + +switch ($_GET['type']) { + case "rss1": + $feed = new RSS1(); + break; + case "rss": + case "rss2": + $feed = new RSS2(); + break; + case "atom": + $feed = new ATOM(); + break; + default: + http_response_code(400); + die("400 Bad Request: feed parameter must have a value of \"rss\", \"rss1\", \"rss2\" or \"atom\"."); +} + +$feed->setTitle($Strings->build("Notifications from server for user", ['server' => SITE_TITLE, 'user' => $user->getName()], false)); + +if (strpos(URL, "http") === 0) { + $url = URL; +} else { + $url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . (($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) ? ":" . $_SERVER['SERVER_PORT'] : "") . URL; +} + +$feed->setLink($url); + +foreach ($notifications as $n) { + $item = $feed->createNewItem(); + $item->setTitle($n['title']); + if (empty($n['url'])) { + $item->setLink($url); + } else { + $item->setLink($n['url']); + } + $item->setDate(strtotime($n['timestamp'])); + if ($n['sensitive']) { + $content = $Strings->get("Sensitive content hidden", false); + } else { + $content = $n['content']; + } + if ($_GET['type'] == "atom") { + $item->setContent($content); + } else { + $item->setDescription($content); + } + $feed->addItem($item); +} + +$feed->printFeed(); diff --git a/langs/en/notifications.json b/langs/en/notifications.json index 71831dc..259c08d 100644 --- a/langs/en/notifications.json +++ b/langs/en/notifications.json @@ -3,5 +3,7 @@ "Notification deleted.": "Notification deleted.", "Mark as read": "Mark as read", "Delete": "Delete", - "All caught up!": "All caught up!" + "All caught up!": "All caught up!", + "Notifications from server for user": "Notifications from {server} for {user}", + "Sensitive content hidden": "Sensitive content hidden" } diff --git a/langs/en/sync.json b/langs/en/sync.json index d175aa3..0f43b93 100644 --- a/langs/en/sync.json +++ b/langs/en/sync.json @@ -9,5 +9,8 @@ "manual setup": "Manual Setup:", "sync key": "Sync key:", "url": "URL:", - "sync code name": "Device nickname" + "sync code name": "Device nickname", + "notification feed explained": "You can receive notifications via a RSS or ATOM news reader by clicking one of the buttons or manually adding a URL. Click the Reset button if you think someone else might know your feed URL (you'll need to delete and re-add the feed on all your devices).", + "Reset": "Reset", + "Feed key reset.": "Feed key reset." } diff --git a/langs/messages.php b/langs/messages.php index fd007e1..0562904 100644 --- a/langs/messages.php +++ b/langs/messages.php @@ -72,5 +72,9 @@ define("MESSAGES", [ "notification_deleted" => [ "string" => "Notification deleted.", "type" => "success" + ], + "feed_key_reset" => [ + "string" => "Feed key reset.", + "type" => "success" ] ]); diff --git a/lib/RandomString.lib.php b/lib/RandomString.lib.php new file mode 100644 index 0000000..56887d3 --- /dev/null +++ b/lib/RandomString.lib.php @@ -0,0 +1,31 @@ +insert('mobile_codes', ['uid' => $_SESSION['uid'], 'code' => $code, 'description' => $desc]); } - if (strpos(URL, "http") !== FALSE) { + if (strpos(URL, "http") === 0) { $url = URL . "mobile/index.php"; } else { $url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . (($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) ? ":" . $_SERVER['SERVER_PORT'] : "") . URL . "mobile/index.php"; @@ -124,4 +124,49 @@ if (!empty($_GET['delsynccode'])) { +
+
+
+
get("Notifications"); ?>
+
+

+ get("notification feed explained"); ?> +

+ has('userkeys', ['AND' => ['uid' => $_SESSION['uid'], 'typeid' => 1]])) { + $key = $database->get('userkeys', 'key', ['AND' => ['uid' => $_SESSION['uid'], 'typeid' => 1]]); + } else { + $key = RandomString::generate(50); + while ($database->has('userkeys', ['key' => $key])) { + $key = RandomString::generate(50); + } + $database->insert('userkeys', ['uid' => $_SESSION['uid'], 'typeid' => 1, 'created' => date('Y-m-d H:i:s'), 'key' => $key]); + } + + if (strpos(URL, "http") === 0) { + $url = URL; + } else { + $url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . (($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) ? ":" . $_SERVER['SERVER_PORT'] : "") . URL; + } + $url = $url . "feed.php?key=$key"; + ?> + RSS 2.0 + RSS 1.0 + ATOM +
+ RSS 2.0: +
+ RSS 1.0: +
+ ATOM: +
+
+ + + +
+
+
+
+ \ No newline at end of file