From 72cecf5fdd1f84d6a3d2a5c74595962e6055ef00 Mon Sep 17 00:00:00 2001 From: Radex Date: Thu, 21 Aug 2008 17:18:55 +0200 Subject: [PATCH] =?utf8?q?ups...=20co=C5=9B=20nie=20wysz=C5=82o.=20Teraz?= =?utf8?q?=20powinno=20by=C4=87=20ok.=20To=20samo=20co=20poprzedni=20commi?= =?utf8?q?t.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- cms/4DEVS | 101 ++++++++----------------------- cms/index.php | 6 ++ cms/wtrmln/helpers/helpers.php | 2 +- cms/wtrmln/libs/config.php | 1 + cms/wtrmln/libs/controller.php | 1 + cms/wtrmln/libs/db.php | 12 +++- cms/wtrmln/libs/loader.php | 11 +++- cms/wtrmln/libs/plugins_handle.php | 34 ++++++----- cms/wtrmln/modules/controllers/login.php | 15 +++-- cms/wtrmln/modules/controllers/test.php | 44 +++++++++----- cms/wtrmln/modules/models/model_user.php | 12 ++-- cms/wtrmln/modules/plugins/user.php | 80 ++++++++++++++++++++++-- cms/wtrmln/system.php | 30 ++++++--- cms/wtrmln/themes/wcmslay/index.php | 36 ++++++----- cms/wtrmln/themes/wcmslay/skin.php | 2 +- cms/wtrmln/themes/wcmslay/style.css | 51 +++++++++++++++- 16 files changed, 286 insertions(+), 152 deletions(-) diff --git a/cms/4DEVS b/cms/4DEVS index e121c40..f5f4ae1 100644 --- a/cms/4DEVS +++ b/cms/4DEVS @@ -6,14 +6,14 @@ # # # # # # # # # # # # # # # # #### # # ###### # ### #### # # # # ### # # - STYL PISANIA KODU WATERMELON CMS'A + STYL PISANIA KODU WATERMELON CMS-A PRAWIE GOTOWE ... LEKTURA OBOWIĄZKOWA! ____________________________________________________________________________ - To jest OBOWIĄZUJĄCY dla programistów Watermelon CMS'a styl programowa- - nia. Jeśli zauważysz, że ktoś zrobił inaczej, popraw. Jeśli robi to - notorycznie - poinformuj go o tym. + To jest obowiązyjący dla programistów Watermelon CMS-a styl programowa- + nia. Jednolity styl poprawia wygląd kodu i ułatwia jego późniejszą refa- + ktoryzację. Jeśli zauważysz, że ktoś zrobił inaczej, popraw. 1. Wygląd kodu @@ -54,6 +54,9 @@ ____________________________________________________________________________ $test = ( $a * $h ) / 2; Pisanie spacji nie dotyczy operatorów zasięgu ( "::" oraz "->" ) + + Foo::Bar(); + $foo->bar(); Po przecinku zawsze spacja! @@ -66,30 +69,23 @@ ____________________________________________________________________________ e) Stałe itp. - Prawdę, fałsz i null zapisujemy tak: - - TRUE - FALSE - NULL - - Stałe piszemy także dużymi literami. Stałe samego CMS'a zaczynają + Stałe piszemy także dużymi literami. Stałe samego CMS-a zaczynają się od WTRMLN_ - Stałe własnych modułów MUSIMY poprzedzić prefiksem, aby mieć - pewność, że nie będzie kolidowało z czymś innym. Przykład stałej - własnego modułu: + Stałe własnego kodu musimy poprzedzić prefiksem, aby mieć pewność, + że nie będzie kolidowało z czymś innym. - INSZYNEWS_JAKIESDANE + FOO_SOMETHING - Pamiętamy, żeby używać stałych we własnych modułach tylko jeśli - to NAPRAWDĘ konieczne. + Pamiętamy, żeby używać stałych jeśli to NAPRAWDĘ konieczne. 2. Styl programowania a) Pobieranie danych z DB - Dane z bazy danych pobieramy do obiektu! Pobieranie danych poprzez - funkcję result jest ZABRONIONE, a do tablicy odradzane. + Dane z bazy danych pobieramy do obiektu. Nie pobieramy nic przez + funkcję mysql_result. Ewentualnie można użyć tablicy zamiast + obiektu, ale raczej preferujemy obiekty (czytelniej wygląda kod) Przykład pobrania danych, które jest OK: @@ -102,8 +98,10 @@ ____________________________________________________________________________ b) Działania na tablicach - Jeśli chcesz przejść po wszystkich elementach tablicy użyj foreach. - for jest odradzane w tym przypadku. + Jeśli chcesz przejść po wszystkich elementach tablicy użyj foreach, + ponieważ jest dużo czytelniejsze od for. Ewentualnie można użyć + funkcji typu array_map, ale jest to raczej mniej wygodne i mniej + czytelne. DOBRZE: @@ -120,66 +118,17 @@ ____________________________________________________________________________ } Myślę, że różnica czytelności obu przykładów pokazuje, dlaczego - należy użyć foreach ;) + lepiej użyć foreach ;) c) Globale - Pod ŻADNYM POZOREM NIE UŻYWAJ globali. Globale są do niczego. - - Możliwe, że wydaje się Tobie, że potrzebujesz ich, ale są sposoby - na obejście tego. - - Jeśli potrzebujesz jakichś danych w kilku funkcjach w klasie, dodaj - prywatną zmienną do klasy. - - Jeśli potrzebujesz potrzebujesz jakichś danych przy kilku odpale- - niach danej funkcji, użyj zmiennej statycznej. - - Jeśli potrzebujesz danych jakiejś klasy w zupełnie różnych miejsca- - ch kodu, użyj Singletona. - - Przyjęliśmy, że tak to ma wyglądać: - - /* - * object Instance() - * - * Singleton... - * - */ - static function Instance() - { - if(!self::$instance instanceof self) - self::$instance = new self; - return self::$instance; - } - - oraz jeszcze zmienna: - - private static $instance = NULL; // Singleton... + Zdecydowanie nie używamy globali. Są dobre sposoby, aby "przeżyć" + bez nich. Są to: pola (właściwości) klasy (zwykle prywatne, ale + mogą też być publiczne), singleton (odradzamy), referencje itd... 3. Pozostałe Wszystkie pliki zapisujemy z kodowaniem UTF-8 i uniksowymi enterami, - tzn. \n - - Jeśli widzisz w projekcie jakiś stary i zaniedbany plik, możesz się - upewnić co do poprawności tabów i enterów poprzez funkcję "Znajdź i - zamień". - - Taby: - - Znajdź: "\t" - Zamień: " " <- tutaj trzy spacje - - Entery - - Znajdź: "\r" - Zamień: "" <- nic - - Projekt oryginalnie był pisany na windowsie na różnych edytorach - jeszcze przed wprowadzeniem konkretnych zasad. Właśnie to spowodo- - wało globalny "syf" w projekcie. W przypadku Eclipse PDT (w tym - programie obecnie piszę wcms'a) możesz użyć File->Convert Line - Delimeters To->Unix. - + tzn. \n, nie \r\n jak na windowsie. + \ No newline at end of file diff --git a/cms/index.php b/cms/index.php index 0a15259..e4c6e59 100644 --- a/cms/index.php +++ b/cms/index.php @@ -48,6 +48,12 @@ error_reporting(E_ALL | E_STRICT); //define('NOMENU', ''); +/* + * dla developerów + */ + +define('DEBUG', ''); + include 'config.php'; include WTRMLN_CMSPATH . 'system.php'; diff --git a/cms/wtrmln/helpers/helpers.php b/cms/wtrmln/helpers/helpers.php index a75e9e7..b99c21a 100644 --- a/cms/wtrmln/helpers/helpers.php +++ b/cms/wtrmln/helpers/helpers.php @@ -171,7 +171,7 @@ function strHash($string, $algo = NULL) if($algo === NULL) { $algo = Config::$hashAlgo; - $algo = $algo[0]; + $algo = $algo[Config::$defaultHashAlgo]; } elseif(is_int($algo)) { diff --git a/cms/wtrmln/libs/config.php b/cms/wtrmln/libs/config.php index a0d9f1a..e3420ec 100644 --- a/cms/wtrmln/libs/config.php +++ b/cms/wtrmln/libs/config.php @@ -25,6 +25,7 @@ class Config public static $siteName; public static $siteSlogan; public static $hashAlgo; + public static $defaultHashAlgo; public static $defaultController; public static $theme; } diff --git a/cms/wtrmln/libs/controller.php b/cms/wtrmln/libs/controller.php index f721dbf..b01a433 100644 --- a/cms/wtrmln/libs/controller.php +++ b/cms/wtrmln/libs/controller.php @@ -27,6 +27,7 @@ class Controller $this->url = new URL(); $this->db = new DB(); $this->load = new Loader(); + $this->user = new User(); } /* diff --git a/cms/wtrmln/libs/db.php b/cms/wtrmln/libs/db.php index b96f612..e58aed2 100644 --- a/cms/wtrmln/libs/db.php +++ b/cms/wtrmln/libs/db.php @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* * Lib DB - * wersja 1.9.5 + * wersja 1.9.6 * * Komunikacja z bazą danych * @@ -138,7 +138,15 @@ class DB else { self::$errorList[] = mysql_error(); - return FALSE; + if(defined('DEBUG')) + { + throw new Exception('Nieudane wykonanie zapytania. Błąd: ' . self::lastError()); + } + else + { + panic('Błąd SQL'); + } + return false; } } diff --git a/cms/wtrmln/libs/loader.php b/cms/wtrmln/libs/loader.php index bd83309..5eda288 100644 --- a/cms/wtrmln/libs/loader.php +++ b/cms/wtrmln/libs/loader.php @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* * Lib Loader - * wersja 1.3.5 + * wersja 1.3.6 * * Ładowanie różnego rodzaju modułów * @@ -124,6 +124,13 @@ class Loader $model = strtolower($model); $model = 'model_' . $model; + + if(class_exists($model)) + { + $model_object = new $model(); + + return $model_object; + } $path = WTRMLN_MODELS . $model . '.php'; @@ -135,7 +142,7 @@ class Loader } else { - return FALSE; + return false; } } diff --git a/cms/wtrmln/libs/plugins_handle.php b/cms/wtrmln/libs/plugins_handle.php index 7080269..7ed550b 100644 --- a/cms/wtrmln/libs/plugins_handle.php +++ b/cms/wtrmln/libs/plugins_handle.php @@ -22,9 +22,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* * Lib PluginsHandle - * wersja 1.3.0 + * wersja 1.4.0 * * Łączność z pluginami / między pluginami + * + * (ta klasa jest do wyrzucenia, teraz używamy PluginsConfigDatabase * */ @@ -43,7 +45,7 @@ class PluginsHandle * Dane PluginsHandle (dostęp od nich przez funkcje getData, putData i deleteDate) */ - private $data = array(); + private static $data = array(); /* * public mixed getData(string $module[, string $key]); @@ -55,15 +57,15 @@ class PluginsHandle public function getData($module, $key = NULL) { - $instance = self::Instance(); + //$instance = self::Instance(); if($key == NULL) { - return $instance->data[$module]; + return self::$data[$module]; } else { - return $instance->data[$module][$key]; + return self::$data[$module][$key]; } } @@ -84,17 +86,17 @@ class PluginsHandle public function putData($module, $key, $text = NULL) { - $instance = self::Instance(); + //$instance = self::Instance(); if($text == NULL) { $text = $key; // żeby nie pomieszać - $instance->putDataNormal($module, $text); + $this->putDataNormal($module, $text); } else { - $instance->putDataAssoc($module, $key, $text); + $this->putDataAssoc($module, $key, $text); } } @@ -107,9 +109,9 @@ class PluginsHandle public function deleteData($module, $key) { - $instance = self::Instance(); + //$instance = self::Instance(); - unset($instance->data[$module][$key]); + unset(self::$data[$module][$key]); } /* @@ -121,9 +123,9 @@ class PluginsHandle public function insertData($module, $key, $text) { - $instance = self::Instance(); + //$instance = self::Instance(); - $instance->data[$module][$key] .= $text; + self::$data[$module][$key] .= $text; } /* @@ -156,9 +158,9 @@ class PluginsHandle private function putDataNormal($module, $text) { - $instance = self::Instance(); + //$instance = self::Instance(); - $instance->data[$module][] = $text; + self::$data[$module][] = $text; } /* @@ -173,9 +175,9 @@ class PluginsHandle private function putDataAssoc($module, $key, $text) { - $instance = self::Instance(); + //$instance = self::Instance(); - $instance->data[$module][$key] = $text; + self::$data[$module][$key] = $text; } } diff --git a/cms/wtrmln/modules/controllers/login.php b/cms/wtrmln/modules/controllers/login.php index cfd6825..1b18250 100644 --- a/cms/wtrmln/modules/controllers/login.php +++ b/cms/wtrmln/modules/controllers/login.php @@ -22,10 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. class Login extends Controller { - private $User; - public function Login() + function Login() { - $this->User = new User(); parent::Controller(); } @@ -52,7 +50,7 @@ class Login extends Controller $pass = $_POST['password']; $autologin = isset($_POST['autologin']); - $this->User->Login($login, $pass, $autologin); + $this->user->Login($login, $pass, $autologin); //TODO } @@ -69,6 +67,15 @@ class Login extends Controller echo $this->load->view('login_sendnewpassword'); } + + /* + * wylogowanie + */ + + function Logout() + { + $this->user->logout(); + } /* * przysyłanie nowego hasła (walidacja itd.) diff --git a/cms/wtrmln/modules/controllers/test.php b/cms/wtrmln/modules/controllers/test.php index f7a1dd2..ee59bb9 100644 --- a/cms/wtrmln/modules/controllers/test.php +++ b/cms/wtrmln/modules/controllers/test.php @@ -30,33 +30,45 @@ class Test extends Controller function Index() { SetH1('Strona Główna'); - - echo 'Panel Admina'; - + + echo 'Panel Admina

