summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexis Degrugillier <github@ainw.org> 2014-01-03 00:03:28 -0500
committerGravatar Alexis Degrugillier <github@ainw.org> 2014-01-03 00:03:28 -0500
commitf0c2bb74ebbae1bd336d79a22c5ccf4080620bb4 (patch)
treeafc52950d50d5d4567437e42240b3998b51c4f6e
parent7db271e95ebab52c31c78f51270de71af1d750d2 (diff)
parent1d3ff88ae6cbb072f0d2a76308a42f2baf6cb84d (diff)
Merge branch 'dev' into shortcuts
-rw-r--r--CHANGELOG31
-rw-r--r--README.md17
-rwxr-xr-xapp/Controllers/configureController.php4
-rwxr-xr-xapp/Controllers/indexController.php2
-rw-r--r--app/FreshRSS.php2
-rwxr-xr-xapp/actualize_script.php21
-rw-r--r--app/i18n/install.en.php5
-rw-r--r--app/i18n/install.fr.php11
-rw-r--r--app/layout/layout.phtml4
-rw-r--r--app/views/helpers/view/normal_view.phtml2
-rw-r--r--app/views/javascript/actualize.phtml32
-rw-r--r--data/.gitignore1
-rw-r--r--lib/lib_rss.php15
-rw-r--r--p/favicon.icobin1150 -> 13094 bytes
-rw-r--r--p/favicon.pngbin694 -> 0 bytes
-rw-r--r--p/index.html4
-rw-r--r--p/themes/icons/favicon-128.pngbin0 -> 1608 bytes
-rw-r--r--p/themes/icons/favicon-16.pngbin0 -> 313 bytes
-rw-r--r--p/themes/icons/favicon-256.pngbin0 -> 3156 bytes
-rw-r--r--p/themes/icons/favicon-32.pngbin0 -> 513 bytes
-rw-r--r--p/themes/icons/favicon-48.pngbin0 -> 700 bytes
-rw-r--r--p/themes/icons/favicon-512.pngbin0 -> 6394 bytes
-rw-r--r--p/themes/icons/favicon-64.pngbin0 -> 868 bytes
23 files changed, 97 insertions, 54 deletions
diff --git a/CHANGELOG b/CHANGELOG
index f4b168b41..92658bbc9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,6 @@
# Journal des modifications
-## 2014-01-xx FreshRSS 0.7.5
+## 2014-01-xx FreshRSS 0.7
* Nouveau mode multi-utilisateur
* L’utilisateur par défaut (administrateur) peut créer et supprimer d’autres utilisateurs
@@ -8,21 +8,14 @@
* par HTTP (par exemple sous Apache en créant un fichier ./p/i/.htaccess et .htpasswd)
* le nom d’utilisateur HTTP doit correspondre au nom d’utilisateur FreshRSS
* par Mozilla Persona, en renseignant l’adresse courriel des utilisateurs
-* Options
- * Réorganisation des options
-* PHP
- * Compatibilité PHP 5.5+ avec OPcache
- * Amélioration des performances
-
-## 2014-01-xx FreshRSS 0.7
-
-* Installeur
- * Nouvel utilisateur par défaut, en prévision du futur support multi-utilisateurs
- * Supporte une mise à jour depuis la version 0.6
- * Juste placer application.ini et Configuration.array.php dans le nouveau répertoire “./data/”
+* Installateur supportant les mises à jour :
+ * Depuis une v0.6, placer application.ini et Configuration.array.php dans le nouveau répertoire “./data/” (voir réorganisation ci-dessous)
+ * Pour les versions suivantes, juste garder “./data/config.php” “./data/*_user.php”
* Importation OPML instantanée et plus tolérante
- * Nouvelle gestion des favicons avec téléchargement en parallèle et compatibilité multi-utilisateurs
+* Nouvelle gestion des favicons avec téléchargement en parallèle
* Nouvelles options
+ * Réorganisation des options
+ * Gestion des utilisateurs
* Améliorations partage vers Shaarli, Poche, Diaspora*, Facebook, Twitter, Google+, courriel
* Permet la suppression de tous les articles d’un flux
* Option pour marquer les articles comme lus dès la réception
@@ -30,18 +23,17 @@
* Permet de modifier la description et l’adresse d’un flux RSS ainsi que le site Web associé
* Nouveau raccourci pour ouvrir/fermer un article (‘c’ par défaut)
* Boutons pour effacer les logs et pour purger les vieux articles
- * Légère réorganisation des options
* SQL :
* Nouveau moteur de recherche, aussi accessible depuis la vue mobile
* Mots clefs de recherche “intitle:”, “inurl:”, “author:”
* Les articles sont triés selon la date de leur ajout dans FreshRSS plutôt que la date déclarée (souvent erronée)
* Permet de marquer tout comme lu sans affecter les nouveaux articles arrivés en cours de lecture
* Refactorisation
- * Les tables sont préfixées avec le nom d’utilisateur en prévision du futur support multi-utilisateurs
+ * Les tables sont préfixées avec le nom d’utilisateur afin de permettre le mode multi-utilisateurs
* Amélioration des performances
* Tolère un beaucoup plus grand nombre d’articles
* Compression des données côté MySQL plutôt que côté PHP
- * Incompatible avec la version 0.6 (nécessite une mise à jour grâce à l’installeur)
+ * Incompatible avec la version 0.6 (nécessite une mise à jour grâce à l’installateur)
* Affichage de la taille de la base de données dans FreshRSS
* Correction problème de marquage de tous les favoris comme lus
* HTML5 :
@@ -56,10 +48,11 @@
* FreshRSS fonctionne aussi en mode dégradé sans images (alternatives Unicode) et/ou sans CSS
* Diverses améliorations mineures
* PHP :
- * Meilleure gestion des caractères spéciaux dans différents cas
- * Amélioration des performances
* Encore plus tolérant pour les flux comportant des erreurs
* Mise à jour automatique de l’URL du flux (en base de données) lorsque SimplePie découvre qu’elle a changé
+ * Meilleure gestion des caractères spéciaux dans différents cas
+ * Compatibilité PHP 5.5+ avec OPcache
+ * Amélioration des performances
* Chargement automatique des classes
* Alternative dans le cas d’absence de librairie JSON
* Pour le développement, le cache HTTP peut être désactivé en créant un fichier “./no-cache.txt”
diff --git a/README.md b/README.md
index 0a5bca9f5..2edc33049 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,8 @@ Il permet de gérer plusieurs utilisateurs, et dispose d’un mode de lecture an
* Site officiel : http://freshrss.org
* Démo : http://marienfressinaud.fr/projets/freshrss/
* Développeur : Marien Fressinaud <dev@marienfressinaud.fr>
-* Version actuelle : 0.8-dev
-* Date de publication 2014-xx-xx
+* Version actuelle : 0.7-beta4
+* Date de publication 2014-01-xx
* 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)
@@ -22,8 +22,10 @@ Privilégiez pour cela des demandes sur GitHub
(https://github.com/marienfressinaud/FreshRSS/issues) ou par mail (dev@marienfressinaud.fr)
# Pré-requis
-* Serveur Apache2 ou Nginx (non testé sur les autres)
-* PHP 5.2+ (PHP 5.3.3+ recommandé)
+* 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)
+* Serveur Web Apache2 ou Nginx (non testé sur les autres)
+* PHP 5.2+ (PHP 5.3.4+ 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)
* Recommandés : [JSON](http://php.net/json), [zlib](http://php.net/zlib), [mbstring](http://php.net/mbstring), [iconv](http://php.net/iconv)
* MySQL 5.0.3+ (ou SQLite 3.7.4+ à venir)
@@ -47,10 +49,13 @@ Il est requis pour le mode multi-utilisateur, et recommandé dans tous les cas,
* Créer dans ce cas un fichier `./p/i/.htaccess` avec un fichier `.htpasswd` correspondant.
# Rafraîchissement automatique des flux
-* Vous pouvez ajouter une tâche CRON sur le script d’actualisation des flux. Par exemple, pour exécuter le script toutes les heures :
+* Vous pouvez ajouter une tâche Cron lançant régulièrement le script d’actualisation automatique des flux.
+Consultez la documentation de Cron de votre système d’exploitation ([Debian/Ubuntu](http://doc.ubuntu-fr.org/cron), [Red Hat/Fedora](http://doc.fedora-fr.org/wiki/CRON_:_Configuration_de_t%C3%A2ches_automatis%C3%A9es), [Slackware](http://docs.slackware.com/fr:slackbook:process_control?#cron), [Gentoo](http://wiki.gentoo.org/wiki/Cron/fr), [Arch Linux](http://wiki.archlinux.fr/Cron)…).
+C’est une bonne idée d’utiliser le même utilisateur que votre serveur Web (souvent “www-data”).
+Par exemple, pour exécuter le script toutes les heures :
```
-7 * * * * php /chemin/vers/FreshRSS/app/actualize_script.php >/dev/null 2>&1
+7 * * * * php /chemin/vers/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1
```
# Conseils
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php
index 0e4801a2d..0a403fc2d 100755
--- a/app/Controllers/configureController.php
+++ b/app/Controllers/configureController.php
@@ -100,12 +100,14 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$httpAuth = $user . ':' . $pass;
}
+ $cat = intval(Minz_Request::param('category', 0));
+
$values = array (
'name' => Minz_Request::param ('name', ''),
'description' => sanitizeHTML(Minz_Request::param('description', '', true)),
'website' => Minz_Request::param('website', ''),
'url' => Minz_Request::param('url', ''),
- 'category' => intval(Minz_Request::param ('category', 0)),
+ 'category' => $cat,
'pathEntries' => Minz_Request::param ('path_entries', ''),
'priority' => intval(Minz_Request::param ('priority', 0)),
'httpAuth' => $httpAuth,
diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php
index 5b51b3e28..690ca57be 100755
--- a/app/Controllers/indexController.php
+++ b/app/Controllers/indexController.php
@@ -133,7 +133,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
// Si on a récupéré aucun article "non lus"
// on essaye de récupérer tous les articles
- if ($state === 'not_read' && empty($entries)) { //TODO: Remove in v0.8
+ if ($state === 'not_read' && empty($entries)) {
Minz_Log::record ('Conflicting information about nbNotRead!', Minz_Log::DEBUG);
$this->view->state = 'all';
$entries = $this->entryDAO->listWhere($getType, $getId, 'all', $order, $nb, $first, $filter, $date_min, $keepHistoryDefault);
diff --git a/app/FreshRSS.php b/app/FreshRSS.php
index 4ebb6d631..f9857a4cb 100644
--- a/app/FreshRSS.php
+++ b/app/FreshRSS.php
@@ -6,7 +6,7 @@ class FreshRSS extends Minz_FrontController {
}
$this->accessControl(Minz_Session::param('currentUser', ''));
$this->loadParamsView();
- $this->loadStylesAndScripts();
+ $this->loadStylesAndScripts(); //TODO: Do not load that when not needed, e.g. some Ajax requests
$this->loadNotifications();
}
diff --git a/app/actualize_script.php b/app/actualize_script.php
index e0f995afe..9ac80a852 100755
--- a/app/actualize_script.php
+++ b/app/actualize_script.php
@@ -1,7 +1,20 @@
<?php
require(dirname(__FILE__) . '/../constants.php');
-//TODO: check if already running
+//<Mutex>
+$lock = DATA_PATH . '/actualize.lock.txt';
+if (file_exists($lock) && ((time() - @filemtime($lock)) > 3600)) {
+ @unlink($lock);
+}
+if (($handle = @fopen($lock, 'x')) === false) {
+ syslog(LOG_NOTICE, 'FreshRSS actualize already running?');
+ fwrite(STDERR, 'FreshRSS actualize already running?' . "\n");
+ return;
+}
+register_shutdown_function('unlink', $lock);
+//Could use http://php.net/function.pcntl-signal.php to catch interruptions
+@fclose($handle);
+//</Mutex>
require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader
@@ -10,8 +23,12 @@ ob_implicit_flush(false);
ob_start();
echo 'Results: ', "\n"; //Buffered
+Minz_Configuration::init();
+
$users = listUsers();
-shuffle($users);
+shuffle($users); //Process users in random order
+array_unshift($users, Minz_Configuration::defaultUser()); //But always start with admin
+$users = array_unique($users);
foreach ($users as $myUser) {
syslog(LOG_INFO, 'FreshRSS actualize ' . $myUser);
diff --git a/app/i18n/install.en.php b/app/i18n/install.en.php
index 8df48989f..4d8006977 100644
--- a/app/i18n/install.en.php
+++ b/app/i18n/install.en.php
@@ -5,6 +5,7 @@ return array (
'installation_step' => 'Installation - step %d',
'steps' => 'Steps',
'checks' => 'Checks',
+ 'general_configuration' => 'General configuration',
'bdd_configuration' => 'Database configuration',
'bdd_type' => 'Type of database',
'version_update' => 'Update',
@@ -31,6 +32,10 @@ return array (
'pdomysql_is_nok' => 'You lack PDO or its driver for MySQL (php5-mysql package)',
'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)',
+ 'pcre_is_ok' => 'You have the required library for regular expressions (PCRE)',
+ 'pcre_is_nok' => 'You lack a required library for regular expressions (php-pcre)',
+ 'ctype_is_ok' => 'You have the required library for character type checking (ctype)',
+ 'ctype_is_nok' => 'You lack a required library for character type checking (php-ctype)',
'cache_is_ok' => 'Permissions on cache directory are good',
'log_is_ok' => 'Permissions on logs directory are good',
'favicons_is_ok' => 'Permissions on favicons directory are good',
diff --git a/app/i18n/install.fr.php b/app/i18n/install.fr.php
index a1ae8fcb5..e9dba7c23 100644
--- a/app/i18n/install.fr.php
+++ b/app/i18n/install.fr.php
@@ -5,6 +5,7 @@ return array (
'installation_step' => 'Installation - étape %d',
'steps' => 'Étapes',
'checks' => 'Vérifications',
+ 'general_configuration' => 'Configuration générale',
'bdd_configuration' => 'Base de données',
'bdd_type' => 'Type de base de données',
'version_update' => 'Mise à jour',
@@ -26,11 +27,15 @@ return array (
'minz_is_ok' => 'Vous disposez du framework Minz',
'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_nok' => 'Vous ne disposez pas de cURL (librairie php5-curl)',
- 'pdomysql_is_ok' => 'Vous disposez de PDO et de son driver pour MySQL (librairie php5-mysql)',
+ '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)',
'pdomysql_is_nok' => 'Vous ne disposez pas de PDO ou de son driver pour MySQL',
'dom_is_ok' => 'Vous disposez du nécessaire pour parcourir le DOM',
- 'dom_is_nok' => 'Vous ne disposez pas du nécessaire pour parcourir le DOM (librairie 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_nok' => 'Il manque une librairie pour les expressions régulières (php-pcre)',
+ 'ctype_is_ok' => 'Vous disposez du nécessaire pour la vérification des types de caractères (ctype)',
+ 'ctype_is_nok' => 'Il manque une librairie pour la vérification des types de caractères (php-ctype)',
'cache_is_ok' => 'Les droits sur le répertoire de cache sont bons',
'log_is_ok' => 'Les droits sur le répertoire des logs sont bons',
'favicons_is_ok' => 'Les droits sur le répertoire des favicons sont bons',
diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml
index ae75c9bdb..e67d8a791 100644
--- a/app/layout/layout.phtml
+++ b/app/layout/layout.phtml
@@ -16,7 +16,8 @@
?>
<link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display (array ('c' => Minz_Request::controllerName (), 'a' => Minz_Request::actionName (), 'params' => $params)); ?>" />
<?php } ?>
- <link rel="icon" href="<?php echo Minz_Url::display ('/favicon.ico'); ?>" />
+ <link rel="shortcut icon" 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'); ?>" />
<?php if (isset ($this->rss_url)) { ?>
<link rel="alternate" type="application/rss+xml" title="<?php echo $this->rss_title; ?>" href="<?php echo Minz_Url::display ($this->rss_url); ?>" />
<?php } ?>
@@ -24,6 +25,7 @@
<link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('non-starred', true); ?>">
<link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('read', true); ?>">
<link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('unread', true); ?>">
+ <meta name="msapplication-TileColor" content="#FFF" />
<meta name="robots" content="noindex,nofollow" />
</head>
<body>
diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml
index 1b4388796..ce036e281 100644
--- a/app/views/helpers/view/normal_view.phtml
+++ b/app/views/helpers/view/normal_view.phtml
@@ -25,7 +25,7 @@ if (!empty($this->entries)) {
$bottomline_favorite = $this->conf->bottomline_favorite;
$bottomline_sharing = $this->conf->bottomline_sharing && (
$shaarli || $poche || $diaspora || $twitter ||
- $google_plus || $facebook || $email);
+ $google_plus || $facebook || $email || $print);
$bottomline_tags = $this->conf->bottomline_tags;
$bottomline_date = $this->conf->bottomline_date;
$bottomline_link = $this->conf->bottomline_link;
diff --git a/app/views/javascript/actualize.phtml b/app/views/javascript/actualize.phtml
index 69689133c..1f6072c29 100644
--- a/app/views/javascript/actualize.phtml
+++ b/app/views/javascript/actualize.phtml
@@ -1,37 +1,41 @@
-var feeds = new Array ();
+"use strict";
+var feeds = [];
<?php foreach ($this->feeds as $feed) { ?>
-feeds.push ("<?php echo Minz_Url::display (array ('c' => 'feed', 'a' => 'actualize', 'params' => array ('id' => $feed->id (), 'ajax' => '1')), 'php'); ?>");
+feeds.push("<?php echo Minz_Url::display (array ('c' => 'feed', 'a' => 'actualize', 'params' => array ('id' => $feed->id (), 'ajax' => '1')), 'php'); ?>");
<?php } ?>
-function initProgressBar (init) {
+function initProgressBar(init) {
if (init) {
- $("body").after ("\<div id=\"actualizeProgress\" class=\"actualizeProgress\">\
+ $("body").after("\<div id=\"actualizeProgress\" class=\"actualizeProgress\">\
<?php echo Minz_Translate::t ('refresh'); ?> <span class=\"progress\">0 / " + feeds.length + "</span><br />\
<progress id=\"actualizeProgressBar\" value=\"0\" max=\"" + feeds.length + "\"></progress>\
</div>");
} else {
- window.location.reload ();
+ window.location.reload();
}
}
-function updateProgressBar (i) {
+function updateProgressBar(i) {
$("#actualizeProgressBar").val(i);
- $("#actualizeProgress .progress").html (i + " / " + feeds.length);
+ $("#actualizeProgress .progress").html(i + " / " + feeds.length);
}
-function updateFeeds () {
- initProgressBar (true);
+function updateFeeds() {
+ if (feeds.length === 0) {
+ return;
+ }
+ initProgressBar(true);
var i = 0;
for (var f in feeds) {
- $.ajax ({
+ $.ajax({
type: 'POST',
url: feeds[f],
- }).done (function (data) {
+ }).done(function (data) {
i++;
- updateProgressBar (i);
+ updateProgressBar(i);
- if (i == feeds.length) {
- initProgressBar (false);
+ if (i === feeds.length) {
+ initProgressBar(false);
}
});
}
diff --git a/data/.gitignore b/data/.gitignore
index 005982b00..afb16d9aa 100644
--- a/data/.gitignore
+++ b/data/.gitignore
@@ -5,3 +5,4 @@ config.php
touch.txt
no-cache.txt
*.bak.php
+*.lock.txt
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index ae3e4808d..4f98ed14a 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -91,10 +91,17 @@ function timestamptodate ($t, $hour = true) {
function html_only_entity_decode($text) {
static $htmlEntitiesOnly = null;
if ($htmlEntitiesOnly === null) {
- $htmlEntitiesOnly = array_flip(array_diff(
- get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES, 'UTF-8'), //Decode HTML entities
- get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES, 'UTF-8') //Preserve XML entities
- ));
+ if (version_compare(PHP_VERSION, '5.3.4') >= 0) {
+ $htmlEntitiesOnly = array_flip(array_diff(
+ get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES, 'UTF-8'), //Decode HTML entities
+ get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES, 'UTF-8') //Preserve XML entities
+ ));
+ } else {
+ $htmlEntitiesOnly = array_map('utf8_encode', array_flip(array_diff(
+ get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES), //Decode HTML entities
+ get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES) //Preserve XML entities
+ )));
+ }
}
return strtr($text, $htmlEntitiesOnly);
}
diff --git a/p/favicon.ico b/p/favicon.ico
index f7ae0a5b9..a2c3bc84e 100644
--- a/p/favicon.ico
+++ b/p/favicon.ico
Binary files differ
diff --git a/p/favicon.png b/p/favicon.png
deleted file mode 100644
index 3038dc3d1..000000000
--- a/p/favicon.png
+++ /dev/null
Binary files differ
diff --git a/p/index.html b/p/index.html
index eaa0d71f8..5adacab2c 100644
--- a/p/index.html
+++ b/p/index.html
@@ -5,8 +5,10 @@
<meta name="viewport" content="initial-scale=1.0" />
<meta http-equiv="Refresh" content="0; url=i/" />
<title>FreshRSS</title>
+<link rel="shortcut icon" type="image/x-icon" sizes="16x16 64x64" href="favicon.ico" />
+<link rel="icon msapplication-TileImage apple-touch-icon" type="image/png" sizes="256x256" href="themes/icons/favicon-256.png" />
+<meta name="msapplication-TileColor" content="#FFF" />
<meta name="robots" content="noindex,nofollow" />
-<link rel="icon" href="favicon.ico" />
<style>
body {
font-family: sans-serif;
diff --git a/p/themes/icons/favicon-128.png b/p/themes/icons/favicon-128.png
new file mode 100644
index 000000000..329b5c0f6
--- /dev/null
+++ b/p/themes/icons/favicon-128.png
Binary files differ
diff --git a/p/themes/icons/favicon-16.png b/p/themes/icons/favicon-16.png
new file mode 100644
index 000000000..abe71c491
--- /dev/null
+++ b/p/themes/icons/favicon-16.png
Binary files differ
diff --git a/p/themes/icons/favicon-256.png b/p/themes/icons/favicon-256.png
new file mode 100644
index 000000000..9d9a11904
--- /dev/null
+++ b/p/themes/icons/favicon-256.png
Binary files differ
diff --git a/p/themes/icons/favicon-32.png b/p/themes/icons/favicon-32.png
new file mode 100644
index 000000000..cfada8c46
--- /dev/null
+++ b/p/themes/icons/favicon-32.png
Binary files differ
diff --git a/p/themes/icons/favicon-48.png b/p/themes/icons/favicon-48.png
new file mode 100644
index 000000000..870b43ef1
--- /dev/null
+++ b/p/themes/icons/favicon-48.png
Binary files differ
diff --git a/p/themes/icons/favicon-512.png b/p/themes/icons/favicon-512.png
new file mode 100644
index 000000000..cc8d9b559
--- /dev/null
+++ b/p/themes/icons/favicon-512.png
Binary files differ
diff --git a/p/themes/icons/favicon-64.png b/p/themes/icons/favicon-64.png
new file mode 100644
index 000000000..5ee379f19
--- /dev/null
+++ b/p/themes/icons/favicon-64.png
Binary files differ