Switched to public API for authentication and a horrible device auth implementation for unsecured connections.
This commit is contained in:
parent
951ec95ca2
commit
d0cab7054f
16 changed files with 169 additions and 115 deletions
|
@ -50,6 +50,10 @@ $config['flashiiUrl']['feedback'] = 'https://flashii.net/forum';
|
|||
$config['flashiiUrl']['changelog'] = 'https://flashii.net/changelog';
|
||||
$config['flashiiUrl']['rules'] = 'https://flashii.net/info/rules';
|
||||
$config['flashiiUrl']['contact'] = 'https://flashii.net/info/contact';
|
||||
$config['flashiiId']['api'] = '';
|
||||
$config['flashiiId']['id'] = '';
|
||||
$config['flashiiId']['clientId'] = '';
|
||||
$config['flashiiId']['clientSecret'] = '';
|
||||
|
||||
if(is_file(AJAX_CHAT_PATH . '/config/config-db.php'))
|
||||
include_once AJAX_CHAT_PATH . '/config/config-db.php';
|
||||
|
|
|
@ -119,3 +119,5 @@ $lang['logsTime'] = 'Time';
|
|||
$lang['logsSearch'] = 'Search';
|
||||
$lang['logsPrivateChannels'] = 'Private Channels';
|
||||
$lang['logsPrivateMessages'] = 'Private Messages';
|
||||
$lang['fidAuthzRequestFailed'] = 'Could not request authorization code.';
|
||||
$lang['fidAuthzTokenFailed'] = 'Could not complete authorization request, please try again.';
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
color:#f0f0f0;
|
||||
border: 1px solid #808080;
|
||||
background-image: linear-gradient(to bottom, #222, #000);
|
||||
background-image: -moz-linear-gradient(to bottom, #222, #000);
|
||||
background-image: -webkit-linear-gradient(top, #222, #000);
|
||||
}
|
||||
#content select, #loginForm select, #loginForm input, #content textarea {
|
||||
background-color:#000;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
color:#f0f0f0;
|
||||
border: 1px solid #808080;
|
||||
background-image: linear-gradient(to bottom, #002545, #000);
|
||||
background-image: -moz-linear-gradient(to bottom, #002545, #000);
|
||||
background-image: -webkit-linear-gradient(top, #002545, #000);
|
||||
}
|
||||
#content select, #loginForm select, #loginForm input, #content textarea {
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
#loginContent {
|
||||
background-color: #000000;
|
||||
background-image: -linear-gradient(to bottom, #4c3b52, #000000);
|
||||
background-image: linear-gradient(to bottom, #4c3b52, #000000);
|
||||
background-image: -moz-linear-gradient(to bottom, #4c3b52, #000000);
|
||||
background-image: -webkit-linear-gradient(top, #4c3b52, #000000);
|
||||
color: #999999;
|
||||
}
|
||||
#loginContent h1 {
|
||||
|
@ -42,6 +44,8 @@
|
|||
#content {
|
||||
background-color: #000000;
|
||||
background-image: linear-gradient(to bottom, #4c3b52, #000000);
|
||||
background-image: -moz-linear-gradient(to bottom, #4c3b52, #000000);
|
||||
background-image: -webkit-linear-gradient(top, #4c3b52, #000000);
|
||||
color: #999999;
|
||||
}
|
||||
#content h1 {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
color:#f0f0f0;
|
||||
border: 1px solid #808080;
|
||||
background-image: linear-gradient(to bottom, #110033, #000000);
|
||||
background-image: -moz-linear-gradient(to bottom, #110033, #000000);
|
||||
background-image: -webkit-linear-gradient(top, #110033, #000000);
|
||||
}
|
||||
#loginContent #loginButton {
|
||||
|
@ -24,6 +25,7 @@
|
|||
color:#f0f0f0;
|
||||
border: 1px solid #808080;
|
||||
background-image: linear-gradient(to bottom, #110033, #000000);
|
||||
background-image: -moz-linear-gradient(to bottom, #110033, #000000);
|
||||
background-image: -webkit-linear-gradient(top, #110033, #000000);
|
||||
}
|
||||
#loginContent input {
|
||||
|
|
|
@ -15,7 +15,10 @@ h3 {
|
|||
font-size: 15px;
|
||||
padding: 2px;
|
||||
margin: 10px;
|
||||
background: linear-gradient(180deg, #900, #600) #700;
|
||||
background-color: #700;
|
||||
background-image: linear-gradient(to bottom, #900, #600);
|
||||
background-image: -moz-linear-gradient(to bottom, #900, #600);
|
||||
background-image: -webkit-linear-gradient(top, #900, #600);
|
||||
}
|
||||
|
||||
div.copyright {
|
||||
|
|
|
@ -14,7 +14,11 @@ body {
|
|||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
background: linear-gradient(180deg, #C2AFFE, #FBEEFF) repeat-x scroll center top #FBEEFF;
|
||||
background-color: #fbeeff;
|
||||
background-image: linear-gradient(to bottom, #c2affe, #fbeeff);
|
||||
background-image: -moz-linear-gradient(to bottom, #c2affe, #fbeeff);
|
||||
background-image: -webkit-linear-gradient(top, #c2affe, #fbeeff);
|
||||
background-repeat: repeat-x;
|
||||
background-size: auto 200px;
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -23,7 +27,7 @@ img.logo {
|
|||
height: 150px;
|
||||
width: 450px;
|
||||
border: 0px;
|
||||
background: url('https://static.flash.moe/logos/logo.png') no-repeat scroll left top transparent;
|
||||
background: url('//static.flash.moe/logos/logo.png') no-repeat scroll left top transparent;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
@ -424,7 +428,7 @@ div.ucp_avatar_cont {
|
|||
height: 23px;
|
||||
width: 23px;
|
||||
border: 0px;
|
||||
background: url('https://static.flash.moe/images/window-sprite.png') no-repeat scroll 0px 0px transparent;
|
||||
background: url('//static.flash.moe/images/window-sprite.png') no-repeat scroll 0px 0px transparent;
|
||||
}
|
||||
|
||||
.maxbutton {
|
||||
|
@ -432,7 +436,7 @@ div.ucp_avatar_cont {
|
|||
height: 23px;
|
||||
width: 23px;
|
||||
border: 0px;
|
||||
background: url('https://static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -23px transparent;
|
||||
background: url('//static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -23px transparent;
|
||||
}
|
||||
|
||||
.minbutton {
|
||||
|
@ -440,7 +444,7 @@ div.ucp_avatar_cont {
|
|||
height: 23px;
|
||||
width: 23px;
|
||||
border: 0px;
|
||||
background: url('https://static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -46px transparent;
|
||||
background: url('//static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -46px transparent;
|
||||
}
|
||||
|
||||
.donate-btn {
|
||||
|
@ -448,7 +452,7 @@ div.ucp_avatar_cont {
|
|||
height: 26px;
|
||||
width: 90px;
|
||||
border: 0px;
|
||||
background: url('https://static.flash.moe/images/donate-btn.png') no-repeat scroll 0px 0px transparent;
|
||||
background: url('//static.flash.moe/images/donate-btn.png') no-repeat scroll 0px 0px transparent;
|
||||
}
|
||||
|
||||
div.topLeftBar {
|
||||
|
|
|
@ -357,6 +357,7 @@
|
|||
color:#f0f0f0;
|
||||
border: 1px solid #808080;
|
||||
background-image: linear-gradient(to bottom, #222, #000);
|
||||
background-image: -moz-linear-gradient(to bottom, #222, #000);
|
||||
background-image: -webkit-linear-gradient(top, #222, #000);
|
||||
}
|
||||
#content select, #loginForm select, #loginForm input, #content textarea {
|
||||
|
|
|
@ -331,6 +331,8 @@
|
|||
color: #f0f0f0;
|
||||
border: 1px solid #808080;
|
||||
background-image: linear-gradient(to bottom, #222, #000);
|
||||
background-image: -moz-linear-gradient(to bottom, #222, #000);
|
||||
background-image: -webkit-linear-gradient(top, #222, #000);
|
||||
}
|
||||
#content select, #loginForm select, #loginForm input, #content textarea {
|
||||
background-color: #000;
|
||||
|
|
|
@ -15,7 +15,11 @@ html {
|
|||
}
|
||||
body {
|
||||
font: 12px/20px Verdana, sans-serif;
|
||||
background: linear-gradient(180deg, #C2AFFE, #FBEEFF) no-repeat scroll left top #FBEEFF;
|
||||
background-color: #fbeeff;
|
||||
background-repeat: no-repeat;
|
||||
background-image: linear-gradient(to bottom, #c2affe, #fbeeff);
|
||||
background-image: -moz-linear-gradient(to bottom, #c2affe, #fbeeff);
|
||||
background-image: -webkit-linear-gradient(top, #c2affe, #fbeeff);
|
||||
background-size: cover;
|
||||
color: #000;
|
||||
height: 100%;
|
||||
|
@ -118,7 +122,7 @@ a.default:active {
|
|||
}
|
||||
a.gotop {
|
||||
display: inline-block;
|
||||
background: url('https://static.flash.moe/images/arrow.png') #111;
|
||||
background: url('//static.flash.moe/images/arrow.png') #111;
|
||||
color: #FFF;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
|
@ -192,7 +196,9 @@ a.gotop:active {
|
|||
/* Site Header Styling */
|
||||
.header {
|
||||
text-align: center;
|
||||
background: linear-gradient(180deg, #C2AFFE, #CCBAFE);
|
||||
background-image: linear-gradient(to bottom, #c2affe, #ccbafe);
|
||||
background-image: -moz-linear-gradient(to bottom, #c2affe, #ccbafe);
|
||||
background-image: -webkit-linear-gradient(top, #c2affe, #ccbafe);
|
||||
box-shadow: 0 0 5px #8364A1;
|
||||
}
|
||||
/*.header .logo {
|
||||
|
@ -349,7 +355,10 @@ a.gotop:active {
|
|||
width: 100%;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 30px;
|
||||
background: linear-gradient(180deg, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%) #C2AFFE;
|
||||
background-color: #c2affe;
|
||||
background-image: linear-gradient(to bottom, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%);
|
||||
background-image: -moz-linear-gradient(to bottom, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%);
|
||||
background-image: -webkit-linear-gradient(top, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
@ -537,7 +546,7 @@ a.gotop:active {
|
|||
font-weight: 700;
|
||||
font-size: 20px;
|
||||
color: #306;
|
||||
background: linear-gradient(90deg, rgba(148,117,178,.7), rgba(148,117,178,0)) #C2AFFE;
|
||||
background: linear-gradient(90deg, rgba(148,117,178,.7), rgba(148,117,178,0));
|
||||
border-radius: 2px;
|
||||
}
|
||||
.content-right .head,
|
||||
|
@ -558,7 +567,10 @@ a.gotop:active {
|
|||
text-align: center;
|
||||
border-radius: 5px;
|
||||
font-weight: 100;
|
||||
background: linear-gradient(180deg, #874399, #35245E) #874399;
|
||||
background-color: #874399;
|
||||
background-image: linear-gradient(to bottom, #874399, #35245E);
|
||||
background-image: -moz-linear-gradient(to bottom, #874399, #35245E);
|
||||
background-image: -webkit-linear-gradient(top, #874399, #35245E);
|
||||
transition: text-shadow .25s;
|
||||
color: #FFF;
|
||||
font-size: 16px;
|
||||
|
@ -570,7 +582,10 @@ a.gotop:active {
|
|||
cursor: pointer;
|
||||
}
|
||||
.content-right .registerbutton {
|
||||
background: linear-gradient(180deg, #874399, #35245E) #874399;
|
||||
background-color: #874399;
|
||||
background-image: linear-gradient(to bottom, #874399, #35245E);
|
||||
background-image: -moz-linear-gradient(to bottom, #874399, #35245E);
|
||||
background-image: -webkit-linear-gradient(top, #874399, #35245E);
|
||||
}
|
||||
.button.profileOption {
|
||||
width: auto !important;
|
||||
|
|
|
@ -2410,7 +2410,7 @@ var ajaxChat = {
|
|||
|
||||
replaceCommandWhois: function(textParts) {
|
||||
return '<span class="chatBotMessage">'
|
||||
+ this.lang['whois'].replace(/%s/, textParts[1]) + ' <a target="_blank" href="https://flash.moe/whois/'
|
||||
+ this.lang['whois'].replace(/%s/, textParts[1]) + ' <a target="_blank" href="//flash.moe/whois/'
|
||||
+ textParts[2]
|
||||
+ '">'
|
||||
+ textParts[2]
|
||||
|
|
|
@ -303,7 +303,11 @@ HTML;
|
|||
function getErrorMessageTags() {
|
||||
$errorMessages = '';
|
||||
foreach($this->ajaxChat->getInfoMessages('error') as $error) {
|
||||
$errorMessages .= '<h3 class="miotitle">'.$this->ajaxChat->htmlEncode($this->ajaxChat->getLang($error)).'</h3>';
|
||||
$html = $this->ajaxChat->getLang($error);
|
||||
if($error !== 'errorInvalidUser')
|
||||
$html = $this->ajaxChat->htmlEncode($html);
|
||||
|
||||
$errorMessages .= '<h3 class="miotitle">'.$html.'</h3>';
|
||||
}
|
||||
return $errorMessages;
|
||||
}
|
||||
|
|
|
@ -9,52 +9,108 @@
|
|||
|
||||
namespace AJAXChat;
|
||||
|
||||
use Flashii\{FlashiiClient,FlashiiUrls};
|
||||
use Flashii\Credentials\{BasicCredentials,BearerCredentials,MisuzuCredentials};
|
||||
|
||||
class CustomAJAXChat extends AJAXChat {
|
||||
|
||||
// Returns an associative array containing userName, userID and userRole
|
||||
// Returns null if login is invalid
|
||||
function getValidLoginUserData() {
|
||||
if(empty($_COOKIE['msz_auth'])) {
|
||||
header('Location: ' . $this->getConfig('flashiiAuth', 'login'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$userInfo = SockChatAuth::attempt(
|
||||
$this->getConfig('flashiiAuth', 'verify'),
|
||||
$this->getConfig('flashiiSecret'),
|
||||
(string)filter_input(INPUT_COOKIE, 'msz_auth')
|
||||
// TODO: this sucks
|
||||
$urls = new FlashiiUrls(
|
||||
(fn() => (($url = $this->getConfig('flashiiId', 'api')) === '' ? FlashiiUrls::PROD_API_URL : $url))(),
|
||||
(fn() => (($url = $this->getConfig('flashiiId', 'id')) === '' ? FlashiiUrls::PROD_ID_URL : $url))()
|
||||
);
|
||||
|
||||
if($userInfo->success) {
|
||||
// Check if we have a valid registered user:
|
||||
if(filter_has_var(INPUT_SERVER, 'HTTPS')) {
|
||||
$authToken = trim((string)filter_input(INPUT_COOKIE, 'msz_auth'));
|
||||
if($authToken === '') {
|
||||
header('Location: ' . $this->getConfig('flashiiAuth', 'login'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$chatUser = [
|
||||
'userID' => $userInfo->user_id,
|
||||
'userName' => $userInfo->username,
|
||||
'userRole' => AJAX_CHAT_GUEST,
|
||||
];
|
||||
|
||||
// sock chat auth doesn't actually return role ids lol
|
||||
if($userInfo->colour_raw === 0xEE9400)
|
||||
$chatUser['userRole'] = DONATOR;
|
||||
elseif($userInfo->colour_raw === 0x0099FF)
|
||||
$chatUser['userRole'] = CMOD;
|
||||
elseif($userInfo->colour_raw === 0x7353C4)
|
||||
$chatUser['userRole'] = PURPLE;
|
||||
elseif($userInfo->colour_raw === 0x9E8DA7)
|
||||
$chatUser['userRole'] = BOTS;
|
||||
elseif($userInfo->rank >= 10)
|
||||
$chatUser['userRole'] = AJAX_CHAT_ADMIN;
|
||||
elseif($userInfo->rank >= 5)
|
||||
$chatUser['userRole'] = AJAX_CHAT_MODERATOR;
|
||||
elseif($userInfo->rank >= 1)
|
||||
$chatUser['userRole'] = AJAX_CHAT_USER;
|
||||
|
||||
return $chatUser;
|
||||
$flashii = new FlashiiClient('AJAX Chat', new MisuzuCredentials($authToken), $urls);
|
||||
} else {
|
||||
// Guest users:
|
||||
return $this->getGuestUser();
|
||||
$flashii = new FlashiiClient('AJAX Chat', new BasicCredentials(
|
||||
$this->getConfig('flashiiId', 'clientId'),
|
||||
$this->getConfig('flashiiId', 'clientSecret')
|
||||
), $urls);
|
||||
|
||||
$doPoll = true;
|
||||
$expiresIn = (int)$this->getSessionVar('fidDeviceExpiresIn');
|
||||
if($expiresIn < time()) {
|
||||
$this->regenerateSessionID();
|
||||
|
||||
$doPoll = false;
|
||||
$request = $flashii->oauth2()->requestAuthorize('identify');
|
||||
if($request instanceof \Flashii\OAuth2\OAuth2AuthorizationRequest) {
|
||||
$this->setSessionVar('fidDeviceCode', $request->getDeviceCode());
|
||||
$this->setSessionVar('fidDeviceUserCode', $request->getUserCode());
|
||||
$this->setSessionVar('fidDeviceExpiresIn', time() + $request->getExpiresIn());
|
||||
$this->setSessionVar('fidDevicePollInterval', $request->getInterval());
|
||||
$this->setSessionVar('fidDeviceUri', $request->getVerificationUri());
|
||||
$this->setSessionVar('fidDeviceUriFull', $request->getVerificationUriComplete());
|
||||
} else
|
||||
$this->addInfoMessage('fidAuthzRequestFailed');
|
||||
}
|
||||
|
||||
$deviceCode = $this->getSessionVar('fidDeviceCode');
|
||||
if(!empty($deviceCode)) {
|
||||
if($doPoll) {
|
||||
$token = $flashii->oauth2()->tokenWithDeviceCode($deviceCode);
|
||||
if($token instanceof \Flashii\OAuth2\OAuth2Token)
|
||||
$flashii = $flashii->forkWithAccessToken($token->getAccessToken());
|
||||
else {
|
||||
if($token->getCode() !== 'slow_down') {
|
||||
$this->setSessionVar('fidDeviceExpiresIn', 0);
|
||||
$this->regenerateSessionID();
|
||||
}
|
||||
|
||||
$this->addInfoMessage('fidAuthzTokenFailed');
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLang(); // load language
|
||||
$this->_lang['errorInvalidUser'] = sprintf(
|
||||
$this->_lang['fidPoll'] ?? 'You need to approve the login attempt! If your browser supports HTTPS <a href="%s" target="_blank" rel="noopener">click here</a>, or go to %s on a device that does and enter <code>%s</code> and press the Login button again.',
|
||||
$this->getSessionVar('fidDeviceUriFull'),
|
||||
$this->getSessionVar('fidDeviceUri'),
|
||||
$this->getSessionVar('fidDeviceUserCode')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have a valid registered user:
|
||||
$userInfo = $flashii->v1()->me();
|
||||
|
||||
// Guest users:
|
||||
if($userInfo === null)
|
||||
return $this->getGuestUser();
|
||||
|
||||
$chatUser = [
|
||||
'userID' => $userInfo->getId(),
|
||||
'userName' => $userInfo->getName(),
|
||||
];
|
||||
|
||||
if($userInfo->hasRole('admin'))
|
||||
$chatUser['userRole'] = AJAX_CHAT_ADMIN;
|
||||
elseif($userInfo->hasRole('gmod'))
|
||||
$chatUser['userRole'] = AJAX_CHAT_MODERATOR;
|
||||
elseif($userInfo->hasRole('dev'))
|
||||
$chatUser['userRole'] = PURPLE;
|
||||
elseif($userInfo->hasRole('bot'))
|
||||
$chatUser['userRole'] = BOTS;
|
||||
elseif($userInfo->hasRole('tenshi'))
|
||||
$chatUser['userRole'] = DONATOR;
|
||||
elseif($userInfo->hasRole('og') || $userInfo->getId() === '72')
|
||||
$chatUser['userRole'] = CMOD; // OGs are blue here i guess lol
|
||||
elseif($userInfo->getRank() > 0)
|
||||
$chatUser['userRole'] = AJAX_CHAT_USER;
|
||||
else
|
||||
$chatUser['userRole'] = AJAX_CHAT_GUEST;
|
||||
|
||||
return $chatUser;
|
||||
}
|
||||
|
||||
// Store the channels the current user has access to
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
namespace AJAXChat;
|
||||
|
||||
final class SockChatAuth {
|
||||
public static function attempt(string $endPoint, string $secret, string $cookie): object {
|
||||
if(!empty($cookie)) {
|
||||
$method = 'Misuzu';
|
||||
$signature = sprintf('verify#%s#%s#%s', $method, $cookie, $_SERVER['REMOTE_ADDR']);
|
||||
$signature = hash_hmac('sha256', $signature, $secret);
|
||||
|
||||
$login = curl_init($endPoint);
|
||||
curl_setopt_array($login, [
|
||||
CURLOPT_AUTOREFERER => false,
|
||||
CURLOPT_FAILONERROR => false,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query([
|
||||
'method' => $method,
|
||||
'token' => $cookie,
|
||||
'ipaddr' => $_SERVER['REMOTE_ADDR'],
|
||||
], '', '&', PHP_QUERY_RFC3986),
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TCP_FASTOPEN => true,
|
||||
CURLOPT_CONNECTTIMEOUT => 2,
|
||||
CURLOPT_MAXREDIRS => 2,
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
||||
CURLOPT_TIMEOUT => 5,
|
||||
CURLOPT_USERAGENT => 'AJAX Chat',
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'X-SharpChat-Signature: ' . $signature,
|
||||
],
|
||||
]);
|
||||
$userInfo = json_decode(curl_exec($login));
|
||||
curl_close($login);
|
||||
}
|
||||
|
||||
if(empty($userInfo->success)) {
|
||||
$userInfo = new stdClass;
|
||||
$userInfo->success = false;
|
||||
$userInfo->user_id = 0;
|
||||
$userInfo->username = 'Anonymous';
|
||||
$userInfo->colour_raw = 0x40000000;
|
||||
$userInfo->rank = 0;
|
||||
$userInfo->hierarchy = 0;
|
||||
$userInfo->perms = 0;
|
||||
}
|
||||
|
||||
return $userInfo;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,9 @@
|
|||
|
||||
div.toplogo {
|
||||
font-size: 30px;
|
||||
background-image: linear-gradient(180deg, #190015/*#2F426C#FF2400*/, transparent);
|
||||
background-image: linear-gradient(to bottom, #190015/*#2F426C#FF2400*/, transparent);
|
||||
background-image: -moz-linear-gradient(to bottom, #190015/*#2F426C#FF2400*/, transparent);
|
||||
background-image: -webkit-linear-gradient(top, #190015/*#2F426C#FF2400*/, transparent);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-family: "Century Gothic", Gothic, sans-serif;
|
||||
|
@ -72,11 +74,15 @@
|
|||
div.topmenu a:hover {
|
||||
text-shadow: 0px 0px 8px #F1F1F1;
|
||||
background-image: linear-gradient(to bottom, #8800BB, transparent);
|
||||
background-image: -moz-linear-gradient(to bottom, #8800BB, transparent);
|
||||
background-image: -webkit-linear-gradient(top, #8800BB, transparent);
|
||||
}
|
||||
|
||||
div.topmenu a:active {
|
||||
text-shadow: 0px 0px 8px #0042FF;
|
||||
background-image: linear-gradient(to bottom, #440077, transparent);
|
||||
background-image: -moz-linear-gradient(to bottom, #440077, transparent);
|
||||
background-image: -webkit-linear-gradient(top, #440077, transparent);
|
||||
}
|
||||
</style>
|
||||
[STYLE_SHEETS/]
|
||||
|
|
Loading…
Reference in a new issue