'; + + if($this->user->isLoggedIn()) + { + echo '
Jesteś zalogowany' . + 'Możesz się wylogować.
'; + } + else + { + echo '
Nie jesteś zalogowany' . + 'Możesz się zalogować. Jeśli jeszcze nie masz konta ' . + 'możesz się zarejestrować.
'; + } + echo '

Witaj! Oto jest okrojona i testowa wersja Watermelon CMS-a :) Więcej bajerów wkrótce ;)

'; - + echo '

Do zobaczenia w tej wersji masz:

'; - + echo ''; - - echo '

Watermelon CMS 1.0 pre-alpha2 [Codename: Ogór]

'; - + + echo '

Watermelon CMS 1.0 pre-alpha3 [Codename: Ogór]

'; + echo '

Zamiast Lorem Ipsum

'; - + echo '

Алексей Федорович Карамазов был вовсе необразованный, и положил, еще продолжались его приезда. Всего вероятнее, что ты хворый, думаю, что оно аль забыл? Не знаю, но и романа в кресло и неотразимо повлекло его мигом вошел в этом помещике как ребенок всё это вздор, и даже, знаете, что старцем его давние споры с намерением рассмешить и спрашивают, что Федору Павловичу. Петр Александрович Миусов, обращаясь к народу. Толпа затеснилась к митрополиту Платону спорить о Мите, то сейчас же последнее надеюсь. Ум-то у тебя же лазеечка к причастию-то? Допустили. Боюсь; помирать боюсь. Старец уселся на другой раз, когда произносил: Не чудеса склоняют реалиста никогда не умрет с своим воспитанием и плачут от ученого атеиста.

