diff options
Diffstat (limited to 'public')
54 files changed, 956 insertions, 656 deletions
diff --git a/public/.htaccess b/public/.htaccess index 8653826f8..fefe8b226 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -27,7 +27,7 @@ AddDefaultCharset UTF-8 ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" - ExpiresByType image/x-icon "access plus 1 year" + ExpiresByType image/x-icon "access plus 1 month" ExpiresByType text/css "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" <FilesMatch "\.php$"> diff --git a/public/data/.gitignore b/public/data/.gitignore deleted file mode 100644 index 8498bc17e..000000000 --- a/public/data/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -favicons -Configuration.array.php -*.sqlite -touch.txt
\ No newline at end of file diff --git a/public/f.php b/public/f.php new file mode 100644 index 000000000..a56d58617 --- /dev/null +++ b/public/f.php @@ -0,0 +1,70 @@ +<?php +require('../constants.php'); +$favicons_dir = DATA_PATH . '/favicons/'; + +/* Télécharge le favicon d'un site et le place sur le serveur */ +function download_favicon ($website, $dest) { + $ok = false; + $url = 'http://g.etfv.co/' . $website; + + /*if (!is_dir ($favicons_dir)) { + if (!mkdir ($favicons_dir, 0755, true)) { + header('Location: ' . $url); + return false; + } + }*/ + + $c = curl_init ($url); + curl_setopt ($c, CURLOPT_HEADER, false); + curl_setopt ($c, CURLOPT_RETURNTRANSFER, true); + curl_setopt ($c, CURLOPT_BINARYTRANSFER, true); + $imgRaw = curl_exec ($c); + + if (curl_getinfo ($c, CURLINFO_HTTP_CODE) == 200) { + $file = fopen ($dest, 'w'); + if ($file !== false) { + fwrite ($file, $imgRaw); + fclose ($file); + $ok = true; + } + } + curl_close ($c); + if (!$ok) { + header('Location: ' . $url); + return false; + } + return true; +} + +$id = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '0'; +if (!ctype_digit($id)) { + $id = '0'; +} + +$txt = $favicons_dir . $id . '.txt'; +$ico = $favicons_dir . $id . '.ico'; + +$icoMTime = @filemtime($ico); +$txtMTime = @filemtime($txt); + +if (($icoMTime == false) || ($txtMTime > $icoMTime)) { + if ($txtMTime == false) { + header('HTTP/1.1 404 Not Found'); + header('Content-Type: image/gif'); + readfile(PUBLIC_PATH . '/themes/icons/grey.gif'); //TODO: Better 404 favicon + die(); + } + $url = file_get_contents($txt); + if (!download_favicon($url, $ico)) { + die(); + } +} + +require(LIB_PATH . '/http-conditional.php'); + +header('Content-Type: image/x-icon'); +header('Content-Disposition: inline; filename="' . $id . '.ico"'); + +if (!httpConditional($icoMTime, 2592000, 2)) { + readfile($ico); +} diff --git a/public/index.php b/public/index.php index d3b752905..c8b15b3d9 100755 --- a/public/index.php +++ b/public/index.php @@ -18,45 +18,34 @@ # # ***** END LICENSE BLOCK ***** -// Constantes de chemins -define ('PUBLIC_PATH', realpath (dirname (__FILE__))); -define ('LIB_PATH', realpath (PUBLIC_PATH . '/../lib')); -define ('APP_PATH', realpath (PUBLIC_PATH . '/../app')); -define ('LOG_PATH', realpath (PUBLIC_PATH . '/../log')); -define ('CACHE_PATH', realpath (PUBLIC_PATH . '/../cache')); - -if (file_exists (PUBLIC_PATH . '/install.php')) { - include ('install.php'); +if (file_exists ('install.php')) { + require('install.php'); } else { + require('../constants.php'); + session_cache_limiter(''); - require (LIB_PATH . '/http-conditional.php'); - $dateLastModification = max( - @filemtime(PUBLIC_PATH . '/data/touch.txt'), - @filemtime(LOG_PATH . '/application.log'), - @filemtime(PUBLIC_PATH . '/data/Configuration.array.php'), - @filemtime(APP_PATH . '/configuration/application.ini'), - time() - 14400 - ); - if (httpConditional($dateLastModification, 0, 0, false, false, true)) { - exit(); //No need to send anything + if (!file_exists(DATA_PATH . '/no-cache.txt')) { + require (LIB_PATH . '/http-conditional.php'); + $dateLastModification = max( + @filemtime(DATA_PATH . '/touch.txt'), + @filemtime(LOG_PATH . '/application.log'), + @filemtime(DATA_PATH . '/config.php') + ); + $_SERVER['QUERY_STRING'] .= '&utime=' . file_get_contents(DATA_PATH . '/touch.txt'); //For ETag + if (httpConditional($dateLastModification, 0, 0, false, false, true)) { + exit(); //No need to send anything + } } - set_include_path (get_include_path () - . PATH_SEPARATOR - . LIB_PATH - . PATH_SEPARATOR - . LIB_PATH . '/minz' - . PATH_SEPARATOR - . APP_PATH); - - require (APP_PATH . '/App_FrontController.php'); + require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader try { - $front_controller = new App_FrontController (); + $front_controller = new FreshRSS(); $front_controller->init (); $front_controller->run (); - } catch (PDOConnectionException $e) { + } catch (Exception $e) { + echo '### Fatal error! ###<br />', "\n"; Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); - print '### Application problem ###<br />'."\n".'See logs files'; + echo 'See logs files.'; } } diff --git a/public/install.php b/public/install.php index fa4d59f20..377b2916d 100644 --- a/public/install.php +++ b/public/install.php @@ -1,4 +1,6 @@ <?php +require('../constants.php'); +include(LIB_PATH . '/lib_rss.php'); session_start (); @@ -8,48 +10,125 @@ if (isset ($_GET['step'])) { define ('STEP', 1); } -define ('SQL_REQ_CREATE_DB', 'CREATE DATABASE %s DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); - -define ('SQL_REQ_CAT', 'CREATE TABLE IF NOT EXISTS `%scategory` ( - `id` varchar(6) NOT NULL, - `name` varchar(255) NOT NULL, - `color` varchar(7) NOT NULL, - PRIMARY KEY (`id`) -);'); - -define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( - `id` varchar(6) NOT NULL, - `url` text NOT NULL, - `category` varchar(6) DEFAULT \'000000\', - `name` varchar(255) NOT NULL, - `website` text NOT NULL, - `description` text NOT NULL, - `lastUpdate` int(11) NOT NULL, - `priority` int(2) NOT NULL DEFAULT \'10\', - `pathEntries` varchar(500) DEFAULT NULL, - `httpAuth` varchar(500) DEFAULT NULL, - `error` int(1) NOT NULL DEFAULT \'0\', - `keep_history` int(1) NOT NULL DEFAULT \'0\', - PRIMARY KEY (`id`), - FOREIGN KEY (`category`) REFERENCES %scategory(id) ON DELETE SET NULL ON UPDATE CASCADE -);'); - -define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( - `id` varchar(6) NOT NULL, - `guid` text NOT NULL, - `title` varchar(255) NOT NULL, - `author` varchar(255) NOT NULL, - `content` text NOT NULL, - `link` text NOT NULL, - `date` int(11) NOT NULL, - `is_read` int(11) NOT NULL DEFAULT \'0\', - `is_favorite` int(11) NOT NULL DEFAULT \'0\', - `id_feed` varchar(6) NOT NULL, - `tags` text NOT NULL, - PRIMARY KEY (`id`), - FOREIGN KEY (`id_feed`) REFERENCES %sfeed(id) ON DELETE CASCADE ON UPDATE CASCADE -);'); - +define ('SQL_CREATE_DB', 'CREATE DATABASE %1$s DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); + +define ('SQL_CAT', 'CREATE TABLE IF NOT EXISTS `%1$scategory` ( + `id` SMALLINT NOT NULL AUTO_INCREMENT, -- v0.7 + `name` varchar(255) NOT NULL, + `color` char(7), + PRIMARY KEY (`id`), + UNIQUE KEY (`name`) -- v0.7 +) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci +ENGINE = INNODB;'); + +define ('SQL_FEED', 'CREATE TABLE IF NOT EXISTS `%1$sfeed` ( + `id` SMALLINT NOT NULL AUTO_INCREMENT, -- v0.7 + `url` varchar(511) CHARACTER SET latin1 NOT NULL, + `category` SMALLINT DEFAULT 0, -- v0.7 + `name` varchar(255) NOT NULL, + `website` varchar(255) CHARACTER SET latin1, + `description` text, + `lastUpdate` int(11) DEFAULT 0, + `priority` tinyint(2) NOT NULL DEFAULT 10, + `pathEntries` varchar(511) DEFAULT NULL, + `httpAuth` varchar(511) DEFAULT NULL, + `error` boolean DEFAULT 0, + `keep_history` boolean NOT NULL DEFAULT 0, + `cache_nbEntries` int DEFAULT 0, -- v0.7 + `cache_nbUnreads` int DEFAULT 0, -- v0.7 + PRIMARY KEY (`id`), + FOREIGN KEY (`category`) REFERENCES `%1$scategory`(`id`) ON DELETE SET NULL ON UPDATE CASCADE, + UNIQUE KEY (`url`), -- v0.7 + INDEX (`name`), -- v0.7 + INDEX (`priority`), -- v0.7 + INDEX (`keep_history`) -- v0.7 +) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci +ENGINE = INNODB;'); + +define ('SQL_ENTRY', 'CREATE TABLE IF NOT EXISTS `%1$sentry` ( + `id` bigint NOT NULL, -- v0.7 + `guid` varchar(760) CHARACTER SET latin1 NOT NULL, -- Maximum for UNIQUE is 767B + `title` varchar(255) NOT NULL, + `author` varchar(255), + `content_bin` blob, -- v0.7 + `link` varchar(1023) CHARACTER SET latin1 NOT NULL, + `date` int(11), + `is_read` boolean NOT NULL DEFAULT 0, + `is_favorite` boolean NOT NULL DEFAULT 0, + `id_feed` SMALLINT, -- v0.7 + `tags` varchar(1023), + PRIMARY KEY (`id`), + FOREIGN KEY (`id_feed`) REFERENCES `%1$sfeed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE, + UNIQUE KEY (`id_feed`,`guid`), -- v0.7 + INDEX (`is_favorite`), -- v0.7 + INDEX (`is_read`) -- v0.7 +) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci +ENGINE = INNODB;'); + +//<updates> +define('SQL_SHOW_TABLES', 'SHOW tables;'); + +define('SQL_BACKUP006', 'RENAME TABLE `%1$scategory` TO `%1$scategory006`, `%1$sfeed` TO `%1$sfeed006`, `%1$sentry` TO `%1$sentry006`;'); + +define('SQL_SHOW_COLUMNS_UPDATEv006', 'SHOW columns FROM `%1$sentry006` LIKE "id2";'); + +define('SQL_UPDATEv006', ' +ALTER TABLE `%1$scategory006` ADD id2 SMALLINT; + +SET @i = 0; +UPDATE `%1$scategory006` SET id2=(@i:=@i+1) ORDER BY id; + +ALTER TABLE `%1$sfeed006` ADD id2 SMALLINT, ADD category2 SMALLINT; + +SET @i = 0; +UPDATE `%1$sfeed006` SET id2=(@i:=@i+1) ORDER BY name; + +UPDATE `%1$sfeed006` f +INNER JOIN `%1$scategory006` c ON f.category = c.id +SET f.category2 = c.id2; + +INSERT IGNORE INTO `%2$scategory` (name, color) +SELECT name, color +FROM `%1$scategory006` +ORDER BY id2; + +INSERT IGNORE INTO `%2$sfeed` (url, category, name, website, description, priority, pathEntries, httpAuth, keep_history) +SELECT url, category2, name, website, description, priority, pathEntries, httpAuth, keep_history +FROM `%1$sfeed006` +ORDER BY id2; + +ALTER TABLE `%1$sentry006` ADD id2 bigint; + +UPDATE `%1$sentry006` SET id2 = ((date * 1000000) + (rand() * 100000000)); + +INSERT IGNORE INTO `%2$sentry` (id, guid, title, author, link, date, is_read, is_favorite, id_feed, tags) +SELECT e0.id2, e0.guid, e0.title, e0.author, e0.link, e0.date, e0.is_read, e0.is_favorite, f0.id2, e0.tags +FROM `%1$sentry006` e0 +INNER JOIN `%1$sfeed006` f0 ON e0.id_feed = f0.id; +'); + +define('SQL_CONVERT_SELECTv006', ' +SELECT e0.id2, e0.content +FROM `%1$sentry006` e0 +INNER JOIN `%2$sentry` e1 ON e0.id2 = e1.id +WHERE e1.content_bin IS NULL'); + +define('SQL_CONVERT_UPDATEv006', 'UPDATE `%1$sentry` SET content_bin=COMPRESS(?) WHERE id=?;'); + +define('SQL_UPDATE_CACHED_VALUESv006', ' +UPDATE `%1$sfeed` f +INNER JOIN ( + SELECT e.id_feed, + COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, + COUNT(e.id) AS nbEntries + FROM `%1$sentry` e + GROUP BY e.id_feed +) x ON x.id_feed=f.id +SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads +'); + +define('SQL_DROP_BACKUPv006', 'DROP TABLE IF EXISTS `%1$sentry006`, `%1$sfeed006`, `%1$scategory006`;'); +//</updates> function writeLine ($f, $line) { fwrite ($f, $line . "\n"); @@ -66,15 +145,6 @@ function writeArray ($f, $array) { } } -function small_hash ($txt) { - $t = rtrim (base64_encode (hash ('crc32', $txt, true)), '='); - $t = str_replace ('+', '-', $t); // Get rid of characters which need encoding in URLs. - $t = str_replace ('/', '_', $t); - $t = str_replace ('=', '@', $t); - - return $t; -} - // gestion internationalisation $translates = array (); $actual = 'en'; @@ -82,15 +152,16 @@ function initTranslate () { global $translates; global $actual; - $l = getBetterLanguage ('en'); - if (isset ($_SESSION['language'])) { - $l = $_SESSION['language']; - } - $actual = $l; + $actual = isset($_SESSION['language']) ? $_SESSION['language'] : getBetterLanguage('en'); $file = APP_PATH . '/i18n/' . $actual . '.php'; - if (file_exists ($file)) { - $translates = include ($file); + if (file_exists($file)) { + $translates = array_merge($translates, include($file)); + } + + $file = APP_PATH . '/i18n/install.' . $actual . '.php'; + if (file_exists($file)) { + $translates = array_merge($translates, include($file)); } } function getBetterLanguage ($fallback) { @@ -138,29 +209,26 @@ function saveLanguage () { function saveStep2 () { if (!empty ($_POST)) { if (empty ($_POST['title']) || - empty ($_POST['old_entries'])) { + empty ($_POST['old_entries']) || + empty ($_POST['default_user']) { return false; } - $_SESSION['sel'] = md5 ( - uniqid (mt_rand (), true).implode ('', stat (__FILE__)) - ); - $_SESSION['base_url'] = addslashes ($_POST['base_url']); - $_SESSION['title'] = addslashes ($_POST['title']); + $_SESSION['sel_application'] = sha1(uniqid(mt_rand(), true).implode('', stat(__FILE__))); + $_SESSION['title'] = addslashes(substr(trim($_POST['title']), 0, 25)); $_SESSION['old_entries'] = $_POST['old_entries']; - if (!is_int (intval ($_SESSION['old_entries'])) || - $_SESSION['old_entries'] < 1) { + if ((!ctype_digit($_SESSION['old_entries'])) || ($_SESSION['old_entries'] < 1)) { $_SESSION['old_entries'] = 3; } $_SESSION['mail_login'] = addslashes ($_POST['mail_login']); + $_SESSION['default_user'] = substr(preg_replace ('/[^a-zA-Z0-9]/', '', $_POST['default_user']), 0, 16); $token = ''; if ($_SESSION['mail_login']) { - $token = small_hash (time () . $_SESSION['sel']) - . small_hash ($_SESSION['base_url'] . $_SESSION['sel']); + $token = sha1($_SESSION['sel_application'] . $_SESSION['mail_login']); } - $file_data = PUBLIC_PATH . '/data/Configuration.array.php'; + $file_data = DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'; $f = fopen ($file_data, 'w'); writeLine ($f, '<?php'); @@ -177,6 +245,7 @@ function saveStep2 () { header ('Location: index.php?step=3'); } } + function saveStep3 () { if (!empty ($_POST)) { if (empty ($_POST['type']) || @@ -189,26 +258,34 @@ function saveStep3 () { $_SESSION['bd_type'] = isset ($_POST['type']) ? $_POST['type'] : 'mysql'; $_SESSION['bd_host'] = addslashes ($_POST['host']); $_SESSION['bd_user'] = addslashes ($_POST['user']); - $_SESSION['bd_pass'] = addslashes ($_POST['pass']); - $_SESSION['bd_name'] = addslashes ($_POST['base']); + $_SESSION['bd_password'] = addslashes ($_POST['pass']); + $_SESSION['bd_base'] = addslashes ($_POST['base']); $_SESSION['bd_prefix'] = addslashes ($_POST['prefix']); + $_SESSION['bd_prefix_user'] = $_SESSION['bd_prefix'] . (empty($_SESSION['default_user']) ? '' : ($_SESSION['default_user'] . '_')); + + $ini_array = array( + 'general' => array( + 'environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], + 'use_url_rewriting' => false, + 'sel_application' => $_SESSION['sel_application'], + 'base_url' => '', + 'title' => $_SESSION['title'], + 'default_user' => $_SESSION['default_user'], + ), + 'db' => array( + 'type' => $_SESSION['bd_type'], + 'host' => $_SESSION['bd_host'], + 'user' => $_SESSION['bd_user'], + 'password' => $_SESSION['bd_password'], + 'base' => $_SESSION['bd_base'], + 'prefix' => $_SESSION['bd_prefix'], + ), + ); + file_put_contents(DATA_PATH . '/config.php', "<?php\n return " . var_export($ini_array, true) . ';'); - $file_conf = APP_PATH . '/configuration/application.ini'; - $f = fopen ($file_conf, 'w'); - writeLine ($f, '[general]'); - writeLine ($f, 'environment = "production"'); - writeLine ($f, 'use_url_rewriting = false'); - writeLine ($f, 'sel_application = "' . $_SESSION['sel'] . '"'); - writeLine ($f, 'base_url = "' . $_SESSION['base_url'] . '"'); - writeLine ($f, 'title = "' . $_SESSION['title'] . '"'); - writeLine ($f, '[db]'); - writeLine ($f, 'type = "' . $_SESSION['bd_type'] . '"'); - writeLine ($f, 'host = "' . $_SESSION['bd_host'] . '"'); - writeLine ($f, 'user = "' . $_SESSION['bd_user'] . '"'); - writeLine ($f, 'password = "' . $_SESSION['bd_pass'] . '"'); - writeLine ($f, 'base = "' . $_SESSION['bd_name'] . '"'); - writeLine ($f, 'prefix = "' . $_SESSION['bd_prefix'] . '"'); - fclose ($f); + if (file_exists(DATA_PATH . '/config.php') && file_exists(DATA_PATH . '/application.ini')) { + @unlink(DATA_PATH . '/application.ini'); //v0.6 + } $res = checkBD (); @@ -219,12 +296,171 @@ function saveStep3 () { $_SESSION['bd_error'] = true; } } + invalidateHttpCache(); +} + +function updateDatabase($perform = false) { + $needs = array('bd_type', 'bd_host', 'bd_base', 'bd_user', 'bd_password', 'bd_prefix', 'bd_prefix_user'); + foreach ($needs as $need) { + if (!isset($_SESSION[$need])) { + return false; + } + } + + try { + $str = ''; + switch ($_SESSION['bd_type']) { + case 'mysql': + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', + ); + break; + case 'sqlite': + $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_base'] . '.sqlite'; + $driver_options = null; + break; + default: + return false; + } + + $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + + $stm = $c->prepare(SQL_SHOW_TABLES); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + if (!in_array($_SESSION['bd_prefix'] . 'entry006', $res)) { + return false; + } + + $sql = sprintf(SQL_SHOW_COLUMNS_UPDATEv006, $_SESSION['bd_prefix']); + $stm = $c->prepare($sql); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + if (!in_array('id2', $res)) { + if (!$perform) { + return true; + } + $sql = sprintf(SQL_UPDATEv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true)); + $stm->execute(); + } + + $sql = sprintf(SQL_UPDATE_CACHED_VALUESv006, $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql); + $stm->execute(); + + $sql = sprintf(SQL_CONVERT_SELECTv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']); + if (!$perform) { + $sql .= ' LIMIT 1'; + } + $stm = $c->prepare($sql); + $stm->execute(); + if (!$perform) { + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + return count($res) > 0; + } else { + @set_time_limit(300); + } + + $c2 = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + $sql = sprintf(SQL_CONVERT_UPDATEv006, $_SESSION['bd_prefix_user']); + $stm2 = $c2->prepare($sql); + while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { + $id = $row['id2']; + $content = unserialize(gzinflate(base64_decode($row['content']))); + $stm2->execute(array($content, $id)); + } + return true; + } catch (PDOException $e) { + return false; + } + return false; } + function deleteInstall () { $res = unlink (PUBLIC_PATH . '/install.php'); if ($res) { header ('Location: index.php'); } + + $needs = array('bd_type', 'bd_host', 'bd_base', 'bd_user', 'bd_password', 'bd_prefix'); + foreach ($needs as $need) { + if (!isset($_SESSION[$need])) { + return false; + } + } + + try { + switch ($_SESSION['bd_type']) { + case 'mysql': + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', + ); + break; + case 'sqlite': + $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_base'] . '.sqlite'; + $driver_options = null; + break; + default: + return false; + } + + $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + $sql = sprintf(SQL_DROP_BACKUPv006, $_SESSION['bd_prefix']); + $stm = $c->prepare($sql); + $stm->execute(); + + return true; + } catch (PDOException $e) { + return false; + } + return false; +} + +function moveOldFiles() { + $mvs = array( + '/app/configuration/application.ini' => '/data/application.ini', //v0.6 + '/public/data/Configuration.array.php' => '/data/Configuration.array.php', //v0.6 + ); + $ok = true; + foreach ($mvs as $fFrom => $fTo) { + if (file_exists(FRESHRSS_PATH . $fFrom)) { + if (copy(FRESHRSS_PATH . $fFrom, FRESHRSS_PATH . $fTo)) { + @unlink(FRESHRSS_PATH . $fFrom); + } else { + $ok = false; + } + } + } + return $ok; +} + +function delTree($dir) { //http://php.net/rmdir#110489 + if (!is_dir($dir)) { + return true; + } + $files = array_diff(scandir($dir), array('.', '..')); + foreach ($files as $file) { + $f = $dir . '/' . $file; + if (is_dir($f)) { + @chmod($f, 0777); + delTree($f); + } + else unlink($f); + } + return rmdir($dir); +} + +function removeOldFiles() { + $oldDirs = array('/app/configuration/', '/cache/', '/log/', '/public/data/', '/public/themes/printer/'); //v0.6 + + $ok = true; + foreach ($oldDirs as $oldDir) { + $ok &= delTree(FRESHRSS_PATH . $oldDir); + } + return $ok; } /*** VÉRIFICATIONS ***/ @@ -244,6 +480,52 @@ function checkStep () { } } function checkStep0 () { + moveOldFiles() && removeOldFiles(); + + if (file_exists(DATA_PATH . '/config.php')) { + $ini_array = include(DATA_PATH . '/config.php'); + } elseif (file_exists(DATA_PATH . '/application.ini')) { + $ini_array = parse_ini_file(DATA_PATH . '/application.ini', true); + } else { + $ini_array = null; + } + + if ($ini_array) { + $ini_general = isset($ini_array['general']) ? $ini_array['general'] : null; + if ($ini_general) { + $keys = array('environment', 'sel_application', 'title', 'default_user'); + foreach ($keys as $key) { + if ((empty($_SESSION[$key])) && isset($ini_general[$key])) { + $_SESSION[$key] = $ini_general[$key]; + } + } + } + $ini_db = isset($ini_array['db']) ? $ini_array['db'] : null; + if ($ini_db) { + $keys = array('type', 'host', 'user', 'password', 'base', 'prefix'); + foreach ($keys as $key) { + if ((!isset($_SESSION['bd_' . $key])) && isset($ini_db[$key])) { + $_SESSION['bd_' . $key] = $ini_db[$key]; + } + } + } + } + + if (isset($_SESSION['default_user']) && file_exists(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php')) { + $userConfig = include(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'); + } elseif (file_exists(DATA_PATH . '/Configuration.array.php')) { + $userConfig = include(DATA_PATH . '/Configuration.array.php'); //v0.6 + } else { + $userConfig = array(); + } + + $keys = array('language', 'old_entries', 'mail_login'); + foreach ($keys as $key) { + if ((!isset($_SESSION[$key])) && isset($userConfig[$key])) { + $_SESSION[$key] = $userConfig[$key]; + } + } + $languages = availableLanguages (); $language = isset ($_SESSION['language']) && isset ($languages[$_SESSION['language']]); @@ -254,15 +536,15 @@ function checkStep0 () { ); } function checkStep1 () { - $php = version_compare (PHP_VERSION, '5.1.0') >= 0; - $minz = file_exists (LIB_PATH . '/minz'); + $php = version_compare (PHP_VERSION, '5.2.0') >= 0; + $minz = file_exists (LIB_PATH . '/Minz'); $curl = extension_loaded ('curl'); $pdo = extension_loaded ('pdo_mysql'); $dom = class_exists('DOMDocument'); + $data = DATA_PATH && is_writable (DATA_PATH); $cache = CACHE_PATH && is_writable (CACHE_PATH); $log = LOG_PATH && is_writable (LOG_PATH); - $conf = APP_PATH && is_writable (APP_PATH . '/configuration'); - $data = is_writable (PUBLIC_PATH . '/data'); + $favicons = is_writable (DATA_PATH . '/favicons'); return array ( 'php' => $php ? 'ok' : 'ko', @@ -270,20 +552,28 @@ function checkStep1 () { 'curl' => $curl ? 'ok' : 'ko', 'pdo-mysql' => $pdo ? 'ok' : 'ko', 'dom' => $dom ? 'ok' : 'ko', + 'data' => $data ? 'ok' : 'ko', 'cache' => $cache ? 'ok' : 'ko', 'log' => $log ? 'ok' : 'ko', - 'configuration' => $conf ? 'ok' : 'ko', - 'data' => $data ? 'ok' : 'ko', - 'all' => $php && $minz && $curl && $pdo && $dom && $cache && $log && $conf && $data ? 'ok' : 'ko' + 'favicons' => $favicons ? 'ok' : 'ko', + 'all' => $php && $minz && $curl && $pdo && $dom && $data && $cache && $log && $favicons ? 'ok' : 'ko' ); } + function checkStep2 () { - $conf = isset ($_SESSION['sel']) && - isset ($_SESSION['base_url']) && - isset ($_SESSION['title']) && - isset ($_SESSION['old_entries']) && - isset ($_SESSION['mail_login']); - $data = file_exists (PUBLIC_PATH . '/data/Configuration.array.php'); + $conf = !empty($_SESSION['sel_application']) && + !empty($_SESSION['title']) && + !empty($_SESSION['old_entries']) && + isset($_SESSION['mail_login']) && + !empty($_SESSION['default_user']); + $defaultUser = empty($_POST['default_user']) ? null : $_POST['default_user']; + if ($defaultUser === null) { + $defaultUser = empty($_SESSION['default_user']) ? '' : $_SESSION['default_user']; + } + $data = file_exists (DATA_PATH . '/' . $defaultUser . '_user.php'); + if ($data) { + @unlink(DATA_PATH . '/Configuration.array.php'); //v0.6 + } return array ( 'conf' => $conf ? 'ok' : 'ko', @@ -292,12 +582,15 @@ function checkStep2 () { ); } function checkStep3 () { - $conf = file_exists (APP_PATH . '/configuration/application.ini'); + $conf = file_exists (DATA_PATH . '/config.php'); + $bd = isset ($_SESSION['bd_type']) && isset ($_SESSION['bd_host']) && isset ($_SESSION['bd_user']) && - isset ($_SESSION['bd_pass']) && - isset ($_SESSION['bd_name']); + isset ($_SESSION['bd_password']) && + isset ($_SESSION['bd_base']) && + isset ($_SESSION['bd_prefix']) && + isset ($_SESSION['bd_error']); $conn = !isset ($_SESSION['bd_error']) || !$_SESSION['bd_error']; return array ( @@ -307,54 +600,61 @@ function checkStep3 () { 'all' => $bd && $conn && $conf ? 'ok' : 'ko' ); } + function checkBD () { $error = false; try { $str = ''; $driver_options = null; - if($_SESSION['bd_type'] == 'mysql') { - $driver_options = array( - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' - ); - - // on ouvre une connexion juste pour créer la base si elle n'existe pas - $str = 'mysql:host=' . $_SESSION['bd_host'] . ';'; - $c = new PDO ($str, - $_SESSION['bd_user'], - $_SESSION['bd_pass'], - $driver_options); - - $sql = sprintf (SQL_REQ_CREATE_DB, $_SESSION['bd_name']); - $res = $c->query ($sql); - - // on écrase la précédente connexion en sélectionnant la nouvelle BDD - $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_name']; - } elseif($_SESSION['bd_type'] == 'sqlite') { - $str = 'sqlite:' . PUBLIC_PATH - . '/data/' . $_SESSION['bd_name'] . '.sqlite'; + switch ($_SESSION['bd_type']) { + case 'mysql': + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' + ); + + // on ouvre une connexion juste pour créer la base si elle n'existe pas + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';'; + $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + + $sql = sprintf (SQL_CREATE_DB, $_SESSION['bd_base']); + $res = $c->query ($sql); + + // on écrase la précédente connexion en sélectionnant la nouvelle BDD + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; + break; + case 'sqlite': + $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_base'] . '.sqlite'; + break; + default: + return false; } - $c = new PDO ($str, - $_SESSION['bd_user'], - $_SESSION['bd_pass'], - $driver_options); + $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + + $stm = $c->prepare(SQL_SHOW_TABLES); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + if (in_array($_SESSION['bd_prefix'] . 'entry', $res) && !in_array($_SESSION['bd_prefix'] . 'entry006', $res)) { + $sql = sprintf(SQL_BACKUP006, $_SESSION['bd_prefix']); //v0.6 + $res = $c->query($sql); //Backup tables + } - $sql = sprintf (SQL_REQ_CAT, $_SESSION['bd_prefix']); + $sql = sprintf (SQL_CAT, $_SESSION['bd_prefix_user']); $res = $c->query ($sql); if (!$res) { $error = true; } - $sql = sprintf (SQL_REQ_FEED, $_SESSION['bd_prefix'], $_SESSION['bd_prefix']); + $sql = sprintf (SQL_FEED, $_SESSION['bd_prefix_user']); $res = $c->query ($sql); if (!$res) { $error = true; } - $sql = sprintf (SQL_REQ_ENTRY, $_SESSION['bd_prefix'], $_SESSION['bd_prefix']); + $sql = sprintf (SQL_ENTRY, $_SESSION['bd_prefix_user']); $res = $c->query ($sql); if (!$res) { @@ -364,8 +664,8 @@ function checkBD () { $error = true; } - if ($error && file_exists (APP_PATH . '/configuration/application.ini')) { - unlink (APP_PATH . '/configuration/application.ini'); + if ($error && file_exists (DATA_PATH . '/config.php')) { + unlink (DATA_PATH . '/config.php'); } return !$error; @@ -420,7 +720,7 @@ function printStep1 () { <?php if ($res['minz'] == 'ok') { ?> <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('minz_is_ok'); ?></p> <?php } else { ?> - <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 if ($res['curl'] == 'ok') { ?> @@ -442,28 +742,28 @@ function printStep1 () { <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('dom_is_nok'); ?></p> <?php } ?> + <?php if ($res['data'] == 'ok') { ?> + <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('data_is_ok'); ?></p> + <?php } else { ?> + <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', DATA_PATH); ?></p> + <?php } ?> + <?php if ($res['cache'] == 'ok') { ?> <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('cache_is_ok'); ?></p> <?php } else { ?> - <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', PUBLIC_PATH . '/../cache'); ?></p> + <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', CACHE_PATH); ?></p> <?php } ?> <?php if ($res['log'] == 'ok') { ?> <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('log_is_ok'); ?></p> <?php } else { ?> - <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', PUBLIC_PATH . '/../log'); ?></p> - <?php } ?> - - <?php if ($res['configuration'] == 'ok') { ?> - <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('conf_is_ok'); ?></p> - <?php } else { ?> - <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', APP_PATH . '/configuration'); ?></p> + <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', LOG_PATH); ?></p> <?php } ?> - <?php if ($res['data'] == 'ok') { ?> - <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('data_is_ok'); ?></p> + <?php if ($res['favicons'] == 'ok') { ?> + <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('favicons_is_ok'); ?></p> <?php } else { ?> - <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', PUBLIC_PATH . '/data'); ?></p> + <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', DATA_PATH . '/favicons'); ?></p> <?php } ?> <?php if ($res['all'] == 'ok') { ?> @@ -485,13 +785,6 @@ function printStep2 () { <?php $url = substr ($_SERVER['PHP_SELF'], 0, -10); ?> - <div class="form-group" style="display:none"> - <!-- TODO: if no problem during version 0.6, remove for version 0.7 --> - <label class="group-name" for="base_url"><?php echo _t ('base_url'); ?></label> - <div class="group-controls"> - <input type="text" id="base_url" name="base_url" value="<?php echo isset ($_SESSION['base_url']) ? $_SESSION['base_url'] : $url; ?>" /> <i class="icon i_help"></i> <?php echo _t ('do_not_change_if_doubt'); ?> - </div> - </div> <div class="form-group"> <label class="group-name" for="title"><?php echo _t ('title'); ?></label> @@ -508,6 +801,13 @@ function printStep2 () { </div> <div class="form-group"> + <label class="group-name" for="default_user"><?php echo _t ('default_user'); ?></label> + <div class="group-controls"> + <input type="text" id="default_user" name="default_user" maxlength="16" value="<?php echo isset ($_SESSION['default_user']) ? $_SESSION['default_user'] : ''; ?>" placeholder="user1" /> + </div> + </div> + + <div class="form-group"> <label class="group-name" for="mail_login"><?php echo _t ('persona_connection_email'); ?></label> <div class="group-controls"> <input type="email" id="mail_login" name="mail_login" value="<?php echo isset ($_SESSION['mail_login']) ? $_SESSION['mail_login'] : ''; ?>" placeholder="<?php echo _t ('blank_to_disable'); ?>" /> @@ -538,24 +838,22 @@ function printStep3 () { <form action="index.php?step=3" method="post"> <legend><?php echo _t ('bdd_configuration'); ?></legend> - <!-- - TODO : l'utilisation de SQLite n'est pas encore possible. Pour tester tout de même, décommentez ce bloc <div class="form-group"> <label class="group-name" for="type"><?php echo _t ('bdd_type'); ?></label> <div class="group-controls"> <select name="type" id="type"> <option value="mysql" - <?php echo $_SESSION['bd_type'] && $_SESSION['bd_type'] == 'mysql' ? 'selected="selected"' : ''; ?>> + <?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql') ? 'selected="selected"' : ''; ?>> MySQL </option> + <!-- TODO : l'utilisation de SQLite n'est pas encore possible. Pour tester tout de même, décommentez ce bloc <option value="sqlite" - <?php echo $_SESSION['bd_type'] && $_SESSION['bd_type'] == 'sqlite' ? 'selected="selected"' : ''; ?>> + <?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'sqlite') ? 'selected="selected"' : ''; ?>> SQLite - </option> + </option>--> </select> </div> </div> - --> <div class="form-group"> <label class="group-name" for="host"><?php echo _t ('host'); ?></label> @@ -574,21 +872,21 @@ function printStep3 () { <div class="form-group"> <label class="group-name" for="pass"><?php echo _t ('password'); ?></label> <div class="group-controls"> - <input type="password" id="pass" name="pass" value="<?php echo isset ($_SESSION['bd_pass']) ? $_SESSION['bd_pass'] : ''; ?>" /> + <input type="password" id="pass" name="pass" value="<?php echo isset ($_SESSION['bd_password']) ? $_SESSION['bd_password'] : ''; ?>" /> </div> </div> <div class="form-group"> <label class="group-name" for="base"><?php echo _t ('bdd'); ?></label> <div class="group-controls"> - <input type="text" id="base" name="base" value="<?php echo isset ($_SESSION['bd_name']) ? $_SESSION['bd_name'] : ''; ?>" /> + <input type="text" id="base" name="base" maxlength="64" value="<?php echo isset ($_SESSION['bd_base']) ? $_SESSION['bd_base'] : ''; ?>" placeholder="freshrss" /> </div> </div> <div class="form-group"> <label class="group-name" for="prefix"><?php echo _t ('prefix'); ?></label> <div class="group-controls"> - <input type="text" id="prefix" name="prefix" value="<?php echo isset ($_SESSION['bd_prefix']) ? $_SESSION['bd_prefix'] : 'freshrss_'; ?>" /> + <input type="text" id="prefix" name="prefix" maxlength="16" value="<?php echo isset ($_SESSION['bd_prefix']) ? $_SESSION['bd_prefix'] : 'freshrss_'; ?>" /> </div> </div> @@ -607,21 +905,40 @@ function printStep3 () { function printStep4 () { ?> - <p class="alert alert-success"><span class="alert-head"><?php echo _t ('congratulations'); ?></span> <?php echo _t ('installation_is_ok'); ?></p> - <a class="btn btn-important next-step" href="?step=5"><?php echo _t ('finish_installation'); ?></a> + <form action="index.php?step=4" method="post"> + <legend><?php echo _t ('version_update'); ?></legend> + <div class="form-group form-actions"> + <div class="group-controls"> + <?php if (updateDatabase(false)) { ?> + <input type="hidden" name="updateDatabase" value="1" /> + <button type="submit" class="btn btn-important"><?php echo _t ('update_start'); ?></button> + <p><?php echo _t ('update_long'); ?></p> + <?php } else { ?> + <a class="btn btn-important next-step" href="?step=5"><?php echo _t ('next_step'); ?></a> + <?php } ?> + </div> + </div> + </form> <?php } function printStep5 () { ?> - <p class="alert alert-error"><span class="alert-head"><?php echo _t ('oops'); ?></span> <?php echo _t ('install_not_deleted', PUBLIC_PATH . '/install.php'); ?></p> + <p class="alert alert-success"><span class="alert-head"><?php echo _t ('congratulations'); ?></span> <?php echo _t ('installation_is_ok'); ?></p> + <a class="btn btn-important next-step" href="?step=6"><?php echo _t ('finish_installation'); ?></a> <?php } -initTranslate (); +function printStep6 () { +?> + <p class="alert alert-error"><span class="alert-head"><?php echo _t ('oops'); ?></span> <?php echo _t ('install_not_deleted', PUBLIC_PATH . '/install.php'); ?></p> +<?php +} checkStep (); +initTranslate (); + switch (STEP) { case 0: default: @@ -636,8 +953,13 @@ case 3: saveStep3 (); break; case 4: + if (!empty($_POST['updateDatabase'])) { + updateDatabase(true); + } break; case 5: + break; +case 6: deleteInstall (); break; } @@ -667,7 +989,8 @@ case 5: <li class="item<?php echo STEP == 1 ? ' active' : ''; ?>"><a href="?step=1"><?php echo _t ('checks'); ?></a></li> <li class="item<?php echo STEP == 2 ? ' active' : ''; ?>"><a href="?step=2"><?php echo _t ('general_configuration'); ?></a></li> <li class="item<?php echo STEP == 3 ? ' active' : ''; ?>"><a href="?step=3"><?php echo _t ('bdd_configuration'); ?></a></li> - <li class="item<?php echo STEP == 4 ? ' active' : ''; ?>"><a href="?step=4"><?php echo _t ('this_is_the_end'); ?></a></li> + <li class="item<?php echo STEP == 4 ? ' active' : ''; ?>"><a href="?step=4"><?php echo _t ('version_update'); ?></a></li> + <li class="item<?php echo STEP == 5 ? ' active' : ''; ?>"><a href="?step=5"><?php echo _t ('this_is_the_end'); ?></a></li> </ul> <div class="post"> @@ -692,10 +1015,12 @@ case 5: case 5: printStep5 (); break; + case 6: + printStep6 (); + break; } ?> </div> </div> </body> </html> - diff --git a/public/scripts/global_view.js b/public/scripts/global_view.js index 94580dc0d..0cdcdd3fa 100644 --- a/public/scripts/global_view.js +++ b/public/scripts/global_view.js @@ -30,8 +30,7 @@ function load_panel(link) { function init_close_panel() { $("#panel .close").click(function () { - $("#panel").html('<a class="close" href="#"><i class="icon i_close"></i></a>'); - + $("#panel").html('<a class="close" href="#">' + window.iconClose + '</a>'); init_close_panel(); $("#panel").slideToggle(); $("#overlay").fadeOut(); diff --git a/public/scripts/main.js b/public/scripts/main.js index 88d46b2f9..ef05eb2fb 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -1,5 +1,6 @@ "use strict"; -var $stream = null; +var $stream = null, + isCollapsed = true; function is_normal_mode() { return $stream.hasClass('normal'); @@ -39,11 +40,8 @@ function mark_read(active, only_not_read) { url: url, data : { ajax: true } }).done(function (data) { - var res = $.parseJSON(data); - - active.find("a.read").attr("href", res.url); - - var inc = 0; + var $r = active.find("a.read").attr("href", data.url), + inc = 0; if (active.hasClass("not_read")) { active.removeClass("not_read"); inc--; @@ -51,6 +49,7 @@ function mark_read(active, only_not_read) { active.addClass("not_read"); inc++; } + $r.find('.icon').replaceWith(data.icon); //Update unread: feed var feed_url = active.find(".website>a").attr("href"), @@ -58,12 +57,16 @@ function mark_read(active, only_not_read) { elem = $('#' + feed_id + ' .feed').get(0), feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0, feed_priority = elem ? (parseInt(elem.getAttribute('data-priority'), 10) || 0) : 0; - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); + if (elem) { + elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); + } //Update unread: category elem = $('#' + feed_id).parent().prevAll('.category').children(':first').get(0); feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); + if (elem) { + elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); + } //Update unread: all if (feed_priority > 0) { @@ -105,17 +108,16 @@ function mark_favorite(active) { url: url, data : { ajax: true } }).done(function (data) { - var res = $.parseJSON(data); - - active.find("a.bookmark").attr("href", res.url); - var inc = 0; + var $b = active.find("a.bookmark").attr("href", data.url), + inc = 0; if (active.hasClass("favorite")) { active.removeClass("favorite"); inc--; } else { - active.addClass("favorite"); + active.addClass("favorite").find('.bookmark'); inc++; } + $b.find('.icon').replaceWith(data.icon); var favourites = $('.favorites>a').contents().last().get(0); if (favourites && favourites.textContent) { @@ -134,15 +136,18 @@ function mark_favorite(active) { function toggleContent(new_active, old_active) { if (does_lazyload) { - new_active.find('img[data-original]').each(function () { + new_active.find('img[data-original], iframe[data-original]').each(function () { this.setAttribute('src', this.getAttribute('data-original')); this.removeAttribute('data-original'); }); } - old_active.removeClass("active"); + old_active.removeClass("active").removeClass("current"); if (old_active[0] !== new_active[0]) { - new_active.addClass("active"); + if (isCollapsed) { + new_active.addClass("active"); + } + new_active.addClass("current"); } var box_to_move = "html,body", @@ -182,7 +187,7 @@ function toggleContent(new_active, old_active) { } function prev_entry() { - var old_active = $(".flux.active"), + var old_active = $(".flux.current"), last_active = $(".flux:last"), new_active = old_active.prevAll(".flux:first"); @@ -194,7 +199,7 @@ function prev_entry() { } function next_entry() { - var old_active = $(".flux.active"), + var old_active = $(".flux.current"), first_active = $(".flux:first"), last_active = $(".flux:last"), new_active = old_active.nextAll(".flux:first"); @@ -210,6 +215,11 @@ function next_entry() { } } +function collapse_entry() { + isCollapsed = !isCollapsed; + $(".flux.current").toggleClass("active"); +} + function inMarkViewport(flux, box_to_follow, relative_follow) { var top = flux.position().top; if (relative_follow) { @@ -279,7 +289,15 @@ function init_column_categories() { return; } $('#aside_flux').on('click', '.category>a.dropdown-toggle', function () { - $(this).children().toggleClass("i_down").toggleClass("i_up"); + $(this).children().each(function() { + if (this.alt === '▽') { + this.src = this.src.replace('/icons/down.', '/icons/up.'); + this.alt = '△'; + } else { + this.src = this.src.replace('/icons/up.', '/icons/down.'); + this.alt = '▽'; + } + }); $(this).parent().next(".feeds").slideToggle(); return false; }); @@ -296,7 +314,7 @@ function init_shortcuts() { // Touches de manipulation shortcut.add(shortcuts.mark_read, function () { // on marque comme lu ou non lu - var active = $(".flux.active"); + var active = $(".flux.current"); mark_read(active, false); }, { 'disable_in_input': true @@ -310,18 +328,23 @@ function init_shortcuts() { }); shortcut.add(shortcuts.mark_favorite, function () { // on marque comme favori ou non favori - var active = $(".flux.active"); + var active = $(".flux.current"); mark_favorite(active); }, { 'disable_in_input': true }); + shortcut.add(shortcuts.collapse_entry, function () { + collapse_entry(); + }, { + 'disable_in_input': true + }); // Touches de navigation shortcut.add(shortcuts.prev_entry, prev_entry, { 'disable_in_input': true }); shortcut.add("shift+" + shortcuts.prev_entry, function () { - var old_active = $(".flux.active"), + var old_active = $(".flux.current"), first = $(".flux:first"); if (first.hasClass("flux")) { @@ -334,7 +357,7 @@ function init_shortcuts() { 'disable_in_input': true }); shortcut.add("shift+" + shortcuts.next_entry, function () { - var old_active = $(".flux.active"), + var old_active = $(".flux.current"), last = $(".flux:last"); if (last.hasClass("flux")) { @@ -347,7 +370,7 @@ function init_shortcuts() { var url_website = $(".flux.active .link a").attr("href"); if (auto_mark_site) { - $(".flux.active").each(function () { + $(".flux.current").each(function () { mark_read($(this), true); }); } @@ -356,12 +379,19 @@ function init_shortcuts() { }, { 'disable_in_input': true }); + + shortcut.add(shortcuts.load_more, function () { + load_more_posts(); + }, { + 'disable_in_input': true + }); } function init_stream_delegates(divStream) { - divStream.on('click', '.flux_header>.item.title, .flux_header>.item.date', function (e) { //flux_header_toggle - var old_active = $(".flux.active"), - new_active = $(this).parent().parent(); + divStream.on('click', '.flux_header', function (e) { //flux_header_toggle + var old_active = $(".flux.current"), + new_active = $(this).parent(); + isCollapsed = true; if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone if (auto_mark_article) { mark_read(new_active, true); @@ -397,12 +427,6 @@ function init_stream_delegates(divStream) { return false; }); - divStream.on('click', '.bigMarkAsRead', function () { - var url = $(".nav_menu .read_all").attr("href"); - redirect(url, false); - return false; - }); - if (auto_mark_site) { divStream.on('click', '.flux .link a', function () { mark_read($(this).parent().parent().parent(), true); @@ -421,7 +445,7 @@ function init_nav_entries() { return false; }); $nav_entries.find('.up').click(function () { - var active_item = $(".flux.active"), + var active_item = $(".flux.current"), windowTop = $(window).scrollTop(), item_top = active_item.position().top; @@ -493,10 +517,13 @@ function load_more_posts() { $.get(url_load_more, function (data) { box_load_more.children('.flux:last').after($('#stream', data).children('.flux, .day')); $('.pagination').replaceWith($('.pagination', data)); + $('#bigMarkAsRead').attr('href', $('#nav_menu_read_all>a').attr('href')); $('[id^=day_]').each(function (i) { var ids = $('[id="' + this.id + '"]'); - if (ids.length > 1) $('[id="' + this.id + '"]:gt(0)').remove(); + if (ids.length > 1) { + $('[id="' + this.id + '"]:gt(0)').remove(); + } }); init_load_more(box_load_more); @@ -563,16 +590,14 @@ function init_persona() { url: url_login, data: {assertion: assertion}, success: function(res, status, xhr) { - var res_obj = jQuery.parseJSON(res); - - if (res_obj.status == 'failure') { - //alert (res_obj.reason); - } else if (res_obj.status == 'okay') { + /*if (res.status === 'failure') { + alert (res_obj.reason); + } else*/ if (res.status === 'okay') { location.href = url_freshrss; } }, error: function(res, status, xhr) { - alert("login failure : " + res); + alert("Login failure: " + res); } }); }, @@ -598,8 +623,29 @@ function init_persona() { function init_confirm_action() { $('.confirm').click(function () { - return confirm(str_confirmation); - }); + return confirm(str_confirmation); + }); +} + +function init_print_action() { + $('.print-article').click(function () { + var content = "<html><head><style>" + + "body { font-family: Serif; text-align: justify; }" + + "a { color: #000; text-decoration: none; }" + + "a:after { content: ' [' attr(href) ']'}" + + "</style></head><body>" + + $(".flux.current .content").html() + + "</body></html>"; + + var tmp_window = window.open(); + tmp_window.document.writeln(content); + tmp_window.document.close(); + tmp_window.focus(); + tmp_window.print(); + tmp_window.close(); + + return false; + }); } function init_all() { @@ -626,6 +672,7 @@ function init_all() { init_persona(); } init_confirm_action(); + init_print_action(); if (window.console) { console.log('FreshRSS init done.'); } diff --git a/public/themes/default/freshrss.css b/public/themes/default/freshrss.css index ef7f098af..e3c4c3c3b 100644 --- a/public/themes/default/freshrss.css +++ b/public/themes/default/freshrss.css @@ -1,3 +1,5 @@ +@charset "UTF-8"; + /* STRUCTURE */ .header { display: table; @@ -16,8 +18,11 @@ width: 250px; white-space: nowrap; } - .header > .item.title .logo { + .logo { display: inline-block; + font-size: 48px; + height: 32px; + width: 32px; padding: 10px; } .header > .item.title h1 { @@ -25,9 +30,6 @@ margin: 0; text-shadow: 1px -1px 0 #ccc; } - .header > .item.title a:hover { - text-decoration: none; - } .header > .item.search input { width: 230px; transition: width 200ms linear; @@ -39,6 +41,10 @@ width: 100px; } +.item a:hover { + text-decoration: none; +} + #global { display: table; width: 100%; @@ -70,11 +76,6 @@ right: 33px; } - .aside.aside_flux .i_category { - background-image: url("../icons/category-white.png"); - background-image: url("../icons/category-white.svg"); - } - .nav-login { display: none; } @@ -86,6 +87,9 @@ text-align: center; padding: 5px 0; } + .nav_menu .search { + display:none; + } .favicon { height: 16px; @@ -177,17 +181,16 @@ .categories .feeds .dropdown-menu:after { left: 2px; } - .categories .feeds .item .dropdown-toggle i { - background-image: none; + .categories .feeds .item .dropdown-toggle > .icon { + visibility: hidden; cursor: pointer; } - .categories .feeds .item .dropdown-target:target ~ .dropdown-toggle i, - .categories .feeds .item:hover .dropdown-toggle i, - .categories .feeds .item.active .dropdown-toggle i { - background-image: url("../icons/configure.png"); - background-image: url("../icons/configure.svg"); + .categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, + .categories .feeds .item:hover .dropdown-toggle > .icon, + .categories .feeds .item.active .dropdown-toggle > .icon { background-color: #fff; border-radius: 3px; + visibility: visible; } .post { @@ -234,10 +237,6 @@ .flux:hover { background: #fff; } - .flux.active { - border-left: 3px solid #0062BE; - background: #fff; - } .flux.not_read { border-left: 3px solid #FF5300; background: #FFF3ED; @@ -246,80 +245,64 @@ border-left: 3px solid #FFC300; background: #FFF6DA; } + .flux.current { + border-left: 3px solid #0062BE; + background: #fff; + } .flux_header { + background: inherit; height: 25px; font-size: 12px; - line-height: 25px; border-top: 1px solid #ddd; + cursor: pointer; } - .item.manage { + .flux .flux_header > .item > a, + .flux .bottom > .item > a { + display: inline-block; + height: 40px; + width: 100%; + line-height: 40px; + } + .flux .item.manage { width: 40px; white-space: nowrap; - font-size: 0px; text-align: center; } - .read { - display: inline-block; - width: 40px; - height: 40px; - background: url("../icons/read.png") center center no-repeat; - background: url("../icons/read.svg") center center no-repeat; - vertical-align: middle; - } - .read:hover { - text-decoration: none; - } - .flux.not_read .read { - background: url("../icons/unread.png") center center no-repeat; - background: url("../icons/unread.svg") center center no-repeat; - } - .bookmark { - display: inline-block; - width: 40px; - height: 40px; - background: url("../icons/non-starred.png") center center no-repeat; - background: url("../icons/non-starred.svg") center center no-repeat; - vertical-align: middle; - } - .bookmark:hover { - text-decoration: none; - } - .flux.favorite .bookmark { - background: url("../icons/starred.png") center center no-repeat; - background: url("../icons/starred.svg") center center no-repeat; - } - .flux_header .item.website { + .flux .item.website { width: 200px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; line-height: 40px; } - .flux_header .item.website .favicon { + .flux .item.website .favicon { padding: 5px; } - .flux_header .item.website a { + .flux .item.website a { display: block; height: 40px; } - .flux_header .item.title { + .flux .item.title { + background: inherit; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - cursor: pointer; } - .flux_header .item.title a { + .flux:hover .item.title { + border-right: 2px solid rgba(127, 127, 127, 0.1); + padding-right: 1em; + position: absolute; + } + .flux .item.title a { color: #000; outline: none; } - .flux_header .item.title a:hover { - text-decoration: none - } - .flux.not_read .flux_header .item.title { + .flux.not_read .item.title, + .flux.current .item.title { font-weight: bold; } - .item.date { + .flux .item.date { width: 200px; overflow: hidden; padding:0 5px 0 0; @@ -328,23 +311,11 @@ text-align: right; font-size: 10px; color: #666; - cursor: pointer; } - .item.link { + .link { width: 40px; text-align: center; } - .item.link a { - display: inline-block; - width: 40px; - height: 40px; - background: url("../icons/link.png") center center no-repeat; - background: url("../icons/link.svg") center center no-repeat; - vertical-align: middle; - } - .item.link a:hover { - text-decoration: none; - } #stream.reader .flux { padding: 0 0 30px; @@ -416,19 +387,20 @@ } .content { - min-height: 300px; + min-height: 150px; max-width: 550px; margin: 0 auto; padding: 20px 10px; line-height: 170%; word-wrap: break-word; } - .content .title { - margin: 0 0 5px; - } .content h1, .content h2, .content h3 { margin: 20px 0 5px; } + .content > .title { + font-size: x-large; + margin: 0; + } .content p { margin: 0 0 20px; @@ -576,19 +548,22 @@ font-size: 0; } -.bigMarkAsRead { - cursor: pointer; - height: 300px; +#bigMarkAsRead { + display: block; + font-style: normal; + padding: 32px 0 64px 0; + text-align: center; + text-decoration: none; text-shadow: 0 -1px 0 #aaa; } -.bigMarkAsRead:hover { - background: #333; - color: #fff; -} -.bigTick { - font-size: 72pt; - margin: 75px 0 10px 0; -} + #bigMarkAsRead:hover { + background: #333; + color: #fff; + } + .bigTick { + font-size: 72pt; + line-height: 1.6em; + } /*** NOTIFICATION ***/ .notification { @@ -675,6 +650,10 @@ background: #f4f4f4; color: #aaa; } + .log.debug { + background: #111; + color: #eee; + } .form-group table { border-collapse:collapse; @@ -710,6 +689,7 @@ .content { font-size: 120%; + padding: 0; } .pagination { @@ -768,6 +748,17 @@ .nav_menu .stick .btn { margin: 5px 0; } + .nav_menu .search { + display: inline-block; + max-width: 97%; + } + .nav_menu .search input { + max-width: 97%; + width: 90px; + } + .nav_menu .search input:focus { + width: 400px; + } #panel { left: 5px; right: 5px; @@ -860,3 +851,40 @@ -ms-transition: width 200ms linear; } } + +@media print { + .header, + .aside, + .nav_menu, + .day, + .flux_header, + .flux_content .bottom, + .pagination { + display: none; + } + + html, body { + background: #fff; + color: #000; + font-family: Serif; + font-size: 12pt; + } + + #global, + .flux_content { + display: block !important; + } + + .flux_content .content { + width: 100% !important; + text-align: justify; + } + + .flux_content .content a { + color: #000; + } + .flux_content .content a:after { + content: " (" attr(href) ") "; + text-decoration: underline; + } +} diff --git a/public/themes/default/global.css b/public/themes/default/global.css index 94c11b957..1c554d2dc 100644 --- a/public/themes/default/global.css +++ b/public/themes/default/global.css @@ -1,3 +1,5 @@ +@charset "UTF-8"; + /* FONTS */ @font-face { font-family: "OpenSans"; @@ -435,6 +437,7 @@ input, select, textarea { display: inline; } .dropdown-close a { + font-size: 0; position: fixed; top: 0; bottom: 0; left: 0; right: 0; @@ -477,108 +480,11 @@ input, select, textarea { color: #844; } -/* ICONES */ +/* ICÔNES */ .icon { display: inline-block; width: 16px; height: 16px; vertical-align: middle; line-height: 16px; - background: center center no-repeat; } - .i_refresh { - background-image: url("../icons/refresh.png"); - background-image: url("../icons/refresh.svg"); - } - .i_bookmark { - background-image: url("../icons/starred.png"); - background-image: url("../icons/starred.svg"); - } - .i_not_bookmark { - background-image: url("../icons/unstarred.png"); - background-image: url("../icons/unstarred.svg"); - } - .i_read { - background-image: url("../icons/read.png"); - background-image: url("../icons/read.svg"); - } - .i_unread { - background-image: url("../icons/unread.png"); - background-image: url("../icons/unread.svg"); - } - .i_all { - background-image: url("../icons/all.png"); - background-image: url("../icons/all.svg"); - } - .i_close { - background-image: url("../icons/close.png"); - background-image: url("../icons/close.svg"); - } - .i_search { - background-image: url("../icons/search.png"); - background-image: url("../icons/search.svg"); - } - .i_configure { - background-image: url("../icons/configure.png"); - background-image: url("../icons/configure.svg"); - } - .i_login { - background-image: url("../icons/login.png"); - background-image: url("../icons/login.svg"); - } - .i_logout { - background-image: url("../icons/logout.png"); - background-image: url("../icons/logout.svg"); - } - .i_add { - background-image: url("../icons/add.png"); - background-image: url("../icons/add.svg"); - } - .i_link { - background-image: url("../icons/link.png"); - background-image: url("../icons/link.svg"); - } - .i_down { - background-image: url("../icons/down.png"); - background-image: url("../icons/down.svg"); - } - .i_up { - background-image: url("../icons/up.png"); - background-image: url("../icons/up.svg"); - } - .i_next { - background-image: url("../icons/next.png"); - background-image: url("../icons/next.svg"); - } - .i_prev { - background-image: url("../icons/previous.png"); - background-image: url("../icons/previous.svg"); - } - .i_help { - background-image: url("../icons/help.png"); - background-image: url("../icons/help.svg"); - } - .i_note { - background-image: url("../icons/note.png"); - background-image: url("../icons/note.svg"); - } - .i_note_empty { - background-image: url("../icons/note_empty.png"); - background-image: url("../icons/note_empty.svg"); - } - .i_category { - background-image: url("../icons/category.png"); - background-image: url("../icons/category.svg"); - } - .i_rss { - background-image: url("../icons/rss.png"); - background-image: url("../icons/rss.svg"); - } - .i_share { - background-image: url("../icons/share.png"); - background-image: url("../icons/share.svg"); - } - .i_tag { - background-image: url("../icons/tag.png"); - background-image: url("../icons/tag.svg"); - } diff --git a/public/themes/flat-design/freshrss.css b/public/themes/flat-design/freshrss.css index 2b3cfd948..fa1ed13e6 100644 --- a/public/themes/flat-design/freshrss.css +++ b/public/themes/flat-design/freshrss.css @@ -1,3 +1,5 @@ +@charset "UTF-8"; + /* STRUCTURE */ body { background: #fafafa; @@ -19,8 +21,10 @@ body { width: 250px; white-space: nowrap; } - .header > .item.title .logo { + .logo { display: inline-block; + font-size: 48px; + height: 32px; width: 32px; padding: 10px; } @@ -28,9 +32,6 @@ body { display: inline-block; margin: 0; } - .header > .item.title a:hover { - text-decoration: none; - } .header > .item.search input { width: 230px; transition: width 200ms linear; @@ -42,6 +43,10 @@ body { width: 100px; } +.item a:hover { + text-decoration: none; +} + #global { display: table; width: 100%; @@ -80,6 +85,9 @@ body { text-align: center; padding: 5px 0; } + .nav_menu .search { + display:none; + } .favicon { height: 16px; @@ -161,17 +169,16 @@ body { .categories .feeds .dropdown-menu:after { left: 2px; } - .categories .feeds .item .dropdown-toggle i { - background-image: none; + .categories .feeds .item .dropdown-toggle > .icon { + visibility: hidden; cursor: pointer; } - .categories .feeds .item .dropdown-target:target ~ .dropdown-toggle i, - .categories .feeds .item:hover .dropdown-toggle i, - .categories .feeds .item.active .dropdown-toggle i { - background-image: url("icons/configure.png"); - background-image: url("icons/configure.svg"); + .categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, + .categories .feeds .item:hover .dropdown-toggle > .icon, + .categories .feeds .item.active .dropdown-toggle > .icon { background-color: #95a5a6; border-radius: 3px; + visibility: visible; } .categories .btn:hover .notRead, .categories .btn.active .notRead { @@ -213,8 +220,7 @@ body { .flux { border-left: 3px solid #ecf0f1; } - .flux.active { - border-left-color: #3498db; + .flux:hover { background: #fff; } .flux.not_read { @@ -225,80 +231,60 @@ body { border-left-color: #FFC300; background: #FFF6DA; } + .flux.current { + border-left-color: #3498db; + background: #fff; + } .flux_header { + background: inherit; height: 25px; font-size: 12px; - line-height: 25px; border-top: 1px solid #ecf0f1; + cursor: pointer; } - .item.manage { + .flux .flux_header > .item > a, + .flux .bottom > .item > a { + display: inline-block; + height: 40px; + width: 100%; + line-height: 40px; + } + .flux .item.manage { width: 40px; white-space: nowrap; - font-size: 0px; text-align: center; } - .read { - display: inline-block; - width: 40px; - height: 40px; - background: url("../icons/read.png") center center no-repeat; - background: url("../icons/read.svg") center center no-repeat; - vertical-align: middle; - } - .read:hover { - text-decoration: none; - } - .flux.not_read .read { - background: url("../icons/unread.png") center center no-repeat; - background: url("../icons/unread.svg") center center no-repeat; - } - .bookmark { - display: inline-block; - width: 40px; - height: 40px; - background: url("../icons/non-starred.png") center center no-repeat; - background: url("../icons/non-starred.svg") center center no-repeat; - vertical-align: middle; - } - .bookmark:hover { - text-decoration: none; - } - .flux.favorite .bookmark { - background: url("../icons/starred.png") center center no-repeat; - background: url("../icons/starred.svg") center center no-repeat; - } - .flux_header .item.website { + .flux .item.website { width: 200px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; line-height: 40px; } - .flux_header .item.website .favicon { + .flux .item.website .favicon { padding: 5px; } - .flux_header .item.website a { - display: block; - height: 40px; - } - .flux_header .item.title { + .flux .item.title { + background: inherit; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - cursor: pointer; } - .flux_header .item.title a { + .flux:hover .item.title { + border-right: 2px solid rgba(127, 127, 127, 0.1); + padding-right: 1em; + position: absolute; + } + .flux .item.title a { color: #333; outline: none; } - .flux_header .item.title a:hover { - text-decoration: none - } - .flux.not_read .flux_header .item.title { + .flux.current .item.title, + .flux.not_read .item.title { font-weight: bold; } - .item.date { + .flux .item.date { width: 200px; overflow: hidden; padding:0 5px 0 0; @@ -307,23 +293,11 @@ body { text-align: right; font-size: 10px; color: #666; - cursor: pointer; } - .item.link { + .link { width: 40px; text-align: center; } - .item.link a { - display: inline-block; - width: 40px; - height: 40px; - background: url("../icons/link.png") center center no-repeat; - background: url("../icons/link.svg") center center no-repeat; - vertical-align: middle; - } - .item.link a:hover { - text-decoration: none; - } #stream.reader .flux { position: relative; @@ -333,8 +307,6 @@ body { color: #34495e; font-size: 120%; } - #stream.reader .flux a { - } #stream.reader .flux .author { margin: 0 0 10px; font-size: 90%; @@ -397,19 +369,20 @@ body { } .content { - min-height: 300px; + min-height: 150px; max-width: 550px; margin: 0 auto; padding: 20px 10px; line-height: 170%; word-wrap: break-word; } - .content .title { - margin: 0 0 5px; - } .content h1, .content h2, .content h3 { margin: 20px 0 5px; } + .content > .title { + font-size: x-large; + margin: 0; + } .content p { margin: 0 0 20px; @@ -529,7 +502,6 @@ body { .pagination .item a:hover { color: #ecf0f1; background: #34495e; - text-decoration: none; } #nav_entries { @@ -563,20 +535,23 @@ body { font-size: 0; } -.bigMarkAsRead { +#bigMarkAsRead { background: #ecf0f1; - cursor: pointer; - height: 300px; + display: block; + font-style: normal; + padding: 32px 0 64px 0; + text-align: center; + text-decoration: none; text-shadow: 0 -1px 0 #aaa; } -.bigMarkAsRead:hover { - background: #34495e; - color: #fff; -} -.bigTick { - font-size: 72pt; - margin: 75px 0 10px 0; -} + #bigMarkAsRead:hover { + background: #34495e; + color: #fff; + } + .bigTick { + font-size: 72pt; + line-height: 1.6em; + } /*** NOTIFICATION ***/ .notification { @@ -656,21 +631,25 @@ body { color: #666; font-size: 90%; } - .log .date { + .log>.date { margin: 0 10px 0 0; padding: 5px 10px; border-radius: 20px; } - .log.error .date { + .log.error>.date { background: #e74c3c; color: #fff; } - .log.warning .date { + .log.warning>.date { background: #f39c12; } - .log.notice .date { + .log.notice>.date { background: #ecf0f1; } + .log.debug>.date { + background: #111; + color: #eee; + } .form-group table { border-collapse:collapse; @@ -705,6 +684,7 @@ body { .content { font-size: 120%; + padding: 0; } .pagination { @@ -766,6 +746,17 @@ body { .nav_menu .stick .btn { margin: 5px 0; } + .nav_menu .search { + display: inline-block; + max-width: 97%; + } + .nav_menu .search input { + max-width: 97%; + width: 90px; + } + .nav_menu .search input:focus { + width: 400px; + } #panel { left: 5px; right: 5px; @@ -793,3 +784,40 @@ body { -webkit-transform: rotate(45deg); -ms-transform: rotate(45deg); } + +@media print { + .header, + .aside, + .nav_menu, + .day, + .flux_header, + .flux_content .bottom, + .pagination { + display: none; + } + + html, body { + background: #fff; + color: #000; + font-family: Serif; + font-size: 12pt; + } + + #global, + .flux_content { + display: block !important; + } + + .flux_content .content { + width: 100% !important; + text-align: justify; + } + + .flux_content .content a { + color: #000; + } + .flux_content .content a:after { + content: " (" attr(href) ") "; + text-decoration: underline; + } +} diff --git a/public/themes/flat-design/global.css b/public/themes/flat-design/global.css index 1952cc097..8cf6412b3 100644 --- a/public/themes/flat-design/global.css +++ b/public/themes/flat-design/global.css @@ -1,3 +1,5 @@ +@charset "UTF-8"; + /* FONTS */ @font-face { font-family: "OpenSans"; @@ -427,6 +429,7 @@ input, select, textarea { display: inline; } .dropdown-close a { + font-size: 0; position: fixed; top: 0; bottom: 0; left: 0; right: 0; @@ -469,100 +472,11 @@ input, select, textarea { color: #844; } -/* ICONES */ +/* ICÔNES */ .icon { display: inline-block; width: 16px; height: 16px; vertical-align: middle; line-height: 16px; - background: center center no-repeat; } - .i_refresh { - background-image: url("icons/refresh.png"); - background-image: url("icons/refresh.svg"); - } - .i_bookmark { - background-image: url("../icons/starred.png"); - background-image: url("../icons/starred.svg"); - } - .i_not_bookmark { - background-image: url("../icons/unstarred.png"); - background-image: url("../icons/unstarred.svg"); - } - .i_read { - background-image: url("../icons/read.png"); - background-image: url("../icons/read.svg"); - } - .i_unread { - background-image: url("../icons/unread.png"); - background-image: url("../icons/unread.svg"); - } - .i_all { - background-image: url("icons/all.png"); - background-image: url("icons/all.svg"); - } - .i_close { - background-image: url("icons/close.png"); - background-image: url("icons/close.svg"); - } - .i_search { - background-image: url("icons/search.png"); - background-image: url("icons/search.svg"); - } - .i_configure { - background-image: url("icons/configure.png"); - background-image: url("icons/configure.svg"); - } - .i_login { - background-image: url("../icons/login.png"); - background-image: url("../icons/login.svg"); - } - .i_logout { - background-image: url("../icons/logout.png"); - background-image: url("../icons/logout.svg"); - } - .i_add { - background-image: url("icons/add.png"); - background-image: url("icons/add.svg"); - } - .i_link { - background-image: url("../icons/link.png"); - background-image: url("../icons/link.svg"); - } - .i_down { - background-image: url("icons/down.png"); - background-image: url("icons/down.svg"); - } - .i_up { - background-image: url("icons/up.png"); - background-image: url("icons/up.svg"); - } - .i_next { - background-image: url("icons/next.png"); - background-image: url("icons/next.svg"); - } - .i_prev { - background-image: url("icons/previous.png"); - background-image: url("icons/previous.svg"); - } - .i_help { - background-image: url("../icons/help.png"); - background-image: url("../icons/help.svg"); - } - .i_category { - background-image: url("../icons/category-white.png"); - background-image: url("../icons/category-white.svg"); - } - .i_rss { - background-image: url("../icons/rss.png"); - background-image: url("../icons/rss.svg"); - } - .i_share { - background-image: url("../icons/share.png"); - background-image: url("../icons/share.svg"); - } - .i_tag { - background-image: url("../icons/tag.png"); - background-image: url("../icons/tag.svg"); - } diff --git a/public/themes/flat-design/icons/add.png b/public/themes/flat-design/icons/add.png Binary files differdeleted file mode 100644 index 237de3e15..000000000 --- a/public/themes/flat-design/icons/add.png +++ /dev/null diff --git a/public/themes/flat-design/icons/all.png b/public/themes/flat-design/icons/all.png Binary files differdeleted file mode 100644 index 6d8338ac7..000000000 --- a/public/themes/flat-design/icons/all.png +++ /dev/null diff --git a/public/themes/flat-design/icons/close.png b/public/themes/flat-design/icons/close.png Binary files differdeleted file mode 100644 index 1f91a4f4e..000000000 --- a/public/themes/flat-design/icons/close.png +++ /dev/null diff --git a/public/themes/flat-design/icons/configure.png b/public/themes/flat-design/icons/configure.png Binary files differdeleted file mode 100644 index 982c24619..000000000 --- a/public/themes/flat-design/icons/configure.png +++ /dev/null diff --git a/public/themes/flat-design/icons/down.png b/public/themes/flat-design/icons/down.png Binary files differdeleted file mode 100644 index 4603976ac..000000000 --- a/public/themes/flat-design/icons/down.png +++ /dev/null diff --git a/public/themes/flat-design/icons/next.png b/public/themes/flat-design/icons/next.png Binary files differdeleted file mode 100644 index d240ac6eb..000000000 --- a/public/themes/flat-design/icons/next.png +++ /dev/null diff --git a/public/themes/flat-design/icons/previous.svg b/public/themes/flat-design/icons/prev.svg index 9ba03ceb2..9ba03ceb2 100644 --- a/public/themes/flat-design/icons/previous.svg +++ b/public/themes/flat-design/icons/prev.svg diff --git a/public/themes/flat-design/icons/previous.png b/public/themes/flat-design/icons/previous.png Binary files differdeleted file mode 100644 index b541f6c0c..000000000 --- a/public/themes/flat-design/icons/previous.png +++ /dev/null diff --git a/public/themes/flat-design/icons/refresh.png b/public/themes/flat-design/icons/refresh.png Binary files differdeleted file mode 100644 index 2fdd1b0a5..000000000 --- a/public/themes/flat-design/icons/refresh.png +++ /dev/null diff --git a/public/themes/flat-design/icons/search.png b/public/themes/flat-design/icons/search.png Binary files differdeleted file mode 100644 index 60e25d121..000000000 --- a/public/themes/flat-design/icons/search.png +++ /dev/null diff --git a/public/themes/flat-design/icons/up.png b/public/themes/flat-design/icons/up.png Binary files differdeleted file mode 100644 index 3a6fcd898..000000000 --- a/public/themes/flat-design/icons/up.png +++ /dev/null diff --git a/public/themes/icons/add.png b/public/themes/icons/add.png Binary files differdeleted file mode 100644 index 90cdf4830..000000000 --- a/public/themes/icons/add.png +++ /dev/null diff --git a/public/themes/icons/all.png b/public/themes/icons/all.png Binary files differdeleted file mode 100644 index b0dbe5483..000000000 --- a/public/themes/icons/all.png +++ /dev/null diff --git a/public/themes/icons/bookmark.svg b/public/themes/icons/bookmark.svg new file mode 100644 index 000000000..d6e2cebb5 --- /dev/null +++ b/public/themes/icons/bookmark.svg @@ -0,0 +1,32 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:svg='http://www.w3.org/2000/svg' id='svg7384' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' sodipodi:docname='starred-symbolic.svg' version='1.1' inkscape:version='0.48.1 r9760' height='16' 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:cy='0.50817' pagecolor='#555753' borderopacity='1' showborder='false' inkscape:bbox-paths='false' guidetolerance='10' inkscape:object-paths='true' inkscape:window-width='1457' showguides='true' inkscape:object-nodes='true' inkscape:snap-bbox='true' inkscape:pageshadow='2' inkscape:guide-bbox='true' inkscape:snap-nodes='false' bordercolor='#666666' objecttolerance='10' id='namedview88' showgrid='false' inkscape:window-maximized='0' inkscape:window-x='86' inkscape:snap-global='true' inkscape:window-y='51' gridtolerance='10' inkscape:window-height='1093' inkscape:snap-to-guides='true' inkscape:current-layer='layer9' inkscape:snap-bbox-midpoints='false' inkscape:zoom='1' inkscape:cx='19.029058' inkscape:snap-grids='true' inkscape:pageopacity='1'> + <inkscape:grid spacingx='1px' spacingy='1px' id='grid4866' empspacing='2' enabled='true' type='xygrid' snapvisiblegridlinesonly='true' visible='true'/> + </sodipodi:namedview> + <title id='title9167'>Gnome Symbolic Icon Theme</title> + <defs id='defs7386'/> + <g inkscape:label='status' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer9' style='display:inline'> + <g inkscape:label='folder-remote' transform='translate(-186.9996,-599)' id='g11910-1'> + + </g> + <path sodipodi:cy='180.96373' sodipodi:r2='3.8276224' transform='matrix(1.0472113,-0.00871584,0.00871584,1.0472113,-504.35434,220.15425)' inkscape:rounded='0.2104596' inkscape:flatsided='false' inkscape:transform-center-x='-0.0094346789' inkscape:transform-center-y='-0.69491065' d='m 530.9488,186.70897 c -0.77941,0.55189 -3.15759,-1.90601 -4.11253,-1.9179 -0.95532,-0.0119 -3.39494,2.38585 -4.16096,1.8149 -0.76573,-0.57072 0.83698,-3.59203 0.55319,-4.50391 -0.2839,-0.91223 -3.31818,-2.49151 -3.01189,-3.39647 0.30617,-0.90461 3.67487,-0.31399 4.45442,-0.86567 0.77986,-0.5519 1.3442,-3.92569 2.29952,-3.91404 0.95494,0.0116 1.43421,3.39798 2.19979,3.9689 0.76588,0.57114 4.14893,0.0653 4.43307,0.97746 0.28402,0.9118 -2.78848,2.41405 -3.09488,3.31858 -0.30652,0.90489 1.21999,3.96605 0.44027,4.51815 z' id='path11922-0' sodipodi:type='star' sodipodi:arg1='0.95492637' sodipodi:r1='7.0383992' style='color:#000000;fill:#f1c40f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate' sodipodi:arg2='1.5829876' inkscape:randomized='0' sodipodi:cx='526.88293' sodipodi:sides='5'/> + </g> + <g inkscape:label='devices' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer10'/> + <g inkscape:label='apps' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer11'/> + <g inkscape:label='actions' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer12'/> + <g inkscape:label='places' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer13'/> + <g inkscape:label='mimetypes' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer14'/> + <g inkscape:label='emblems' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='layer15' style='display:inline'/> + <g inkscape:label='categories' transform='translate(-41.000202,-397)' inkscape:groupmode='layer' id='g4953' style='display:inline'/> +</svg> diff --git a/public/themes/icons/category-white.png b/public/themes/icons/category-white.png Binary files differdeleted file mode 100644 index 9243650da..000000000 --- a/public/themes/icons/category-white.png +++ /dev/null diff --git a/public/themes/icons/category.png b/public/themes/icons/category.png Binary files differdeleted file mode 100644 index e3a9bf34b..000000000 --- a/public/themes/icons/category.png +++ /dev/null diff --git a/public/themes/icons/close.png b/public/themes/icons/close.png Binary files differdeleted file mode 100644 index 452f1d1cf..000000000 --- a/public/themes/icons/close.png +++ /dev/null diff --git a/public/themes/icons/configure.png b/public/themes/icons/configure.png Binary files differdeleted file mode 100644 index 8c6fb531c..000000000 --- a/public/themes/icons/configure.png +++ /dev/null diff --git a/public/themes/icons/down.png b/public/themes/icons/down.png Binary files differdeleted file mode 100644 index 5a647245f..000000000 --- a/public/themes/icons/down.png +++ /dev/null diff --git a/public/data/grey.gif b/public/themes/icons/grey.gif Binary files differindex c7212bc1f..c7212bc1f 100644 --- a/public/data/grey.gif +++ b/public/themes/icons/grey.gif diff --git a/public/themes/icons/help.png b/public/themes/icons/help.png Binary files differdeleted file mode 100644 index aa63c5411..000000000 --- a/public/themes/icons/help.png +++ /dev/null diff --git a/public/themes/icons/icon-128.png b/public/themes/icons/icon-128.png Binary files differdeleted file mode 100644 index 41f8eaa0f..000000000 --- a/public/themes/icons/icon-128.png +++ /dev/null diff --git a/public/themes/icons/icon-16.png b/public/themes/icons/icon-16.png Binary files differdeleted file mode 100644 index cc6efb54b..000000000 --- a/public/themes/icons/icon-16.png +++ /dev/null diff --git a/public/themes/icons/icon-256.png b/public/themes/icons/icon-256.png Binary files differdeleted file mode 100644 index 979581a75..000000000 --- a/public/themes/icons/icon-256.png +++ /dev/null diff --git a/public/themes/icons/icon-32.png b/public/themes/icons/icon-32.png Binary files differdeleted file mode 100644 index 00c4ce2a9..000000000 --- a/public/themes/icons/icon-32.png +++ /dev/null diff --git a/public/themes/icons/icon-64.png b/public/themes/icons/icon-64.png Binary files differdeleted file mode 100644 index e2dad000d..000000000 --- a/public/themes/icons/icon-64.png +++ /dev/null diff --git a/public/themes/icons/link.png b/public/themes/icons/link.png Binary files differdeleted file mode 100644 index de2b187d7..000000000 --- a/public/themes/icons/link.png +++ /dev/null diff --git a/public/themes/icons/login.png b/public/themes/icons/login.png Binary files differdeleted file mode 100644 index cebe0cf7d..000000000 --- a/public/themes/icons/login.png +++ /dev/null diff --git a/public/themes/icons/logout.png b/public/themes/icons/logout.png Binary files differdeleted file mode 100644 index 49255fccd..000000000 --- a/public/themes/icons/logout.png +++ /dev/null diff --git a/public/themes/icons/next.png b/public/themes/icons/next.png Binary files differdeleted file mode 100644 index ab3490c3b..000000000 --- a/public/themes/icons/next.png +++ /dev/null diff --git a/public/themes/icons/non-starred.png b/public/themes/icons/non-starred.png Binary files differdeleted file mode 100644 index 4aafb6d8a..000000000 --- a/public/themes/icons/non-starred.png +++ /dev/null diff --git a/public/themes/icons/previous.svg b/public/themes/icons/prev.svg index 67685c50c..67685c50c 100644 --- a/public/themes/icons/previous.svg +++ b/public/themes/icons/prev.svg diff --git a/public/themes/icons/previous.png b/public/themes/icons/previous.png Binary files differdeleted file mode 100644 index 10e40669e..000000000 --- a/public/themes/icons/previous.png +++ /dev/null diff --git a/public/themes/icons/read.png b/public/themes/icons/read.png Binary files differdeleted file mode 100644 index a402689c7..000000000 --- a/public/themes/icons/read.png +++ /dev/null diff --git a/public/themes/icons/refresh.png b/public/themes/icons/refresh.png Binary files differdeleted file mode 100644 index dba399981..000000000 --- a/public/themes/icons/refresh.png +++ /dev/null diff --git a/public/themes/icons/rss.png b/public/themes/icons/rss.png Binary files differdeleted file mode 100644 index c20455af0..000000000 --- a/public/themes/icons/rss.png +++ /dev/null diff --git a/public/themes/icons/search.png b/public/themes/icons/search.png Binary files differdeleted file mode 100644 index 48e7373c4..000000000 --- a/public/themes/icons/search.png +++ /dev/null diff --git a/public/themes/icons/share.png b/public/themes/icons/share.png Binary files differdeleted file mode 100644 index 74c4c5dda..000000000 --- a/public/themes/icons/share.png +++ /dev/null diff --git a/public/themes/icons/starred.png b/public/themes/icons/starred.png Binary files differdeleted file mode 100644 index ff2cf31a7..000000000 --- a/public/themes/icons/starred.png +++ /dev/null diff --git a/public/themes/icons/tag.png b/public/themes/icons/tag.png Binary files differdeleted file mode 100644 index cb1a13833..000000000 --- a/public/themes/icons/tag.png +++ /dev/null diff --git a/public/themes/icons/unread.png b/public/themes/icons/unread.png Binary files differdeleted file mode 100644 index ffcd323b1..000000000 --- a/public/themes/icons/unread.png +++ /dev/null diff --git a/public/themes/icons/up.png b/public/themes/icons/up.png Binary files differdeleted file mode 100644 index 8bfc2fb13..000000000 --- a/public/themes/icons/up.png +++ /dev/null diff --git a/public/themes/printer/style.css b/public/themes/printer/style.css deleted file mode 100644 index 87d019c58..000000000 --- a/public/themes/printer/style.css +++ /dev/null @@ -1,34 +0,0 @@ -.header, -.aside, -.nav_menu, -.day, -.flux_header, -.flux_content .bottom, -.pagination { - display: none; -} - -html, body { - background: #fff; - color: #000; - font-family: Serif; - font-size: 12pt; -} - -#global, -.flux_content { - display: block !important; -} - -.flux_content .content { - width: 100% !important; - text-align: justify; -} - -.flux_content .content a { - color: #000; -} -.flux_content .content a:after { - content: " (" attr(href) ") "; - text-decoration: underline; -}
\ No newline at end of file |
