From 4dd673157b05fea5fe3643f16e22d01bbf005fe9 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 13 Feb 2014 21:45:25 +0100 Subject: Add possibility to anonymous to refresh feeds Obviously, it's optional! (and deactivate by default) Need some more tests? See #351 --- lib/Minz/Configuration.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'lib/Minz/Configuration.php') diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index 572b9984d..b3de9e39e 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -52,6 +52,7 @@ class Minz_Configuration { private static $delay_cache = 3600; private static $default_user = ''; private static $allow_anonymous = false; + private static $allow_anonymous_refresh = false; private static $auth_type = 'none'; private static $db = array ( @@ -118,6 +119,9 @@ class Minz_Configuration { public static function allowAnonymous() { return self::$allow_anonymous; } + public static function allowAnonymousRefresh() { + return self::$allow_anonymous_refresh; + } public static function authType() { return self::$auth_type; } @@ -131,6 +135,9 @@ class Minz_Configuration { public static function _allowAnonymous($allow = false) { self::$allow_anonymous = ((bool)$allow) && self::canLogIn(); } + public static function _allowAnonymousRefresh($allow = false) { + self::$allow_anonymous_refresh = ((bool)$allow) && self::allowAnonymous(); + } public static function _authType($value) { $value = strtolower($value); switch ($value) { @@ -170,6 +177,7 @@ class Minz_Configuration { 'title' => self::$title, 'default_user' => self::$default_user, 'allow_anonymous' => self::$allow_anonymous, + 'allow_anonymous_refresh' => self::$allow_anonymous_refresh, 'auth_type' => self::$auth_type, ), 'db' => self::$db, @@ -276,7 +284,16 @@ class Minz_Configuration { self::_authType($general['auth_type']); } if (isset ($general['allow_anonymous'])) { - self::$allow_anonymous = ((bool)($general['allow_anonymous'])) && ($general['allow_anonymous'] !== 'no'); + self::$allow_anonymous = ( + ((bool)($general['allow_anonymous'])) && + ($general['allow_anonymous'] !== 'no') + ); + } + if (isset ($general['allow_anonymous_refresh'])) { + self::$allow_anonymous_refresh = ( + ((bool)($general['allow_anonymous_refresh'])) && + ($general['allow_anonymous_refresh'] !== 'no') + ); } // Base de données -- cgit v1.2.3 From 6dffb8706f096acdbcda367210d0b7ad41937174 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 27 Feb 2014 22:48:11 +0100 Subject: Alpha version of Google Reader compatible API https://github.com/marienfressinaud/FreshRSS/issues/13 Hardcoded passwords, no possibility to add/delete feeds or edit categories yet. --- app/Models/EntryDAO.php | 88 +++++++- app/Models/FeedDAO.php | 13 ++ lib/Minz/Configuration.php | 15 ++ p/api/greader.php | 552 +++++++++++++++++++++++++++++++++++++++++++++ p/api/index.html | 17 ++ 5 files changed, 674 insertions(+), 11 deletions(-) create mode 100644 p/api/greader.php create mode 100644 p/api/index.html (limited to 'lib/Minz/Configuration.php') diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index f41d6c560..b25ae444b 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -64,15 +64,15 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { return false; } } - public function markReadEntries ($idMax = 0, $favorites = false) { + public function markReadEntries ($idMax = 0, $onlyFavorites = false, $priorityMin = 0) { if ($idMax == 0) { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' - . 'WHERE e.is_read = 0 AND '; - if ($favorites) { - $sql .= 'e.is_favorite = 1'; - } else { - $sql .= 'f.priority > 0'; + . 'WHERE e.is_read = 0'; + if ($onlyFavorites) { + $sql .= ' AND e.is_favorite = 1'; + } elseif ($priorityMin >= 0) { + $sql .= ' AND f.priority > ' . intval($priorityMin); } $stm = $this->bd->prepare ($sql); if ($stm && $stm->execute ()) { @@ -87,11 +87,11 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' - . 'WHERE e.is_read = 0 AND e.id <= ? AND '; - if ($favorites) { - $sql .= 'e.is_favorite = 1'; - } else { - $sql .= 'f.priority > 0'; + . 'WHERE e.is_read = 0 AND e.id <= ?'; + if ($onlyFavorites) { + $sql .= ' AND e.is_favorite = 1'; + } elseif ($priorityMin >= 0) { + $sql .= ' AND f.priority > ' . intval($priorityMin); } $values = array ($idMax); $stm = $this->bd->prepare ($sql); @@ -126,6 +126,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { return $affected; } } + public function markReadCat ($id, $idMax = 0) { if ($idMax == 0) { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' @@ -181,6 +182,68 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { return $affected; } } + + public function markReadCatName($name, $idMax = 0) { + if ($idMax == 0) { + $sql = 'UPDATE `' . $this->prefix . 'entry` e ' + . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE c.name = ?'; + $values = array($name); + $stm = $this->bd->prepare($sql); + if ($stm && $stm->execute($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } else { + $this->bd->beginTransaction(); + + $sql = 'UPDATE `' . $this->prefix . 'entry` e ' + . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category ' + . 'SET e.is_read = 1 ' + . 'WHERE c.name = ? AND e.id <= ?'; + $values = array($name, $idMax); + $stm = $this->bd->prepare($sql); + if (!($stm && $stm->execute($values))) { + $info = $stm->errorInfo(); + Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack(); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'LEFT OUTER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(*) AS nbUnreads ' + . 'FROM `' . $this->prefix . 'entry` e ' + . 'WHERE e.is_read = 0 ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category ' + . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0) ' + . 'WHERE c.name = ?'; + $values = array($name); + $stm = $this->bd->prepare($sql); + if (!($stm && $stm->execute($values))) { + $info = $stm->errorInfo(); + Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack(); + return false; + } + } + + $this->bd->commit(); + return $affected; + } + } + public function markReadFeed ($id, $idMax = 0) { if ($idMax == 0) { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' @@ -281,6 +344,9 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { $where .= 'e1.id_feed = ? '; $values[] = intval($id); break; + case 'A': + $where .= '1 '; + break; default: throw new FreshRSS_EntriesGetter_Exception ('Bad type in Entry->listByType: [' . $type . ']!'); } diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php index 7ebe68d2b..79d8cff90 100644 --- a/app/Models/FeedDAO.php +++ b/app/Models/FeedDAO.php @@ -198,6 +198,19 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo { return self::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC)); } + public function listCategoryNames() { + $sql = 'SELECT f.id, c.name as c_name FROM `' . $this->prefix . 'feed` f ' + . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll(PDO::FETCH_ASSOC); + $feedCategoryNames = array(); + foreach ($res as $line) { + $feedCategoryNames[$line['id']] = $line['c_name']; + } + return $feedCategoryNames; + } + public function listFeedsOrderUpdate ($cacheDuration = 1500) { $sql = 'SELECT id, name, url, lastUpdate, pathEntries, httpAuth, keep_history ' . 'FROM `' . $this->prefix . 'feed` ' diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index b3de9e39e..ff71d747c 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -54,6 +54,7 @@ class Minz_Configuration { private static $allow_anonymous = false; private static $allow_anonymous_refresh = false; private static $auth_type = 'none'; + private static $api_enabled = false; private static $db = array ( 'type' => 'mysql', @@ -131,6 +132,9 @@ class Minz_Configuration { public static function canLogIn() { return self::$auth_type === 'form' || self::$auth_type === 'persona'; } + public static function apiEnabled() { + return self::$api_enabled; + } public static function _allowAnonymous($allow = false) { self::$allow_anonymous = ((bool)$allow) && self::canLogIn(); @@ -151,6 +155,10 @@ class Minz_Configuration { self::_allowAnonymous(self::$allow_anonymous); } + public static function _enableApi($value = false) { + self::$api_enabled = (bool)$value; + } + /** * Initialise les variables de configuration * @exception Minz_FileNotExistException si le CONF_PATH_NAME n'existe pas @@ -179,6 +187,7 @@ class Minz_Configuration { 'allow_anonymous' => self::$allow_anonymous, 'allow_anonymous_refresh' => self::$allow_anonymous_refresh, 'auth_type' => self::$auth_type, + 'api_enabled' => self::$api_enabled, ), 'db' => self::$db, ); @@ -295,6 +304,12 @@ class Minz_Configuration { ($general['allow_anonymous_refresh'] !== 'no') ); } + if (isset ($general['api_enabled'])) { + self::$api_enabled = ( + ((bool)($general['api_enabled'])) && + ($general['api_enabled'] !== 'no') + ); + } // Base de données if (isset ($ini_array['db'])) { diff --git a/p/api/greader.php b/p/api/greader.php new file mode 100644 index 000000000..2969f5935 --- /dev/null +++ b/p/api/greader.php @@ -0,0 +1,552 @@ + date('c'), 'headers' => $ALL_HEADERS, '_SERVER' => $_SERVER, '_GET' => $_GET, '_POST' => $_POST, '_COOKIE' => $_COOKIE, 'INPUT' => $ORIGINAL_INPUT); + +if (PHP_INT_SIZE < 8) { //32-bit + function dec2hex($dec) { + return str_pad(gmp_strval(gmp_init($dec, 10), 16), 16, '0', STR_PAD_LEFT); + } + function hex2dec($hex) { + return gmp_strval(gmp_init($hex, 16), 10); + } +} else { //64-bit + function dec2hex($dec) { //http://code.google.com/p/google-reader-api/wiki/ItemId + return str_pad(dechex($dec), 16, '0', STR_PAD_LEFT); + } + function hex2dec($hex) { + return hexdec($hex); + } +} + +function headerVariable($headerName, $varName) { + global $ALL_HEADERS; + if (empty($ALL_HEADERS[$headerName])) { + return null; + } + parse_str($ALL_HEADERS[$headerName], $pairs); + //logMe('headerVariable(' . $headerName . ') => ' . print_r($pairs, true)); + return isset($pairs[$varName]) ? $pairs[$varName] : null; +} + +function multiplePosts($name) { //https://bugs.php.net/bug.php?id=51633 + global $ORIGINAL_INPUT; + $inputs = explode('&', $ORIGINAL_INPUT); + $result = array(); + $prefix = $name . '='; + $prefixLength = strlen($prefix); + foreach ($inputs as $input) { + if (strpos($input, $prefix) === 0) { + $result[] = urldecode(substr($input, $prefixLength)); + } + } + return $result; +} + +class MyPDO extends Minz_ModelPdo { + function prepare($sql) { + return $this->bd->prepare(str_replace('%_', $this->prefix, $sql)); + } +} + +function logMe($text) { + file_put_contents(LOG_PATH . '/api.log', $text, FILE_APPEND); +} + +function badRequest() { + logMe("badRequest()\n"); + header('HTTP/1.1 400 Bad Request'); + header('Content-Type: text/plain; charset=UTF-8'); + die('Bad Request!'); +} + +function unauthorized() { + logMe("unauthorized()\n"); + header('HTTP/1.1 401 Unauthorized'); + header('Content-Type: text/plain; charset=UTF-8'); + header('Google-Bad-Token: true'); + die('Unauthorized!'); +} + +function notImplemented() { + logMe("notImplemented()\n"); + header('HTTP/1.1 501 Not Implemented'); + header('Content-Type: text/plain; charset=UTF-8'); + die('Not Implemented!'); +} + +function serviceUnavailable() { + logMe("serviceUnavailable()\n"); + header('HTTP/1.1 503 Service Unavailable'); + header('Content-Type: text/plain; charset=UTF-8'); + die('Service Unavailable!'); +} + +function checkCompatibility() { + logMe("checkCompatibility()\n"); + header('Content-Type: text/plain; charset=UTF-8'); + $ok = true; + $ok &= function_exists('getallheaders'); + echo $ok ? 'PASS' : 'FAIL'; + exit(); +} + +function authorizationToUser() { + $auth = headerVariable('Authorization', 'GoogleLogin_auth'); //Input is 'GoogleLogin auth', but PHP replaces spaces by '_' http://php.net/language.variables.external + //logMe('authorizationToUser, auth => ' . $auth . "\n"); + list($userName) = explode('/', $auth); + return $userName; +} + +function clientLogin($email, $pass) { //http://web.archive.org/web/20130604091042/http://undoc.in/clientLogin.html + logMe('clientLogin(' . $email . ")\n"); + if ($pass !== TEMP_PASSWORD) { + unauthorized(); + } + header('Content-Type: text/plain; charset=UTF-8'); + $auth = $email . '/' . '0123456789'; + echo 'SID=', $auth, "\n", + 'Auth=', $auth, "\n"; + exit(); +} + +function token($user) { +//http://blog.martindoms.com/2009/08/15/using-the-google-reader-api-part-1/ https://github.com/ericmann/gReader-Library/blob/master/greader.class.php + logMe('token('. $user . ")\n"); + $token = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ01234'; //Must have 57 characters... + echo $token, "\n"; + exit(); +} + +function checkToken($user, $token) { +//http://code.google.com/p/google-reader-api/wiki/ActionToken + logMe('checkToken(' . $token . ")\n"); + if ($token === 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ01234') { + return true; + } + unauthorized(); +} + +function tagList() { + logMe("tagList()\n"); + header('Content-Type: application/json; charset=UTF-8'); + + $pdo = new MyPDO(); + $stm = $pdo->prepare('SELECT c.name FROM `%_category` c'); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + + $tags = array( + array('id' => 'user/-/state/com.google/starred'), + //array('id' => 'user/-/state/com.google/broadcast', 'sortid' => '2'), + ); + + foreach ($res as $cName) { + $tags[] = array( + 'id' => 'user/-/label/' . $cName, + //'sortid' => $cName, + ); + } + + echo json_encode(array('tags' => $tags)), "\n"; + exit(); +} + +function subscriptionList() { + logMe("subscriptionList()\n"); + header('Content-Type: application/json; charset=UTF-8'); + + $pdo = new MyPDO(); + $stm = $pdo->prepare('SELECT f.id, f.name, f.url, f.website, c.id as c_id, c.name as c_name FROM `%_feed` f + INNER JOIN `%_category` c ON c.id = f.category'); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_ASSOC); + + $subscriptions = array(); + + foreach ($res as $line) { + $subscriptions[] = array( + 'id' => 'feed/' . $line['id'], + 'title' => $line['name'], + 'categories' => array( + array( + 'id' => 'user/-/label/' . $line['c_name'], + 'label' => $line['c_name'], + ), + ), + //'sortid' => $line['name'], + //'firstitemmsec' => 0, + 'url' => $line['url'], + 'htmlUrl' => $line['website'], + //'iconUrl' => '', + ); + } + + echo json_encode(array('subscriptions' => $subscriptions)), "\n"; + exit(); +} + +function unreadCount() { + logMe("unreadCount()\n"); + header('Content-Type: application/json; charset=UTF-8'); + + $pdo = new MyPDO(); + $stm = $pdo->prepare('SELECT f.id, f.lastUpdate, f.cache_nbUnreads FROM `%_feed` f'); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_ASSOC); + + $unreadcounts = array(); + $totalUnreads = 0; + $totalLastUpdate = 0; + foreach ($res as $line) { + $nbUnreads = $line['cache_nbUnreads']; + $totalUnreads += $nbUnreads; + $lastUpdate = $line['lastUpdate']; + if ($totalLastUpdate < $lastUpdate) { + $totalLastUpdate = $lastUpdate; + } + $unreadcounts[] = array( + 'id' => 'feed/' . $line['id'], + 'count' => $nbUnreads, + 'newestItemTimestampUsec' => $lastUpdate . '000000', + ); + } + + $unreadcounts[] = array( + 'id' => 'user/-/state/com.google/reading-list', + 'count' => $totalUnreads, + 'newestItemTimestampUsec' => $totalLastUpdate . '000000', + ); + + echo json_encode(array( + 'max' => $totalUnreads, + 'unreadcounts' => $unreadcounts, + )), "\n"; + exit(); +} + +function streamContents($path, $include_target, $start_time, $count, $order, $exclude_target) +{//http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#feed + logMe('streamContents(' . $include_target . ")\n"); + header('Content-Type: application/json; charset=UTF-8'); + + $feedDAO = new FreshRSS_FeedDAO(); + $feedCategoryNames = $feedDAO->listCategoryNames(); + + switch ($path) { + case 'reading-list': + $type = 'A'; + break; + case 'starred': + $type = 's'; + break; + case 'label': + $type = 'c'; + break; + default: + $type = 'A'; + break; + } + + switch ($exclude_target) { + case 'user/-/state/com.google/read': + $state = 'not_read'; + break; + default: + $state = 'all'; + break; + } + + $entryDAO = new FreshRSS_EntryDAO(); + $entries = $entryDAO->listWhere($type, $include_target, $state, $order === 'o' ? 'ASC' : 'DESC', $count, '', '', $start_time); + + $items = array(); + foreach ($entries as $entry) { + $f_id = $entry->feed(); + $c_name = isset($feedCategoryNames[$f_id]) ? $feedCategoryNames[$f_id] : '_'; + $item = array( + 'id' => /*'tag:google.com,2005:reader/item/' .*/ dec2hex($entry->id()), //64-bit hexa http://code.google.com/p/google-reader-api/wiki/ItemId + 'crawlTimeMsec' => substr($entry->id(), 0, -3), + 'published' => $entry->date(true), + 'title' => $entry->title(), + 'summary' => array('content' => $entry->content()), + 'alternate' => array( + array('href' => $entry->link()), + ), + 'categories' => array( + 'user/-/state/com.google/reading-list', + 'user/-/label/' . $c_name, + ), + 'origin' => array( + 'streamId' => 'feed/' . $f_id, + //'title' => $line['f_name'], + //'htmlUrl' => $line['f_website'], + ), + ); + if ($entry->author() != '') { + $item['author'] = $entry->author(); + } + if ($entry->isRead()) { + $item['categories'][] = 'user/-/state/com.google/read'; + } + if ($entry->isFavorite()) { + $item['categories'][] = 'user/-/state/com.google/starred'; + } + $items[] = $item; + } + + echo json_encode(array( + 'id' => 'user/-/state/com.google/reading-list', + 'updated' => time(), + 'items' => $items, + )), "\n"; + exit(); +} + +function streamContentsItemsIds($streamId, $start_time, $count, $order, $exclude_target) +{//http://code.google.com/p/google-reader-api/wiki/ApiStreamItemsIds http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#feed + logMe('streamContentsItemsIds(' . $streamId . ")\n"); + + $type = 'A'; + $id = ''; + if ($streamId === 'user/-/state/com.google/reading-list') { + $type = 'A'; + } elseif ('user/-/state/com.google/starred') { + $type = 's'; + } elseif (strpos($streamId, 'feed/') === 0) { + $type = 'f'; + $id = basename($streamId); + } elseif (strpos($streamId, 'user/-/label/') === 0) { + $type = 'C'; + $c_name = basename($streamId); + notImplemented(); //TODO + } + + switch ($exclude_target) { + case 'user/-/state/com.google/read': + $state = 'not_read'; + break; + default: + $state = 'all'; + break; + } + + $entryDAO = new FreshRSS_EntryDAO(); + $entries = $entryDAO->listWhere($type, $id, $state, $order === 'o' ? 'ASC' : 'DESC', $count, '', '', $start_time); + + $itemRefs = array(); + foreach ($entries as $entry) { + $f_id = $entry->feed(); + $itemRefs[] = array( + 'id' => $entry->id(), //64-bit decimal + //'timestampUsec' => $entry->dateAdded(true), + /*'directStreamIds' => array( + 'feed/' . $entry->feed() + ),*/ + ); + } + + echo json_encode(array( + 'itemRefs' => $itemRefs, + )), "\n"; + exit(); +} + +function editTag($e_ids, $a, $r) { + logMe("editTag()\n"); + $entryDAO = new FreshRSS_EntryDAO(); + + foreach ($e_ids as $e_id) { //TODO: User WHERE...IN + $e_id = hex2dec(basename($e_id)); //Strip prefix 'tag:google.com,2005:reader/item/' + switch ($a) { + case 'user/-/state/com.google/read': + $entryDAO->markRead($e_id, true); + break; + case 'user/-/state/com.google/starred': + $entryDAO->markFavorite($e_id, true); + break; + /*case 'user/-/state/com.google/tracking-kept-unread': + break; + case 'user/-/state/com.google/like': + break; + case 'user/-/state/com.google/broadcast': + break;*/ + } + switch ($r) { + case 'user/-/state/com.google/read': + $entryDAO->markRead($e_id, false); + break; + case 'user/-/state/com.google/starred': + $entryDAO->markFavorite($e_id, false); + break; + } + } + + echo 'OK'; + exit(); +} + +function markAllAsRead($streamId, $olderThanId) { + logMe('markAllAsRead(' . $streamId . ")\n"); + $entryDAO = new FreshRSS_EntryDAO(); + if (strpos($streamId, 'feed/') === 0) { + $f_id = basename($streamId); + $entryDAO->markReadFeed($f_id, $olderThanId); + } elseif (strpos($streamId, 'user/-/label/') === 0) { + $c_name = basename($streamId); + $entryDAO->markReadCatName($c_name, $olderThanId); + } elseif ($streamId === 'user/-/state/com.google/reading-list') { + $entryDAO->markReadEntries($olderThanId, false, -1); + } + + echo 'OK'; + exit(); +} + +logMe('----------------------------------------------------------------'."\n"); +logMe(print_r($debugInfo, true)); + +$pathInfo = empty($_SERVER['PATH_INFO']) ? '/Error' : $_SERVER['PATH_INFO']; +$pathInfos = explode('/', $pathInfo); + +logMe('pathInfos => ' . print_r($pathInfos, true)); + +Minz_Configuration::init(); + +if (!Minz_Configuration::apiEnabled()) { + serviceUnavailable(); +} + +Minz_Session::init('FreshRSS'); + +$user = authorizationToUser(); +$conf = null; + +logMe('User => ' . $user . "\n"); + +if ($user != null) { + try { + $conf = new FreshRSS_Configuration($user); + } catch (Exception $e) { + logMe($e->getMessage()); + $user = null; + badRequest(); + } +} + +Minz_Session::_param('currentUser', $user); + +if (count($pathInfos)<3) badRequest(); +elseif ($pathInfos[1] === 'accounts') { + if (($pathInfos[2] === 'ClientLogin') && isset($_REQUEST['Email']) && isset($_REQUEST['Passwd'])) + clientLogin($_REQUEST['Email'], $_REQUEST['Passwd']); +} +elseif ($pathInfos[1] === 'reader' && $pathInfos[2] === 'api' && isset($pathInfos[3]) && $pathInfos[3] === '0' && isset($pathInfos[4])) { + if ($user == null) { + unauthorized(); + } + $timestamp = isset($_GET['ck']) ? intval($_GET['ck']) : 0; //ck=[unix timestamp] : Use the current Unix time here, helps Google with caching. + switch ($pathInfos[4]) { + case 'stream': + $exclude_target = isset($_GET['xt']) ? $_GET['xt'] : ''; //xt=[exclude target] : Used to exclude certain items from the feed. For example, using xt=user/-/state/com.google/read will exclude items that the current user has marked as read, or xt=feed/[feedurl] will exclude items from a particular feed (obviously not useful in this request, but xt appears in other listing requests). + $count = isset($_GET['n']) ? intval($_GET['n']) : 20; //n=[integer] : The maximum number of results to return. + $order = isset($_GET['r']) ? $_GET['r'] : 'd'; //r=[d|n|o] : Sort order of item results. d or n gives items in descending date order, o in ascending order. + $start_time = isset($_GET['ot']) ? intval($_GET['ot']) : 0; //ot=[unix timestamp] : The time from which you want to retrieve items. Only items that have been crawled by Google Reader after this time will be returned. + if (isset($pathInfos[5]) && $pathInfos[5] === 'contents' && isset($pathInfos[6]) && isset($pathInfos[7])) { + if ($pathInfos[6] === 'feed') { + $include_target = $pathInfos[7]; + StreamContents($pathInfos[6], $include_target, $start_time, $count, $order, $exclude_target); + } elseif ($pathInfos[6] === 'user' && isset($pathInfos[8]) && isset($pathInfos[9])) { + if ($pathInfos[8] === 'state') { + if ($pathInfos[9] === 'com.google' && isset($pathInfos[10])) { + if ($pathInfos[10] === 'reading-list' || $pathInfos[10] === 'starred') { + $include_target = ''; + streamContents($pathInfos[10], $include_target, $start_time, $count, $order, $exclude_target); + } + } + } elseif ($pathInfos[8] === 'label') { + $include_target = $pathInfos[9]; + streamContents($pathInfos[8], $include_target, $start_time, $count, $order, $exclude_target); + } + } + } elseif ($pathInfos[5] === 'items') { + if ($pathInfos[6] === 'ids' && isset($_GET['s'])) { + $streamId = $_GET['s']; //StreamId for which to fetch the item IDs. The parameter may be repeated to fetch the item IDs from multiple streams at once (more efficient from a backend perspective than multiple requests). + streamContentsItemsIds($streamId, $start_time, $count, $order, $exclude_target); + } + } + break; + case 'tag': + if (isset($pathInfos[5]) && $pathInfos[5] === 'list') { + $output = isset($_GET['output']) ? $_GET['output'] : ''; + if ($output !== 'json') notImplemented(); + tagList($_GET['output']); + } + break; + case 'subscription': + if (isset($pathInfos[5]) && $pathInfos[5] === 'list') { + $output = isset($_GET['output']) ? $_GET['output'] : ''; + if ($output !== 'json') notImplemented(); + subscriptionList($_GET['output']); + } + break; + case 'unread-count': + $output = isset($_GET['output']) ? $_GET['output'] : ''; + if ($output !== 'json') notImplemented(); + $all = isset($_GET['all']) ? $_GET['all'] : ''; + unreadCount($all); + break; + case 'edit-tag': //http://blog.martindoms.com/2010/01/20/using-the-google-reader-api-part-3/ + $token = isset($_POST['T']) ? trim($_POST['T']) : ''; + checkToken($user, $token); + $a = isset($_POST['a']) ? $_POST['a'] : ''; //Add: user/-/state/com.google/read user/-/state/com.google/starred + $r = isset($_POST['r']) ? $_POST['r'] : ''; //Remove: user/-/state/com.google/read user/-/state/com.google/starred + $e_ids = multiplePosts('i'); //item IDs + editTag($e_ids, $a, $r); + break; + case 'mark-all-as-read': + $token = isset($_POST['T']) ? trim($_POST['T']) : ''; + checkToken($user, $token); + $streamId = $_POST['s']; //StreamId + $ts = isset($_POST['ts']) ? $_POST['ts'] : '0'; //Older than timestamp in nanoseconds + if (!ctype_digit($ts)) { + $ts = '0'; + } + markAllAsRead($streamId, $ts); + break; + case 'token': + Token($user); + break; + } +} elseif ($pathInfos[1] === 'check' && $pathInfos[2] === 'compatibility') { + checkCompatibility(); +} + +badRequest(); diff --git a/p/api/index.html b/p/api/index.html new file mode 100644 index 000000000..123d0d001 --- /dev/null +++ b/p/api/index.html @@ -0,0 +1,17 @@ + + + + +FreshRSS API + + + + + +

FreshRSS API

+ + + + -- cgit v1.2.3 From b07f9157b18bffdb28833ed1363284571be3644e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 2 Mar 2014 13:35:09 +0100 Subject: New unsafe autologin mode https://github.com/marienfressinaud/FreshRSS/issues/440 --- app/Controllers/indexController.php | 26 ++++++++++++++++++++++++++ lib/Minz/Configuration.php | 14 ++++++++++++++ p/i/install.php | 3 +++ 3 files changed, 43 insertions(+) (limited to 'lib/Minz/Configuration.php') diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index c83c5b630..0905e591a 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -352,6 +352,32 @@ class FreshRSS_index_Controller extends Minz_ActionController { } $this->view->_useLayout(false); Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); + } elseif (Minz_Configuration::unsafeAutologinEnabled() && isset($_GET['u']) && isset($_GET['p'])) { + Minz_Session::_param('currentUser'); + Minz_Session::_param('mail'); + Minz_Session::_param('passwordHash'); + $username = ctype_alnum($_GET['u']) ? $_GET['u'] : ''; + $passwordPlain = $_GET['p']; + Minz_Request::_param('p'); //Discard plain-text password ASAP + $_GET['p'] = ''; + if (!function_exists('password_verify')) { + include_once(LIB_PATH . '/password_compat.php'); + } + try { + $conf = new FreshRSS_Configuration($username); + $s = $conf->passwordHash; + $ok = password_verify($passwordPlain, $s); + unset($passwordPlain); + if ($ok) { + Minz_Session::_param('currentUser', $username); + Minz_Session::_param('passwordHash', $s); + } else { + Minz_Log::record('Unsafe password mismatch for user ' . $username, Minz_Log::WARNING); + } + } catch (Minz_Exception $me) { + Minz_Log::record('Unsafe login failure: ' . $me->getMessage(), Minz_Log::WARNING); + } + Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); } elseif (!Minz_Configuration::canLogIn()) { Minz_Error::error ( 403, diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index ff71d747c..324aae881 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -55,6 +55,7 @@ class Minz_Configuration { private static $allow_anonymous_refresh = false; private static $auth_type = 'none'; private static $api_enabled = false; + private static $unsafe_autologin_enabled = false; private static $db = array ( 'type' => 'mysql', @@ -135,6 +136,9 @@ class Minz_Configuration { public static function apiEnabled() { return self::$api_enabled; } + public static function unsafeAutologinEnabled() { + return self::$unsafe_autologin_enabled; + } public static function _allowAnonymous($allow = false) { self::$allow_anonymous = ((bool)$allow) && self::canLogIn(); @@ -158,6 +162,9 @@ class Minz_Configuration { public static function _enableApi($value = false) { self::$api_enabled = (bool)$value; } + public static function _enableAutologin($value = false) { + self::$unsafe_autologin_enabled = (bool)$value; + } /** * Initialise les variables de configuration @@ -188,6 +195,7 @@ class Minz_Configuration { 'allow_anonymous_refresh' => self::$allow_anonymous_refresh, 'auth_type' => self::$auth_type, 'api_enabled' => self::$api_enabled, + 'unsafe_autologin_enabled' => self::$unsafe_autologin_enabled, ), 'db' => self::$db, ); @@ -310,6 +318,12 @@ class Minz_Configuration { ($general['api_enabled'] !== 'no') ); } + if (isset ($general['unsafe_autologin_enabled'])) { + self::$unsafe_autologin_enabled = ( + ((bool)($general['unsafe_autologin_enabled'])) && + ($general['unsafe_autologin_enabled'] !== 'no') + ); + } // Base de données if (isset ($ini_array['db'])) { diff --git a/p/i/install.php b/p/i/install.php index 720813323..a7563d5ee 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -235,6 +235,9 @@ function saveStep3 () { 'default_user' => $_SESSION['default_user'], 'auth_type' => $_SESSION['auth_type'], 'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false, + 'allow_anonymous_refresh' => false, + 'unsafe_autologin_enabled' => false, + 'api_enabled' => false, ), 'db' => array( 'type' => $_SESSION['bd_type'], -- cgit v1.2.3 From 72ae58d45534b4c8b49ea0ac33a9a9ec9df4bdb1 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 22 Mar 2014 13:20:49 +0100 Subject: Minz: remove Minz_Cache https://github.com/marienfressinaud/FreshRSS/issues/163#issuecomment-37990319 https://github.com/marienfressinaud/FreshRSS/issues/303 --- lib/Minz/Cache.php | 116 --------------------------------------------- lib/Minz/Configuration.php | 22 --------- lib/Minz/Dispatcher.php | 57 ++++++++-------------- 3 files changed, 21 insertions(+), 174 deletions(-) delete mode 100644 lib/Minz/Cache.php (limited to 'lib/Minz/Configuration.php') diff --git a/lib/Minz/Cache.php b/lib/Minz/Cache.php deleted file mode 100644 index fcb627eb2..000000000 --- a/lib/Minz/Cache.php +++ /dev/null @@ -1,116 +0,0 @@ - -*/ - -/** - * La classe Cache permet de gérer facilement les pages en cache - */ -class Minz_Cache { - /** - * $expire timestamp auquel expire le cache de $url - */ - private $expire = 0; - - /** - * $file est le nom du fichier de cache - */ - private $file = ''; - - /** - * $enabled permet de déterminer si le cache est activé - */ - private static $enabled = true; - - /** - * Constructeur - */ - public function __construct () { - $this->_fileName (); - $this->_expire (); - } - - /** - * Setteurs - */ - public function _fileName () { - $file = md5 (Minz_Request::getURI ()); - - $this->file = CACHE_PATH . '/'.$file; - } - - public function _expire () { - if ($this->exist ()) { - $this->expire = filemtime ($this->file) - + Minz_Configuration::delayCache (); - } - } - - /** - * Permet de savoir si le cache est activé - * @return true si activé, false sinon - */ - public static function isEnabled () { - return Minz_Configuration::cacheEnabled () && self::$enabled; - } - - /** - * Active / désactive le cache - */ - public static function switchOn () { - self::$enabled = true; - } - public static function switchOff () { - self::$enabled = false; - } - - /** - * Détermine si le cache de $url a expiré ou non - * @return true si il a expiré, false sinon - */ - public function expired () { - return time () > $this->expire; - } - - /** - * Affiche le contenu du cache - * @print le code html du cache - */ - public function render () { - if ($this->exist ()) { - include ($this->file); - } - } - - /** - * Enregistre $html en cache - * @param $html le html à mettre en cache - */ - public function cache ($html) { - file_put_contents ($this->file, $html); - } - - /** - * Permet de savoir si le cache existe - * @return true si il existe, false sinon - */ - public function exist () { - return file_exists ($this->file); - } - - /** - * Nettoie le cache en supprimant tous les fichiers - */ - public static function clean () { - $files = opendir (CACHE_PATH); - - while ($fic = readdir ($files)) { - if ($fic != '.' && $fic != '..') { - unlink (CACHE_PATH.'/'.$fic); - } - } - - closedir ($files); - } -} diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index 324aae881..d905f6ddd 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -34,8 +34,6 @@ class Minz_Configuration { * $base_url le chemin de base pour accéder à l'application * $title le nom de l'application * $language la langue par défaut de l'application - * $cacheEnabled permet de savoir si le cache doit être activé - * $delayCache la limite de cache * $db paramètres pour la base de données (tableau) * - host le serveur de la base * - user nom d'utilisateur @@ -48,8 +46,6 @@ class Minz_Configuration { private static $use_url_rewriting = false; private static $title = ''; private static $language = 'en'; - private static $cache_enabled = false; - private static $delay_cache = 3600; private static $default_user = ''; private static $allow_anonymous = false; private static $allow_anonymous_refresh = false; @@ -103,12 +99,6 @@ class Minz_Configuration { public static function language () { return self::$language; } - public static function cacheEnabled () { - return self::$cache_enabled; - } - public static function delayCache () { - return self::$delay_cache; - } public static function dataBase () { return self::$db; } @@ -282,18 +272,6 @@ class Minz_Configuration { if (isset ($general['language'])) { self::$language = $general['language']; } - if (isset ($general['cache_enabled'])) { - self::$cache_enabled = $general['cache_enabled']; - if (CACHE_PATH === false && self::$cache_enabled) { - throw new FileNotExistException ( - 'CACHE_PATH', - Minz_Exception::ERROR - ); - } - } - if (isset ($general['delay_cache'])) { - self::$delay_cache = inval($general['delay_cache']); - } if (isset ($general['default_user'])) { self::$default_user = $general['default_user']; } diff --git a/lib/Minz/Dispatcher.php b/lib/Minz/Dispatcher.php index 71dfe8ac6..819f4cd5c 100644 --- a/lib/Minz/Dispatcher.php +++ b/lib/Minz/Dispatcher.php @@ -41,7 +41,6 @@ class Minz_Dispatcher { * @exception Minz_Exception */ public function run ($ob = true) { - $cache = new Minz_Cache(); // Le ob_start est dupliqué : sans ça il y a un bug sous Firefox // ici on l'appelle avec 'ob_gzhandler', après sans. // Vraisemblablement la compression fonctionne mais c'est sale @@ -50,45 +49,31 @@ class Minz_Dispatcher { ob_start ('ob_gzhandler'); } - if (Minz_Cache::isEnabled () && !$cache->expired ()) { - if ($ob) { - ob_start (); - } - $cache->render (); - if ($ob) { - $text = ob_get_clean(); - } - } else { - $text = ''; //TODO: Clean this code - while (Minz_Request::$reseted) { - Minz_Request::$reseted = false; + $text = ''; //TODO: Clean this code + while (Minz_Request::$reseted) { + Minz_Request::$reseted = false; - try { - $this->createController ('FreshRSS_' . Minz_Request::controllerName () . '_Controller'); - $this->controller->init (); - $this->controller->firstAction (); - $this->launchAction ( - Minz_Request::actionName () - . 'Action' - ); - $this->controller->lastAction (); + try { + $this->createController ('FreshRSS_' . Minz_Request::controllerName () . '_Controller'); + $this->controller->init (); + $this->controller->firstAction (); + $this->launchAction ( + Minz_Request::actionName () + . 'Action' + ); + $this->controller->lastAction (); - if (!Minz_Request::$reseted) { - if ($ob) { - ob_start (); - } - $this->controller->view ()->build (); - if ($ob) { - $text = ob_get_clean(); - } + if (!Minz_Request::$reseted) { + if ($ob) { + ob_start (); + } + $this->controller->view ()->build (); + if ($ob) { + $text = ob_get_clean(); } - } catch (Minz_Exception $e) { - throw $e; } - } - - if (Minz_Cache::isEnabled ()) { - $cache->cache ($text); + } catch (Minz_Exception $e) { + throw $e; } } -- cgit v1.2.3 From c8aa451c768a3d4dfce3d19648f3c8420dedb74c Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 24 Mar 2014 20:55:18 +0100 Subject: Minz: remove url_rewriting As suggested https://github.com/marienfressinaud/FreshRSS/issues/163#issuecomment-38478669 At the same time, removes a bunch of (almost) dead code such as Minz_Router (the few remaining lines being moved to Minz_FrontController to avoid a class) Contributes to https://github.com/marienfressinaud/FreshRSS/issues/303 --- lib/Minz/ActionController.php | 6 +- lib/Minz/Configuration.php | 9 -- lib/Minz/Dispatcher.php | 16 +-- lib/Minz/FrontController.php | 43 ++++++-- lib/Minz/RouteNotFoundException.php | 16 --- lib/Minz/Router.php | 209 ------------------------------------ lib/Minz/Url.php | 13 +-- p/i/install.php | 1 - 8 files changed, 40 insertions(+), 273 deletions(-) delete mode 100644 lib/Minz/RouteNotFoundException.php delete mode 100644 lib/Minz/Router.php (limited to 'lib/Minz/Configuration.php') diff --git a/lib/Minz/ActionController.php b/lib/Minz/ActionController.php index 409d9611f..b47c54554 100644 --- a/lib/Minz/ActionController.php +++ b/lib/Minz/ActionController.php @@ -8,16 +8,12 @@ * La classe ActionController représente le contrôleur de l'application */ class Minz_ActionController { - protected $router; protected $view; /** * Constructeur - * @param $controller nom du controller - * @param $action nom de l'action à lancer */ - public function __construct ($router) { - $this->router = $router; + public function __construct () { $this->view = new Minz_View (); $this->view->attributeParams (); } diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index d905f6ddd..16c8eb727 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -30,7 +30,6 @@ class Minz_Configuration { * définition des variables de configuration * $salt une chaîne de caractères aléatoires (obligatoire) * $environment gère le niveau d'affichage pour log et erreurs - * $use_url_rewriting indique si on utilise l'url_rewriting * $base_url le chemin de base pour accéder à l'application * $title le nom de l'application * $language la langue par défaut de l'application @@ -43,7 +42,6 @@ class Minz_Configuration { private static $salt = ''; private static $environment = Minz_Configuration::PRODUCTION; private static $base_url = ''; - private static $use_url_rewriting = false; private static $title = ''; private static $language = 'en'; private static $default_user = ''; @@ -90,9 +88,6 @@ class Minz_Configuration { public static function baseUrl () { return self::$base_url; } - public static function useUrlRewriting () { - return self::$use_url_rewriting; - } public static function title () { return self::$title; } @@ -176,7 +171,6 @@ class Minz_Configuration { $ini_array = array( 'general' => array( 'environment' => self::environment(true), - 'use_url_rewriting' => self::$use_url_rewriting, 'salt' => self::$salt, 'base_url' => self::$base_url, 'title' => self::$title, @@ -262,9 +256,6 @@ class Minz_Configuration { if (isset ($general['base_url'])) { self::$base_url = $general['base_url']; } - if (isset ($general['use_url_rewriting'])) { - self::$use_url_rewriting = $general['use_url_rewriting']; - } if (isset ($general['title'])) { self::$title = $general['title']; diff --git a/lib/Minz/Dispatcher.php b/lib/Minz/Dispatcher.php index ca1fd1f5c..f62a92911 100644 --- a/lib/Minz/Dispatcher.php +++ b/lib/Minz/Dispatcher.php @@ -16,26 +16,18 @@ class Minz_Dispatcher { private static $instance = null; private static $needsReset; - private $router; private $controller; /** * Récupère l'instance du Dispatcher */ - public static function getInstance ($router) { + public static function getInstance () { if (self::$instance === null) { - self::$instance = new Minz_Dispatcher ($router); + self::$instance = new Minz_Dispatcher (); } return self::$instance; } - /** - * Constructeur - */ - private function __construct ($router) { - $this->router = $router; - } - /** * Lance le controller indiqué dans Request * Remplit le body de Response à partir de la Vue @@ -58,7 +50,7 @@ class Minz_Dispatcher { $this->controller->lastAction (); if (!self::$needsReset) { - echo $this->controller->view ()->build (); + $this->controller->view ()->build (); } } catch (Minz_Exception $e) { throw $e; @@ -90,7 +82,7 @@ class Minz_Dispatcher { Minz_Exception::ERROR ); } - $this->controller = new $controller_name ($this->router); + $this->controller = new $controller_name (); if (! ($this->controller instanceof Minz_ActionController)) { throw new Minz_ControllerNotActionControllerException ( diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php index 3e50db1cf..f13882801 100644 --- a/lib/Minz/FrontController.php +++ b/lib/Minz/FrontController.php @@ -24,11 +24,10 @@ */ class Minz_FrontController { protected $dispatcher; - protected $router; /** * Constructeur - * Initialise le router et le dispatcher + * Initialise le dispatcher, met à jour la Request */ public function __construct () { if (LOG_PATH === false) { @@ -40,24 +39,46 @@ class Minz_FrontController { Minz_Request::init (); - $this->router = new Minz_Router (); - $this->router->init (); - } catch (Minz_RouteNotFoundException $e) { - Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); - Minz_Error::error ( - 404, - array ('error' => array ($e->getMessage ())) + $url = $this->buildUrl(); + $url['params'] = array_merge ( + $url['params'], + Minz_Request::fetchPOST () ); + Minz_Request::forward ($url); } catch (Minz_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); $this->killApp ($e->getMessage ()); } - $this->dispatcher = Minz_Dispatcher::getInstance ($this->router); + $this->dispatcher = Minz_Dispatcher::getInstance(); + } + + /** + * Retourne un tableau représentant l'url passée par la barre d'adresses + * @return tableau représentant l'url + */ + private function buildUrl() { + $url = array (); + + $url['c'] = Minz_Request::fetchGET ( + 'c', + Minz_Request::defaultControllerName () + ); + $url['a'] = Minz_Request::fetchGET ( + 'a', + Minz_Request::defaultActionName () + ); + $url['params'] = Minz_Request::fetchGET (); + + // post-traitement + unset ($url['params']['c']); + unset ($url['params']['a']); + + return $url; } /** - * Démarre l'application (lance le dispatcher et renvoie la réponse + * Démarre l'application (lance le dispatcher et renvoie la réponse) */ public function run () { try { diff --git a/lib/Minz/RouteNotFoundException.php b/lib/Minz/RouteNotFoundException.php deleted file mode 100644 index dc4f6fbad..000000000 --- a/lib/Minz/RouteNotFoundException.php +++ /dev/null @@ -1,16 +0,0 @@ -route = $route; - - $message = 'Route `' . $route . '` not found'; - - parent::__construct ($message, $code); - } - - public function route () { - return $this->route; - } -} diff --git a/lib/Minz/Router.php b/lib/Minz/Router.php deleted file mode 100644 index 1ccd72597..000000000 --- a/lib/Minz/Router.php +++ /dev/null @@ -1,209 +0,0 @@ - -*/ - -/** - * La classe Router gère le routage de l'application - * Les routes sont définies dans APP_PATH.'/configuration/routes.php' - */ -class Minz_Router { - const ROUTES_PATH_NAME = '/configuration/routes.php'; - - private $routes = array (); - - /** - * Constructeur - * @exception FileNotExistException si ROUTES_PATH_NAME n'existe pas - * et que l'on utilise l'url rewriting - */ - public function __construct () { - if (Minz_Configuration::useUrlRewriting ()) { - if (file_exists (APP_PATH . self::ROUTES_PATH_NAME)) { - $routes = include ( - APP_PATH . self::ROUTES_PATH_NAME - ); - - if (!is_array ($routes)) { - $routes = array (); - } - - $this->routes = array_map ( - array ('Url', 'checkUrl'), - $routes - ); - } else { - throw new Minz_FileNotExistException ( - self::ROUTES_PATH_NAME, - Minz_Exception::ERROR - ); - } - } - } - - /** - * Initialise le Router en déterminant le couple Controller / Action - * Mets à jour la Request - * @exception RouteNotFoundException si l'uri n'est pas présente dans - * > la table de routage - */ - public function init () { - $url = array (); - - if (Minz_Configuration::useUrlRewriting ()) { - try { - $url = $this->buildWithRewriting (); - } catch (Minz_RouteNotFoundException $e) { - throw $e; - } - } else { - $url = $this->buildWithoutRewriting (); - } - - $url['params'] = array_merge ( - $url['params'], - Minz_Request::fetchPOST () - ); - - Minz_Request::forward ($url); - } - - /** - * Retourne un tableau représentant l'url passée par la barre d'adresses - * Ne se base PAS sur la table de routage - * @return tableau représentant l'url - */ - public function buildWithoutRewriting () { - $url = array (); - - $url['c'] = Minz_Request::fetchGET ( - 'c', - Minz_Request::defaultControllerName () - ); - $url['a'] = Minz_Request::fetchGET ( - 'a', - Minz_Request::defaultActionName () - ); - $url['params'] = Minz_Request::fetchGET (); - - // post-traitement - unset ($url['params']['c']); - unset ($url['params']['a']); - - return $url; - } - - /** - * Retourne un tableau représentant l'url passée par la barre d'adresses - * Se base sur la table de routage - * @return tableau représentant l'url - * @exception RouteNotFoundException si l'uri n'est pas présente dans - * > la table de routage - */ - public function buildWithRewriting () { - $url = array (); - $uri = Minz_Request::getURI (); - $find = false; - - foreach ($this->routes as $route) { - $regex = '*^' . $route['route'] . '$*'; - if (preg_match ($regex, $uri, $matches)) { - $url['c'] = $route['controller']; - $url['a'] = $route['action']; - $url['params'] = $this->getParams ( - $route['params'], - $matches - ); - $find = true; - break; - } - } - - if (!$find && $uri != '/') { - throw new Minz_RouteNotFoundException ( - $uri, - Minz_Exception::ERROR - ); - } - - // post-traitement - $url = Minz_Url::checkUrl ($url); - - return $url; - } - - /** - * Retourne l'uri d'une url en se basant sur la table de routage - * @param l'url sous forme de tableau - * @return l'uri formatée (string) selon une route trouvée - */ - public function printUriRewrited ($url) { - $route = $this->searchRoute ($url); - - if ($route !== false) { - return $this->replaceParams ($route, $url['params']); - } - - return ''; - } - - /** - * Recherche la route correspondante à une url - * @param l'url sous forme de tableau - * @return la route telle que spécifiée dans la table de routage, - * false si pas trouvée - */ - public function searchRoute ($url) { - foreach ($this->routes as $route) { - if ($route['controller'] == $url['c'] - && $route['action'] == $url['a']) { - // calcule la différence des tableaux de params - $params = array_flip ($route['params']); - $difference_params = array_diff_key ( - $params, - $url['params'] - ); - - // vérifie que pas de différence - // et le cas où $params est vide et pas $url['params'] - if (empty ($difference_params) - && (!empty ($params) || empty ($url['params']))) { - return $route; - } - } - } - - return false; - } - - /** - * Récupère un tableau dont - * - les clés sont définies dans $params_route - * - les valeurs sont situées dans $matches - * Le tableau $matches est décalé de +1 par rapport à $params_route - */ - private function getParams($params_route, $matches) { - $params = array (); - - for ($i = 0; $i < count ($params_route); $i++) { - $param = $params_route[$i]; - $params[$param] = $matches[$i + 1]; - } - - return $params; - } - - /** - * Remplace les éléments de la route par les valeurs contenues dans $params - */ - private function replaceParams ($route, $params_replace) { - $uri = $route['route']; - $params = array(); - foreach($route['params'] as $param) { - $uri = preg_replace('#\((.+)\)#U', $params_replace[$param], $uri, 1); - } - - return stripslashes($uri); - } -} diff --git a/lib/Minz/Url.php b/lib/Minz/Url.php index 17f1ddece..af48f00f5 100644 --- a/lib/Minz/Url.php +++ b/lib/Minz/Url.php @@ -5,8 +5,7 @@ */ class Minz_Url { /** - * Affiche une Url formatée selon que l'on utilise l'url_rewriting ou non - * si oui, on cherche dans la table de routage la correspondance pour formater + * Affiche une Url formatée * @param $url l'url à formater définie comme un tableau : * $url['c'] = controller * $url['a'] = action @@ -39,13 +38,7 @@ class Minz_Url { } if ($isArray) { - $router = new Minz_Router (); - - if (Minz_Configuration::useUrlRewriting ()) { - $url_string .= $router->printUriRewrited ($url); - } else { - $url_string .= self::printUri ($url, $encodage); - } + $url_string .= self::printUri ($url, $encodage); } else { $url_string .= $url; } @@ -54,7 +47,7 @@ class Minz_Url { } /** - * Construit l'URI d'une URL sans url rewriting + * Construit l'URI d'une URL * @param l'url sous forme de tableau * @param $encodage pour indiquer comment encoder les & (& ou & pour html) * @return l'uri sous la forme ?key=value&key2=value2 diff --git a/p/i/install.php b/p/i/install.php index a7563d5ee..f97f95d37 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -228,7 +228,6 @@ function saveStep3 () { $ini_array = array( 'general' => array( 'environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], - 'use_url_rewriting' => false, 'salt' => $_SESSION['salt'], 'base_url' => '', 'title' => $_SESSION['title'], -- cgit v1.2.3