'; - + echo '

W innej wersji...

'; - + echo '

Drogi Marszałku, Wysoka Izbo. PKB rośnie. Różnorakie i rozwijanie struktur pomaga w wypracowaniu obecnej sytuacji. Praktyka dnia codziennego dowodzi, że rozszerzenie bazy o nowe rekordy pociąga za sobą proces wdrożenia i realizacji dalszych poczynań. Już nie zaś teorię, okazuje się iż usprawnienie systemu finansowego umożliwia w większym stopniu tworzenie postaw uczestników wobec zadań stanowionych przez organizację. Takowe informacje są tajne, nie trzeba udowadniać, ponieważ usprawnienie systemu rozszerza nam efekt postaw uczestników wobec zadań stanowionych przez organizację. Różnorakie i koledzy, zmiana przestarzałego systemu powszechnego uczestnictwa.

'; - + echo '

Trzeba naprawdę wiele wiedzieć, żeby wiedzieć jak mało się wie.

'; - + echo '

Nikt Ktoś kiedyśtam mądrze powiedział nic nie powiedziałem.

'; } } diff --git a/cms/wtrmln/modules/models/model_user.php b/cms/wtrmln/modules/models/model_user.php index 3bc239d..7a76bc8 100644 --- a/cms/wtrmln/modules/models/model_user.php +++ b/cms/wtrmln/modules/models/model_user.php @@ -27,11 +27,6 @@ class Model_User extends Model parent::Model(); } - public function HelloWorld() - { - echo 'hi people.'; - } - public function LoginUserData($login) { $login = mysql_real_escape_string($login); @@ -39,6 +34,13 @@ class Model_User extends Model return $this->db->query("SELECT `password`, `hashalgo`, `salt` FROM `__users` ". "WHERE `nick` = '%1'", $login); } + + public function UpdatePassword($nick, $hash, $salt, $hashAlgo) + { + return $this->db->query("UPDATE `__users` SET " . + "`password` = '%1', `hashalgo` = '%2', `salt` = '%3' " . + "WHERE `nick` = '%4'", $hash, $hashAlgo, $salt, $nick); + } } ?> \ No newline at end of file diff --git a/cms/wtrmln/modules/plugins/user.php b/cms/wtrmln/modules/plugins/user.php index b6a9154..0386086 100644 --- a/cms/wtrmln/modules/plugins/user.php +++ b/cms/wtrmln/modules/plugins/user.php @@ -28,6 +28,8 @@ class User extends Plugin * Instancja klasy Model_User */ private $User; + + private static $LoggedIn = null; /* * public void User() @@ -58,8 +60,6 @@ class User extends Plugin public function Login($user, $password, $autologin) { // Walidacja wprowadzonych danych - - var_dump($autologin); if(empty($user)) { @@ -106,10 +106,31 @@ class User extends Plugin echo $this->load->view('login_loginerrors', array('errors' => $errors)); return false; } + + // generujemy nowy salt i hash i + // zmieniamy hashalgo (jeśli nieaktualne) + + $salt = strHash(uniqid(mt_rand(), true)); + + $salt = substr($salt, 0, 16); + + $hash = strHash($password . $salt); + + $this->User->updatePassword($user, $hash, $salt, Config::$defaultHashAlgo); + + // logujemy :] + + $_SESSION['WTRMLN_USER'] = $user; + $_SESSION['WTRMLN_PASS'] = $hash; + $_SESSION['WTRMLN_LASTSEEN'] = time(); - echo 'bez błędów :P'; - - //TODO + // jeszcze informacyjka + + setH1('Logowanie udane'); + + echo $this->load->view('login_success'); + + return true; } public function Register($user, $password, $password2, $email, $email2, $data) @@ -124,6 +145,55 @@ class User extends Plugin public function Logout() { + session_destroy(); + + self::$LoggedIn = false; + + //TODO + } + + public function IsLoggedIn() + { + // sprawdzamy, czy już wcześniej funkcja była odpalana + + if(self::$LoggedIn !== null) + { + return self::$LoggedIn; + } + + // sprawdzamy, czy user istnieje + + $userdata = $this->User->LoginUserData($_SESSION['WTRMLN_USER']); + + if($userdata->num_rows() == 0) + { + self::$LoggedIn = false; + return false; + } + + // sprawdzamy poprawność hasła + + $userdata = $userdata->to_obj(); + + if($_SESSION['WTRMLN_PASS'] != $userdata->password) + { + self::$LoggedIn = false; + return false; + } + + // sprawdzamy kiedy ostatnio był koleś (limit długości sesji) + + if($_SESSION['WTRMLN_LASTSEEN'] < time() - 1800) + { + $this->Logout(); + } + + $_SESSION['WTRMLN_LASTSEEN'] = time(); + + self::$LoggedIn = true; + + return true; + //TODO } diff --git a/cms/wtrmln/system.php b/cms/wtrmln/system.php index 0a8a3ab..a6a1c26 100644 --- a/cms/wtrmln/system.php +++ b/cms/wtrmln/system.php @@ -26,15 +26,18 @@ header("Content-Type: text/html; charset=UTF-8"); # Biblioteki # ######################################## -include(WTRMLN_LIBS . 'url.php'); -include(WTRMLN_LIBS . 'db.php'); -include(WTRMLN_LIBS . 'loader.php'); -include(WTRMLN_LIBS . 'plugins_handle.php'); -include(WTRMLN_LIBS . 'controller.php'); -include(WTRMLN_LIBS . 'model.php'); -include(WTRMLN_LIBS . 'plugin.php'); +include WTRMLN_LIBS . 'url.php'; +include WTRMLN_LIBS . 'db.php'; +include WTRMLN_LIBS . 'loader.php'; +//include WTRMLN_LIBS . 'plugins_handle.php'; +include WTRMLN_LIBS . 'pluginscdb.php'; +include WTRMLN_LIBS . 'controller.php'; +include WTRMLN_LIBS . 'model.php'; +include WTRMLN_LIBS . 'plugin.php'; -include(WTRMLN_HELPERS . 'helpers.php'); +include WTRMLN_HELPERS . 'helpers.php'; + +//Instance( //////////////////////////////////////// @@ -65,6 +68,17 @@ class Watermelon * $head_element - pojedynczy element do umieszczenia w sekcji */ public static $metaSrc = array(); + + /* + * public static object $pcdb + * + * dane klasy PluginsConfigDatabase + * + * [jak będzie ktoś miał czas i chęci to trzeba to przenieść do klasy Plugins + * ConfigDatabase. To nie powinno być tutaj] + */ + + public static $pcdb = null; /* * public void Watermelon(string $dbHost, string $dbUser, string $dbPass, string $dbName, diff --git a/cms/wtrmln/themes/wcmslay/index.php b/cms/wtrmln/themes/wcmslay/index.php index f77cb1b..2cb558f 100644 --- a/cms/wtrmln/themes/wcmslay/index.php +++ b/cms/wtrmln/themes/wcmslay/index.php @@ -3,30 +3,36 @@ - - + + -
- + +
diff --git a/cms/wtrmln/themes/wcmslay/skin.php b/cms/wtrmln/themes/wcmslay/skin.php index c4e50e8..b72173d 100644 --- a/cms/wtrmln/themes/wcmslay/skin.php +++ b/cms/wtrmln/themes/wcmslay/skin.php @@ -7,7 +7,7 @@ $meta = ''; foreach($_w_metaSrc as $metaItem) { - $meta .= "\t" . $metaItem . "\n"; + $meta .= " " . $metaItem . "\n"; } /* menu diff --git a/cms/wtrmln/themes/wcmslay/style.css b/cms/wtrmln/themes/wcmslay/style.css index 739f45e..7d12708 100644 --- a/cms/wtrmln/themes/wcmslay/style.css +++ b/cms/wtrmln/themes/wcmslay/style.css @@ -152,7 +152,7 @@ li text-align: center; } -/* Boksy z różnymi informacjami (błędy, podpowiedzi itp. +/* Boksy z różnymi informacjami (błędy, podpowiedzi itp.) ********************************************************************/ .box_e @@ -196,6 +196,11 @@ li color: #359; } +.box_c strong +{ + color: #693; +} + .box_t strong { color: #888; @@ -215,6 +220,7 @@ li .box_e strong, .box_w strong, .box_i strong, +.box_c strong, .box_t strong { display: block; @@ -279,11 +285,54 @@ li font-size: 2em; padding-left: 200px; padding-top: 50px; + height: 31px; } #hs { padding-left: 350px; + height: 16px; +} + +#header ul +{ + margin-top: 39px; +} + +#header ul li +{ + display: block; + padding: 5px; + color: #fff; + background: #000; + font-weight: bold; + float: left; + opacity: .5; + margin-right: 5px; + height: 16px; +} + +#header ul li.actual_page +{ + opacity: 1; + background: #fff; +} + +#header ul li a +{ + border: 0; + background: #000; +} + +#header ul li.actual_page a +{ + background: #fff; +} + +#header ul li.actual_page a:hover, +#header ul li.actual_page a:visited:hover +{ + color: #000; } /***/ -- 2.11.4.GIT