1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/freshrss_ynh.git synced 2024-09-03 18:36:33 +02:00

Upgrade sources to 0.7.4

This commit is contained in:
plopoyop 2014-09-21 12:12:35 +02:00
parent 55ea9e6e9e
commit ba9fd9941c
114 changed files with 2110 additions and 1215 deletions

View file

@ -1,5 +1,25 @@
# Journal des modifications # Journal des modifications
## 2014-08-xx FreshRSS 0.7.4
* UI
* Hide categories/feeds with unread articles when showing only unread articles
* Dynamic favicon showing the number of unread articles
* New theme: Screwdriver by Mister aiR
* Statistics
* New page with article repartition
* Improvements
* Security
* Basic protection against XSRF (Cross-Site Request Forgery) based on HTTP Referer (POST requests only)
* API
* Compatible with lighttpd
* Misc.
* Changed lazyload implementation
* Support of HTML5 notifications for new upcoming articles
* Add option to stay logged in
* Bux fixes in export function, add/remove users, keyboard shortcuts, etc.
## 2014-07-21 FreshRSS 0.7.3 ## 2014-07-21 FreshRSS 0.7.3
* New options * New options

View file

@ -1,3 +1,5 @@
* [English version](README.md)
# FreshRSS # FreshRSS
FreshRSS est un agrégateur de flux RSS à auto-héberger à limage de [Leed](http://projet.idleman.fr/leed/) ou de [Kriss Feed](http://tontof.net/kriss/feed/). FreshRSS est un agrégateur de flux RSS à auto-héberger à limage de [Leed](http://projet.idleman.fr/leed/) ou de [Kriss Feed](http://tontof.net/kriss/feed/).
@ -8,8 +10,8 @@ Il permet de gérer plusieurs utilisateurs, et dispose dun mode de lecture an
* Site officiel : http://freshrss.org * Site officiel : http://freshrss.org
* Démo : http://demo.freshrss.org/ * Démo : http://demo.freshrss.org/
* Développeur : Marien Fressinaud <dev@marienfressinaud.fr> * Développeur : Marien Fressinaud <dev@marienfressinaud.fr>
* Version actuelle : 0.7.3 * Version actuelle : 0.7.4
* Date de publication 2014-07-21 * Date de publication 2014-08-24
* License [GNU AGPL 3](http://www.gnu.org/licenses/agpl-3.0.html) * License [GNU AGPL 3](http://www.gnu.org/licenses/agpl-3.0.html)
![Logo de FreshRSS](http://marienfressinaud.fr/data/images/freshrss/freshrss_title.png) ![Logo de FreshRSS](http://marienfressinaud.fr/data/images/freshrss/freshrss_title.png)
@ -31,11 +33,11 @@ Privilégiez pour cela des demandes sur GitHub
# Pré-requis # Pré-requis
* Serveur modeste, par exemple sous Linux ou Windows * Serveur modeste, par exemple sous Linux ou Windows
* Fonctionne même sur un Raspberry Pi avec des temps de réponse < 1s (testé sur 150 flux, 22k articles, soit 32Mo de données partiellement compressées) * Fonctionne même sur un Raspberry Pi avec des temps de réponse < 1s (testé sur 150 flux, 22k articles, soit 32Mo de données partiellement compressées)
* Serveur Web Apache2 ou Nginx (non testé sur les autres) * Serveur Web Apache2 (recommandé), ou nginx, lighttpd (non testé sur les autres)
* PHP 5.2.1+ (PHP 5.3.7+ recommandé) * PHP 5.2.1+ (PHP 5.3.7+ recommandé)
* Requis : [PDO_MySQL](http://php.net/pdo-mysql), [cURL](http://php.net/curl), [LibXML](http://php.net/xml), [PCRE](http://php.net/pcre), [ctype](http://php.net/ctype) * Requis : [PDO_MySQL](http://php.net/pdo-mysql) ou [PDO_SQLite](http://php.net/pdo-sqlite), [cURL](http://php.net/curl), [GMP](http://php.net/gmp) (seulement pour accès API sur platformes < 64 bits)
* Recommandés : [JSON](http://php.net/json), [zlib](http://php.net/zlib), [mbstring](http://php.net/mbstring), [iconv](http://php.net/iconv), [Zip](http://php.net/zip) * Recommandés : [JSON](http://php.net/json), [mbstring](http://php.net/mbstring), [zlib](http://php.net/zlib), [Zip](http://php.net/zip)
* MySQL 5.0.3+ (recommandé) ou SQLite 3.7.4+ (en bêta) * MySQL 5.0.3+ (recommandé) ou SQLite 3.7.4+
* Un navigateur Web récent tel Firefox 4+, Chrome, Opera, Safari, Internet Explorer 9+ * Un navigateur Web récent tel Firefox 4+, Chrome, Opera, Safari, Internet Explorer 9+
* Fonctionne aussi sur mobile * Fonctionne aussi sur mobile
@ -93,7 +95,6 @@ mysqldump -u utilisateur -p --databases freshrss > freshrss.sql
## Uniquement pour certaines options ## Uniquement pour certaines options
* [bcrypt.js](https://github.com/dcodeIO/bcrypt.js) * [bcrypt.js](https://github.com/dcodeIO/bcrypt.js)
* [phpQuery](http://code.google.com/p/phpquery/) * [phpQuery](http://code.google.com/p/phpquery/)
* [Lazy Load](http://www.appelsiini.net/projects/lazyload)
## Si les fonctions natives ne sont pas disponibles ## Si les fonctions natives ne sont pas disponibles
* [Services_JSON](http://pear.php.net/pepr/pepr-proposal-show.php?id=198) * [Services_JSON](http://pear.php.net/pepr/pepr-proposal-show.php?id=198)

View file

@ -184,6 +184,8 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->conf->_default_view((int)Minz_Request::param('default_view', FreshRSS_Entry::STATE_ALL)); $this->view->conf->_default_view((int)Minz_Request::param('default_view', FreshRSS_Entry::STATE_ALL));
$this->view->conf->_auto_load_more(Minz_Request::param('auto_load_more', false)); $this->view->conf->_auto_load_more(Minz_Request::param('auto_load_more', false));
$this->view->conf->_display_posts(Minz_Request::param('display_posts', false)); $this->view->conf->_display_posts(Minz_Request::param('display_posts', false));
$this->view->conf->_display_categories(Minz_Request::param('display_categories', false));
$this->view->conf->_hide_read_feeds(Minz_Request::param('hide_read_feeds', false));
$this->view->conf->_onread_jump_next(Minz_Request::param('onread_jump_next', false)); $this->view->conf->_onread_jump_next(Minz_Request::param('onread_jump_next', false));
$this->view->conf->_lazyload(Minz_Request::param('lazyload', false)); $this->view->conf->_lazyload(Minz_Request::param('lazyload', false));
$this->view->conf->_sticky_post(Minz_Request::param('sticky_post', false)); $this->view->conf->_sticky_post(Minz_Request::param('sticky_post', false));

View file

@ -1,26 +1,38 @@
<?php <?php
class FreshRSS_error_Controller extends Minz_ActionController { class FreshRSS_error_Controller extends Minz_ActionController {
public function indexAction () { public function indexAction() {
switch (Minz_Request::param ('code')) { switch (Minz_Request::param('code')) {
case 403: case 403:
$this->view->code = 'Error 403 - Forbidden'; $this->view->code = 'Error 403 - Forbidden';
break; break;
case 404: case 404:
$this->view->code = 'Error 404 - Not found'; $this->view->code = 'Error 404 - Not found';
break; break;
case 500: case 500:
$this->view->code = 'Error 500 - Internal Server Error'; $this->view->code = 'Error 500 - Internal Server Error';
break; break;
case 503: case 503:
$this->view->code = 'Error 503 - Service Unavailable'; $this->view->code = 'Error 503 - Service Unavailable';
break; break;
default: default:
$this->view->code = 'Error 404 - Not found'; $this->view->code = 'Error 404 - Not found';
} }
$this->view->logs = Minz_Request::param ('logs'); $errors = Minz_Request::param('logs', array());
$this->view->errorMessage = trim(implode($errors));
Minz_View::prependTitle ($this->view->code . ' · '); if ($this->view->errorMessage == '') {
switch(Minz_Request::param('code')) {
case 403:
$this->view->errorMessage = Minz_Translate::t('forbidden_access');
break;
case 404:
default:
$this->view->errorMessage = Minz_Translate::t('page_not_found');
break;
}
}
Minz_View::prependTitle($this->view->code . ' · ');
} }
} }

View file

@ -5,7 +5,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
if (!$this->view->loginOk) { if (!$this->view->loginOk) {
Minz_Error::error( Minz_Error::error(
403, 403,
array('error' => array(Minz_Translate::t('access_denied'))) array('error' => array(_t('access_denied')))
); );
} }
@ -20,33 +20,51 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$this->view->categories = $this->catDAO->listCategories(); $this->view->categories = $this->catDAO->listCategories();
$this->view->feeds = $this->feedDAO->listFeeds(); $this->view->feeds = $this->feedDAO->listFeeds();
Minz_View::prependTitle(Minz_Translate::t('import_export') . ' · '); Minz_View::prependTitle(_t('import_export') . ' · ');
} }
public function importAction() { public function importAction() {
if (Minz_Request::isPost() && $_FILES['file']['error'] == 0) { if (!Minz_Request::isPost()) {
@set_time_limit(300); Minz_Request::forward(array('c' => 'importExport', 'a' => 'index'), true);
}
$file = $_FILES['file']; $file = $_FILES['file'];
$type_file = $this->guessFileType($file['name']); $status_file = $file['error'];
$list_files = array( if ($status_file !== 0) {
'opml' => array(), Minz_Log::error('File cannot be uploaded. Error code: ' . $status_file);
'json_starred' => array(), Minz_Request::bad(_t('file_cannot_be_uploaded'),
'json_feed' => array() array('c' => 'importExport', 'a' => 'index'));
); }
// We try to list all files according to their type @set_time_limit(300);
// A zip file is first opened and then its files are listed
$list = array();
if ($type_file === 'zip') {
$zip = zip_open($file['tmp_name']);
while (($zipfile = zip_read($zip)) !== false) { $type_file = $this->guessFileType($file['name']);
$type_zipfile = $this->guessFileType(
zip_entry_name($zipfile)
);
$list_files = array(
'opml' => array(),
'json_starred' => array(),
'json_feed' => array()
);
// We try to list all files according to their type
$list = array();
if ($type_file === 'zip' && extension_loaded('zip')) {
$zip = zip_open($file['tmp_name']);
if (!is_resource($zip)) {
// zip_open cannot open file: something is wrong
Minz_Log::error('Zip archive cannot be imported. Error code: ' . $zip);
Minz_Request::bad(_t('zip_error'),
array('c' => 'importExport', 'a' => 'index'));
}
while (($zipfile = zip_read($zip)) !== false) {
if (!is_resource($zipfile)) {
// zip_entry() can also return an error code!
Minz_Log::error('Zip file cannot be imported. Error code: ' . $zipfile);
} else {
$type_zipfile = $this->guessFileType(zip_entry_name($zipfile));
if ($type_file !== 'unknown') { if ($type_file !== 'unknown') {
$list_files[$type_zipfile][] = zip_entry_read( $list_files[$type_zipfile][] = zip_entry_read(
$zipfile, $zipfile,
@ -54,59 +72,37 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
); );
} }
} }
zip_close($zip);
} elseif ($type_file !== 'unknown') {
$list_files[$type_file][] = file_get_contents(
$file['tmp_name']
);
} }
// Import different files. zip_close($zip);
// OPML first(so categories and feeds are imported) } elseif ($type_file === 'zip') {
// Starred articles then so the "favourite" status is already set // Zip extension is not loaded
// And finally all other files. Minz_Request::bad(_t('no_zip_extension'),
$error = false; array('c' => 'importExport', 'a' => 'index'));
foreach ($list_files['opml'] as $opml_file) { } elseif ($type_file !== 'unknown') {
$error = $this->importOpml($opml_file); $list_files[$type_file][] = file_get_contents($file['tmp_name']);
}
foreach ($list_files['json_starred'] as $article_file) {
$error = $this->importArticles($article_file, true);
}
foreach ($list_files['json_feed'] as $article_file) {
$error = $this->importArticles($article_file);
}
// And finally, we get import status and redirect to the home page
$notif = null;
if ($error === true) {
$content_notif = Minz_Translate::t(
'feeds_imported_with_errors'
);
} else {
$content_notif = Minz_Translate::t(
'feeds_imported'
);
}
Minz_Session::_param('notification', array(
'type' => 'good',
'content' => $content_notif
));
Minz_Session::_param('actualize_feeds', true);
Minz_Request::forward(array(
'c' => 'index',
'a' => 'index'
), true);
} }
// What are you doing? you have to call this controller // Import file contents.
// with a POST request! // OPML first(so categories and feeds are imported)
Minz_Request::forward(array( // Starred articles then so the "favourite" status is already set
'c' => 'importExport', // And finally all other files.
'a' => 'index' $error = false;
)); foreach ($list_files['opml'] as $opml_file) {
$error = $this->importOpml($opml_file);
}
foreach ($list_files['json_starred'] as $article_file) {
$error = $this->importArticles($article_file, true);
}
foreach ($list_files['json_feed'] as $article_file) {
$error = $this->importArticles($article_file);
}
// And finally, we get import status and redirect to the home page
Minz_Session::_param('actualize_feeds', true);
$content_notif = $error === true ? _t('feeds_imported_with_errors') :
_t('feeds_imported');
Minz_Request::good($content_notif);
} }
private function guessFileType($filename) { private function guessFileType($filename) {
@ -120,7 +116,8 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
} elseif (substr_compare($filename, '.opml', -5) === 0 || } elseif (substr_compare($filename, '.opml', -5) === 0 ||
substr_compare($filename, '.xml', -4) === 0) { substr_compare($filename, '.xml', -4) === 0) {
return 'opml'; return 'opml';
} elseif (strcmp($filename, 'starred.json') === 0) { } elseif (substr_compare($filename, '.json', -5) === 0 &&
strpos($filename, 'starred') !== false) {
return 'json_starred'; return 'json_starred';
} elseif (substr_compare($filename, '.json', -5) === 0 && } elseif (substr_compare($filename, '.json', -5) === 0 &&
strpos($filename, 'feed_') === 0) { strpos($filename, 'feed_') === 0) {
@ -176,15 +173,15 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
} }
// We get different useful information // We get different useful information
$url = html_chars_utf8($feed_elt['xmlUrl']); $url = Minz_Helper::htmlspecialchars_utf8($feed_elt['xmlUrl']);
$name = html_chars_utf8($feed_elt['text']); $name = Minz_Helper::htmlspecialchars_utf8($feed_elt['text']);
$website = ''; $website = '';
if (isset($feed_elt['htmlUrl'])) { if (isset($feed_elt['htmlUrl'])) {
$website = html_chars_utf8($feed_elt['htmlUrl']); $website = Minz_Helper::htmlspecialchars_utf8($feed_elt['htmlUrl']);
} }
$description = ''; $description = '';
if (isset($feed_elt['description'])) { if (isset($feed_elt['description'])) {
$description = html_chars_utf8($feed_elt['description']); $description = Minz_Helper::htmlspecialchars_utf8($feed_elt['description']);
} }
$error = false; $error = false;
@ -210,7 +207,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
private function addCategoryOpml($cat_elt, $parent_cat) { private function addCategoryOpml($cat_elt, $parent_cat) {
// Create a new Category object // Create a new Category object
$cat = new FreshRSS_Category(html_chars_utf8($cat_elt['text'])); $cat = new FreshRSS_Category(Minz_Helper::htmlspecialchars_utf8($cat_elt['text']));
$id = $this->catDAO->addCategoryObject($cat); $id = $this->catDAO->addCategoryObject($cat);
$error = ($id === false); $error = ($id === false);
@ -287,7 +284,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$url = $origin[$key]; $url = $origin[$key];
$name = $origin['title']; $name = $origin['title'];
$website = $origin['htmlUrl']; $website = $origin['htmlUrl'];
$error = false;
try { try {
// Create a Feed object and add it in DB // Create a Feed object and add it in DB
$feed = new FreshRSS_Feed($url); $feed = new FreshRSS_Feed($url);
@ -311,44 +308,53 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
} }
public function exportAction() { public function exportAction() {
if (Minz_Request::isPost()) { if (!Minz_Request::isPost()) {
$this->view->_useLayout(false); Minz_Request::forward(array('c' => 'importExport', 'a' => 'index'), true);
}
$export_opml = Minz_Request::param('export_opml', false); $this->view->_useLayout(false);
$export_starred = Minz_Request::param('export_starred', false);
$export_feeds = Minz_Request::param('export_feeds', false);
// From https://stackoverflow.com/questions/1061710/php-zip-files-on-the-fly $export_opml = Minz_Request::param('export_opml', false);
$file = tempnam('tmp', 'zip'); $export_starred = Minz_Request::param('export_starred', false);
$zip = new ZipArchive(); $export_feeds = Minz_Request::param('export_feeds', array());
$zip->open($file, ZipArchive::OVERWRITE);
// Stuff with content $export_files = array();
if ($export_opml) { if ($export_opml) {
$zip->addFromString( $export_files['feeds.opml'] = $this->generateOpml();
'feeds.opml', $this->generateOpml() }
);
} if ($export_starred) {
if ($export_starred) { $export_files['starred.json'] = $this->generateArticles('starred');
$zip->addFromString( }
'starred.json', $this->generateArticles('starred')
); foreach ($export_feeds as $feed_id) {
} $feed = $this->feedDAO->searchById($feed_id);
foreach ($export_feeds as $feed_id) { if ($feed) {
$feed = $this->feedDAO->searchById($feed_id); $filename = 'feed_' . $feed->category() . '_'
$zip->addFromString( . $feed->id() . '.json';
'feed_' . $feed->category() . '_' . $feed->id() . '.json', $export_files[$filename] = $this->generateArticles(
$this->generateArticles('feed', $feed) 'feed', $feed
); );
} }
}
// Close and send to user $nb_files = count($export_files);
$zip->close(); if ($nb_files > 1) {
header('Content-Type: application/zip'); // If there are more than 1 file to export, we need a zip archive.
header('Content-Length: ' . filesize($file)); try {
header('Content-Disposition: attachment; filename="freshrss_export.zip"'); $this->exportZip($export_files);
readfile($file); } catch (Exception $e) {
unlink($file); # Oops, there is no Zip extension!
Minz_Request::bad(_t('export_no_zip_extension'),
array('c' => 'importExport', 'a' => 'index'));
}
} elseif ($nb_files === 1) {
// Only one file? Guess its type and export it.
$filename = key($export_files);
$type = $this->guessFileType($filename);
$this->exportFile('freshrss_' . $filename, $export_files[$filename], $type);
} else {
Minz_Request::forward(array('c' => 'importExport', 'a' => 'index'), true);
} }
} }
@ -367,7 +373,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$this->view->categories = $this->catDAO->listCategories(); $this->view->categories = $this->catDAO->listCategories();
if ($type == 'starred') { if ($type == 'starred') {
$this->view->list_title = Minz_Translate::t('starred_list'); $this->view->list_title = _t('starred_list');
$this->view->type = 'starred'; $this->view->type = 'starred';
$unread_fav = $this->entryDAO->countUnreadReadFavorites(); $unread_fav = $this->entryDAO->countUnreadReadFavorites();
$this->view->entries = $this->entryDAO->listWhere( $this->view->entries = $this->entryDAO->listWhere(
@ -375,9 +381,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$unread_fav['all'] $unread_fav['all']
); );
} elseif ($type == 'feed' && !is_null($feed)) { } elseif ($type == 'feed' && !is_null($feed)) {
$this->view->list_title = Minz_Translate::t( $this->view->list_title = _t('feed_list', $feed->name());
'feed_list', $feed->name()
);
$this->view->type = 'feed/' . $feed->id(); $this->view->type = 'feed/' . $feed->id();
$this->view->entries = $this->entryDAO->listWhere( $this->view->entries = $this->entryDAO->listWhere(
'f', $feed->id(), FreshRSS_Entry::STATE_ALL, 'ASC', 'f', $feed->id(), FreshRSS_Entry::STATE_ALL, 'ASC',
@ -388,4 +392,44 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
return $this->view->helperToString('export/articles'); return $this->view->helperToString('export/articles');
} }
private function exportZip($files) {
if (!extension_loaded('zip')) {
throw new Exception();
}
// From https://stackoverflow.com/questions/1061710/php-zip-files-on-the-fly
$zip_file = tempnam('tmp', 'zip');
$zip = new ZipArchive();
$zip->open($zip_file, ZipArchive::OVERWRITE);
foreach ($files as $filename => $content) {
$zip->addFromString($filename, $content);
}
// Close and send to user
$zip->close();
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($zip_file));
header('Content-Disposition: attachment; filename="freshrss_export.zip"');
readfile($zip_file);
unlink($zip_file);
}
private function exportFile($filename, $content, $type) {
if ($type === 'unknown') {
return;
}
$content_type = '';
if ($type === 'opml') {
$content_type = "text/opml";
} elseif ($type === 'json_feed' || $type === 'json_starred') {
$content_type = "text/json";
}
header('Content-Type: ' . $content_type . '; charset=utf-8');
header('Content-disposition: attachment; filename=' . $filename);
print($content);
}
} }

View file

@ -69,9 +69,6 @@ class FreshRSS_index_Controller extends Minz_ActionController {
// mise à jour des titres // mise à jour des titres
$this->view->rss_title = $this->view->currentName . ' | ' . Minz_View::title(); $this->view->rss_title = $this->view->currentName . ' | ' . Minz_View::title();
if ($this->view->nb_not_read > 0) {
Minz_View::prependTitle('(' . formatNumber($this->view->nb_not_read) . ') ');
}
Minz_View::prependTitle( Minz_View::prependTitle(
($this->nb_not_read_cat > 0 ? '(' . formatNumber($this->nb_not_read_cat) . ') ' : '') . ($this->nb_not_read_cat > 0 ? '(' . formatNumber($this->nb_not_read_cat) . ') ' : '') .
$this->view->currentName . $this->view->currentName .
@ -79,14 +76,14 @@ class FreshRSS_index_Controller extends Minz_ActionController {
); );
// On récupère les différents éléments de filtrage // On récupère les différents éléments de filtrage
$this->view->state = $state = Minz_Request::param ('state', $this->view->conf->default_view); $this->view->state = Minz_Request::param('state', $this->view->conf->default_view);
$state_param = Minz_Request::param ('state', null); $state_param = Minz_Request::param ('state', null);
$filter = Minz_Request::param ('search', ''); $filter = Minz_Request::param ('search', '');
$this->view->order = $order = Minz_Request::param ('order', $this->view->conf->sort_order); $this->view->order = $order = Minz_Request::param ('order', $this->view->conf->sort_order);
$nb = Minz_Request::param ('nb', $this->view->conf->posts_per_page); $nb = Minz_Request::param ('nb', $this->view->conf->posts_per_page);
$first = Minz_Request::param ('next', ''); $first = Minz_Request::param ('next', '');
if ($state === FreshRSS_Entry::STATE_NOT_READ) { //Any unread article in this category at all? if ($this->view->state === FreshRSS_Entry::STATE_NOT_READ) { //Any unread article in this category at all?
switch ($getType) { switch ($getType) {
case 'a': case 'a':
$hasUnread = $this->view->nb_not_read > 0; $hasUnread = $this->view->nb_not_read > 0;
@ -107,7 +104,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
break; break;
} }
if (!$hasUnread && ($state_param === null)) { if (!$hasUnread && ($state_param === null)) {
$this->view->state = $state = FreshRSS_Entry::STATE_ALL; $this->view->state = FreshRSS_Entry::STATE_ALL;
} }
} }
@ -120,11 +117,11 @@ class FreshRSS_index_Controller extends Minz_ActionController {
$keepHistoryDefault = $this->view->conf->keep_history_default; $keepHistoryDefault = $this->view->conf->keep_history_default;
try { try {
$entries = $entryDAO->listWhere($getType, $getId, $state, $order, $nb + 1, $first, $filter, $date_min, true, $keepHistoryDefault); $entries = $entryDAO->listWhere($getType, $getId, $this->view->state, $order, $nb + 1, $first, $filter, $date_min, true, $keepHistoryDefault);
// Si on a récupéré aucun article "non lus" // Si on a récupéré aucun article "non lus"
// on essaye de récupérer tous les articles // on essaye de récupérer tous les articles
if ($state === FreshRSS_Entry::STATE_NOT_READ && empty($entries) && ($state_param === null) && ($filter == '')) { if ($this->view->state === FreshRSS_Entry::STATE_NOT_READ && empty($entries) && ($state_param === null) && ($filter == '')) {
Minz_Log::record('Conflicting information about nbNotRead!', Minz_Log::DEBUG); Minz_Log::record('Conflicting information about nbNotRead!', Minz_Log::DEBUG);
$feedDAO = FreshRSS_Factory::createFeedDao(); $feedDAO = FreshRSS_Factory::createFeedDao();
try { try {
@ -135,6 +132,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
$this->view->state = FreshRSS_Entry::STATE_ALL; $this->view->state = FreshRSS_Entry::STATE_ALL;
$entries = $entryDAO->listWhere($getType, $getId, $this->view->state, $order, $nb, $first, $filter, $date_min, true, $keepHistoryDefault); $entries = $entryDAO->listWhere($getType, $getId, $this->view->state, $order, $nb, $first, $filter, $date_min, true, $keepHistoryDefault);
} }
Minz_Request::_param('state', $this->view->state);
if (count($entries) <= $nb) { if (count($entries) <= $nb) {
$this->view->nextId = ''; $this->view->nextId = '';
@ -298,6 +296,41 @@ class FreshRSS_index_Controller extends Minz_ActionController {
Minz_Session::_param('passwordHash'); Minz_Session::_param('passwordHash');
} }
private static function makeLongTermCookie($username, $passwordHash) {
do {
$token = sha1(Minz_Configuration::salt() . $username . uniqid(mt_rand(), true));
$tokenFile = DATA_PATH . '/tokens/' . $token . '.txt';
} while (file_exists($tokenFile));
if (@file_put_contents($tokenFile, $username . "\t" . $passwordHash) === false) {
return false;
}
$expire = time() + 2629744; //1 month //TODO: Use a configuration instead
Minz_Session::setLongTermCookie('FreshRSS_login', $token, $expire);
Minz_Session::_param('token', $token);
return $token;
}
private static function deleteLongTermCookie() {
Minz_Session::deleteLongTermCookie('FreshRSS_login');
$token = Minz_Session::param('token', null);
if (ctype_alnum($token)) {
@unlink(DATA_PATH . '/tokens/' . $token . '.txt');
}
Minz_Session::_param('token');
if (rand(0, 10) === 1) {
self::purgeTokens();
}
}
private static function purgeTokens() {
$oldest = time() - 2629744; //1 month //TODO: Use a configuration instead
foreach (new DirectoryIterator(DATA_PATH . '/tokens/') as $fileInfo) {
if ($fileInfo->getExtension() === 'txt' && $fileInfo->getMTime() < $oldest) {
@unlink($fileInfo->getPathname());
}
}
}
public function formLoginAction () { public function formLoginAction () {
if (Minz_Request::isPost()) { if (Minz_Request::isPost()) {
$ok = false; $ok = false;
@ -315,6 +348,11 @@ class FreshRSS_index_Controller extends Minz_ActionController {
if ($ok) { if ($ok) {
Minz_Session::_param('currentUser', $username); Minz_Session::_param('currentUser', $username);
Minz_Session::_param('passwordHash', $s); Minz_Session::_param('passwordHash', $s);
if (Minz_Request::param('keep_logged_in', false)) {
self::makeLongTermCookie($username, $s);
} else {
self::deleteLongTermCookie();
}
} else { } else {
Minz_Log::record('Password mismatch for user ' . $username . ', nonce=' . $nonce . ', c=' . $c, Minz_Log::WARNING); Minz_Log::record('Password mismatch for user ' . $username . ', nonce=' . $nonce . ', c=' . $c, Minz_Log::WARNING);
} }
@ -374,6 +412,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
Minz_Session::_param('currentUser'); Minz_Session::_param('currentUser');
Minz_Session::_param('mail'); Minz_Session::_param('mail');
Minz_Session::_param('passwordHash'); Minz_Session::_param('passwordHash');
self::deleteLongTermCookie();
Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true);
} }
} }

View file

@ -4,9 +4,9 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
public function indexAction() { public function indexAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO(); $statsDAO = FreshRSS_Factory::createStatsDAO();
Minz_View::appendScript (Minz_Url::display ('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
$this->view->repartition = $statsDAO->calculateEntryRepartition(); $this->view->repartition = $statsDAO->calculateEntryRepartition();
$this->view->count = ($statsDAO->calculateEntryCount()); $this->view->count = $statsDAO->calculateEntryCount();
$this->view->feedByCategory = $statsDAO->calculateFeedByCategory(); $this->view->feedByCategory = $statsDAO->calculateFeedByCategory();
$this->view->entryByCategory = $statsDAO->calculateEntryByCategory(); $this->view->entryByCategory = $statsDAO->calculateEntryByCategory();
$this->view->topFeed = $statsDAO->calculateTopFeed(); $this->view->topFeed = $statsDAO->calculateTopFeed();
@ -15,7 +15,13 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
public function idleAction() { public function idleAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO(); $statsDAO = FreshRSS_Factory::createStatsDAO();
$feeds = $statsDAO->calculateFeedLastDate(); $feeds = $statsDAO->calculateFeedLastDate();
$idleFeeds = array(); $idleFeeds = array(
'last_year' => array(),
'last_6_month' => array(),
'last_3_month' => array(),
'last_month' => array(),
'last_week' => array(),
);
$now = new \DateTime(); $now = new \DateTime();
$feedDate = clone $now; $feedDate = clone $now;
$lastWeek = clone $now; $lastWeek = clone $now;
@ -34,26 +40,37 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
if ($feedDate >= $lastWeek) { if ($feedDate >= $lastWeek) {
continue; continue;
} }
if ($feedDate < $lastWeek) {
$idleFeeds['last_week'][] = $feed['name'];
}
if ($feedDate < $lastMonth) {
$idleFeeds['last_month'][] = $feed['name'];
}
if ($feedDate < $last3Month) {
$idleFeeds['last_3_month'][] = $feed['name'];
}
if ($feedDate < $last6Month) {
$idleFeeds['last_6_month'][] = $feed['name'];
}
if ($feedDate < $lastYear) { if ($feedDate < $lastYear) {
$idleFeeds['last_year'][] = $feed['name']; $idleFeeds['last_year'][] = $feed;
} elseif ($feedDate < $last6Month) {
$idleFeeds['last_6_month'][] = $feed;
} elseif ($feedDate < $last3Month) {
$idleFeeds['last_3_month'][] = $feed;
} elseif ($feedDate < $lastMonth) {
$idleFeeds['last_month'][] = $feed;
} elseif ($feedDate < $lastWeek) {
$idleFeeds['last_week'][] = $feed;
} }
} }
$this->view->idleFeeds = array_reverse($idleFeeds); $this->view->idleFeeds = $idleFeeds;
} }
public function repartitionAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO();
$categoryDAO = new FreshRSS_CategoryDAO();
$feedDAO = FreshRSS_Factory::createFeedDao();
Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
$id = Minz_Request::param ('id', null);
$this->view->categories = $categoryDAO->listCategories();
$this->view->feed = $feedDAO->searchById($id);
$this->view->days = $statsDAO->getDays();
$this->view->months = $statsDAO->getMonths();
$this->view->repartitionHour = $statsDAO->calculateEntryRepartitionPerFeedPerHour($id);
$this->view->repartitionDayOfWeek = $statsDAO->calculateEntryRepartitionPerFeedPerDayOfWeek($id);
$this->view->repartitionMonth = $statsDAO->calculateEntryRepartitionPerFeedPerMonth($id);
}
public function firstAction() { public function firstAction() {
if (!$this->view->loginOk) { if (!$this->view->loginOk) {
Minz_Error::error( Minz_Error::error(

View file

@ -100,7 +100,7 @@ class FreshRSS_users_Controller extends Minz_ActionController {
public function createAction() { public function createAction() {
if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) {
$db = Minz_Configuration::dataBase(); $db = Minz_Configuration::dataBase();
require_once(APP_PATH . '/SQL/sql.' . $db['type'] . '.php'); require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php');
$new_user_language = Minz_Request::param('new_user_language', $this->view->conf->language); $new_user_language = Minz_Request::param('new_user_language', $this->view->conf->language);
if (!in_array($new_user_language, $this->view->conf->availableLanguages())) { if (!in_array($new_user_language, $this->view->conf->availableLanguages())) {
@ -172,7 +172,7 @@ class FreshRSS_users_Controller extends Minz_ActionController {
public function deleteAction() { public function deleteAction() {
if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) {
$db = Minz_Configuration::dataBase(); $db = Minz_Configuration::dataBase();
require_once(APP_PATH . '/SQL/sql.' . $db['type'] . '.php'); require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php');
$username = Minz_Request::param('username'); $username = Minz_Request::param('username');
$ok = ctype_alnum($username); $ok = ctype_alnum($username);

View file

@ -6,17 +6,49 @@ class FreshRSS extends Minz_FrontController {
} }
$loginOk = $this->accessControl(Minz_Session::param('currentUser', '')); $loginOk = $this->accessControl(Minz_Session::param('currentUser', ''));
$this->loadParamsView(); $this->loadParamsView();
if (Minz_Request::isPost() && (empty($_SERVER['HTTP_REFERER']) ||
Minz_Request::getDomainName() !== parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST))) {
$loginOk = false; //Basic protection against XSRF attacks
Minz_Error::error(
403,
array('error' => array(Minz_Translate::t('access_denied') . ' [HTTP_REFERER=' .
htmlspecialchars(empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER']) . ']'))
);
}
Minz_View::_param('loginOk', $loginOk);
$this->loadStylesAndScripts($loginOk); //TODO: Do not load that when not needed, e.g. some Ajax requests $this->loadStylesAndScripts($loginOk); //TODO: Do not load that when not needed, e.g. some Ajax requests
$this->loadNotifications(); $this->loadNotifications();
} }
private static function getCredentialsFromLongTermCookie() {
$token = Minz_Session::getLongTermCookie('FreshRSS_login');
if (!ctype_alnum($token)) {
return array();
}
$tokenFile = DATA_PATH . '/tokens/' . $token . '.txt';
$mtime = @filemtime($tokenFile);
if ($mtime + 2629744 < time()) { //1 month //TODO: Use a configuration instead
@unlink($tokenFile);
return array(); //Expired or token does not exist
}
$credentials = @file_get_contents($tokenFile);
return $credentials === false ? array() : explode("\t", $credentials, 2);
}
private function accessControl($currentUser) { private function accessControl($currentUser) {
if ($currentUser == '') { if ($currentUser == '') {
switch (Minz_Configuration::authType()) { switch (Minz_Configuration::authType()) {
case 'form': case 'form':
$currentUser = Minz_Configuration::defaultUser(); $credentials = self::getCredentialsFromLongTermCookie();
Minz_Session::_param('passwordHash'); if (isset($credentials[1])) {
$loginOk = false; $currentUser = trim($credentials[0]);
Minz_Session::_param('passwordHash', trim($credentials[1]));
}
$loginOk = $currentUser != '';
if (!$loginOk) {
$currentUser = Minz_Configuration::defaultUser();
Minz_Session::_param('passwordHash');
}
break; break;
case 'http_auth': case 'http_auth':
$currentUser = httpAuthUser(); $currentUser = httpAuthUser();
@ -95,7 +127,6 @@ class FreshRSS extends Minz_FrontController {
break; break;
} }
} }
Minz_View::_param ('loginOk', $loginOk);
return $loginOk; return $loginOk;
} }
@ -127,13 +158,9 @@ class FreshRSS extends Minz_FrontController {
Minz_View::appendScript('https://login.persona.org/include.js'); Minz_View::appendScript('https://login.persona.org/include.js');
break; break;
} }
$includeLazyLoad = $this->conf->lazyload && ($this->conf->display_posts || Minz_Request::param ('output') === 'reader'); Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')));
Minz_View::appendScript (Minz_Url::display ('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')), false, !$includeLazyLoad, !$includeLazyLoad); Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js')));
if ($includeLazyLoad) { Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js')));
Minz_View::appendScript (Minz_Url::display ('/scripts/jquery.lazyload.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.lazyload.min.js')));
}
Minz_View::appendScript (Minz_Url::display ('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js')));
Minz_View::appendScript (Minz_Url::display ('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js')));
} }
private function loadNotifications () { private function loadNotifications () {

View file

@ -17,6 +17,8 @@ class FreshRSS_Configuration {
'default_view' => FreshRSS_Entry::STATE_NOT_READ, 'default_view' => FreshRSS_Entry::STATE_NOT_READ,
'auto_load_more' => true, 'auto_load_more' => true,
'display_posts' => false, 'display_posts' => false,
'display_categories' => false,
'hide_read_feeds' => true,
'onread_jump_next' => true, 'onread_jump_next' => true,
'lazyload' => true, 'lazyload' => true,
'sticky_post' => true, 'sticky_post' => true,
@ -141,6 +143,12 @@ class FreshRSS_Configuration {
public function _display_posts ($value) { public function _display_posts ($value) {
$this->data['display_posts'] = ((bool)$value) && $value !== 'no'; $this->data['display_posts'] = ((bool)$value) && $value !== 'no';
} }
public function _display_categories ($value) {
$this->data['display_categories'] = ((bool)$value) && $value !== 'no';
}
public function _hide_read_feeds($value) {
$this->data['hide_read_feeds'] = (bool)$value;
}
public function _onread_jump_next ($value) { public function _onread_jump_next ($value) {
$this->data['onread_jump_next'] = ((bool)$value) && $value !== 'no'; $this->data['onread_jump_next'] = ((bool)$value) && $value !== 'no';
} }

View file

@ -17,7 +17,9 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
} }
public function addEntry($valuesTmp, $preparedStatement = null) { public function addEntry($valuesTmp, $preparedStatement = null) {
$stm = $preparedStatement === null ? addEntryPrepare() : $preparedStatement; $stm = $preparedStatement === null ?
FreshRSS_EntryDAO::addEntryPrepare() :
$preparedStatement;
$values = array( $values = array(
$valuesTmp['id'], $valuesTmp['id'],
@ -63,7 +65,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
} }
if (!isset($existingGuids[$entry->guid()]) && if (!isset($existingGuids[$entry->guid()]) &&
($feedHistory != 0 || $eDate >= $date_min)) { ($feedHistory != 0 || $eDate >= $date_min || $entry->isFavorite())) {
$values = $entry->toArray(); $values = $entry->toArray();
$useDeclaredDate = empty($existingGuids); $useDeclaredDate = empty($existingGuids);
@ -173,7 +175,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0) { public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0) {
if ($idMax == 0) { if ($idMax == 0) {
$idMax = time() . '000000'; $idMax = time() . '000000';
Minz_Log::record($nb . 'Calling markReadEntries(0) is deprecated!', Minz_Log::DEBUG); Minz_Log::record('Calling markReadEntries(0) is deprecated!', Minz_Log::DEBUG);
} }
$sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed=f.id ' $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed=f.id '
@ -201,7 +203,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
public function markReadCat($id, $idMax = 0) { public function markReadCat($id, $idMax = 0) {
if ($idMax == 0) { if ($idMax == 0) {
$idMax = time() . '000000'; $idMax = time() . '000000';
Minz_Log::record($nb . 'Calling markReadCat(0) is deprecated!', Minz_Log::DEBUG); Minz_Log::record('Calling markReadCat(0) is deprecated!', Minz_Log::DEBUG);
} }
$sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed=f.id ' $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed=f.id '
@ -224,11 +226,11 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
public function markReadFeed($id, $idMax = 0) { public function markReadFeed($id, $idMax = 0) {
if ($idMax == 0) { if ($idMax == 0) {
$idMax = time() . '000000'; $idMax = time() . '000000';
Minz_Log::record($nb . 'Calling markReadFeed(0) is deprecated!', Minz_Log::DEBUG); Minz_Log::record('Calling markReadFeed(0) is deprecated!', Minz_Log::DEBUG);
} }
$this->bd->beginTransaction(); $this->bd->beginTransaction();
$sql = 'UPDATE `' . $this->prefix . 'entry` ' $sql = 'UPDATE `' . $this->prefix . 'entry` '
. 'SET is_read=1 ' . 'SET is_read=1 '
. 'WHERE id_feed=? AND is_read=0 AND id <= ?'; . 'WHERE id_feed=? AND is_read=0 AND id <= ?';
$values = array($id, $idMax); $values = array($id, $idMax);

View file

@ -72,7 +72,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO {
public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0) { public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0) {
if ($idMax == 0) { if ($idMax == 0) {
$idMax = time() . '000000'; $idMax = time() . '000000';
Minz_Log::record($nb . 'Calling markReadEntries(0) is deprecated!', Minz_Log::DEBUG); Minz_Log::record('Calling markReadEntries(0) is deprecated!', Minz_Log::DEBUG);
} }
$sql = 'UPDATE `' . $this->prefix . 'entry` SET is_read=1 WHERE is_read=0 AND id <= ?'; $sql = 'UPDATE `' . $this->prefix . 'entry` SET is_read=1 WHERE is_read=0 AND id <= ?';
@ -98,7 +98,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO {
public function markReadCat($id, $idMax = 0) { public function markReadCat($id, $idMax = 0) {
if ($idMax == 0) { if ($idMax == 0) {
$idMax = time() . '000000'; $idMax = time() . '000000';
Minz_Log::record($nb . 'Calling markReadCat(0) is deprecated!', Minz_Log::DEBUG); Minz_Log::record('Calling markReadCat(0) is deprecated!', Minz_Log::DEBUG);
} }
$sql = 'UPDATE `' . $this->prefix . 'entry` ' $sql = 'UPDATE `' . $this->prefix . 'entry` '

View file

@ -28,6 +28,12 @@ class FreshRSS_Feed extends Minz_Model {
} }
} }
public static function example() {
$f = new FreshRSS_Feed('http://example.net/', false);
$f->faviconPrepare();
return $f;
}
public function id() { public function id() {
return $this->id; return $this->id;
} }
@ -277,11 +283,11 @@ class FreshRSS_Feed extends Minz_Model {
$elinks[$elink] = '1'; $elinks[$elink] = '1';
$mime = strtolower($enclosure->get_type()); $mime = strtolower($enclosure->get_type());
if (strpos($mime, 'image/') === 0) { if (strpos($mime, 'image/') === 0) {
$content .= '<br /><img src="' . $elink . '" alt="" />'; $content .= '<br /><img lazyload="" postpone="" src="' . $elink . '" alt="" />';
} elseif (strpos($mime, 'audio/') === 0) { } elseif (strpos($mime, 'audio/') === 0) {
$content .= '<br /><audio src="' . $elink . '" controls="controls" />'; $content .= '<br /><audio lazyload="" postpone="" preload="none" src="' . $elink . '" controls="controls" />';
} elseif (strpos($mime, 'video/') === 0) { } elseif (strpos($mime, 'video/') === 0) {
$content .= '<br /><video src="' . $elink . '" controls="controls" />'; $content .= '<br /><video lazyload="" postpone="" preload="none" src="' . $elink . '" controls="controls" />';
} }
} }
} }

View file

@ -85,9 +85,83 @@ SQL;
* @return array * @return array
*/ */
protected function initEntryCountArray() { protected function initEntryCountArray() {
return $this->initStatsArray(-self::ENTRY_COUNT_PERIOD, -1);
}
/**
* Calculates the number of article per hour of the day per feed
*
* @param integer $feed id
* @return string
*/
public function calculateEntryRepartitionPerFeedPerHour($feed = null) {
return $this->calculateEntryRepartitionPerFeedPerPeriod('%H', $feed);
}
/**
* Calculates the number of article per day of week per feed
*
* @param integer $feed id
* @return string
*/
public function calculateEntryRepartitionPerFeedPerDayOfWeek($feed = null) {
return $this->calculateEntryRepartitionPerFeedPerPeriod('%w', $feed);
}
/**
* Calculates the number of article per month per feed
*
* @param integer $feed
* @return string
*/
public function calculateEntryRepartitionPerFeedPerMonth($feed = null) {
return $this->calculateEntryRepartitionPerFeedPerPeriod('%m', $feed);
}
/**
* Calculates the number of article per period per feed
*
* @param string $period format string to use for grouping
* @param integer $feed id
* @return string
*/
protected function calculateEntryRepartitionPerFeedPerPeriod($period, $feed = null) {
if ($feed) {
$restrict = "WHERE e.id_feed = {$feed}";
} else {
$restrict = '';
}
$sql = <<<SQL
SELECT DATE_FORMAT(FROM_UNIXTIME(e.date), '{$period}') AS period
, COUNT(1) AS count
FROM {$this->prefix}entry AS e
{$restrict}
GROUP BY period
ORDER BY period ASC
SQL;
$stm = $this->bd->prepare($sql);
$stm->execute();
$res = $stm->fetchAll(PDO::FETCH_NAMED);
foreach ($res as $value) {
$repartition[(int) $value['period']] = (int) $value['count'];
}
return $this->convertToSerie($repartition);
}
/**
* Initialize an array for statistics depending on a range
*
* @param integer $min
* @param integer $max
* @return array
*/
protected function initStatsArray($min, $max) {
return array_map(function () { return array_map(function () {
return 0; return 0;
}, array_flip(range(-self::ENTRY_COUNT_PERIOD, -1))); }, array_flip(range($min, $max)));
} }
/** /**
@ -170,7 +244,8 @@ SQL;
*/ */
public function calculateFeedLastDate() { public function calculateFeedLastDate() {
$sql = <<<SQL $sql = <<<SQL
SELECT MAX(f.name) AS name SELECT MAX(f.id) as id
, MAX(f.name) AS name
, MAX(date) AS last_date , MAX(date) AS last_date
FROM {$this->prefix}feed AS f, FROM {$this->prefix}feed AS f,
{$this->prefix}entry AS e {$this->prefix}entry AS e
@ -204,4 +279,57 @@ SQL;
return json_encode($serie); return json_encode($serie);
} }
/**
* Gets days ready for graphs
*
* @return string
*/
public function getDays() {
return $this->convertToTranslatedJson(array(
'sun',
'mon',
'tue',
'wed',
'thu',
'fri',
'sat',
));
}
/**
* Gets months ready for graphs
*
* @return string
*/
public function getMonths() {
return $this->convertToTranslatedJson(array(
'jan',
'feb',
'mar',
'apr',
'may',
'jun',
'jul',
'aug',
'sep',
'oct',
'nov',
'dec',
));
}
/**
* Translates array content and encode it as JSON
*
* @param array $data
* @return string
*/
private function convertToTranslatedJson($data = array()) {
$translated = array_map(function ($a) {
return Minz_Translate::t($a);
}, $data);
return json_encode($translated);
}
} }

View file

@ -28,10 +28,36 @@ SQL;
$res = $stm->fetchAll(PDO::FETCH_ASSOC); $res = $stm->fetchAll(PDO::FETCH_ASSOC);
foreach ($res as $value) { foreach ($res as $value) {
$count[(int)$value['day']] = (int) $value['count']; $count[(int) $value['day']] = (int) $value['count'];
} }
return $this->convertToSerie($count); return $this->convertToSerie($count);
} }
protected function calculateEntryRepartitionPerFeedPerPeriod($period, $feed = null) {
if ($feed) {
$restrict = "WHERE e.id_feed = {$feed}";
} else {
$restrict = '';
}
$sql = <<<SQL
SELECT strftime('{$period}', e.date, 'unixepoch') AS period
, COUNT(1) AS count
FROM {$this->prefix}entry AS e
{$restrict}
GROUP BY period
ORDER BY period ASC
SQL;
$stm = $this->bd->prepare($sql);
$stm->execute();
$res = $stm->fetchAll(PDO::FETCH_NAMED);
foreach ($res as $value) {
$repartition[(int) $value['period']] = (int) $value['count'];
}
return $this->convertToSerie($repartition);
}
} }

View file

@ -3,19 +3,22 @@
class FreshRSS_UserDAO extends Minz_ModelPdo { class FreshRSS_UserDAO extends Minz_ModelPdo {
public function createUser($username) { public function createUser($username) {
$db = Minz_Configuration::dataBase(); $db = Minz_Configuration::dataBase();
require_once(APP_PATH . '/SQL/sql.' . $db['type'] . '.php'); require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php');
if (defined('SQL_CREATE_TABLES')) { $userPDO = new Minz_ModelPdo($username);
$ok = false;
if (defined('SQL_CREATE_TABLES')) { //E.g. MySQL
$sql = sprintf(SQL_CREATE_TABLES, $db['prefix'] . $username . '_', Minz_Translate::t('default_category')); $sql = sprintf(SQL_CREATE_TABLES, $db['prefix'] . $username . '_', Minz_Translate::t('default_category'));
$stm = $c->prepare($sql); $stm = $userPDO->bd->prepare($sql);
$ok = $stm && $stm->execute(); $ok = $stm && $stm->execute();
} else { } else { //E.g. SQLite
global $SQL_CREATE_TABLES; global $SQL_CREATE_TABLES;
if (is_array($SQL_CREATE_TABLES)) { if (is_array($SQL_CREATE_TABLES)) {
$ok = true; $ok = true;
foreach ($SQL_CREATE_TABLES as $instruction) { foreach ($SQL_CREATE_TABLES as $instruction) {
$sql = sprintf($instruction, '', Minz_Translate::t('default_category')); $sql = sprintf($instruction, '', Minz_Translate::t('default_category'));
$stm = $c->prepare($sql); $stm = $userPDO->bd->prepare($sql);
$ok &= ($stm && $stm->execute()); $ok &= ($stm && $stm->execute());
} }
} }
@ -24,7 +27,7 @@ class FreshRSS_UserDAO extends Minz_ModelPdo {
if ($ok) { if ($ok) {
return true; return true;
} else { } else {
$info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); $info = empty($stm) ? array(2 => 'syntax error') : $stm->errorInfo();
Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
return false; return false;
} }
@ -32,16 +35,22 @@ class FreshRSS_UserDAO extends Minz_ModelPdo {
public function deleteUser($username) { public function deleteUser($username) {
$db = Minz_Configuration::dataBase(); $db = Minz_Configuration::dataBase();
require_once(APP_PATH . '/SQL/sql.' . $db['type'] . '.php'); require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php');
$sql = sprintf(SQL_DROP_TABLES, $db['prefix'] . $username . '_'); if ($db['type'] === 'sqlite') {
$stm = $this->bd->prepare($sql); return unlink(DATA_PATH . '/' . $username . '.sqlite');
if ($stm && $stm->execute()) {
return true;
} else { } else {
$info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); $userPDO = new Minz_ModelPdo($username);
Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
return false; $sql = sprintf(SQL_DROP_TABLES, $db['prefix'] . $username . '_');
$stm = $userPDO->bd->prepare($sql);
if ($stm && $stm->execute()) {
return true;
} else {
$info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
return false;
}
} }
} }
} }

View file

@ -1,4 +1,5 @@
<?php <?php
global $SQL_CREATE_TABLES;
$SQL_CREATE_TABLES = array( $SQL_CREATE_TABLES = array(
'CREATE TABLE IF NOT EXISTS `%1$scategory` ( 'CREATE TABLE IF NOT EXISTS `%1$scategory` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,

View file

@ -3,6 +3,7 @@
return array ( return array (
// LAYOUT // LAYOUT
'login' => 'Login', 'login' => 'Login',
'keep_logged_in' => 'Keep me logged in <small>(1 month)</small>',
'login_with_persona' => 'Login with Persona', 'login_with_persona' => 'Login with Persona',
'logout' => 'Logout', 'logout' => 'Logout',
'search' => 'Search words or #tags', 'search' => 'Search words or #tags',
@ -48,6 +49,10 @@ return array (
'stats' => 'Statistics', 'stats' => 'Statistics',
'stats_idle' => 'Idle feeds', 'stats_idle' => 'Idle feeds',
'stats_main' => 'Main statistics', 'stats_main' => 'Main statistics',
'stats_repartition' => 'Articles repartition',
'stats_entry_per_hour' => 'Per hour',
'stats_entry_per_day_of_week' => 'Per day of week',
'stats_entry_per_month' => 'Per month',
'last_week' => 'Last week', 'last_week' => 'Last week',
'last_month' => 'Last month', 'last_month' => 'Last month',
@ -177,10 +182,15 @@ return array (
'focus_search' => 'Access search box', 'focus_search' => 'Access search box',
'file_to_import' => 'File to import<br />(OPML, Json or Zip)', 'file_to_import' => 'File to import<br />(OPML, Json or Zip)',
'file_to_import_no_zip' => 'File to import<br />(OPML or Json)',
'import' => 'Import', 'import' => 'Import',
'file_cannot_be_uploaded' => 'File cannot be uploaded!',
'zip_error' => 'An error occured during Zip import.',
'no_zip_extension' => 'Zip extension is not present on your server.',
'export' => 'Export', 'export' => 'Export',
'export_opml' => 'Export list of feeds (OPML)', 'export_opml' => 'Export list of feeds (OPML)',
'export_starred' => 'Export your favourites', 'export_starred' => 'Export your favourites',
'export_no_zip_extension' => 'Zip extension is not present on your server. Please try to export files one by one.',
'starred_list' => 'List of favourite articles', 'starred_list' => 'List of favourite articles',
'feed_list' => 'List of %s articles', 'feed_list' => 'List of %s articles',
'or' => 'or', 'or' => 'or',
@ -257,6 +267,8 @@ return array (
'sort_order' => 'Sort order', 'sort_order' => 'Sort order',
'auto_load_more' => 'Load next articles at the page bottom', 'auto_load_more' => 'Load next articles at the page bottom',
'display_articles_unfolded' => 'Show articles unfolded by default', 'display_articles_unfolded' => 'Show articles unfolded by default',
'display_categories_unfolded' => 'Show categories folded by default',
'hide_read_feeds' => 'Hide categories &amp; feeds with no unread article (only in “unread articles” display mode)',
'after_onread' => 'After “mark all as read”,', 'after_onread' => 'After “mark all as read”,',
'jump_next' => 'jump to next unread sibling (feed or category)', 'jump_next' => 'jump to next unread sibling (feed or category)',
'article_icons' => 'Article icons', 'article_icons' => 'Article icons',
@ -339,20 +351,41 @@ return array (
'login_required' => 'Login required:', 'login_required' => 'Login required:',
'confirm_action' => 'Are you sure you want to perform this action? It cannot be cancelled!', 'confirm_action' => 'Are you sure you want to perform this action? It cannot be cancelled!',
'notif_title_new_articles' => 'FreshRSS: new articles!',
'notif_body_new_articles' => 'There are \d new articles to read on FreshRSS.',
// DATE // DATE
'january' => 'january', 'january' => 'January',
'february' => 'february', 'february' => 'February',
'march' => 'march', 'march' => 'March',
'april' => 'april', 'april' => 'April',
'may' => 'may', 'may' => 'May',
'june' => 'june', 'june' => 'June',
'july' => 'july', 'july' => 'July',
'august' => 'august', 'august' => 'August',
'september' => 'september', 'september' => 'September',
'october' => 'october', 'october' => 'October',
'november' => 'november', 'november' => 'November',
'december' => 'december', 'december' => 'December',
'january' => 'Jan',
'february' => 'Feb',
'march' => 'Mar',
'april' => 'Apr',
'may' => 'May',
'june' => 'Jun',
'july' => 'Jul',
'august' => 'Aug',
'september' => 'Sep',
'october' => 'Oct',
'november' => 'Nov',
'december' => 'Dec',
'sun' => 'Sun',
'mon' => 'Mon',
'tue' => 'Tue',
'wed' => 'Wed',
'thu' => 'Thu',
'fri' => 'Fri',
'sat' => 'Sat',
// special format for date() function // special format for date() function
'Jan' => '\J\a\n\u\a\r\y', 'Jan' => '\J\a\n\u\a\r\y',
'Feb' => '\F\e\b\r\u\a\r\y', 'Feb' => '\F\e\b\r\u\a\r\y',

View file

@ -3,6 +3,7 @@
return array ( return array (
// LAYOUT // LAYOUT
'login' => 'Connexion', 'login' => 'Connexion',
'keep_logged_in' => 'Rester connecté <small>(1 mois)</small>',
'login_with_persona' => 'Connexion avec Persona', 'login_with_persona' => 'Connexion avec Persona',
'logout' => 'Déconnexion', 'logout' => 'Déconnexion',
'search' => 'Rechercher des mots ou des #tags', 'search' => 'Rechercher des mots ou des #tags',
@ -48,6 +49,10 @@ return array (
'stats' => 'Statistiques', 'stats' => 'Statistiques',
'stats_idle' => 'Flux inactifs', 'stats_idle' => 'Flux inactifs',
'stats_main' => 'Statistiques principales', 'stats_main' => 'Statistiques principales',
'stats_repartition' => 'Répartition des articles',
'stats_entry_per_hour' => 'Par heure',
'stats_entry_per_day_of_week' => 'Par jour de la semaine',
'stats_entry_per_month' => 'Par mois',
'last_week' => 'La dernière semaine', 'last_week' => 'La dernière semaine',
'last_month' => 'Le dernier mois', 'last_month' => 'Le dernier mois',
@ -177,10 +182,15 @@ return array (
'focus_search' => 'Accéder à la recherche', 'focus_search' => 'Accéder à la recherche',
'file_to_import' => 'Fichier à importer<br />(OPML, Json ou Zip)', 'file_to_import' => 'Fichier à importer<br />(OPML, Json ou Zip)',
'file_to_import_no_zip' => 'Fichier à importer<br />(OPML ou Json)',
'import' => 'Importer', 'import' => 'Importer',
'file_cannot_be_uploaded' => 'Le fichier ne peut pas être téléchargé!',
'zip_error' => 'Une erreur est survenue durant limport du fichier Zip.',
'no_zip_extension' => 'Lextension Zip nest pas présente sur votre serveur.',
'export' => 'Exporter', 'export' => 'Exporter',
'export_opml' => 'Exporter la liste des flux (OPML)', 'export_opml' => 'Exporter la liste des flux (OPML)',
'export_starred' => 'Exporter les favoris', 'export_starred' => 'Exporter les favoris',
'export_no_zip_extension' => 'Lextension Zip nest pas présente sur votre serveur. Veuillez essayer dexporter les fichiers un par un.',
'starred_list' => 'Liste des articles favoris', 'starred_list' => 'Liste des articles favoris',
'feed_list' => 'Liste des articles de %s', 'feed_list' => 'Liste des articles de %s',
'or' => 'ou', 'or' => 'ou',
@ -224,7 +234,7 @@ return array (
'persona_connection_email' => 'Adresse courriel de connexion<br /><small>(pour <a href="https://persona.org/" rel="external">Mozilla Persona</a>)</small>', 'persona_connection_email' => 'Adresse courriel de connexion<br /><small>(pour <a href="https://persona.org/" rel="external">Mozilla Persona</a>)</small>',
'allow_anonymous' => 'Autoriser la lecture anonyme des articles de lutilisateur par défaut (%s)', 'allow_anonymous' => 'Autoriser la lecture anonyme des articles de lutilisateur par défaut (%s)',
'allow_anonymous_refresh' => 'Autoriser le rafraîchissement anonyme des flux', 'allow_anonymous_refresh' => 'Autoriser le rafraîchissement anonyme des flux',
'unsafe_autologin' => 'Autoriser les connexion automatiques non-sûres au format : ', 'unsafe_autologin' => 'Autoriser les connexions automatiques non-sûres au format : ',
'api_enabled' => 'Autoriser laccès par <abbr>API</abbr> <small>(nécessaire pour les applis mobiles)</small>', 'api_enabled' => 'Autoriser laccès par <abbr>API</abbr> <small>(nécessaire pour les applis mobiles)</small>',
'auth_token' => 'Jeton didentification', 'auth_token' => 'Jeton didentification',
'explain_token' => 'Permet daccéder à la sortie RSS de lutilisateur par défaut sans besoin de sauthentifier.<br /><kbd>%s?output=rss&token=%s</kbd>', 'explain_token' => 'Permet daccéder à la sortie RSS de lutilisateur par défaut sans besoin de sauthentifier.<br /><kbd>%s?output=rss&token=%s</kbd>',
@ -257,6 +267,8 @@ return array (
'sort_order' => 'Ordre de tri', 'sort_order' => 'Ordre de tri',
'auto_load_more' => 'Charger les articles suivants en bas de page', 'auto_load_more' => 'Charger les articles suivants en bas de page',
'display_articles_unfolded' => 'Afficher les articles dépliés par défaut', 'display_articles_unfolded' => 'Afficher les articles dépliés par défaut',
'display_categories_unfolded' => 'Afficher les catégories pliées par défaut',
'hide_read_feeds' => 'Cacher les catégories &amp; flux sans article non-lu (uniquement en affichage “articles non lus”)',
'after_onread' => 'Après “marquer tout comme lu”,', 'after_onread' => 'Après “marquer tout comme lu”,',
'jump_next' => 'sauter au prochain voisin non lu (flux ou catégorie)', 'jump_next' => 'sauter au prochain voisin non lu (flux ou catégorie)',
'article_icons' => 'Icônes darticle', 'article_icons' => 'Icônes darticle',
@ -339,6 +351,8 @@ return array (
'login_required' => 'Accès protégé par mot de passe :', 'login_required' => 'Accès protégé par mot de passe :',
'confirm_action' => 'Êtes-vous sûr(e) de vouloir continuer ? Cette action ne peut être annulée !', 'confirm_action' => 'Êtes-vous sûr(e) de vouloir continuer ? Cette action ne peut être annulée !',
'notif_title_new_articles' => 'FreshRSS : nouveaux articles !',
'notif_body_new_articles' => 'Il y a \d nouveaux articles à lire sur FreshRSS.',
// DATE // DATE
'january' => 'janvier', 'january' => 'janvier',
@ -353,6 +367,25 @@ return array (
'october' => 'octobre', 'october' => 'octobre',
'november' => 'novembre', 'november' => 'novembre',
'december' => 'décembre', 'december' => 'décembre',
'jan' => 'jan.',
'feb' => 'fév.',
'mar' => 'mar.',
'apr' => 'avr.',
'may' => 'mai.',
'jun' => 'juin',
'jul' => 'jui.',
'aug' => 'août',
'sep' => 'sep.',
'oct' => 'oct.',
'nov' => 'nov.',
'dec' => 'déc.',
'sun' => 'dim.',
'mon' => 'lun.',
'tue' => 'mar.',
'wed' => 'mer.',
'thu' => 'jeu.',
'fri' => 'ven.',
'sat' => 'sam.',
// format spécial pour la fonction date() // format spécial pour la fonction date()
'Jan' => '\j\a\n\v\i\e\r', 'Jan' => '\j\a\n\v\i\e\r',
'Feb' => '\f\é\v\r\i\e\r', 'Feb' => '\f\é\v\r\i\e\r',

View file

@ -28,8 +28,8 @@ return array (
'minz_is_nok' => 'You lack the Minz framework. You should execute <em>build.sh</em> script or <a href="https://github.com/marienfressinaud/MINZ">download it on Github</a> and install in <em>%s</em> directory the content of its <em>/lib</em> directory.', 'minz_is_nok' => 'You lack the Minz framework. You should execute <em>build.sh</em> script or <a href="https://github.com/marienfressinaud/MINZ">download it on Github</a> and install in <em>%s</em> directory the content of its <em>/lib</em> directory.',
'curl_is_ok' => 'You have version %s of cURL', 'curl_is_ok' => 'You have version %s of cURL',
'curl_is_nok' => 'You lack cURL (php5-curl package)', 'curl_is_nok' => 'You lack cURL (php5-curl package)',
'pdomysql_is_ok' => 'You have PDO and its driver for MySQL', 'pdo_is_ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite)',
'pdomysql_is_nok' => 'You lack PDO or its driver for MySQL (php5-mysql package)', 'pdo_is_nok' => 'You lack PDO or one of the supported drivers (pdo_mysql, pdo_sqlite)',
'dom_is_ok' => 'You have the required library to browse the DOM', 'dom_is_ok' => 'You have the required library to browse the DOM',
'dom_is_nok' => 'You lack a required library to browse the DOM (php-xml package)', 'dom_is_nok' => 'You lack a required library to browse the DOM (php-xml package)',
'pcre_is_ok' => 'You have the required library for regular expressions (PCRE)', 'pcre_is_ok' => 'You have the required library for regular expressions (PCRE)',

View file

@ -28,8 +28,8 @@ return array (
'minz_is_nok' => 'Vous ne disposez pas de la librairie Minz. Vous devriez exécuter le script <em>build.sh</em> ou bien <a href="https://github.com/marienfressinaud/MINZ">la télécharger sur Github</a> et installer dans le répertoire <em>%s</em> le contenu de son répertoire <em>/lib</em>.', 'minz_is_nok' => 'Vous ne disposez pas de la librairie Minz. Vous devriez exécuter le script <em>build.sh</em> ou bien <a href="https://github.com/marienfressinaud/MINZ">la télécharger sur Github</a> et installer dans le répertoire <em>%s</em> le contenu de son répertoire <em>/lib</em>.',
'curl_is_ok' => 'Vous disposez de cURL dans sa version %s', 'curl_is_ok' => 'Vous disposez de cURL dans sa version %s',
'curl_is_nok' => 'Vous ne disposez pas de cURL (paquet php5-curl)', 'curl_is_nok' => 'Vous ne disposez pas de cURL (paquet php5-curl)',
'pdomysql_is_ok' => 'Vous disposez de PDO et de son driver pour MySQL (paquet php5-mysql)', 'pdo_is_ok' => 'Vous disposez de PDO et dau moins un des drivers supportés (pdo_mysql, pdo_sqlite)',
'pdomysql_is_nok' => 'Vous ne disposez pas de PDO ou de son driver pour MySQL', 'pdo_is_nok' => 'Vous ne disposez pas de PDO ou dun des drivers supportés (pdo_mysql, pdo_sqlite)',
'dom_is_ok' => 'Vous disposez du nécessaire pour parcourir le DOM', 'dom_is_ok' => 'Vous disposez du nécessaire pour parcourir le DOM',
'dom_is_nok' => 'Il manque une librairie pour parcourir le DOM (paquet php-xml)', 'dom_is_nok' => 'Il manque une librairie pour parcourir le DOM (paquet php-xml)',
'pcre_is_ok' => 'Vous disposez du nécessaire pour les expressions régulières (PCRE)', 'pcre_is_ok' => 'Vous disposez du nécessaire pour les expressions régulières (PCRE)',

View file

@ -249,11 +249,11 @@ function saveStep3 () {
'base_url' => '', 'base_url' => '',
'title' => $_SESSION['title'], 'title' => $_SESSION['title'],
'default_user' => $_SESSION['default_user'], 'default_user' => $_SESSION['default_user'],
'auth_type' => $_SESSION['auth_type'],
'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false, 'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false,
'allow_anonymous_refresh' => false, 'allow_anonymous_refresh' => isset($_SESSION['allow_anonymous_refresh']) ? $_SESSION['allow_anonymous_refresh'] : false,
'unsafe_autologin_enabled' => false, 'auth_type' => $_SESSION['auth_type'],
'api_enabled' => false, 'api_enabled' => isset($_SESSION['api_enabled']) ? $_SESSION['api_enabled'] : false,
'unsafe_autologin_enabled' => isset($_SESSION['unsafe_autologin_enabled']) ? $_SESSION['unsafe_autologin_enabled'] : false,
), ),
'db' => array( 'db' => array(
'type' => $_SESSION['bd_type'], 'type' => $_SESSION['bd_type'],
@ -499,7 +499,7 @@ function checkStep0 () {
if ($ini_array) { if ($ini_array) {
$ini_general = isset($ini_array['general']) ? $ini_array['general'] : null; $ini_general = isset($ini_array['general']) ? $ini_array['general'] : null;
if ($ini_general) { if ($ini_general) {
$keys = array('environment', 'salt', 'title', 'default_user', 'allow_anonymous', 'auth_type'); $keys = array('environment', 'salt', 'title', 'default_user', 'allow_anonymous', 'allow_anonymous_refresh', 'auth_type', 'api_enabled', 'unsafe_autologin_enabled');
foreach ($keys as $key) { foreach ($keys as $key) {
if ((empty($_SESSION[$key])) && isset($ini_general[$key])) { if ((empty($_SESSION[$key])) && isset($ini_general[$key])) {
$_SESSION[$key] = $ini_general[$key]; $_SESSION[$key] = $ini_general[$key];
@ -574,7 +574,9 @@ function checkStep1 () {
$php = version_compare (PHP_VERSION, '5.2.1') >= 0; $php = version_compare (PHP_VERSION, '5.2.1') >= 0;
$minz = file_exists (LIB_PATH . '/Minz'); $minz = file_exists (LIB_PATH . '/Minz');
$curl = extension_loaded ('curl'); $curl = extension_loaded ('curl');
$pdo = extension_loaded ('pdo_mysql'); $pdo_mysql = extension_loaded ('pdo_mysql');
$pdo_sqlite = extension_loaded ('pdo_sqlite');
$pdo = $pdo_mysql || $pdo_sqlite;
$pcre = extension_loaded ('pcre'); $pcre = extension_loaded ('pcre');
$ctype = extension_loaded ('ctype'); $ctype = extension_loaded ('ctype');
$dom = class_exists('DOMDocument'); $dom = class_exists('DOMDocument');
@ -588,7 +590,9 @@ function checkStep1 () {
'php' => $php ? 'ok' : 'ko', 'php' => $php ? 'ok' : 'ko',
'minz' => $minz ? 'ok' : 'ko', 'minz' => $minz ? 'ok' : 'ko',
'curl' => $curl ? 'ok' : 'ko', 'curl' => $curl ? 'ok' : 'ko',
'pdo-mysql' => $pdo ? 'ok' : 'ko', 'pdo-mysql' => $pdo_mysql ? 'ok' : 'ko',
'pdo-sqlite' => $pdo_sqlite ? 'ok' : 'ko',
'pdo' => $pdo ? 'ok' : 'ko',
'pcre' => $pcre ? 'ok' : 'ko', 'pcre' => $pcre ? 'ok' : 'ko',
'ctype' => $ctype ? 'ok' : 'ko', 'ctype' => $ctype ? 'ok' : 'ko',
'dom' => $dom ? 'ok' : 'ko', 'dom' => $dom ? 'ok' : 'ko',
@ -766,10 +770,10 @@ function printStep1 () {
<p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('minz_is_nok', LIB_PATH . '/Minz'); ?></p> <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('minz_is_nok', LIB_PATH . '/Minz'); ?></p>
<?php } ?> <?php } ?>
<?php if ($res['pdo-mysql'] == 'ok') { ?> <?php if ($res['pdo'] == 'ok') { ?>
<p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('pdomysql_is_ok'); ?></p> <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('pdo_is_ok'); ?></p>
<?php } else { ?> <?php } else { ?>
<p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('pdomysql_is_nok'); ?></p> <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('pdo_is_nok'); ?></p>
<?php } ?> <?php } ?>
<?php if ($res['curl'] == 'ok') { ?> <?php if ($res['curl'] == 'ok') { ?>
@ -923,14 +927,18 @@ function printStep3 () {
<label class="group-name" for="type"><?php echo _t ('bdd_type'); ?></label> <label class="group-name" for="type"><?php echo _t ('bdd_type'); ?></label>
<div class="group-controls"> <div class="group-controls">
<select name="type" id="type" onchange="mySqlShowHide()"> <select name="type" id="type" onchange="mySqlShowHide()">
<?php if (extension_loaded('pdo_mysql')) {?>
<option value="mysql" <option value="mysql"
<?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql') ? 'selected="selected"' : ''; ?>> <?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql') ? 'selected="selected"' : ''; ?>>
MySQL MySQL
</option> </option>
<?php }?>
<?php if (extension_loaded('pdo_sqlite')) {?>
<option value="sqlite" <option value="sqlite"
<?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'sqlite') ? 'selected="selected"' : ''; ?>> <?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'sqlite') ? 'selected="selected"' : ''; ?>>
SQLite SQLite
</option> </option>
<?php }?>
</select> </select>
</div> </div>
</div> </div>

View file

@ -1,4 +1,4 @@
<div class="aside aside_flux" id="aside_flux"> <div class="aside aside_flux<?php if ($this->conf->hide_read_feeds && ($this->state & FreshRSS_Entry::STATE_NOT_READ) && !($this->state & FreshRSS_Entry::STATE_READ)) echo ' state_unread'; ?>" id="aside_flux">
<a class="toggle_aside" href="#close"><?php echo FreshRSS_Themes::icon('close'); ?></a> <a class="toggle_aside" href="#close"><?php echo FreshRSS_Themes::icon('close'); ?></a>
<ul class="categories"> <ul class="categories">
@ -41,11 +41,17 @@
foreach ($this->cat_aside as $cat) { foreach ($this->cat_aside as $cat) {
$feeds = $cat->feeds (); $feeds = $cat->feeds ();
if (!empty ($feeds)) { if (!empty ($feeds)) {
?><li><?php
$c_active = false; $c_active = false;
if ($this->get_c == $cat->id ()) { if ($this->conf->display_categories) {
$c_active = true; if ($this->get_c == $cat->id () && $this->get_f) {
$c_active = true;
}
} else {
if ($this->get_c == $cat->id ()) {
$c_active = true;
}
} }
?><li data-unread="<?php echo $cat->nbNotRead(); ?>"<?php if ($c_active) echo ' class="active"'; ?>><?php
?><div class="category stick<?php echo $c_active ? ' active' : ''; ?>"><?php ?><div class="category stick<?php echo $c_active ? ' active' : ''; ?>"><?php
?><a data-unread="<?php echo formatNumber($cat->nbNotRead()); ?>" class="btn<?php echo $c_active ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 'c_' . $cat->id(); echo Minz_Url::display($arUrl); ?>"><?php echo $cat->name (); ?></a><?php ?><a data-unread="<?php echo formatNumber($cat->nbNotRead()); ?>" class="btn<?php echo $c_active ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 'c_' . $cat->id(); echo Minz_Url::display($arUrl); ?>"><?php echo $cat->name (); ?></a><?php
?><a class="btn dropdown-toggle" href="#"><?php echo FreshRSS_Themes::icon($c_active ? 'up' : 'down'); ?></a><?php ?><a class="btn dropdown-toggle" href="#"><?php echo FreshRSS_Themes::icon($c_active ? 'up' : 'down'); ?></a><?php
@ -55,7 +61,7 @@
$feed_id = $feed->id (); $feed_id = $feed->id ();
$nbEntries = $feed->nbEntries (); $nbEntries = $feed->nbEntries ();
$f_active = ($this->get_f == $feed_id); $f_active = ($this->get_f == $feed_id);
?><li id="f_<?php echo $feed_id; ?>" class="item<?php echo $f_active ? ' active' : ''; ?><?php echo $feed->inError () ? ' error' : ''; ?><?php echo $nbEntries == 0 ? ' empty' : ''; ?>"><?php ?><li id="f_<?php echo $feed_id; ?>" class="item<?php echo $f_active ? ' active' : ''; ?><?php echo $feed->inError () ? ' error' : ''; ?><?php echo $nbEntries == 0 ? ' empty' : ''; ?>" data-unread="<?php echo $feed->nbNotRead(); ?>"><?php
?><div class="dropdown"><?php ?><div class="dropdown"><?php
?><div class="dropdown-target"></div><?php ?><div class="dropdown-target"></div><?php
?><a class="dropdown-toggle" data-fweb="<?php echo $feed->website (); ?>"><?php echo FreshRSS_Themes::icon('configure'); ?></a><?php ?><a class="dropdown-toggle" data-fweb="<?php echo $feed->website (); ?>"><?php echo FreshRSS_Themes::icon('configure'); ?></a><?php
@ -77,6 +83,7 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="dropdown-close"><a href="#close"></a></li> <li class="dropdown-close"><a href="#close"></a></li>
<li class="item"><a href="<?php echo _url ('index', 'index', 'get', 'f_!!!!!!'); ?>"><?php echo Minz_Translate::t ('filter'); ?></a></li> <li class="item"><a href="<?php echo _url ('index', 'index', 'get', 'f_!!!!!!'); ?>"><?php echo Minz_Translate::t ('filter'); ?></a></li>
<li class="item"><a href="<?php echo _url ('stats', 'repartition', 'id', '!!!!!!'); ?>"><?php echo Minz_Translate::t ('stats'); ?></a></li>
<li class="item"><a target="_blank" href="http://example.net/"><?php echo Minz_Translate::t ('see_website'); ?></a></li> <li class="item"><a target="_blank" href="http://example.net/"><?php echo Minz_Translate::t ('see_website'); ?></a></li>
<?php if ($this->loginOk) { ?> <?php if ($this->loginOk) { ?>
<li class="separator"></li> <li class="separator"></li>

View file

@ -6,4 +6,7 @@
<li class="item<?php echo Minz_Request::actionName () == 'idle' ? ' active' : ''; ?>"> <li class="item<?php echo Minz_Request::actionName () == 'idle' ? ' active' : ''; ?>">
<a href="<?php echo _url ('stats', 'idle'); ?>"><?php echo Minz_Translate::t ('stats_idle'); ?></a> <a href="<?php echo _url ('stats', 'idle'); ?>"><?php echo Minz_Translate::t ('stats_idle'); ?></a>
</li> </li>
<li class="item<?php echo Minz_Request::actionName () == 'repartition' ? ' active' : ''; ?>">
<a href="<?php echo _url ('stats', 'repartition'); ?>"><?php echo Minz_Translate::t ('stats_repartition'); ?></a>
</li>
</ul> </ul>

View file

@ -16,7 +16,7 @@
?> ?>
<link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display(array('c' => Minz_Request::controllerName(), 'a' => Minz_Request::actionName(), 'params' => $params)); ?>" /> <link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display(array('c' => Minz_Request::controllerName(), 'a' => Minz_Request::actionName(), 'params' => $params)); ?>" />
<?php } ?> <?php } ?>
<link rel="shortcut icon" type="image/x-icon" sizes="16x16 64x64" href="<?php echo Minz_Url::display('/favicon.ico'); ?>" /> <link rel="shortcut icon" id="favicon" type="image/x-icon" sizes="16x16 64x64" href="<?php echo Minz_Url::display('/favicon.ico'); ?>" />
<link rel="icon msapplication-TileImage apple-touch-icon" type="image/png" sizes="256x256" href="<?php echo Minz_Url::display('/themes/icons/favicon-256.png'); ?>" /> <link rel="icon msapplication-TileImage apple-touch-icon" type="image/png" sizes="256x256" href="<?php echo Minz_Url::display('/themes/icons/favicon-256.png'); ?>" />
<?php <?php
if (isset($this->url)) { if (isset($this->url)) {

View file

@ -164,11 +164,15 @@
break; break;
} }
} }
if ($this->order === 'ASC') {
$idMax = 0; $p = isset($this->entries[0]) ? $this->entries[0] : null;
} else { $idMax = $p === null ? (time() - 1) . '000000' : $p->id();
$p = isset($this->entries[0]) ? $this->entries[0] : null;
$idMax = $p === null ? '0' : $p->id(); if ($this->order === 'ASC') { //In this case we do not know but we guess idMax
$idMax2 = (time() - 1) . '000000';
if (strcmp($idMax2, $idMax) > 0) {
$idMax = $idMax2;
}
} }
$arUrl = array('c' => 'entry', 'a' => 'read', 'params' => array('get' => $get, 'nextGet' => $nextGet, 'idMax' => $idMax)); $arUrl = array('c' => 'entry', 'a' => 'read', 'params' => array('get' => $get, 'nextGet' => $nextGet, 'idMax' => $idMax));
@ -221,7 +225,9 @@
<?php <?php
$url_output['params']['output'] = 'rss'; $url_output['params']['output'] = 'rss';
$url_output['params']['token'] = $this->conf->token; if ($this->conf->token) {
$url_output['params']['token'] = $this->conf->token;
}
?> ?>
<a class="view_rss btn" target="_blank" title="<?php echo Minz_Translate::t ('rss_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>"> <a class="view_rss btn" target="_blank" title="<?php echo Minz_Translate::t ('rss_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
<?php echo FreshRSS_Themes::icon('rss'); ?> <?php echo FreshRSS_Themes::icon('rss'); ?>

View file

@ -9,7 +9,7 @@
<div class="form-group"> <div class="form-group">
<label class="group-name" for="posts_per_page"><?php echo Minz_Translate::t ('articles_per_page'); ?></label> <label class="group-name" for="posts_per_page"><?php echo Minz_Translate::t ('articles_per_page'); ?></label>
<div class="group-controls"> <div class="group-controls">
<input type="number" id="posts_per_page" name="posts_per_page" value="<?php echo $this->conf->posts_per_page; ?>" /> <input type="number" id="posts_per_page" name="posts_per_page" value="<?php echo $this->conf->posts_per_page; ?>" min="5" max="50" />
</div> </div>
</div> </div>
@ -44,10 +44,9 @@
<div class="form-group"> <div class="form-group">
<div class="group-controls"> <div class="group-controls">
<label class="checkbox" for="auto_load_more"> <label class="checkbox" for="hide_read_feeds">
<input type="checkbox" name="auto_load_more" id="auto_load_more" value="1"<?php echo $this->conf->auto_load_more ? ' checked="checked"' : ''; ?> /> <input type="checkbox" name="hide_read_feeds" id="hide_read_feeds" value="1"<?php echo $this->conf->hide_read_feeds ? ' checked="checked"' : ''; ?> />
<?php echo Minz_Translate::t ('auto_load_more'); ?> <?php echo Minz_Translate::t('hide_read_feeds'); ?>
<noscript><strong><?php echo Minz_Translate::t ('javascript_should_be_activated'); ?></strong></noscript>
</label> </label>
</div> </div>
</div> </div>
@ -64,9 +63,9 @@
<div class="form-group"> <div class="form-group">
<div class="group-controls"> <div class="group-controls">
<label class="checkbox" for="lazyload"> <label class="checkbox" for="display_categories">
<input type="checkbox" name="lazyload" id="lazyload" value="1"<?php echo $this->conf->lazyload ? ' checked="checked"' : ''; ?> /> <input type="checkbox" name="display_categories" id="display_categories" value="1"<?php echo $this->conf->display_categories ? ' checked="checked"' : ''; ?> />
<?php echo Minz_Translate::t ('img_with_lazyload'); ?> <?php echo Minz_Translate::t ('display_categories_unfolded'); ?>
<noscript><strong><?php echo Minz_Translate::t ('javascript_should_be_activated'); ?></strong></noscript> <noscript><strong><?php echo Minz_Translate::t ('javascript_should_be_activated'); ?></strong></noscript>
</label> </label>
</div> </div>
@ -82,6 +81,26 @@
</div> </div>
</div> </div>
<div class="form-group">
<div class="group-controls">
<label class="checkbox" for="auto_load_more">
<input type="checkbox" name="auto_load_more" id="auto_load_more" value="1"<?php echo $this->conf->auto_load_more ? ' checked="checked"' : ''; ?> />
<?php echo Minz_Translate::t ('auto_load_more'); ?>
<noscript><strong><?php echo Minz_Translate::t ('javascript_should_be_activated'); ?></strong></noscript>
</label>
</div>
</div>
<div class="form-group">
<div class="group-controls">
<label class="checkbox" for="lazyload">
<input type="checkbox" name="lazyload" id="lazyload" value="1"<?php echo $this->conf->lazyload ? ' checked="checked"' : ''; ?> />
<?php echo Minz_Translate::t ('img_with_lazyload'); ?>
<noscript><strong><?php echo Minz_Translate::t ('javascript_should_be_activated'); ?></strong></noscript>
</label>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="group-controls"> <div class="group-controls">
<label class="checkbox" for="reading_confirm"> <label class="checkbox" for="reading_confirm">

View file

@ -1,18 +1,9 @@
<div class="post"> <div class="post">
<div class="alert alert-error"> <div class="alert alert-error">
<h1 class="alert-head"><?php echo $this->code; ?></h1> <h1 class="alert-head"><?php echo $this->code; ?></h1>
<p> <p>
<?php <?php echo $this->errorMessage; ?><br />
switch(Minz_Request::param ('code')) { <a href="<?php echo _url('index', 'index'); ?>"><?php echo Minz_Translate::t('back_to_rss_feeds'); ?></a>
case 403:
echo Minz_Translate::t ('forbidden_access');
break;
case 404:
default:
echo Minz_Translate::t ('page_not_found');
} ?><br />
<a href="<?php echo _url ('index', 'index'); ?>"><?php echo Minz_Translate::t ('back_to_rss_feeds'); ?></a>
</p> </p>
</div> </div>
</div> </div>

View file

@ -18,9 +18,9 @@ foreach ($this->categories as $key => $cat) {
$opml_array['body'][$key]['@outlines'][] = array( $opml_array['body'][$key]['@outlines'][] = array(
'text' => htmlspecialchars_decode($feed->name()), 'text' => htmlspecialchars_decode($feed->name()),
'type' => 'rss', 'type' => 'rss',
'xmlUrl' => $feed->url(), 'xmlUrl' => htmlspecialchars_decode($feed->url()),
'htmlUrl' => $feed->website(), 'htmlUrl' => htmlspecialchars_decode($feed->website()),
'description' => $feed->description() 'description' => htmlspecialchars_decode($feed->description()),
); );
} }
} }

View file

@ -10,7 +10,6 @@ echo 'var ',
',auto_mark_site=', $mark['site'] ? 'true' : 'false', ',auto_mark_site=', $mark['site'] ? 'true' : 'false',
',auto_mark_scroll=', $mark['scroll'] ? 'true' : 'false', ',auto_mark_scroll=', $mark['scroll'] ? 'true' : 'false',
',auto_load_more=', $this->conf->auto_load_more ? 'true' : 'false', ',auto_load_more=', $this->conf->auto_load_more ? 'true' : 'false',
',full_lazyload=', $this->conf->lazyload && ($this->conf->display_posts || Minz_Request::param('output') === 'reader') ? 'true' : 'false',
',does_lazyload=', $this->conf->lazyload ? 'true' : 'false', ',does_lazyload=', $this->conf->lazyload ? 'true' : 'false',
',sticky_post=', $this->conf->sticky_post ? 'true' : 'false'; ',sticky_post=', $this->conf->sticky_post ? 'true' : 'false';
@ -50,6 +49,8 @@ echo 'authType="', $authType, '",',
'url_logout="', _url ('index', 'logout'), '",'; 'url_logout="', _url ('index', 'logout'), '",';
echo 'str_confirmation="', Minz_Translate::t('confirm_action'), '"', ",\n"; echo 'str_confirmation="', Minz_Translate::t('confirm_action'), '"', ",\n";
echo 'str_notif_title_articles="', Minz_Translate::t('notif_title_new_articles'), '"', ",\n";
echo 'str_notif_body_articles="', Minz_Translate::t('notif_body_new_articles'), '"', ",\n";
$autoActualise = Minz_Session::param('actualize_feeds', false); $autoActualise = Minz_Session::param('actualize_feeds', false);
echo 'auto_actualize_feeds=', $autoActualise ? 'true' : 'false', ";\n"; echo 'auto_actualize_feeds=', $autoActualise ? 'true' : 'false', ";\n";

View file

@ -14,7 +14,7 @@
<?php } elseif ($markReadUrl) { ?> <?php } elseif ($markReadUrl) { ?>
<a id="bigMarkAsRead" href="<?php echo $markReadUrl; ?>"<?php if ($this->conf->reading_confirm) { echo ' class="confirm"';} ?>> <a id="bigMarkAsRead" href="<?php echo $markReadUrl; ?>"<?php if ($this->conf->reading_confirm) { echo ' class="confirm"';} ?>>
<?php echo Minz_Translate::t ('nothing_to_load'); ?><br /> <?php echo Minz_Translate::t ('nothing_to_load'); ?><br />
<span class="bigTick"></span><br /> <span class="bigTick"></span><br />
<?php echo Minz_Translate::t ('mark_all_read'); ?> <?php echo Minz_Translate::t ('mark_all_read'); ?>
</a> </a>
<?php } else { ?> <?php } else { ?>

View file

@ -81,7 +81,12 @@ if (!empty($this->entries)) {
} }
} }
$feed = FreshRSS_CategoryDAO::findFeed($this->cat_aside, $item->feed ()); //We most likely already have the feed object in cache $feed = FreshRSS_CategoryDAO::findFeed($this->cat_aside, $item->feed ()); //We most likely already have the feed object in cache
if (empty($feed)) $feed = $item->feed (true); if ($feed == null) {
$feed = $item->feed(true);
if ($feed == null) {
$feed = FreshRSS_Feed::example();
}
}
?><li class="item website"><a href="<?php echo _url ('index', 'index', 'get', 'f_' . $feed->id ()); ?>"><img class="favicon" src="<?php echo $feed->favicon (); ?>" alt="✇" /> <span><?php echo $feed->name(); ?></span></a></li> ?><li class="item website"><a href="<?php echo _url ('index', 'index', 'get', 'f_' . $feed->id ()); ?>"><img class="favicon" src="<?php echo $feed->favicon (); ?>" alt="✇" /> <span><?php echo $feed->name(); ?></span></a></li>
<li class="item title"><a target="_blank" href="<?php echo $item->link (); ?>"><?php echo $item->title (); ?></a></li> <li class="item title"><a target="_blank" href="<?php echo $item->link (); ?>"><?php echo $item->title (); ?></a></li>
<?php if ($topline_date) { ?><li class="item date"><?php echo $item->date (); ?> </li><?php } ?> <?php if ($topline_date) { ?><li class="item date"><?php echo $item->date (); ?> </li><?php } ?>
@ -92,13 +97,9 @@ if (!empty($this->entries)) {
<div class="content <?php echo $content_width; ?>"> <div class="content <?php echo $content_width; ?>">
<h1 class="title"><a target="_blank" href="<?php echo $item->link (); ?>"><?php echo $item->title (); ?></a></h1> <h1 class="title"><a target="_blank" href="<?php echo $item->link (); ?>"><?php echo $item->title (); ?></a></h1>
<?php <?php
$author = $item->author (); $author = $item->author();
echo $author != '' ? '<div class="author">' . Minz_Translate::t ('by_author', $author) . '</div>' : ''; echo $author != '' ? '<div class="author">' . Minz_Translate::t('by_author', $author) . '</div>' : '',
if ($lazyload) { $lazyload && $hidePosts ? lazyimg($item->content()) : $item->content();
echo $hidePosts ? lazyIframe(lazyimg($item->content())) : lazyimg($item->content());
} else {
echo $item->content();
}
?> ?>
</div> </div>
<ul class="horizontal-list bottom"><?php <ul class="horizontal-list bottom"><?php

View file

@ -21,19 +21,13 @@ if (!empty($this->entries)) {
</a> </a>
<h1 class="title"><?php echo $item->title (); ?></h1> <h1 class="title"><?php echo $item->title (); ?></h1>
<div class="author"> <div class="author"><?php
<?php $author = $item->author (); ?> $author = $item->author();
<?php echo $author != '' ? Minz_Translate::t ('by_author', $author) . ' — ' : ''; ?> echo $author != '' ? Minz_Translate::t('by_author', $author) . ' — ' : '',
<?php echo $item->date (); ?> $item->date();
</div> ?></div>
<?php <?php echo $item->content(); ?>
if ($lazyload) {
echo lazyimg($item->content ());
} else {
echo $item->content();
}
?>
</div> </div>
</div> </div>
</div> </div>

View file

View file

@ -1,12 +1,14 @@
<?php $this->partial ('aside_feed'); ?> <?php $this->partial('aside_feed'); ?>
<div class="post "> <div class="post ">
<a href="<?php echo _url ('index', 'index'); ?>"><?php echo Minz_Translate::t ('back_to_rss_feeds'); ?></a> <a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
<form method="post" action="<?php echo _url('importExport', 'import'); ?>" enctype="multipart/form-data"> <form method="post" action="<?php echo _url('importExport', 'import'); ?>" enctype="multipart/form-data">
<legend><?php echo Minz_Translate::t ('import'); ?></legend> <legend><?php echo _t('import'); ?></legend>
<div class="form-group"> <div class="form-group">
<label class="group-name" for="file"><?php echo Minz_Translate::t ('file_to_import'); ?></label> <label class="group-name" for="file">
<?php echo extension_loaded('zip') ? _t('file_to_import') : _t('file_to_import_no_zip'); ?>
</label>
<div class="group-controls"> <div class="group-controls">
<input type="file" name="file" id="file" /> <input type="file" name="file" id="file" />
</div> </div>
@ -14,27 +16,34 @@
<div class="form-group form-actions"> <div class="form-group form-actions">
<div class="group-controls"> <div class="group-controls">
<button type="submit" class="btn btn-important"><?php echo Minz_Translate::t ('import'); ?></button> <button type="submit" class="btn btn-important"><?php echo _t('import'); ?></button>
</div> </div>
</div> </div>
</form> </form>
<?php if (count($this->feeds) > 0) { ?> <?php if (count($this->feeds) > 0) { ?>
<form method="post" action="<?php echo _url('importExport', 'export'); ?>"> <form method="post" action="<?php echo _url('importExport', 'export'); ?>">
<legend><?php echo Minz_Translate::t ('export'); ?></legend> <legend><?php echo _t('export'); ?></legend>
<div class="form-group"> <div class="form-group">
<div class="group-controls"> <div class="group-controls">
<label class="checkbox" for="export_opml"> <label class="checkbox" for="export_opml">
<input type="checkbox" name="export_opml" id="export_opml" value="1" checked="checked" /> <input type="checkbox" name="export_opml" id="export_opml" value="1" checked="checked" />
<?php echo Minz_Translate::t ('export_opml'); ?> <?php echo _t('export_opml'); ?>
</label> </label>
<label class="checkbox" for="export_starred"> <label class="checkbox" for="export_starred">
<input type="checkbox" name="export_starred" id="export_starred" value="1" checked="checked" /> <input type="checkbox" name="export_starred" id="export_starred" value="1" <?php echo extension_loaded('zip') ? 'checked="checked"' : ''; ?> />
<?php echo Minz_Translate::t ('export_starred'); ?> <?php echo _t('export_starred'); ?>
</label> </label>
<select name="export_feeds[]" size="<?php echo min(10, count($this->feeds)); ?>" multiple="multiple"> <?php
$select_args = '';
if (extension_loaded('zip')) {
$select_args = ' size="' . min(10, count($this->feeds)) .'" multiple="multiple"';
}
?>
<select name="export_feeds[]"<?php echo $select_args; ?>>
<?php echo extension_loaded('zip') ? '' : '<option></option>'; ?>
<?php foreach ($this->feeds as $feed) { ?> <?php foreach ($this->feeds as $feed) { ?>
<option value="<?php echo $feed->id(); ?>"><?php echo $feed->name(); ?></option> <option value="<?php echo $feed->id(); ?>"><?php echo $feed->name(); ?></option>
<?php } ?> <?php } ?>
@ -44,7 +53,7 @@
<div class="form-group form-actions"> <div class="form-group form-actions">
<div class="group-controls"> <div class="group-controls">
<button type="submit" class="btn btn-important"><?php echo Minz_Translate::t ('export'); ?></button> <button type="submit" class="btn btn-important"><?php echo _t('export'); ?></button>
</div> </div>
</div> </div>
</form> </form>

View file

@ -1,32 +1,39 @@
<div class="prompt"> <div class="prompt">
<h1><?php echo Minz_Translate::t('login'); ?></h1><?php <h1><?php echo _t('login'); ?></h1><?php
switch (Minz_Configuration::authType()) { switch (Minz_Configuration::authType()) {
case 'form': case 'form':
?><form id="loginForm" method="post" action="<?php echo _url('index', 'formLogin'); ?>"> ?><form id="loginForm" method="post" action="<?php echo _url('index', 'formLogin'); ?>">
<div> <div>
<label for="username"><?php echo Minz_Translate::t('username'); ?></label> <label for="username"><?php echo _t('username'); ?></label>
<input type="text" id="username" name="username" size="16" required="required" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" autofocus="autofocus" /> <input type="text" id="username" name="username" size="16" required="required" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" autofocus="autofocus" />
</div> </div>
<div> <div>
<label for="passwordPlain"><?php echo Minz_Translate::t('password'); ?></label> <label for="passwordPlain"><?php echo _t('password'); ?></label>
<input type="password" id="passwordPlain" required="required" /> <input type="password" id="passwordPlain" required="required" />
<input type="hidden" id="challenge" name="challenge" /><br /> <input type="hidden" id="challenge" name="challenge" /><br />
<noscript><strong><?php echo Minz_Translate::t('javascript_should_be_activated'); ?></strong></noscript> <noscript><strong><?php echo _t('javascript_should_be_activated'); ?></strong></noscript>
</div> </div>
<div> <div>
<button id="loginButton" type="submit" class="btn btn-important"><?php echo Minz_Translate::t('login'); ?></button> <label class="checkbox" for="keep_logged_in">
<input type="checkbox" name="keep_logged_in" id="keep_logged_in" value="1" />
<?php echo _t('keep_logged_in'); ?>
</label>
<br />
</div>
<div>
<button id="loginButton" type="submit" class="btn btn-important"><?php echo _t('login'); ?></button>
</div> </div>
</form><?php </form><?php
break; break;
case 'persona': case 'persona':
?><p> ?><p>
<?php echo FreshRSS_Themes::icon('login'); ?> <?php echo _i('login'); ?>
<a class="signin" href="#"><?php echo Minz_Translate::t('login_with_persona'); ?></a> <a class="signin" href="#"><?php echo _t('login_with_persona'); ?></a>
</p><?php </p><?php
break; break;
} ?> } ?>
<p><a href="<?php echo _url('index', 'about'); ?>"><?php echo Minz_Translate::t('about_freshrss'); ?></a></p> <p><a href="<?php echo _url('index', 'about'); ?>"><?php echo _t('about_freshrss'); ?></a></p>
</div> </div>

View file

@ -1,25 +1,24 @@
"use strict"; "use strict";
var feeds = [<?php var feeds = [<?php foreach ($this->feeds as $feed) { ?>{<?php
foreach ($this->feeds as $feed) { ?>url: "<?php echo Minz_Url::display(array('c' => 'feed', 'a' => 'actualize', 'params' => array('id' => $feed->id(), 'ajax' => '1')), 'php'); ?>",<?php
echo "'", Minz_Url::display(array('c' => 'feed', 'a' => 'actualize', 'params' => array('id' => $feed->id(), 'ajax' => '1')), 'php'), "',\n"; ?>title: "<?php echo $feed->name(); ?>"<?php
} ?>},<?php } ?>],
?>],
feed_processed = 0, feed_processed = 0,
feed_count = feeds.length; feed_count = feeds.length;
function initProgressBar(init) { function initProgressBar(init) {
if (init) { if (init) {
$("body").after("\<div id=\"actualizeProgress\" class=\"notification good\">\ $("body").after("\<div id=\"actualizeProgress\" class=\"notification good\">\
<?php echo _t('refresh'); ?> <span class=\"progress\">0 / " + feed_count + "</span><br />\ <?php echo _t('refresh'); ?><br /><span class=\"title\">/</span><br />\
<progress id=\"actualizeProgressBar\" value=\"0\" max=\"" + feed_count + "\"></progress>\ <span class=\"progress\">0 / " + feed_count + "</span>\
</div>"); </div>");
} else { } else {
window.location.reload(); window.location.reload();
} }
} }
function updateProgressBar(i) { function updateProgressBar(i, title_feed) {
$("#actualizeProgressBar").val(i);
$("#actualizeProgress .progress").html(i + " / " + feed_count); $("#actualizeProgress .progress").html(i + " / " + feed_count);
$("#actualizeProgress .title").html(title_feed);
} }
function updateFeeds() { function updateFeeds() {
@ -43,10 +42,10 @@ function updateFeed() {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: feed, url: feed['url'],
}).complete(function (data) { }).complete(function (data) {
feed_processed++; feed_processed++;
updateProgressBar(feed_processed); updateProgressBar(feed_processed, feed['title']);
if (feed_processed === feed_count) { if (feed_processed === feed_count) {
initProgressBar(false); initProgressBar(false);

View file

@ -1,19 +1,25 @@
<?php $this->partial('aside_stats'); ?> <?php $this->partial('aside_stats'); ?>
<div class="post content"> <div class="post content">
<a href="<?php echo _url ('index', 'index'); ?>"><?php echo _t ('back_to_rss_feeds'); ?></a> <a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
<h1><?php echo _t ('stats_idle'); ?></h1> <h1><?php echo _t('stats_idle'); ?></h1>
<?php foreach ($this->idleFeeds as $period => $feeds){ ?> <?php
foreach ($this->idleFeeds as $period => $feeds) {
if (!empty($feeds)) {
?>
<div class="stat"> <div class="stat">
<h2><?php echo _t ($period); ?></h2> <h2><?php echo _t($period); ?></h2>
<ul> <ul>
<?php foreach ($feeds as $feed){ ?> <?php foreach ($feeds as $feed) { ?>
<li><?php echo $feed; ?></li> <li><a href="<?php echo _url('configure', 'feed', 'id', $feed['id']); ?>" title="<?php echo date('Y-m-d', $feed['last_date']); ?>"><?php echo $feed['name']; ?></a></li>
<?php } ?> <?php } ?>
</ul> </ul>
</div> </div>
<?php } ?> <?php
}
}
?>
</div> </div>

View file

@ -1,127 +0,0 @@
<?php $this->partial('aside_stats'); ?>
<div class="post content">
<a href="<?php echo _url ('index', 'index'); ?>"><?php echo Minz_Translate::t ('back_to_rss_feeds'); ?></a>
<h1><?php echo Minz_Translate::t ('stats_main'); ?></h1>
<div class="stat">
<h2><?php echo Minz_Translate::t ('stats_entry_repartition'); ?></h2>
<table>
<thead>
<tr>
<th> </th>
<th><?php echo Minz_Translate::t ('main_stream'); ?></th>
<th><?php echo Minz_Translate::t ('all_feeds'); ?></th>
</tr>
</thead>
<tbody>
<tr>
<th><?php echo Minz_Translate::t ('status_total'); ?></th>
<td class="numeric"><?php echo formatNumber($this->repartition['main_stream']['total']); ?></td>
<td class="numeric"><?php echo formatNumber($this->repartition['all_feeds']['total']); ?></td>
</tr>
<tr>
<th><?php echo Minz_Translate::t ('status_read'); ?></th>
<td class="numeric"><?php echo formatNumber($this->repartition['main_stream']['read']); ?></td>
<td class="numeric"><?php echo formatNumber($this->repartition['all_feeds']['read']); ?></td>
</tr>
<tr>
<th><?php echo Minz_Translate::t ('status_unread'); ?></th>
<td class="numeric"><?php echo formatNumber($this->repartition['main_stream']['unread']); ?></td>
<td class="numeric"><?php echo formatNumber($this->repartition['all_feeds']['unread']); ?></td>
</tr>
<tr>
<th><?php echo Minz_Translate::t ('status_favorites'); ?></th>
<td class="numeric"><?php echo formatNumber($this->repartition['main_stream']['favorite']); ?></td>
<td class="numeric"><?php echo formatNumber($this->repartition['all_feeds']['favorite']); ?></td>
</tr>
</tbody>
</table>
</div>
<div class="stat">
<h2><?php echo Minz_Translate::t ('stats_entry_per_day'); ?></h2>
<div id="statsEntryPerDay" style="height: 300px"></div>
</div>
<div class="stat">
<h2><?php echo Minz_Translate::t ('stats_feed_per_category'); ?></h2>
<div id="statsFeedPerCategory" style="height: 300px"></div>
<div id="statsFeedPerCategoryLegend"></div>
</div>
<div class="stat">
<h2><?php echo Minz_Translate::t ('stats_entry_per_category'); ?></h2>
<div id="statsEntryPerCategory" style="height: 300px"></div>
<div id="statsEntryPerCategoryLegend"></div>
</div>
<div class="stat">
<h2><?php echo Minz_Translate::t ('stats_top_feed'); ?></h2>
<table>
<thead>
<tr>
<th><?php echo Minz_Translate::t ('feed'); ?></th>
<th><?php echo Minz_Translate::t ('category'); ?></th>
<th><?php echo Minz_Translate::t ('stats_entry_count'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($this->topFeed as $feed): ?>
<tr>
<td><?php echo $feed['name']; ?></td>
<td><?php echo $feed['category']; ?></td>
<td class="numeric"><?php echo formatNumber($feed['count']); ?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
</div>
<script>
"use strict";
function initStats() {
if (!window.Flotr) {
if (window.console) {
console.log('FreshRSS waiting for Flotr…');
}
window.setTimeout(initStats, 50);
return;
}
// Entry per day
Flotr.draw(document.getElementById('statsEntryPerDay'),
[<?php echo $this->count ?>],
{
grid: {verticalLines: false},
bars: {horizontal: false, show: true},
xaxis: {noTicks: 6, showLabels: false, tickDecimals: 0},
yaxis: {min: 0},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Feed per category
Flotr.draw(document.getElementById('statsFeedPerCategory'),
<?php echo $this->feedByCategory ?>,
{
grid: {verticalLines: false, horizontalLines: false},
pie: {explode: 10, show: true, labelFormatter: function(){return '';}},
xaxis: {showLabels: false},
yaxis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return obj.series.label + ' - '+ numberFormat(obj.y) + ' ('+ (obj.fraction * 100).toFixed(1) + '%)';}},
legend: {container: document.getElementById('statsFeedPerCategoryLegend'), noColumns: 3}
});
// Entry per category
Flotr.draw(document.getElementById('statsEntryPerCategory'),
<?php echo $this->entryByCategory ?>,
{
grid: {verticalLines: false, horizontalLines: false},
pie: {explode: 10, show: true, labelFormatter: function(){return '';}},
xaxis: {showLabels: false},
yaxis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return obj.series.label + ' - '+ numberFormat(obj.y) + ' ('+ (obj.fraction * 100).toFixed(1) + '%)';}},
legend: {container: document.getElementById('statsEntryPerCategoryLegend'), noColumns: 3}
});
}
initStats();
</script>

View file

@ -0,0 +1,114 @@
<?php $this->partial('aside_stats'); ?>
<div class="post content">
<a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
<h1><?php echo _t('stats_repartition'); ?></h1>
<select id="feed_select">
<option data-url="<?php echo _url('stats', 'repartition')?>"><?php echo _t('all_feeds')?></option>
<?php foreach ($this->categories as $category) {
$feeds = $category->feeds();
if (!empty($feeds)) {
echo '<optgroup label=', $category->name(), '>';
foreach ($feeds as $feed) {
if ($this->feed && $feed->id() == $this->feed->id()){
echo '<option value ="', $feed->id(), '" selected data-url="', _url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
} else {
echo '<option value ="', $feed->id(), '" data-url="', _url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
}
}
echo '</optgroup>';
}
}?>
</select>
<?php if ($this->feed) {?>
<a href="<?php echo _url('configure', 'feed', 'id', $this->feed->id()); ?>">
<?php echo _t('administration'); ?>
</a>
<?php }?>
<div class="stat">
<h2><?php echo _t('stats_entry_per_hour'); ?></h2>
<div id="statsEntryPerHour" style="height: 300px"></div>
</div>
<div class="stat">
<h2><?php echo _t('stats_entry_per_day_of_week'); ?></h2>
<div id="statsEntryPerDayOfWeek" style="height: 300px"></div>
</div>
<div class="stat">
<h2><?php echo _t('stats_entry_per_month'); ?></h2>
<div id="statsEntryPerMonth" style="height: 300px"></div>
</div>
</div>
<script>
"use strict";
function initStats() {
if (!window.Flotr) {
if (window.console) {
console.log('FreshRSS waiting for Flotr…');
}
window.setTimeout(initStats, 50);
return;
}
// Entry per hour
Flotr.draw(document.getElementById('statsEntryPerHour'),
[<?php echo $this->repartitionHour ?>],
{
grid: {verticalLines: false},
bars: {horizontal: false, show: true},
xaxis: {noTicks: 23,
tickFormatter: function(x) {
var x = parseInt(x);
return x + 1;
},
min: -0.9,
max: 23.9,
tickDecimals: 0},
yaxis: {min: 0},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Entry per day of week
Flotr.draw(document.getElementById('statsEntryPerDayOfWeek'),
[<?php echo $this->repartitionDayOfWeek ?>],
{
grid: {verticalLines: false},
bars: {horizontal: false, show: true},
xaxis: {noTicks: 6,
tickFormatter: function(x) {
var x = parseInt(x),
days = <?php echo $this->days?>;
return days[x];
},
min: -0.9,
max: 6.9,
tickDecimals: 0},
yaxis: {min: 0},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Entry per month
Flotr.draw(document.getElementById('statsEntryPerMonth'),
[<?php echo $this->repartitionMonth ?>],
{
grid: {verticalLines: false},
bars: {horizontal: false, show: true},
xaxis: {noTicks: 12,
tickFormatter: function(x) {
var x = parseInt(x),
months = <?php echo $this->months?>;
return months[(x - 1)];
},
min: 0.1,
max: 12.9,
tickDecimals: 0},
yaxis: {min: 0},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
}
initStats();
</script>

View file

@ -1,5 +1,5 @@
<?php <?php
define('FRESHRSS_VERSION', '0.7.3'); define('FRESHRSS_VERSION', '0.7.4');
define('FRESHRSS_WEBSITE', 'http://freshrss.org'); define('FRESHRSS_WEBSITE', 'http://freshrss.org');
// PHP text output compression http://php.net/ob_gzhandler (better to do it at Web server level) // PHP text output compression http://php.net/ob_gzhandler (better to do it at Web server level)

1
sources/data/tokens/.gitignore vendored Executable file
View file

@ -0,0 +1 @@
*.txt

13
sources/data/tokens/index.html Executable file
View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Refresh" content="0; url=/" />
<title>Redirection</title>
<meta name="robots" content="noindex" />
</head>
<body>
<p><a href="/">Redirection</a></p>
</body>
</html>

View file

@ -12,11 +12,22 @@ class Minz_Helper {
* Annule les effets des magic_quotes pour une variable donnée * Annule les effets des magic_quotes pour une variable donnée
* @param $var variable à traiter (tableau ou simple variable) * @param $var variable à traiter (tableau ou simple variable)
*/ */
public static function stripslashes_r ($var) { public static function stripslashes_r($var) {
if (is_array ($var)){ if (is_array($var)){
return array_map (array ('Helper', 'stripslashes_r'), $var); return array_map(array('Minz_Helper', 'stripslashes_r'), $var);
} else { } else {
return stripslashes($var); return stripslashes($var);
} }
} }
/**
* Wrapper for htmlspecialchars.
* Force UTf-8 value and can be used on array too.
*/
public static function htmlspecialchars_utf8($var) {
if (is_array($var)) {
return array_map(array('Minz_Helper', 'htmlspecialchars_utf8'), $var);
}
return htmlspecialchars($var, ENT_COMPAT, 'UTF-8');
}
} }

View file

@ -33,8 +33,8 @@ class Minz_ModelPdo {
* Créé la connexion à la base de données à l'aide des variables * Créé la connexion à la base de données à l'aide des variables
* HOST, BASE, USER et PASS définies dans le fichier de configuration * HOST, BASE, USER et PASS définies dans le fichier de configuration
*/ */
public function __construct() { public function __construct($currentUser = null) {
if (self::$useSharedBd && self::$sharedBd != null) { if (self::$useSharedBd && self::$sharedBd != null && $currentUser === null) {
$this->bd = self::$sharedBd; $this->bd = self::$sharedBd;
$this->prefix = self::$sharedPrefix; $this->prefix = self::$sharedPrefix;
return; return;
@ -42,6 +42,10 @@ class Minz_ModelPdo {
$db = Minz_Configuration::dataBase(); $db = Minz_Configuration::dataBase();
if ($currentUser === null) {
$currentUser = Minz_Session::param('currentUser', '_');
}
try { try {
$type = $db['type']; $type = $db['type'];
if ($type === 'mysql') { if ($type === 'mysql') {
@ -51,9 +55,9 @@ class Minz_ModelPdo {
$driver_options = array( $driver_options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
); );
$this->prefix = $db['prefix'] . Minz_Session::param('currentUser', '_') . '_'; $this->prefix = $db['prefix'] . $currentUser . '_';
} elseif ($type === 'sqlite') { } elseif ($type === 'sqlite') {
$string = 'sqlite:' . DATA_PATH . '/' . Minz_Session::param('currentUser', '_') . '.sqlite'; $string = 'sqlite:' . DATA_PATH . '/' . $currentUser . '.sqlite';
$driver_options = array( $driver_options = array(
//PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
); );
@ -67,7 +71,7 @@ class Minz_ModelPdo {
self::$sharedDbType = $type; self::$sharedDbType = $type;
self::$sharedPrefix = $this->prefix; self::$sharedPrefix = $this->prefix;
$this->bd = new FreshPDO( $this->bd = new MinzPDO(
$string, $string,
$db['user'], $db['user'],
$db['password'], $db['password'],
@ -98,7 +102,7 @@ class Minz_ModelPdo {
} }
} }
class FreshPDO extends PDO { class MinzPDO extends PDO {
private static function check($statement) { private static function check($statement) {
if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) {
invalidateHttpCache(); invalidateHttpCache();
@ -106,12 +110,12 @@ class FreshPDO extends PDO {
} }
public function prepare($statement, $driver_options = array()) { public function prepare($statement, $driver_options = array()) {
FreshPDO::check($statement); MinzPDO::check($statement);
return parent::prepare($statement, $driver_options); return parent::prepare($statement, $driver_options);
} }
public function exec($statement) { public function exec($statement) {
FreshPDO::check($statement); MinzPDO::check($statement);
return parent::exec($statement); return parent::exec($statement);
} }
} }

View file

@ -10,7 +10,7 @@
class Minz_Request { class Minz_Request {
private static $controller_name = ''; private static $controller_name = '';
private static $action_name = ''; private static $action_name = '';
private static $params = array (); private static $params = array();
private static $default_controller_name = 'index'; private static $default_controller_name = 'index';
private static $default_action_name = 'index'; private static $default_action_name = 'index';
@ -18,59 +18,53 @@ class Minz_Request {
/** /**
* Getteurs * Getteurs
*/ */
public static function controllerName () { public static function controllerName() {
return self::$controller_name; return self::$controller_name;
} }
public static function actionName () { public static function actionName() {
return self::$action_name; return self::$action_name;
} }
public static function params () { public static function params() {
return self::$params; return self::$params;
} }
static function htmlspecialchars_utf8 ($p) { public static function param($key, $default = false, $specialchars = false) {
if (is_array($p)) { if (isset(self::$params[$key])) {
return array_map('self::htmlspecialchars_utf8', $p);
}
return htmlspecialchars($p, ENT_COMPAT, 'UTF-8');
}
public static function param ($key, $default = false, $specialchars = false) {
if (isset (self::$params[$key])) {
$p = self::$params[$key]; $p = self::$params[$key];
if(is_object($p) || $specialchars) { if (is_object($p) || $specialchars) {
return $p; return $p;
} else { } else {
return self::htmlspecialchars_utf8($p); return Minz_Helper::htmlspecialchars_utf8($p);
} }
} else { } else {
return $default; return $default;
} }
} }
public static function defaultControllerName () { public static function defaultControllerName() {
return self::$default_controller_name; return self::$default_controller_name;
} }
public static function defaultActionName () { public static function defaultActionName() {
return self::$default_action_name; return self::$default_action_name;
} }
/** /**
* Setteurs * Setteurs
*/ */
public static function _controllerName ($controller_name) { public static function _controllerName($controller_name) {
self::$controller_name = $controller_name; self::$controller_name = $controller_name;
} }
public static function _actionName ($action_name) { public static function _actionName($action_name) {
self::$action_name = $action_name; self::$action_name = $action_name;
} }
public static function _params ($params) { public static function _params($params) {
if (!is_array($params)) { if (!is_array($params)) {
$params = array ($params); $params = array($params);
} }
self::$params = $params; self::$params = $params;
} }
public static function _param ($key, $value = false) { public static function _param($key, $value = false) {
if ($value === false) { if ($value === false) {
unset (self::$params[$key]); unset(self::$params[$key]);
} else { } else {
self::$params[$key] = $value; self::$params[$key] = $value;
} }
@ -79,14 +73,14 @@ class Minz_Request {
/** /**
* Initialise la Request * Initialise la Request
*/ */
public static function init () { public static function init() {
self::magicQuotesOff (); self::magicQuotesOff();
} }
/** /**
* Retourn le nom de domaine du site * Retourn le nom de domaine du site
*/ */
public static function getDomainName () { public static function getDomainName() {
return $_SERVER['HTTP_HOST']; return $_SERVER['HTTP_HOST'];
} }
@ -94,7 +88,7 @@ class Minz_Request {
* Détermine la base de l'url * Détermine la base de l'url
* @return la base de l'url * @return la base de l'url
*/ */
public static function getBaseUrl () { public static function getBaseUrl() {
$defaultBaseUrl = Minz_Configuration::baseUrl(); $defaultBaseUrl = Minz_Configuration::baseUrl();
if (!empty($defaultBaseUrl)) { if (!empty($defaultBaseUrl)) {
return $defaultBaseUrl; return $defaultBaseUrl;
@ -109,13 +103,13 @@ class Minz_Request {
* Récupère l'URI de la requête * Récupère l'URI de la requête
* @return l'URI * @return l'URI
*/ */
public static function getURI () { public static function getURI() {
if (isset ($_SERVER['REQUEST_URI'])) { if (isset($_SERVER['REQUEST_URI'])) {
$base_url = self::getBaseUrl (); $base_url = self::getBaseUrl();
$uri = $_SERVER['REQUEST_URI']; $uri = $_SERVER['REQUEST_URI'];
$len_base_url = strlen ($base_url); $len_base_url = strlen($base_url);
$real_uri = substr ($uri, $len_base_url); $real_uri = substr($uri, $len_base_url);
} else { } else {
$real_uri = ''; $real_uri = '';
} }
@ -129,16 +123,16 @@ class Minz_Request {
* @param $redirect si vrai, force la redirection http * @param $redirect si vrai, force la redirection http
* > sinon, le dispatcher recharge en interne * > sinon, le dispatcher recharge en interne
*/ */
public static function forward ($url = array (), $redirect = false) { public static function forward($url = array(), $redirect = false) {
$url = Minz_Url::checkUrl ($url); $url = Minz_Url::checkUrl($url);
if ($redirect) { if ($redirect) {
header ('Location: ' . Minz_Url::display ($url, 'php')); header('Location: ' . Minz_Url::display($url, 'php'));
exit (); exit();
} else { } else {
self::_controllerName ($url['c']); self::_controllerName($url['c']);
self::_actionName ($url['a']); self::_actionName($url['a']);
self::_params (array_merge ( self::_params(array_merge(
self::$params, self::$params,
$url['params'] $url['params']
)); ));
@ -146,6 +140,31 @@ class Minz_Request {
} }
} }
/**
* Wrappers good notifications + redirection
* @param $msg notification content
* @param $url url array to where we should be forwarded
*/
public static function good($msg, $url = array()) {
Minz_Session::_param('notification', array(
'type' => 'good',
'content' => $msg
));
Minz_Request::forward($url, true);
}
public static function bad($msg, $url = array()) {
Minz_Session::_param('notification', array(
'type' => 'bad',
'content' => $msg
));
Minz_Request::forward($url, true);
}
/** /**
* Permet de récupérer une variable de type $_GET * Permet de récupérer une variable de type $_GET
* @param $param nom de la variable * @param $param nom de la variable
@ -154,10 +173,10 @@ class Minz_Request {
* $_GET si $param = false * $_GET si $param = false
* $default si $_GET[$param] n'existe pas * $default si $_GET[$param] n'existe pas
*/ */
public static function fetchGET ($param = false, $default = false) { public static function fetchGET($param = false, $default = false) {
if ($param === false) { if ($param === false) {
return $_GET; return $_GET;
} elseif (isset ($_GET[$param])) { } elseif (isset($_GET[$param])) {
return $_GET[$param]; return $_GET[$param];
} else { } else {
return $default; return $default;
@ -172,10 +191,10 @@ class Minz_Request {
* $_POST si $param = false * $_POST si $param = false
* $default si $_POST[$param] n'existe pas * $default si $_POST[$param] n'existe pas
*/ */
public static function fetchPOST ($param = false, $default = false) { public static function fetchPOST($param = false, $default = false) {
if ($param === false) { if ($param === false) {
return $_POST; return $_POST;
} elseif (isset ($_POST[$param])) { } elseif (isset($_POST[$param])) {
return $_POST[$param]; return $_POST[$param];
} else { } else {
return $default; return $default;
@ -188,15 +207,16 @@ class Minz_Request {
* $_POST * $_POST
* $_COOKIE * $_COOKIE
*/ */
private static function magicQuotesOff () { private static function magicQuotesOff() {
if (get_magic_quotes_gpc ()) { if (get_magic_quotes_gpc()) {
$_GET = Minz_Helper::stripslashes_r ($_GET); $_GET = Minz_Helper::stripslashes_r($_GET);
$_POST = Minz_Helper::stripslashes_r ($_POST); $_POST = Minz_Helper::stripslashes_r($_POST);
$_COOKIE = Minz_Helper::stripslashes_r ($_COOKIE); $_COOKIE = Minz_Helper::stripslashes_r($_COOKIE);
} }
} }
public static function isPost () { public static function isPost() {
return $_SERVER['REQUEST_METHOD'] === 'POST'; return isset($_SERVER['REQUEST_METHOD']) &&
$_SERVER['REQUEST_METHOD'] === 'POST';
} }
} }

View file

@ -2,28 +2,20 @@
/** /**
* La classe Session gère la session utilisateur * La classe Session gère la session utilisateur
* C'est un singleton
*/ */
class Minz_Session { class Minz_Session {
/**
* $session stocke les variables de session
*/
private static $session = array (); //TODO: Try to avoid having another local copy
/** /**
* Initialise la session, avec un nom * Initialise la session, avec un nom
* Le nom de session est utilisé comme nom pour les cookies et les URLs (i.e. PHPSESSID). * Le nom de session est utilisé comme nom pour les cookies et les URLs(i.e. PHPSESSID).
* Il ne doit contenir que des caractères alphanumériques ; il doit être court et descriptif * Il ne doit contenir que des caractères alphanumériques ; il doit être court et descriptif
*/ */
public static function init ($name) { public static function init($name) {
// démarre la session $cookie = session_get_cookie_params();
session_name ($name); self::keepCookie($cookie['lifetime']);
session_set_cookie_params (0, dirname(empty($_SERVER['REQUEST_URI']) ? '/' : dirname($_SERVER['REQUEST_URI'])), null, false, true);
session_start ();
if (isset ($_SESSION)) { // démarre la session
self::$session = $_SESSION; session_name($name);
} session_start();
} }
@ -32,8 +24,8 @@ class Minz_Session {
* @param $p le paramètre à récupérer * @param $p le paramètre à récupérer
* @return la valeur de la variable de session, false si n'existe pas * @return la valeur de la variable de session, false si n'existe pas
*/ */
public static function param ($p, $default = false) { public static function param($p, $default = false) {
return isset(self::$session[$p]) ? self::$session[$p] : $default; return isset($_SESSION[$p]) ? $_SESSION[$p] : $default;
} }
@ -42,13 +34,11 @@ class Minz_Session {
* @param $p le paramètre à créer ou modifier * @param $p le paramètre à créer ou modifier
* @param $v la valeur à attribuer, false pour supprimer * @param $v la valeur à attribuer, false pour supprimer
*/ */
public static function _param ($p, $v = false) { public static function _param($p, $v = false) {
if ($v === false) { if ($v === false) {
unset ($_SESSION[$p]); unset($_SESSION[$p]);
unset (self::$session[$p]);
} else { } else {
$_SESSION[$p] = $v; $_SESSION[$p] = $v;
self::$session[$p] = $v;
} }
} }
@ -57,15 +47,47 @@ class Minz_Session {
* Permet d'effacer une session * Permet d'effacer une session
* @param $force si à false, n'efface pas le paramètre de langue * @param $force si à false, n'efface pas le paramètre de langue
*/ */
public static function unset_session ($force = false) { public static function unset_session($force = false) {
$language = self::param ('language'); $language = self::param('language');
session_destroy(); session_destroy();
self::$session = array (); $_SESSION = array();
if (!$force) { if (!$force) {
self::_param ('language', $language); self::_param('language', $language);
Minz_Translate::reset (); Minz_Translate::reset();
} }
} }
/**
* Spécifie la durée de vie des cookies
* @param $l la durée de vie
*/
public static function keepCookie($l) {
$cookie_dir = empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI'];
session_set_cookie_params($l, $cookie_dir, '', false, true);
}
/**
* Régénère un id de session.
* Utile pour appeler session_set_cookie_params après session_start()
*/
public static function regenerateID() {
session_regenerate_id(true);
}
public static function deleteLongTermCookie($name) {
setcookie($name, '', 1, '', '', false, true);
}
public static function setLongTermCookie($name, $value, $expire) {
setcookie($name, $value, $expire, '', '', false, true);
}
public static function getLongTermCookie($name) {
return isset($_COOKIE[$name]) ? $_COOKIE[$name] : null;
}
} }

View file

@ -75,5 +75,5 @@ function _t($key) {
unset($args[0]); unset($args[0]);
array_unshift($args, $key); array_unshift($args, $key);
return call_user_func_array("Minz_Translate::t", $args); return call_user_func_array('Minz_Translate::t', $args);
} }

View file

@ -121,10 +121,10 @@ function customSimplePie() {
'onmouseover', 'onmousemove', 'onmouseout', 'onfocus', 'onblur', 'onmouseover', 'onmousemove', 'onmouseout', 'onfocus', 'onblur',
'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange', 'seamless'))); 'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange', 'seamless')));
$simplePie->add_attributes(array( $simplePie->add_attributes(array(
'img' => array('lazyload' => ''), //http://www.w3.org/TR/resource-priorities/ 'img' => array('lazyload' => '', 'postpone' => ''), //http://www.w3.org/TR/resource-priorities/
'audio' => array('preload' => 'none'), 'audio' => array('lazyload' => '', 'postpone' => '', 'preload' => 'none'),
'iframe' => array('postpone' => '', 'sandbox' => 'allow-scripts allow-same-origin'), 'iframe' => array('lazyload' => '', 'postpone' => '', 'sandbox' => 'allow-scripts allow-same-origin'),
'video' => array('postpone' => '', 'preload' => 'none'), 'video' => array('lazyload' => '', 'postpone' => '', 'preload' => 'none'),
)); ));
$simplePie->set_url_replacements(array( $simplePie->set_url_replacements(array(
'a' => 'href', 'a' => 'href',
@ -183,16 +183,8 @@ function get_content_by_parsing ($url, $path) {
*/ */
function lazyimg($content) { function lazyimg($content) {
return preg_replace( return preg_replace(
'/<img([^>]+?)src=[\'"]([^"\']+)[\'"]([^>]*)>/i', '/<((?:img|iframe)[^>]+?)src=[\'"]([^"\']+)[\'"]([^>]*)>/i',
'<img$1src="' . Minz_Url::display('/themes/icons/grey.gif') . '" data-original="$2"$3>', '<$1src="' . Minz_Url::display('/themes/icons/grey.gif') . '" data-original="$2"$3>',
$content
);
}
function lazyIframe($content) {
return preg_replace(
'/<iframe([^>]+?)src=[\'"]([^"\']+)[\'"]([^>]*)>/i',
'<iframe$1src="about:blank" data-original="$2"$3>',
$content $content
); );
} }
@ -238,7 +230,3 @@ function cryptAvailable() {
} }
return false; return false;
} }
function html_chars_utf8($str) {
return htmlspecialchars($str, ENT_COMPAT, 'UTF-8');
}

View file

@ -135,6 +135,7 @@ function checkCompatibility() {
} }
if ((!array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) && //Apache mod_rewrite trick should be fine if ((!array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) && //Apache mod_rewrite trick should be fine
(empty($_SERVER['SERVER_SOFTWARE']) || (stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') === false)) && //nginx should be fine (empty($_SERVER['SERVER_SOFTWARE']) || (stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') === false)) && //nginx should be fine
(empty($_SERVER['SERVER_SOFTWARE']) || (stripos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') === false)) && //lighttpd should be fine
((!function_exists('getallheaders')) || (stripos(php_sapi_name(), 'cgi') !== false))) { //Main problem is Apache/CGI mode ((!function_exists('getallheaders')) || (stripos(php_sapi_name(), 'cgi') !== false))) { //Main problem is Apache/CGI mode
die('FAIL getallheaders! (probably)'); die('FAIL getallheaders! (probably)');
} }

1
sources/p/i/.gitignore vendored Executable file
View file

@ -0,0 +1 @@
.htaccess

View file

@ -1,15 +0,0 @@
/*
* Lazy Load - jQuery plugin for lazy loading images
*
* Copyright (c) 2007-2013 Mika Tuupola
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* http://www.appelsiini.net/projects/lazyload
*
* Version: 1.9.0
*
*/
!function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("<img />").bind("load",function(){var d=c.data(j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.data(j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/iphone|ipod|ipad.*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document);

View file

@ -69,6 +69,10 @@ function incUnreadsFeed(article, feed_id, nb) {
feed_priority = elem ? str2int(elem.getAttribute('data-priority')) : 0; feed_priority = elem ? str2int(elem.getAttribute('data-priority')) : 0;
if (elem) { if (elem) {
elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); elem.setAttribute('data-unread', numberFormat(feed_unreads + nb));
elem = $(elem).closest('li').get(0);
if (elem) {
elem.setAttribute('data-unread', feed_unreads + nb);
}
} }
//Update unread: category //Update unread: category
@ -76,6 +80,10 @@ function incUnreadsFeed(article, feed_id, nb) {
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
if (elem) { if (elem) {
elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); elem.setAttribute('data-unread', numberFormat(feed_unreads + nb));
elem = $(elem).closest('li').get(0);
if (elem) {
elem.setAttribute('data-unread', feed_unreads + nb);
}
} }
//Update unread: all //Update unread: all
@ -98,16 +106,16 @@ function incUnreadsFeed(article, feed_id, nb) {
var isCurrentView = false; var isCurrentView = false;
//Update unread: title //Update unread: title
document.title = document.title.replace(/^((?:\([ 0-9]+\) )?)(.*? · )((?:\([ 0-9]+\) )?)/, function (m, p1, p2, p3) { document.title = document.title.replace(/^((?:\([ 0-9]+\) )?)/, function (m, p1) {
var $feed = $('#' + feed_id); var $feed = $('#' + feed_id);
if (article || ($feed.closest('.active').length > 0 && $feed.siblings('.active').length === 0)) { if (article || ($feed.closest('.active').length > 0 && $feed.siblings('.active').length === 0)) {
isCurrentView = true; isCurrentView = true;
return incLabel(p1, nb, true) + p2 + incLabel(p3, feed_priority > 0 ? nb : 0, true); return incLabel(p1, nb, true);
} else if ($('.all.active').length > 0) { } else if ($('.all.active').length > 0) {
isCurrentView = feed_priority > 0; isCurrentView = feed_priority > 0;
return incLabel(p1, feed_priority > 0 ? nb : 0, true) + p2 + incLabel(p3, feed_priority > 0 ? nb : 0, true); return incLabel(p1, feed_priority > 0 ? nb : 0, true);
} else { } else {
return p1 + p2 + incLabel(p3, feed_priority > 0 ? nb : 0, true); return p1;
} }
}); });
return isCurrentView; return isCurrentView;
@ -152,6 +160,7 @@ function mark_read(active, only_not_read) {
$r.find('.icon').replaceWith(data.icon); $r.find('.icon').replaceWith(data.icon);
incUnreadsFeed(active, feed_id, inc); incUnreadsFeed(active, feed_id, inc);
faviconNbUnread();
pending_feeds.splice(index_pending, 1); pending_feeds.splice(index_pending, 1);
}); });
@ -361,7 +370,12 @@ function last_category() {
function collapse_entry() { function collapse_entry() {
isCollapsed = !isCollapsed; isCollapsed = !isCollapsed;
$(".flux.current").toggleClass("active");
var flux_current = $(".flux.current");
flux_current.toggleClass("active");
if (isCollapsed) {
mark_read(flux_current, true);
}
} }
function auto_share(key) { function auto_share(key) {
@ -407,21 +421,7 @@ function inMarkViewport(flux, box_to_follow, relative_follow) {
return (windowBot >= begin && bot >= windowBot); return (windowBot >= begin && bot >= windowBot);
} }
function init_lazyload() {
if ($.fn.lazyload) {
if (is_global_mode()) {
$(".flux_content img").lazyload({
container: $("#panel")
});
} else {
$(".flux_content img").lazyload();
}
}
}
function init_posts() { function init_posts() {
init_lazyload();
var box_to_follow = $(window), var box_to_follow = $(window),
relative_follow = false; relative_follow = false;
if (is_global_mode()) { if (is_global_mode()) {
@ -663,7 +663,7 @@ function init_stream(divStream) {
if (auto_mark_site) { if (auto_mark_site) {
divStream.on('click', '.flux .link > a', function () { divStream.on('click', '.flux .link > a', function () {
mark_read($(this).parent().parent().parent(), true); mark_read($(this).parents(".flux"), true);
}); });
} }
} }
@ -768,18 +768,66 @@ function init_notifications() {
} }
// </notification> // </notification>
// <notifs html5>
var notifs_html5_permission = 'denied';
function notifs_html5_is_supported() {
return window.Notification !== undefined;
}
function notifs_html5_ask_permission() {
window.Notification.requestPermission(function () {
notifs_html5_permission = window.Notification.permission;
});
}
function notifs_html5_show(nb) {
if (notifs_html5_permission !== "granted") {
return
}
var notification = new window.Notification(str_notif_title_articles, {
icon: "../themes/icons/favicon-256.png",
body: str_notif_body_articles.replace("\d", nb)
});
notification.onclick = function() {
window.location.reload();
}
}
function init_notifs_html5() {
if (!notifs_html5_is_supported()) {
return;
}
notifs_html5_permission = notifs_html5_ask_permission();
}
// </notifs html5>
function refreshUnreads() { function refreshUnreads() {
$.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) { $.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) {
var isAll = $('.category.all > .active').length > 0; var isAll = $('.category.all > .active').length > 0,
new_articles = false;
$.each(data, function(feed_id, nbUnreads) { $.each(data, function(feed_id, nbUnreads) {
feed_id = 'f_' + feed_id; feed_id = 'f_' + feed_id;
var elem = $('#' + feed_id + '>.feed').get(0), var elem = $('#' + feed_id + '>.feed').get(0),
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view? if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view?
(nbUnreads - feed_unreads > 0)) { (nbUnreads - feed_unreads > 0)) {
$('#new-article').show(); $('#new-article').show();
new_articles = true;
}; };
}); });
var nb_unreads = str2int($('.category.all>a').attr('data-unread'));
if (nb_unreads > 0 && new_articles) {
faviconNbUnread(nb_unreads);
notifs_html5_show(nb_unreads);
}
}); });
} }
@ -812,7 +860,6 @@ function load_more_posts() {
}); });
init_load_more(box_load_more); init_load_more(box_load_more);
init_lazyload();
$('#load_more').removeClass('loading'); $('#load_more').removeClass('loading');
load_more = false; load_more = false;
@ -826,6 +873,12 @@ function focus_search() {
function init_load_more(box) { function init_load_more(box) {
box_load_more = box; box_load_more = box;
if (!does_lazyload) {
$('img[postpone], audio[postpone], iframe[postpone], video[postpone]').each(function () {
this.removeAttribute('postpone');
});
}
var $next_link = $("#load_more"); var $next_link = $("#load_more");
if (!$next_link.length) { if (!$next_link.length) {
// no more article to load // no more article to load
@ -967,7 +1020,7 @@ function init_persona() {
//</persona> //</persona>
function init_confirm_action() { function init_confirm_action() {
$('.confirm').click(function () { $('body').on('click', '.confirm', function () {
return confirm(str_confirmation); return confirm(str_confirmation);
}); });
} }
@ -1010,6 +1063,12 @@ function init_share_observers() {
}); });
} }
function init_stats_observers() {
$('#feed_select').on('change', function(e) {
redirect($(this).find(':selected').data('url'));
});
}
function init_remove_observers() { function init_remove_observers() {
$('.post').on('click', 'a.remove', function(e) { $('.post').on('click', 'a.remove', function(e) {
var remove_what = $(this).attr('data-remove'); var remove_what = $(this).attr('data-remove');
@ -1052,8 +1111,44 @@ function init_password_observers() {
}); });
} }
function faviconNbUnread(n) {
if (typeof n === 'undefined') {
n = str2int($('.category.all>a').attr('data-unread'));
}
//http://remysharp.com/2010/08/24/dynamic-favicons/
var canvas = document.createElement('canvas'),
link = document.getElementById('favicon').cloneNode(true);
if (canvas.getContext && link) {
canvas.height = canvas.width = 16;
var img = document.createElement('img');
img.onload = function () {
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
if (n > 0) {
var text = '';
if (n < 1000) {
text = n;
} else if (n < 100000) {
text = Math.floor(n / 1000) + 'k';
} else {
text = 'E' + Math.floor(Math.log10(n));
}
ctx.font = 'bold 9px "Arial", sans-serif';
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fillRect(0, 7, ctx.measureText(text).width, 9);
ctx.fillStyle = '#F00';
ctx.fillText(text, 0, canvas.height - 1);
}
link.href = canvas.toDataURL('image/png');
$('link[rel~=icon]').remove();
document.head.appendChild(link);
};
img.src = '../favicon.ico';
}
}
function init_all() { function init_all() {
if (!(window.$ && window.url_freshrss && ((!full_lazyload) || $.fn.lazyload))) { if (!(window.$ && window.url_freshrss)) {
if (window.console) { if (window.console) {
console.log('FreshRSS waiting for JS…'); console.log('FreshRSS waiting for JS…');
} }
@ -1079,13 +1174,16 @@ function init_all() {
init_stream($stream); init_stream($stream);
init_nav_entries(); init_nav_entries();
init_shortcuts(); init_shortcuts();
faviconNbUnread();
init_print_action(); init_print_action();
init_notifs_html5();
window.setInterval(refreshUnreads, 120000); window.setInterval(refreshUnreads, 120000);
} else { } else {
init_share_observers(); init_share_observers();
init_remove_observers(); init_remove_observers();
init_feed_observers(); init_feed_observers();
init_password_observers(); init_password_observers();
init_stats_observers();
} }
if (window.console) { if (window.console) {

View file

@ -515,15 +515,13 @@ a.btn {
.categories .feeds .item.empty.active { .categories .feeds .item.empty.active {
background: #c95; background: #c95;
} }
.categories .feeds .item.empty.active .feed {
color: #fff;
}
.categories .feeds .item.error .feed { .categories .feeds .item.error .feed {
color: #a44; color: #a44;
} }
.categories .feeds .item.error.active { .categories .feeds .item.error.active {
background: #a44; background: #a44;
} }
.categories .feeds .item.empty.active .feed,
.categories .feeds .item.error.active .feed { .categories .feeds .item.error.active .feed {
color: #fff; color: #fff;
} }
@ -570,7 +568,7 @@ a.btn {
} }
.prompt form { .prompt form {
margin: 10px auto 20px auto; margin: 10px auto 20px auto;
width: 180px; width: 200px;
} }
.prompt input { .prompt input {
margin: 5px auto; margin: 5px auto;

View file

@ -309,6 +309,9 @@ a.btn {
list-style: none; list-style: none;
margin: 0; margin: 0;
} }
.state_unread li:not(.active)[data-unread="0"] {
display: none;
}
.category { .category {
display: block; display: block;
overflow: hidden; overflow: hidden;

View file

@ -492,10 +492,6 @@ a.btn {
.categories .feeds .item.active { .categories .feeds .item.active {
background: #2980b9; background: #2980b9;
} }
.categories .feeds .item.active .feed,
.categories .feeds .item.empty.active .feed {
color: #fff;
}
.categories .feeds .item.empty.active { .categories .feeds .item.empty.active {
background: #f39c12; background: #f39c12;
} }
@ -508,6 +504,11 @@ a.btn {
.categories .feeds .item.error .feed { .categories .feeds .item.error .feed {
color: #bd362f; color: #bd362f;
} }
.categories .feeds .item.active .feed,
.categories .feeds .item.empty.active .feed,
.categories .feeds .item.error.active .feed {
color: #fff;
}
.categories .feeds .item .feed { .categories .feeds .item .feed {
margin: 0; margin: 0;
width: 165px; width: 165px;
@ -551,7 +552,7 @@ a.btn {
} }
.prompt form { .prompt form {
margin: 10px auto 20px auto; margin: 10px auto 20px auto;
width: 180px; width: 200px;
} }
.prompt input { .prompt input {
margin: 5px auto; margin: 5px auto;

View file

@ -309,6 +309,9 @@ a.btn {
list-style: none; list-style: none;
margin: 0; margin: 0;
} }
.state_unread li:not(.active)[data-unread="0"] {
display: none;
}
.category { .category {
display: block; display: block;
overflow: hidden; overflow: hidden;

View file

@ -540,21 +540,23 @@ a.btn {
.categories .feeds .item.active { .categories .feeds .item.active {
background: #0062BE; background: #0062BE;
} }
.categories .feeds .item.active .feed { .categories .feeds .item.empty.active {
color: #fff; background: #e67e22;
}
.categories .feeds .item.error.active {
background: #BD362F;
} }
.categories .feeds .item.empty .feed { .categories .feeds .item.empty .feed {
color: #e67e22; color: #e67e22;
} }
.categories .feeds .item.empty.active {
background: #e67e22;
}
.categories .feeds .item.empty.active .feed {
color: #fff;
}
.categories .feeds .item.error .feed { .categories .feeds .item.error .feed {
color: #BD362F; color: #BD362F;
} }
.categories .feeds .item.active .feed,
.categories .feeds .item.empty.active .feed,
.categories .feeds .item.error.active .feed {
color: #fff;
}
.categories .feeds .item .feed { .categories .feeds .item .feed {
margin: 0; margin: 0;
width: 165px; width: 165px;
@ -598,7 +600,7 @@ a.btn {
} }
.prompt form { .prompt form {
margin: 10px auto 20px auto; margin: 10px auto 20px auto;
width: 180px; width: 200px;
} }
.prompt input { .prompt input {
margin: 5px auto; margin: 5px auto;

View file

@ -309,6 +309,9 @@ a.btn {
list-style: none; list-style: none;
margin: 0; margin: 0;
} }
.state_unread li:not(.active)[data-unread="0"] {
display: none;
}
.category { .category {
display: block; display: block;
overflow: hidden; overflow: hidden;

View file

@ -0,0 +1,36 @@
Screwdriver
=======
**C'est un cocktail! C'est chaud mais "fresh" à la fois. C'est... c'est... un thème pour l'agrégateur de flux RSS<a href="https://github.com/marienfressinaud/FreshRSS/" target="blank">FreshRSS</a>!!**
En toute modestie, ce thème tue du chaton.
![screenshot](https://github.com/misterair/Screwdriver/blob/master/screenshot.png)
Installation
-----------------
1. Placez le dossier du thème dans ledossier /FreshRSS/p/themes/Screwdriver de votre FreshRSS;
2. Allez dans les paramètres d'Affichage et changez de thème;
3. Profitez de votre Screwdriver!
4. Remontez les problèmes sur Github (facultatif mais fortement apprécié)
Screwdriver est distribué sous license BeerWare:
-----------------
« LICENCE BEERWARE » (Révision 42):
mister.air@gmail.com a créé ce fichier. Tant que vous conservez cet avertissement,
vous pouvez faire ce que vous voulez de ce truc. Si on se rencontre un jour et
que vous pensez que ce truc vaut le coup, vous pouvez me payer une bière en retour.
*Mister aiR*

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-60.0002,-726)">
<path style="color:#666666;" fill="#666" d="m67,729,0,4-4,0,0,2,4,0,0,4,2,0,0-4,4,0,0-2-4,0,0-4-2,0z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 220 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-40.0002,-746)" fill="#bebebe">
<rect style="color:#bebebe;" height="2.0002" width="9.9996" y="749" x="43"/>
<rect style="color:#bebebe;" height="2.0002" width="9.9996" y="753" x="43"/>
<rect style="color:#bebebe;" height="2.0002" width="9.9996" y="757" x="43"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-141.0002,-807)" fill="#bebebe">
<path d="m143,807,0,13,4-4,4,4,0-4,0-1-2,0,0-4,2,0,0-4z"/>
<path d="m152,810,0,2-2,0,0,2,2,0,0,2,2,0,0-2,2,0,0-2-2,0,0-2-2,0z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 261 B

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="bookmark.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="745"
id="namedview8"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-2.2033898"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
transform="translate(-41.000202,-397)"
id="g4">
<path
style="enable-background:accumulate;color:#000000;fill:#d18104;fill-opacity:1"
d="m530.95,186.71c-0.77941,0.55189-3.1576-1.906-4.1125-1.9179-0.95532-0.0119-3.3949,2.3858-4.161,1.8149-0.76573-0.57072,0.83698-3.592,0.55319-4.5039-0.2839-0.91223-3.3182-2.4915-3.0119-3.3965,0.30617-0.90461,3.6749-0.31399,4.4544-0.86567,0.77986-0.5519,1.3442-3.9257,2.2995-3.914,0.95494,0.0116,1.4342,3.398,2.1998,3.9689,0.76588,0.57114,4.1489,0.0653,4.4331,0.97746,0.28402,0.9118-2.7885,2.414-3.0949,3.3186-0.30652,0.90489,1.22,3.966,0.44027,4.5182z"
fill-rule="nonzero"
transform="matrix(1.0472113,-0.00871584,0.00871584,1.0472113,-504.35434,220.15425)"
fill="#f1c40f"
id="path6" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-442,-176)">
<g transform="translate(234.0002,-820)">
<path d="m208.53,997c-0.28913,0-0.53125,0.24212-0.53125,0.53125v13.938c0,0.2985,0.23264,0.5312,0.53125,0.5312h14.938c0.2986,0,0.53125-0.2326,0.53125-0.5312v-8.9376c0-0.2891-0.24212-0.5312-0.53125-0.5312h-12.469v7.5c0,0.277-0.223,0.5-0.5,0.5s-0.5-0.223-0.5-0.5v-8c0-0.277,0.223-0.5,0.5-0.5h2.9688,8.5312v-1.4062c0-0.3272-0.26666-0.5938-0.59375-0.5938h-7.4062v-1.4688c0-0.39-0.24-0.63-0.53-0.63z" fill="#FFF"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 567 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-442,-176)">
<g transform="translate(234.0002,-820)">
<path d="m208.53,997c-0.28913,0-0.53125,0.24212-0.53125,0.53125v13.938c0,0.2985,0.23264,0.5312,0.53125,0.5312h14.938c0.2986,0,0.53125-0.2326,0.53125-0.5312v-8.9376c0-0.2891-0.24212-0.5312-0.53125-0.5312h-12.469v7.5c0,0.277-0.223,0.5-0.5,0.5s-0.5-0.223-0.5-0.5v-8c0-0.277,0.223-0.5,0.5-0.5h2.9688,8.5312v-1.4062c0-0.3272-0.26666-0.5938-0.59375-0.5938h-7.4062v-1.4688c0-0.39-0.24-0.63-0.53-0.63z" fill="#666"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 567 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-60,-518)">
<g transform="translate(19,-242)">
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m45,764,1,0c0.01037-0.00012,0.02079-0.00046,0.03125,0,0.25495,0.0112,0.50987,0.12858,0.6875,0.3125l2.282,2.28,2.312-2.28c0.266-0.23,0.447-0.3,0.688-0.31h1v1c0,0.28647-0.03434,0.55065-0.25,0.75l-2.2812,2.2812,2.25,2.25c0.188,0.19,0.281,0.45,0.281,0.72v1h-1c-0.2653-0.00001-0.53059-0.0931-0.71875-0.28125l-2.281-2.28-2.281,2.28c-0.188,0.19-0.454,0.28-0.719,0.28h-1v-1c-0.000003-0.26529,0.09306-0.53058,0.28125-0.71875l2.2812-2.25-2.281-2.28c-0.21-0.19-0.303-0.47-0.281-0.75v-1z" fill-rule="nonzero" fill="#bebebe"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 805 B

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-441.0002,-400.99999)">
<path style="color:#666666;enable-background:accumulate;" d="m449,402c-0.22065,0-0.44081,0.0113-0.65625,0.0312l-0.40625,2.0938c-0.33446,0.0733-0.66305,0.17589-0.96875,0.3125l-1.5312-1.4688c-0.38863,0.23011-0.72695,0.51408-1.0625,0.8125l0.90625,1.9062c-0.22242,0.24899-0.42425,0.5225-0.59375,0.8125l-2.0938-0.28125c-0.17772,0.40877-0.30872,0.83637-0.40625,1.2812l1.8438,1c-0.0171,0.16809-0.0312,0.3274-0.0312,0.5s0.0142,0.33191,0.0312,0.5l-1.8438,1c0.0975,0.44488,0.22853,0.87248,0.40625,1.2812l2.0938-0.28125c0.1695,0.29,0.37133,0.56351,0.59375,0.8125l-0.90625,1.9062c0.33555,0.29842,0.67387,0.58239,1.0625,0.8125l1.5312-1.4688c0.3057,0.13661,0.63429,0.23916,0.96875,0.3125l0.40625,2.0938c0.21544,0.02,0.4356,0.0312,0.65625,0.0312s0.44081-0.0113,0.65625-0.0312l0.40625-2.0938c0.33446-0.0733,0.66305-0.17589,0.96875-0.3125l1.5312,1.4688c0.38863-0.23011,0.72695-0.51408,1.0625-0.8125l-0.90625-1.9062c0.22242-0.24899,0.42425-0.5225,0.59375-0.8125l2.0938,0.28125c0.17772-0.40877,0.30872-0.83637,0.40625-1.2812l-1.8438-1c0.0171-0.16809,0.0312-0.3274,0.0312-0.5s-0.0142-0.33191-0.0312-0.5l1.8438-1c-0.0975-0.44488-0.22853-0.87248-0.40625-1.2812l-2.0938,0.28125c-0.1695-0.29-0.37133-0.56351-0.59375-0.8125l0.90625-1.9062c-0.33555-0.29842-0.67387-0.58239-1.0625-0.8125l-1.5312,1.4688c-0.3057-0.13661-0.63429-0.23916-0.96875-0.3125l-0.40625-2.0938c-0.21544-0.02-0.4356-0.0312-0.65625-0.0312zm0,4c1.6568,0,3,1.3432,3,3s-1.3432,3-3,3-3-1.3432-3-3,1.3432-3,3-3z" fill-rule="nonzero" fill="#666"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-181.0002,-747)">
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m195.03,751,0,1c-0.00091,0.0111,0.00059,0.021-0.00009,0.0312-0.0112,0.25496-0.12835,0.50994-0.31251,0.6875l-5.7188,6.2977-5.7188-6.2977c-0.18821-0.1881-0.28121-0.45346-0.28122-0.71875v-1h1c0.26531,0.00007,0.53059,0.0931,0.71873,0.28131l4.2812,4.829,4.2813-4.829c0.19464-0.21073,0.46925-0.30315,0.74998-0.2813z" fill-rule="nonzero" fill="#bebebe"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<title>Logo FreshRSS</title>
<circle fill="#FFF" cx="128" cy="128" r="128"/>
<circle fill="#0062BE" cx="128" cy="128" r="33"/>
<g fill="none" stroke="#0062BE" stroke-width="24">
<g stroke-opacity="0.3">
<path d="M12,128 A116,116 0 1,1 128,244"/>
<path d="M54,128 A74,74 0 1,1 128,202"/>
</g>
<path d="M128,12 A116,116 0 0,1 244,128"/>
<path d="M128,54 A74,74 0 0,1 202,128"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-182,-490)" fill="#bebebe">
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="m190,490c-4.4147,0-8,3.5853-8,8s3.5853,8,8,8,8-3.5853,8-8-3.5853-8-8-8zm0,2c3.3413,0,6,2.6587,6,6s-2.6587,6-6,6-6-2.6587-6-6,2.6587-6,6-6z"/>
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="M189.34,495c-1.28,0-2.34,1.06-2.34,2.34v1.3125c0,1.2861,1.0576,2.3438,2.3438,2.3438h1.3125c1.29,0.01,2.35-1.05,2.35-2.33v-1.3125c0-1.29-1.06-2.35-2.34-2.35h-1.3125zm0,1,1.3125,0c0.74942,0,1.3438,0.59433,1.3438,1.3438v1.3125c0.01,0.76-0.58,1.35-1.33,1.35h-1.3125c-0.76,0-1.35-0.59-1.35-1.34v-1.3125c0-0.76,0.59-1.35,1.34-1.35z"/>
<path d="m186.72,491.44c-1.5103,0.6073-2.6811,1.7985-3.2812,3.3125l3.75,1.875c0.25196-0.64029,0.74249-1.1706,1.375-1.4375l-1.8438-3.75zm6.5625,0-1.8438,3.75c0.63251,0.26694,1.123,0.79721,1.375,1.4375l3.75-1.875c-0.60015-1.514-1.7709-2.7052-3.2812-3.3125zm-6.0938,8-3.75,1.875c0.60709,1.4886,1.789,2.65,3.2812,3.25l1.875-3.75c-0.62682-0.25556-1.1433-0.75203-1.4062-1.375zm5.625,0c-0.26291,0.62297-0.77943,1.1194-1.4062,1.375l1.875,3.75c1.4923-0.60005,2.6742-1.7614,3.2812-3.25l-3.75-1.875z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<title>Logo FreshRSS</title> <title>Logo FreshRSS</title>
<circle fill="#2980b9" cx="128" cy="128" r="33"/> <circle fill="#0062BE" cx="128" cy="128" r="33"/>
<g fill="none" stroke="#2980b9" stroke-width="24"> <g fill="none" stroke="#0062BE" stroke-width="24">
<g stroke-opacity="0.3"> <g stroke-opacity="0.3">
<path d="M12,128 A116,116 0 1,1 128,244"/> <path d="M12,128 A116,116 0 1,1 128,244"/>
<path d="M54,128 A74,74 0 1,1 128,202"/> <path d="M54,128 A74,74 0 1,1 128,202"/>

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 421 B

View file

@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg">
<g transform="translate(-340.99994,-257)" fill="#ffffff"> <g transform="translate(-340.99994,-257)" fill="#666666">
<path style="block-progression:tb;color:#000000;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="m346,260c-2.7496,0-5,2.2504-5,5s2.2504,5,5,5c1.5862,0,2.9034-0.84459,3.8125-2h4.8438,0.75l0.21875-0.75,1.0312-4,0.3125-1.25h-1.2812-5.875c-0.90914-1.1554-2.2263-2-3.8125-2zm0,2c1.1158,0,2.0379,0.59507,2.5625,1.5l0.3125,0.5h0.5625,4.9688l-0.53125,2h-4.4375-0.5625l-0.3125,0.5c-0.52462,0.90493-1.4466,1.5-2.5625,1.5-1.6687,0-3-1.3313-3-3s1.3313-3,3-3z"/> <path style="block-progression:tb;color:#000000;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="m346,260c-2.7496,0-5,2.2504-5,5s2.2504,5,5,5c1.5862,0,2.9034-0.84459,3.8125-2h4.8438,0.75l0.21875-0.75,1.0312-4,0.3125-1.25h-1.2812-5.875c-0.90914-1.1554-2.2263-2-3.8125-2zm0,2c1.1158,0,2.0379,0.59507,2.5625,1.5l0.3125,0.5h0.5625,4.9688l-0.53125,2h-4.4375-0.5625l-0.3125,0.5c-0.52462,0.90493-1.4466,1.5-2.5625,1.5-1.6687,0-3-1.3313-3-3s1.3313-3,3-3z"/>
<path opacity="0.35" style="enable-background:accumulate;color:#000000;" d="M355.5,265,350,265,349.44,267,355,267z" fill-rule="nonzero"/> <path opacity="0.35" style="enable-background:accumulate;color:#000000;" d="M355.5,265,350,265,349.44,267,355,267z" fill-rule="nonzero"/>
<path style="enable-background:accumulate;color:#000000;" d="m346,265c0,0.55228-0.44772,1-1,1s-1-0.44772-1-1,0.44772-1,1-1,1,0.44772,1,1z" fill-rule="nonzero"/> <path style="enable-background:accumulate;color:#000000;" d="m346,265c0,0.55228-0.44772,1-1,1s-1-0.44772-1-1,0.44772-1,1-1,1,0.44772,1,1z" fill-rule="nonzero"/>

Before

Width:  |  Height:  |  Size: 910 B

After

Width:  |  Height:  |  Size: 910 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16.004" width="16">
<g fill="#bebebe" transform="translate(-183,-529)">
<path style="enable-background:accumulate;color:#000000;" d="m191,533.85,0,10.38-2.344-2.2882-1.3394,2.7346c-0.32808,0.73962-2.0337,0.14492-1.5487-0.84412l1.3255-2.8393h-2.9579l6.8645-7.1436z" fill-rule="nonzero" display="block"/>
<path d="m190.16,530.06c-3.8266,0.46006-6.5788,3.9578-6.0938,7.7812,0.13127,1.0347,0.29377,1.3818,0.29377,1.3818l1.675-1.6318c-0.33104-2.7534,1.6216-5.2315,4.375-5.5625,2.7534-0.33104,5.2315,1.6216,5.5625,4.375,0.31355,2.608-1.3913,5.0249-3.9688,5.5312l0.0312,2s0.52086-0.1059,0.62354-0.13097c3.4156-0.83385,5.7063-4.1273,5.2827-7.6503-0.46006-3.8266-3.9547-6.5538-7.7812-6.0938z" style="baseline-shift:baseline;block-progression:tb;color:#000000;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;"/>
<path opacity="0.3" style="enable-background:accumulate;color:#000000;" d="m187.11,536.81,0-0.20574-0.19826,0.0186c0.0165-0.13095,0.0329-0.26167,0.0496-0.3926h-0.11578l-0.11556,0.14959-0.11578,0.0559-0.1653-0.0932-0.0165-0.20575,0.0331-0.22438,0.24798-0.18688h0.19826l0.0329-0.11229,0.24786,0.0559,0.18183,0.2246,0.0331-0.37419,0.31401-0.26167,0.11567-0.28055,0.23133-0.0934,0.1322-0.18688,0.29738-0.0564,0.14885-0.22415h-0.44623l0.28094-0.13095h0.19814l0.28106-0.0937,0.0331-0.11186-0.0992-0.0937-0.11567-0.0375,0.0331-0.11208-0.0826-0.16822-0.19837,0.0746,0.0331-0.14947-0.23134-0.13096-0.18171,0.3177,0.0165,0.11229-0.18171,0.075-0.11578,0.24302-0.0495-0.22438-0.31402-0.13095-0.0496-0.16822,0.41315-0.24325,0.18182-0.16822,0.0165-0.20563-0.0991-0.0562-0.13219-0.0188-0.0826,0.20575s-0.1382,0.0271-0.17373,0.0358c-0.45378,0.41804-1.3707,1.3204-1.5837,3.024,0.008,0.0395,0.15441,0.26854,0.15441,0.26854l0.347,0.20552,0.347,0.0937m3.9661-4.3003-0.4298-0.16833-0.49552,0.0561-0.61161,0.16822-0.11567,0.11229,0.38008,0.26167,0,0.14959-0.14875,0.14959,0.19846,0.39294,0.13188-0.075,0.16561-0.26168c0.2553-0.0789,0.4842-0.16833,0.72686-0.28053l0.19846-0.5048m2.5292,0.34192-0.375,0.0937-0.21875,0.15625,0,0.125-0.375,0.25,0.0937,0.34375,0.21875-0.15625,0.125,0.15625,0.15625,0.0937,0.0937-0.28125-0.0625-0.15625,0.0625-0.0937,0.21875-0.1875,0.0937,0-0.0937,0.21875,0,0.1875c0.0892-0.0242,0.1588-0.051,0.25-0.0625l-0.25,0.1875v0.125l-0.3125,0.21875-0.28125-0.0625v-0.15625l-0.125,0.0625,0.0625,0.15625h-0.21875l-0.125,0.21875-0.15625,0.15625-0.0937,0.0312v0.1875l0.0312,0.15625h-0.0312v0.53125l0.0625-0.0312,0.0937-0.21875,0.1875-0.125,0.0312-0.0937,0.28125-0.0625,0.15625,0.1875,0.1875,0.0937-0.0937,0.1875,0.15625-0.0312,0.0625-0.21875-0.1875-0.21875h0.0625l0.21875,0.15625,0.0312,0.21875,0.15625,0.21875,0.0625-0.3125,0.0937-0.0312c0.0959,0.0996,0.1692,0.23163,0.25,0.34375h0.28125l0.1875,0.125-0.0937,0.0937-0.15625,0.15625h-0.25l-0.34375-0.0937h-0.1875l-0.125,0.15625-0.34375-0.375-0.25-0.0625-0.375,0.0625-0.15625,0.0937v2.4062l0.0312,0.0312,0.25-0.15625,0.0937,0.0937h0.28125l0.125,0.15625-0.0937,0.3125,0.1875,0.1875v0.375l0.125,0.25-0.0937,0.25c-0.009,0.16159,0,0.30714,0,0.46875,0.0795,0.21894,0.14355,0.43575,0.21875,0.65625l0.0625,0.34375v0.1875h0.125l0.21875-0.125h0.25l0.375-0.4375-0.0312-0.15625,0.25-0.21875-0.1875-0.1875,0.21875-0.1875,0.21875-0.125,0.0937-0.125-0.0625-0.25v-0.59375l0.1875-0.375,0.1875-0.25,0.25-0.5625v-0.15625c-0.11654,0.0146-0.22972,0.0231-0.34375,0.0312-0.0722,0.005-0.14446,0-0.21875,0-0.12359-0.25961-0.2183-0.50966-0.3125-0.78125l-0.15625-0.1875-0.0937-0.3125,0.0625-0.0625,0.21875,0.25,0.25,0.5625,0.15625,0.15625-0.0625,0.21875,0.15625,0.15625,0.25-0.25,0.3125-0.21875,0.15625-0.1875v-0.21875c-0.0389-0.0732-0.0547-0.14545-0.0937-0.21875l-0.15625,0.1875-0.125-0.15625-0.1875-0.125v-0.28125l0.21875,0.21875,0.21875-0.0312c0.10166,0.0923,0.19205,0.20751,0.28125,0.3125l0.15625-0.1875c0-0.17463-0.19976-1.0204-0.625-1.75-0.42526-0.72932-1.1562-1.4062-1.1562-1.4062l-0.0625,0.0937-0.21875,0.21875-0.25-0.25h0.25l0.125-0.125-0.46875-0.0937-0.25-0.0937z" fill-rule="nonzero"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-181.0002,-237)" fill="#bebebe">
<path style="color:#bebebe;" d="m184,244c-0.554,0-1,0.446-1,1v0.53125,5.4688h12v-5.4688-0.53c0-0.554-0.446-1-1-1h-10z" fill-rule="nonzero"/>
<path style="baseline-shift:baseline;block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="m188,238c-1.6447,0-3,1.3553-3,3v7c0,1.6447,1.3553,3,3,3h2c1.6447,0,3-1.3553,3-3v-7c0-1.6447-1.3553-3-3-3h-2zm0,2,2,0c0.5713,0,1,0.4287,1,1v7c0,0.5713-0.4287,1-1,1h-2c-0.5713,0-1-0.4287-1-1v-7c0-0.5713,0.4287-1,1-1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 662 B

View file

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-201.0002,-237)" fill="#bebebe">
<path style="color:#bebebe;" d="m204,246c-0.554,0-1,0.446-1,1v0.53125,5.4688h12v-5.4688-0.53c0-0.554-0.446-1-1-1h-10z" fill-rule="nonzero"/>
<path style="baseline-shift:baseline;block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="m208,237c-1.6447,0-3,1.3553-3,3v3h2v-3c0-0.57129,0.42873-1,1-1h2c0.57127,0,1,0.42871,1,1v7h2v-7c0-1.6447-1.3553-3-3-3h-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 569 B

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-121.0002,-747)">
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m125,749,1,0c0.0104-0.00012,0.0208-0.00046,0.0313,0,0.25495,0.0112,0.50987,0.12858,0.6875,0.3125l6.2977,5.7188-6.2977,5.7188c-0.18816,0.18819-0.45346,0.28125-0.71875,0.28125h-1v-1c0-0.26529,0.0931-0.53058,0.28125-0.71875l4.829-4.2812-4.829-4.2812c-0.21074-0.19463-0.30316-0.46925-0.28125-0.75z" fill-rule="nonzero" fill="#bebebe"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 589 B

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-61.000202,-397)">
<path style="baseline-shift:baseline;block-progression:tb;color:#000000;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" fill="#bebebe" d="m69.003,398.01c-0.2659-0.00099-0.49859,0.1006-0.6647,0.2393-0.16611,0.13869-0.27742,0.32137-0.38968,0.50028-0.22453,0.35782-0.39269,0.76873-0.56546,1.2036-0.17277,0.43483-0.34713,0.88766-0.5046,1.2323-0.15747,0.34465-0.3456,0.57871-0.35862,0.58776-0.01287,0.009-0.30722,0.117-0.69576,0.15181-0.38855,0.0348-0.88122,0.0492-1.3632,0.0694-0.48202,0.0202-0.9703,0.0362-1.393,0.12817-0.21138,0.046-0.4154,0.10148-0.60434,0.20956s-0.36689,0.28631-0.45004,0.53002-0.04901,0.50627,0.03636,0.70157c0.08537,0.19531,0.22656,0.36514,0.3682,0.52344,0.2833,0.31663,0.6327,0.60557,1.0079,0.89849s0.77671,0.55926,1.0678,0.81027c0.29104,0.25101,0.45422,0.50796,0.45912,0.52271,0.0048,0.0146,0.03119,0.33498-0.05456,0.70231-0.08575,0.36732-0.2238,0.81174-0.35282,1.2603-0.12902,0.44861-0.25176,0.90196-0.2917,1.3184-0.01997,0.20819-0.04285,0.40729,0.0053,0.61409,0.04814,0.20679,0.1845,0.43007,0.39902,0.58168,0.21451,0.15161,0.44936,0.1881,0.66823,0.1701s0.43535-0.0703,0.63515-0.15132c0.39961-0.16214,0.80177-0.42851,1.2064-0.68231,0.40465-0.2538,0.80822-0.52155,1.1456-0.71107,0.33734-0.18952,0.6484-0.2686,0.66445-0.26854,0.01586,0.00006,0.30338,0.0951,0.63894,0.28732,0.33556,0.19221,0.72532,0.46503,1.1276,0.72205,0.40229,0.25702,0.81996,0.49752,1.218,0.66284,0.19903,0.0827,0.38893,0.15086,0.60762,0.17059,0.2187,0.0197,0.47978-0.031,0.69551-0.18105,0.21572-0.15001,0.33928-0.35235,0.38918-0.55877s0.04291-0.43517,0.02476-0.64358c-0.03632-0.41683-0.15899-0.86394-0.2841-1.3137-0.12511-0.44978-0.26165-0.88661-0.34421-1.2548-0.08256-0.36813-0.07169-0.68662-0.06666-0.70133,0.005-0.0145,0.18746-0.25247,0.4806-0.50101,0.29313-0.24854,0.67599-0.53755,1.0536-0.82731,0.37764-0.28976,0.76716-0.57158,1.0531-0.88579,0.14298-0.1571,0.2418-0.33444,0.32882-0.52904s0.136-0.42874,0.05481-0.67306-0.27108-0.41314-0.45912-0.52272-0.36679-0.18158-0.57782-0.22931c-0.42206-0.0955-0.91359-0.14009-1.3956-0.16426-0.48198-0.0242-0.94584-0.039-1.3342-0.077s-0.71565-0.13122-0.72859-0.14037c-0.01279-0.009-0.18402-0.23636-0.3384-0.58217s-0.32658-0.78819-0.49548-1.2243c-0.1689-0.4361-0.33477-0.86429-0.55609-1.2238-0.11067-0.17977-0.23335-0.35397-0.39826-0.49396s-0.40309-0.25684-0.66899-0.25783zm0.0086,0.99424c0.0422,0.0358,0.10671,0.13602,0.1841,0.26173,0.15477,0.25141,0.33068,0.6272,0.49397,1.0488,0.16329,0.42163,0.31905,0.88645,0.49598,1.2828,0.17693,0.39633,0.31456,0.73379,0.6753,0.98889,0.36072,0.25509,0.77019,0.29763,1.2152,0.34118,0.44506,0.0435,0.92882,0.0532,1.3948,0.0765,0.46599,0.0234,0.91824,0.0697,1.2135,0.13647,0.14763,0.0334,0.25558,0.0572,0.30381,0.0853-0.02227,0.0498-0.07958,0.15478-0.17956,0.26464-0.19997,0.21973-0.53749,0.48746-0.90261,0.7676-0.36511,0.28015-0.77804,0.57219-1.114,0.85704-0.33595,0.28485-0.63992,0.53221-0.77987,0.94209-0.13995,0.40986-0.05396,0.77681,0.04065,1.1987s0.25406,0.87813,0.37502,1.313c0.12096,0.43486,0.22688,0.84692,0.25228,1.1385,0.01156,0.13264-0.01699,0.23485-0.02778,0.29267-0.05993-0.008-0.1764-0.0324-0.30381-0.0853-0.27836-0.11561-0.64649-0.32808-1.0354-0.57657-0.38894-0.24849-0.8039-0.53053-1.1885-0.75081-0.38457-0.22028-0.70791-0.39837-1.1551-0.40015-0.44722-0.002-0.79205,0.17245-1.1786,0.38965-0.38659,0.21719-0.78438,0.49517-1.1756,0.74055-0.39123,0.24538-0.77636,0.4507-1.0559,0.56412-0.13977,0.0567-0.24616,0.0856-0.3023,0.0902-0.01026-0.0578-0.01522-0.16008-0.0025-0.29243,0.02793-0.29118,0.13818-0.70893,0.26291-1.1426,0.12473-0.43372,0.25404-0.89785,0.35232-1.3188,0.09828-0.42099,0.18672-0.78846,0.05027-1.1994-0.13644-0.41097-0.43218-0.64202-0.76571-0.92967-0.33353-0.28766-0.70551-0.58555-1.0683-0.86876-0.36275-0.2832-0.7178-0.56075-0.91597-0.78224-0.09908-0.11075-0.16221-0.21163-0.1841-0.26173,0.04834-0.0276,0.15448-0.058,0.3023-0.0902,0.29562-0.0643,0.74518-0.10714,1.2112-0.1267,0.46603-0.0196,0.94824-0.0298,1.3935-0.0697,0.44531-0.0399,0.84679-0.0499,1.2097-0.30216,0.36289-0.25221,0.5383-0.60511,0.71876-1.0001,0.18046-0.39497,0.33731-0.84115,0.50435-1.2616,0.16704-0.42041,0.31848-0.83556,0.47556-1.0859,0.07853-0.12515,0.16751-0.20007,0.21012-0.23565z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-301.0002,-747)">
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m313.01,749-1,0c-0.0104-0.00012-0.0208-0.00046-0.0313,0-0.25495,0.0112-0.50987,0.12858-0.6875,0.3125l-6.2977,5.7188,6.2977,5.7188c0.18816,0.18819,0.45346,0.28125,0.71875,0.28125h1v-1c0-0.26529-0.0931-0.53058-0.28125-0.71875l-4.829-4.2812,4.829-4.2812c0.21074-0.19463,0.30316-0.46925,0.28125-0.75z" fill-rule="nonzero" fill="#bebebe"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 592 B

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16.001"
width="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="read.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="745"
id="namedview8"
showgrid="false"
inkscape:zoom="14.749079"
inkscape:cx="-2.2040272"
inkscape:cy="8.0004997"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
transform="translate(-60.99995,-296.9989)"
id="g4" />
<path
style="fill:#cccccc;fill-opacity:1"
inkscape:connector-curvature="0"
d="m 8.0004996,3.2833392 c -3.433907,0 -6.410294,1.9996259 -7.87290101,4.9205634 1.46260701,2.9209364 4.43899401,4.9205624 7.87290101,4.9205624 3.4338474,0 6.4102344,-1.999626 7.8729014,-4.9205624 C 14.410824,5.2829651 11.434347,3.2833392 8.0004996,3.2833392 z m 3.8818634,2.6094965 c 0.925096,0.590068 1.709004,1.3804357 2.29781,2.3110669 -0.588806,0.9306312 -1.372744,1.7209988 -2.29784,2.3110964 -1.162392,0.741404 -2.5047194,1.133295 -3.8818334,1.133295 -1.377143,0 -2.719472,-0.391891 -3.881863,-1.133326 -0.925066,-0.5900366 -1.708974,-1.3804016 -2.29781,-2.3110654 0.588806,-0.9306638 1.372744,-1.7210288 2.29781,-2.3110669 0.06025,-0.038442 0.121108,-0.075682 0.182338,-0.1122479 -0.153123,0.4202145 -0.236925,0.873738 -0.236925,1.3469419 0,2.1740274 1.762423,3.9364493 3.93645,3.9364493 2.1740274,0 3.9364514,-1.7624219 3.9364514,-3.9364493 0,-0.4732039 -0.0838,-0.9267274 -0.236925,-1.3469745 0.0612,0.036566 0.122061,0.073839 0.182337,0.1122805 z M 8.0004996,6.6354719 c 0,0.8152761 -0.660894,1.4761705 -1.476168,1.4761705 -0.815275,0 -1.476169,-0.6608944 -1.476169,-1.4761705 0,-0.8152759 0.660894,-1.4761676 1.476169,-1.4761676 0.815274,0 1.476168,0.6608917 1.476168,1.4761676 z"
id="path3167" />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-241.0002,-627)">
<path style="baseline-shift:baseline;block-progression:tb;color:#666666;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" fill="#666" d="m253.91,628.97a1.0001,1.0001,0,0,0,-0.125,0.0312,1.0001,1.0001,0,0,0,-0.78125,1v1.6875c-0.38225-0.57796-0.84927-1.0822-1.4062-1.5-1.1556-0.86677-2.532-1.2523-3.875-1.1875-0.19186,0.009-0.37223,0.0353-0.5625,0.0625-1.5222,0.21741-2.9782,1.023-3.9688,2.3438-1.9812,2.6414-1.4227,6.425,1.2188,8.4062s6.425,1.4227,8.4062-1.2188a1.0063,1.0063,0,0,0,0.18,-0.59,1.0063,1.0063,0,0,0,0,-0.15625v-0.84375h-0.8125-0.0937a1.0063,1.0063,0,0,0,-0.0937,0,1.0063,1.0063,0,0,0,-0.8125,0.40625c-1.3326,1.7767-3.817,2.1139-5.5938,0.78125-1.7767-1.3326-2.1139-3.817-0.78125-5.5938,1.3326-1.7767,3.817-2.1139,5.5938-0.78125,0.42946,0.32212,0.76954,0.73295,1.0312,1.1875h-1.4375a1.0001,1.0001,0,0,0,-1,1,1.0001,1.0001,0,0,0,0,0.21875v0.78125h0.84375,0.15625,4,1v-1-4a1.0001,1.0001,0,0,0,0,-0.1875v-0.8125h-0.8125a1.0001,1.0001,0,0,0,-0.28125,-0.0312z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g fill-rule="nonzero" transform="translate(-561,-301.00012)" fill="#fff"> <g fill-rule="nonzero" transform="translate(-561,-301.00012)" fill="#666">
<path style="enable-background:new;color:#000000;" d="m325.06,97.188c0,1.7872-0.89543,3.2361-2,3.2361s-2-1.4488-2-3.2361c0-1.7872,0.89543-3.2361,2-3.2361s2,1.4488,2,3.2361z" transform="matrix(1.0000007,0,0,0.61803426,241.93747,252.93479)"/> <path style="enable-background:new;color:#000000;" d="m325.06,97.188c0,1.7872-0.89543,3.2361-2,3.2361s-2-1.4488-2-3.2361c0-1.7872,0.89543-3.2361,2-3.2361s2,1.4488,2,3.2361z" transform="matrix(1.0000007,0,0,0.61803426,241.93747,252.93479)"/>
<path style="enable-background:new;color:#000000;" d="m563,303,0,1c0,0.55016,0.45347,1,1,1,4.9706,0,9,4.0294,9,9,0,0.55016,0.45347,1,1,1h1v-1c0-6.0751-4.9249-11-11-11h-1zm0,4,0,1c0,0.55016,0.45347,1,1,1,2.7614,0,5,2.2386,5,5,0,0.55016,0.45347,1,1,1h1v-1c0-3.866-3.134-7-7-7h-1z"/> <path style="enable-background:new;color:#000000;" d="m563,303,0,1c0,0.55016,0.45347,1,1,1,4.9706,0,9,4.0294,9,9,0,0.55016,0.45347,1,1,1h1v-1c0-6.0751-4.9249-11-11-11h-1zm0,4,0,1c0,0.55016,0.45347,1,1,1,2.7614,0,5,2.2386,5,5,0,0.55016,0.45347,1,1,1h1v-1c0-3.866-3.134-7-7-7h-1z"/>
</g> </g>

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 672 B

View file

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g fill="#666" transform="translate(-441.0004,-195)">
<path style="baseline-shift:baseline;block-progression:tb;color:#666666;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m447.51,196c-3.0289,0-5.5107,2.479-5.5107,5.5045,0,3.0254,2.4819,5.5045,5.5107,5.5045s5.5107-2.479,5.5107-5.5045c0-3.0254-2.4819-5.5045-5.5107-5.5045zm0,2.0089c1.9474,0,3.4995,1.5504,3.4995,3.4955s-1.5522,3.4955-3.4995,3.4955c-1.9474,0-3.4995-1.5504-3.4995-3.4955,0-1.9452,1.5522-3.4955,3.4995-3.4955z"/>
<path style="baseline-shift:baseline;block-progression:tb;color:#666666;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m450.81,204a1.0001,1.0001,0,0,0,-0.5,1.7188l4,4a1.0055,1.0055,0,1,0,1.4062,-1.4375l-4-4a1.0001,1.0001,0,0,0,-0.91,-0.28z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 886 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g fill="#bebebe" transform="translate(-581.0002,-196)">
<path style="enable-background:new;color:#000000;" d="m291,178.03c0,1.0873-0.88144,1.9688-1.9688,1.9688-1.0873,0-1.9688-0.88144-1.9688-1.9688,0-1.0873,0.88144-1.9688,1.9688-1.9688,1.0873,0,1.9688,0.88144,1.9688,1.9688z" fill-rule="nonzero" transform="matrix(1.5079365,0,0,1.5079365,148.15963,-64.49107)"/>
<path style="enable-background:new;color:#000000;" d="m291,178.03c0,1.0873-0.88144,1.9688-1.9688,1.9688-1.0873,0-1.9688-0.88144-1.9688-1.9688,0-1.0873,0.88144-1.9688,1.9688-1.9688,1.0873,0,1.9688,0.88144,1.9688,1.9688z" fill-rule="nonzero" transform="matrix(1.5079365,0,0,1.5079365,158.12818,-59.49107)"/>
<path style="enable-background:new;color:#000000;" d="m291,178.03c0,1.0873-0.88144,1.9688-1.9688,1.9688-1.0873,0-1.9688-0.88144-1.9688-1.9688,0-1.0873,0.88144-1.9688,1.9688-1.9688,1.0873,0,1.9688,0.88144,1.9688,1.9688z" fill-rule="nonzero" transform="matrix(1.5079365,0,0,1.5079365,158.12818,-69.49107)"/>
<path style="baseline-shift:baseline;block-progression:tb;color:#000000;direction:ltr;text-indent:0;text-align:start;enable-background:accumulate;text-transform:none;" d="m593.62,198.16-10.062,4.875-1.8125,0.90625,1.8125,0.90625,10.031,5.0625,0.90625-1.8125-8.2188-4.1562,8.2188-4-0.875-1.7812z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="starred.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="685"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<g
transform="translate(-41.000202,-397)"
id="g4">
<path
style="enable-background:accumulate;color:#000000;fill:#eaa904;fill-opacity:1"
d="m530.95,186.71c-0.77941,0.55189-3.1576-1.906-4.1125-1.9179-0.95532-0.0119-3.3949,2.3858-4.161,1.8149-0.76573-0.57072,0.83698-3.592,0.55319-4.5039-0.2839-0.91223-3.3182-2.4915-3.0119-3.3965,0.30617-0.90461,3.6749-0.31399,4.4544-0.86567,0.77986-0.5519,1.3442-3.9257,2.2995-3.914,0.95494,0.0116,1.4342,3.398,2.1998,3.9689,0.76588,0.57114,4.1489,0.0653,4.4331,0.97746,0.28402,0.9118-2.7885,2.414-3.0949,3.3186-0.30652,0.90489,1.22,3.966,0.44027,4.5182z"
fill-rule="nonzero"
transform="matrix(1.0472113,-0.00871584,0.00871584,1.0472113,-504.35434,220.15425)"
fill="#f1c40f"
id="path6" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-141.0002,-807)">
<path d="m149,809,0,13,4-4,4,4c0.0525-6.8494-0.0285-10.584,0-13z" fill="#bebebe"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 200 B

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="unread.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="745"
id="namedview10"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="20.85965"
inkscape:cx="3.2842788"
inkscape:cy="5.738225"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2">
<sodipodi:guide
orientation="0,1"
position="18.02523,13.039528"
id="guide4011" />
<sodipodi:guide
orientation="0,1"
position="10.738435,2.1093355"
id="guide4013" />
</sodipodi:namedview>
<path
style="fill:#666666;fill-opacity:1"
inkscape:connector-curvature="0"
d="m 7.9824408,3.5290339 c -3.4339072,0 -6.4102945,1.9996258 -7.87290106,4.9205633 C 1.5721463,11.370534 4.5485336,13.37016 7.9824408,13.37016 c 3.4338472,0 6.4102342,-1.999626 7.8729012,-4.9205628 C 14.392765,5.5286597 11.416288,3.5290339 7.9824408,3.5290339 z m 3.8818632,2.6094964 c 0.925096,0.590068 1.709004,1.3804357 2.29781,2.3110669 -0.588806,0.9306312 -1.372744,1.7209988 -2.29784,2.3110968 -1.162392,0.741404 -2.5047196,1.133295 -3.8818332,1.133295 -1.377143,0 -2.7194718,-0.391891 -3.8818628,-1.133326 C 3.1755118,10.170626 2.3916036,9.380261 1.8027674,8.4495972 2.3915738,7.5189334 3.1755118,6.7285684 4.100578,6.1385303 4.160827,6.1000883 4.221686,6.0628483 4.2829153,6.0262824 c -0.1531228,0.4202145 -0.236925,0.873738 -0.236925,1.3469419 0,2.1740274 1.7624231,3.9364497 3.9364505,3.9364497 2.1740272,0 3.9364512,-1.7624223 3.9364512,-3.9364497 0,-0.4732039 -0.0838,-0.9267274 -0.236925,-1.3469745 0.0612,0.036566 0.122061,0.073839 0.182337,0.1122805 z M 7.9824408,6.8811665 c 0,0.8152761 -0.660894,1.4761705 -1.476168,1.4761705 -0.8152757,0 -1.4761697,-0.6608944 -1.4761697,-1.4761705 0,-0.8152759 0.660894,-1.4761676 1.4761697,-1.4761676 0.815274,0 1.476168,0.6608917 1.476168,1.4761676 z"
id="path3167" />
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">
<g transform="translate(-201.0002,-747)">
<path style="block-progression:tb;color:#bebebe;direction:ltr;text-indent:0;text-align:start;enable-background:new;text-transform:none;" d="m215.03,759,0-1c-0.00091-0.0111,0.00059-0.021-0.00009-0.0312-0.0112-0.25496-0.12835-0.50994-0.31251-0.6875l-5.7188-6.2977-5.7188,6.2977c-0.18821,0.1881-0.28121,0.45346-0.28122,0.71875v1h1c0.26531-0.00007,0.53059-0.0931,0.71873-0.28131l4.2812-4.829,4.2813,4.829c0.19464,0.21073,0.46925,0.30315,0.74998,0.2813z" fill-rule="nonzero" fill="#bebebe"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 604 B

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g transform="translate(-61-867)" fill="#fff" color="#000"><rect height="2" rx=".385" ry=".379" width="2" x="64" y="870"/><rect height="2" rx=".385" ry=".379" width="2" x="68" y="870"/><rect height="2" rx=".385" ry=".379" width="2" x="72" y="870"/><rect height="2" rx=".385" ry=".379" width="2" x="64" y="874.02"/><rect height="2" rx=".385" ry=".379" width="2" x="68" y="874.02"/><rect height="2" rx=".385" ry=".379" width="2" x="72" y="874.02"/><rect height="2" rx=".385" ry=".379" width="2" x="64" y="878"/><rect height="2" rx=".385" ry=".379" width="2" x="68" y="878"/><rect height="2" rx=".385" ry=".379" width="2" x="72" y="878"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g transform="translate(-61-867)" fill="#666" color="#000"><rect height="2" rx=".385" ry=".379" width="2" x="64" y="870"/><rect height="2" rx=".385" ry=".379" width="2" x="68" y="870"/><rect height="2" rx=".385" ry=".379" width="2" x="72" y="870"/><rect height="2" rx=".385" ry=".379" width="2" x="64" y="874.02"/><rect height="2" rx=".385" ry=".379" width="2" x="68" y="874.02"/><rect height="2" rx=".385" ry=".379" width="2" x="72" y="874.02"/><rect height="2" rx=".385" ry=".379" width="2" x="64" y="878"/><rect height="2" rx=".385" ry=".379" width="2" x="68" y="878"/><rect height="2" rx=".385" ry=".379" width="2" x="72" y="878"/></g></svg>

Before

Width:  |  Height:  |  Size: 705 B

After

Width:  |  Height:  |  Size: 705 B

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g transform="translate(-40-746)" fill="#fff" color="#fff"><path d="m43 749h10v2h-10z"/><path d="m43 753h10v2h-10z"/><path d="m43 757h10v2h-10z"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g transform="translate(-40-746)" fill="#666" color="#666"><path d="m43 749h10v2h-10z"/><path d="m43 753h10v2h-10z"/><path d="m43 757h10v2h-10z"/></g></svg>

Before

Width:  |  Height:  |  Size: 216 B

After

Width:  |  Height:  |  Size: 216 B

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g transform="translate(-181-867)" fill="#fff" color="#fff"><path d="m 181,868 0,1 0,11 0,1 1,0 5,0 c 0.1754,0 0.52538,0.15166 0.8125,0.34375 0.28712,0.19209 0.46875,0.375 0.46875,0.375 L 189,882.4375 l 0.71875,-0.75 c 0,0 0.8963,-0.6875 1.28125,-0.6875 l 5,0 1,0 0,-1 0,-11 0,-1 -1,0 -5,0 c -0.87652,0 -1.56017,0.34756 -2.03125,0.6875 -0.0301,-0.0207 -0.031,-0.0105 -0.0625,-0.0312 C 188.44557,868.35254 187.82811,868 187,868 l -5,0 -1,0 z m 2,2 4,0 c 0.13821,0 0.51476,0.14746 0.8125,0.34375 0.29774,0.19629 0.5,0.375 0.5,0.375 l 0.71875,0.6875 0.6875,-0.71875 c 0,0 0.89975,-0.6875 1.28125,-0.6875 l 4,0 0,9 -4,0 c -0.87693,0 -1.56008,0.34735 -2.03125,0.6875 -0.0196,-0.0135 -0.011,-0.0177 -0.0312,-0.0312 C 188.47725,879.34834 187.83512,879 187,879 l -4,0 0,-9 z"/><g transform="scale(-1 1)"><rect height="2" rx=".375" width="3" x="-187" y="872"/><rect height="2" rx=".375" width="3" x="-187" y="875"/><rect height="2" rx=".375" width="3" x="-194" y="872"/><rect height="2" rx=".375" width="3" x="-194" y="875"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g transform="translate(-181-867)" fill="#666" color="#666"><path d="m 181,868 0,1 0,11 0,1 1,0 5,0 c 0.1754,0 0.52538,0.15166 0.8125,0.34375 0.28712,0.19209 0.46875,0.375 0.46875,0.375 L 189,882.4375 l 0.71875,-0.75 c 0,0 0.8963,-0.6875 1.28125,-0.6875 l 5,0 1,0 0,-1 0,-11 0,-1 -1,0 -5,0 c -0.87652,0 -1.56017,0.34756 -2.03125,0.6875 -0.0301,-0.0207 -0.031,-0.0105 -0.0625,-0.0312 C 188.44557,868.35254 187.82811,868 187,868 l -5,0 -1,0 z m 2,2 4,0 c 0.13821,0 0.51476,0.14746 0.8125,0.34375 0.29774,0.19629 0.5,0.375 0.5,0.375 l 0.71875,0.6875 0.6875,-0.71875 c 0,0 0.89975,-0.6875 1.28125,-0.6875 l 4,0 0,9 -4,0 c -0.87693,0 -1.56008,0.34735 -2.03125,0.6875 -0.0196,-0.0135 -0.011,-0.0177 -0.0312,-0.0312 C 188.47725,879.34834 187.83512,879 187,879 l -4,0 0,-9 z"/><g transform="scale(-1 1)"><rect height="2" rx=".375" width="3" x="-187" y="872"/><rect height="2" rx=".375" width="3" x="-187" y="875"/><rect height="2" rx=".375" width="3" x="-194" y="872"/><rect height="2" rx=".375" width="3" x="-194" y="875"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -0,0 +1,7 @@
{
"name": "Screwdriver",
"author": "Mister aiR",
"description": "C'est un cocktail ! C'est chaud mais « fresh » à la fois. Ce thème tue du chaton.",
"version": 1.1,
"files": ["template.css","screwdriver.css"]
}

File diff suppressed because it is too large Load diff

View file

@ -2,10 +2,10 @@
/*=== GENERAL */ /*=== GENERAL */
/*============*/ /*============*/
html, body { html, body {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 100%; font-size: 92%;
} }
/*=== Links */ /*=== Links */

View file

@ -1,30 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:svg='http://www.w3.org/2000/svg' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' id='svg7384' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' version='1.1' inkscape:version='0.47 r22583' height='16' sodipodi:docname='list-add-symbolic.svg' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns='http://www.w3.org/2000/svg' width='16'>
<metadata id='metadata90'>
<rdf:RDF>
<cc:Work rdf:about=''>
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview inkscape:object-paths='true' inkscape:cy='17.83946' inkscape:current-layer='layer12' inkscape:window-width='1920' pagecolor='#555753' showborder='false' showguides='true' inkscape:snap-nodes='false' objecttolerance='10' showgrid='true' inkscape:object-nodes='true' inkscape:pageshadow='2' inkscape:guide-bbox='true' inkscape:window-x='0' inkscape:snap-bbox='true' bordercolor='#FFFFFF' id='namedview88' inkscape:window-maximized='1' inkscape:snap-global='true' inkscape:window-y='26' gridtolerance='10' inkscape:zoom='1' inkscape:window-height='1021' borderopacity='1' guidetolerance='10' inkscape:snap-bbox-midpoints='false' inkscape:cx='-2.56708' inkscape:bbox-paths='false' inkscape:snap-grids='true' inkscape:pageopacity='1' inkscape:snap-to-guides='true'>
<inkscape:grid visible='true' spacingx='1px' type='xygrid' spacingy='1px' id='grid4866' empspacing='2' enabled='true' snapvisiblegridlinesonly='true'/>
</sodipodi:namedview>
<title id='title9167'>Gnome Symbolic Icon Theme</title>
<defs id='defs7386'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer9' inkscape:label='status' style='display:inline'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer10' inkscape:label='devices'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer11' inkscape:label='apps'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer12' inkscape:label='actions'>
<path d='m 67.0002,729 0,4 -4,0 0,2 4,0 0,4 2,0 0,-4 4,0 0,-2 -4,0 0,-4 -2,0 z' id='rect31992' style='color:#FFFFFF;fill:#FFFFFF;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible'/>
</g>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer13' inkscape:label='places'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer14' inkscape:label='mimetypes'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='layer15' inkscape:label='emblems' style='display:inline'/>
<g transform='translate(-60.0002,-726)' inkscape:groupmode='layer' id='g4953' inkscape:label='categories' style='display:inline'/>
</svg>

Before

Width:  |  Height:  |  Size: 3 KiB

Some files were not shown because too many files have changed in this diff Show more