Removing xCAT-web-exp. All of it is incorporated into xCAT-UI.

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@3655 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
bp-sawyers 2009-06-29 18:35:06 +00:00
parent f9c95e8c6c
commit 1c09109d86
15 changed files with 0 additions and 845 deletions

View File

@ -1,17 +0,0 @@
svn co http://xcat.svn.sourceforge.net/svnroot/xcat/xcat-core/trunk/xCAT-web-exp
svn co http://xcat.svn.sourceforge.net/svnroot/xcat/xcat-dep/trunk/javascript
mkdir -p $1
cp -a xCAT-web-exp/* $1
OLDWD=`pwd`
cd $1
tar jxvf $OLDWD/javascript/jsTree*
patch -p0 < $OLDWD/javascript/jstree*patch
mv jsTree/images .
mv jsTree/tree* .
mv jsTree/css.js .
mv jsTree/jquery.js .
mv jsTree/jquery.listen.js .
rm -rf jsTree
cp $OLDWD/javascript/jquery.ui.js .
cp $OLDWD/javascript/theme/theme.css .
cp $OLDWD/javascript/theme/images/* images

View File

@ -1,4 +0,0 @@
$(document).ready(function(){
$("#alltabs > ul").tabs({spinner: ''});
$("#nodetabs > ul").tabs({spinner: ''});
});

View File

@ -1,11 +0,0 @@
<script type="text/javascript">
$(document).ready(function() {
$("#eventlogbutton").click(function() {
$("#mydisp").text("Would have queried eventlog from "+noderange);
});
});
</script>
<body>
<div id="mydisp"></div>
<button id="eventlogbutton">Get Eventlog</button>
</body>

View File

@ -1,316 +0,0 @@
<?php
# cat client-key.pem client-cert.pem ca.pem >>certchain.pem
$version = "0.1";
#$cert = ".xcat/client-cred.pem";
$msg;
$xcathost = "localhost";
$port = "3001";
#if(! file_exists($cert)){
# echo "$cert does not exist. Please run xcatwebsetup first";
#}
$xcatcmds = array(
"rpower" => array("on","off","reset","stat","state","boot","off","cycle"),
"rvitals" => array("all","temp","wattage","voltage","fanspeed","power","leds","state"),
"reventlog" => array("all", "clear"),
"rinv" => array("all", "model", "serial", "vpd", "mprom", "deviceid", "uuid", "guid", "firm", "bios", "diag", "mprom", "sprom", "mparom", "mac", "mtm"),
"resetboot" => array("net", "hd", "cd", "def", "stat")
);
#function to enable password storage to split between cookie and session variable
function xorcrypt($data,$key) {
$datalen=strlen($data);
$keylen=strlen($key);
for ($i=0;$i<$datalen;$i++) {
$data[$i]=chr(ord($data[$i])^ord($key[$i]));
}
return $data;
}
function getpassword() {
if (isset($GLOBALS['xcatauthsecret'])) {
$cryptext=$GLOBALS['xcatauthsecret'];
} else if (isset($_COOKIE["xcatauthsecret"])) {
$cryptext = $_COOKIE["xcatauthsecret"];
} else {
return false;
}
return xorcrypt($_SESSION["secretkey"],base64_decode($cryptext));
}
#remembers the password, splitting knowledge between server and client side
#persistant storage
#Caller should regenerate session id when contemplating a new user/password,
#to preclude session fixation, though fixation is limited without the secret.
function setpassword($password) {
$randlen=strlen($password);
$key=getrandchars($randlen);
$cryptext=xorcrypt($password,$key);
$cryptext=base64_encode($cryptext); #non-ascii chars, base64 it
#Not bothering with explicit expiration, as time sync would be too hairy
#should go away when browser closes. Any timeout will be handled server
#side. If the session id invalidates and the one-time key discarded,
#the cookie contents are worthless anyway
#nevertheless, when logout happens, cookie should be reaped
setcookie("xcatauthsecret",$cryptext);
$GLOBALS["xcatauthsecret"]=$cryptext; #May need it sooner, prefer globals
$_SESSION["secretkey"]=$key;
}
function getrandchars($length) {
$charset='0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*';
$charsize=strlen($charset);
srand();
$chars='';
for ($i=0;$i<$length;$i++) {
$num=rand()%$charsize;
$chars=$chars.substr($charset,$num,1);
}
return $chars;
}
#functions for editing tables
function savexCATchanges($file, $tab){
$request = simplexml_load_string('<xcatrequest></xcatrequest>');
$request->addChild('command','tabrestore');
$fh = fopen($file, 'r') or die("can't open $file");
while(!feof($fh)){
$line = fgets($fh,4096);
if(empty($line)){
continue;
}
$line = str_replace("\"\"", "",$line);
$line = str_replace("\"", "&quot;",$line);
$request->addChild('data', $line);
}
fclose($fh);
$request->addChild('table',$tab);
$resp = submit_request($request, 1);
# 0 means it didn't work
return($resp);
}
function splitTableFields($arr){
$fields = array();
$fields = explode(',', $arr);
$rf = array();
# now we have to do damage control for fields that look like this:
# "idplx15","idplx,ipmi,compute,all",,,
$inc = '';
foreach($fields as $f){
#if(ereg("\"[a-zA-Z0-9\-\.\:\!\| ]+\"", $f)){
if(ereg("\"[^\"]+\"", $f)){
$rf[] = $f;
continue;
}
#if(ereg("^[a-zA-Z0-9\-\. ]+\"", $f)){
if(ereg("[^\"]+\"", $f)){
$inc .= ",$f";
$rf[] = $inc;
$inc = '';
continue;
}
#if(ereg("\"[a-zA-Z0-9\-\. ]+", $f)){
if(ereg("\"[^\"]+", $f)){
$inc .= $f;
continue;
}
#if(ereg("[a-zA-Z0-9\-\. ]+", $f)){
if(ereg("[a-zA-Z0-9\-\. ]+", $f)){
$inc .= ",$f";
continue;
}
$rf[] = "";
}
return $rf;
}
function getTabNames() {
$xml = docmd('tabdump','','');
$tabs = $xml->xcatresponse->children();
return $tabs;
}
function getTabHeaders($tab){
$arr = $tab->xcatresponse->children();
$line = $arr[0];
$headers = array();
$headers = explode(',', $line);
return $headers;
}
# get the keys of the hash table.
function keysByNodeName($ht) {
$nh = array();
foreach($ht->xcatresponse as $v){
$node = (string) $v->node->name;
if(!array_key_exists($node, $nh)){
$nh[$node] = array();
}
$desc = (string) $v->node->data->desc;
$cont = (string) $v->node->data->contents;
$nh[$node][$desc] = $cont;
}
return($nh);
}
function attributesOfNodes($ht) {
$arr = array();
foreach($ht->xcatresponse as $v){
foreach($v->node as $va){
$val = (string) $va->data->desc;
if($val == ""){
$val = (string) $va->data->contents;
}
$arr[] = $val;
}
}
$arr = array_unique($arr);
return($arr);
}
function parseNodeGroups ($groups){
# groups is an array that may have duplicate commas in them.
$arr = array();
foreach($groups as $gline){
$newg = explode(',', $gline);
foreach($newg as $g){
if(empty($g)){ continue; }
if(!array_key_exists($g, $arr)){
$arr[] = $g;
}
}
}
return array_unique($arr);
}
# this is a kluge... should make better data structures.
# but too lazy right now...
function addNodesToGroups($groups, $node){
$arr = array();
foreach($groups as $g){
$arr[$g] = array();
foreach($node->xcatresponse as $v){
foreach($v->node as $n){
$na = (string) $n->data->contents;
$nag = explode(',', $na);
foreach($nag as $foo){
if(strcmp($foo,$g) == 0){
$name = (string) $n->name;
$arr[$g][] = $name;
continue;
}
}
}
}
}
return $arr;
}
function is_logged() {
if (isset($_SESSION["username"]) and !is_bool(getpassword())) {
return true;
} else {
return false;
}
}
function logout() {
#clear the secret cookie from browser.
#expire cookie a week ago, server time, may not work if client clock way off, but the value will be cleared at least.
if (isset($_COOKIE["xcatauthsecret"])) {
setcookie("xcatauthsecret",'',time()-86400*7); #NOTE: though firefox doesn't seem to zap it dynamically from cookie store in
#the client side dialog, firefox does stop submitting the value. The sensitivity of the 'stale' cookie even if compromised
#is negligible, as the session id will be invalidated and the one-time-key needed to decrypt the password is destroyed on the server
}
#expire the sesion cookie
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(),"",time()-86400*7,"/");
}
#clear server store of data
$_SESSION=array();
session_destroy();
}
function docmd($cmd, $nr, $arg){
$request = simplexml_load_string('<xcatrequest></xcatrequest>');
$usernode=$request->addChild('becomeuser');
$usernode->addChild('username',$_SESSION["username"]);
$usernode->addChild('password',getpassword());
$request->addChild('command',$cmd);
if(!empty($arg)){
$request->addChild('arg',$arg);
}
#$request->addChild('noderange', 'all');
if(!empty($nr)){
$request->addChild('noderange',$nr);
}
#echo $request->asXML();
$nodes = submit_request($request,0);
return($nodes);
}
function submit_request($req, $skipVerify){
global $cert,$port,$xcathost;
$fp;
$rsp = '';
$pos;
$response = '';
$cleanexit=0;
$moreresponses=1;
$context = stream_context_create(); #array('ssl'=>array('local_cert' => $cert)));
if($fp = stream_socket_client('ssl://'.$xcathost.':'.$port,$errno,$errstr,30,
STREAM_CLIENT_CONNECT,$context)){
fwrite($fp,$req->asXML());
while($moreresponses and $fp and !feof($fp)){
$currline=fgets($fp);
$response .= $currline;
$response = preg_replace('/\n/','', $response);
#$pattern = "<xcatresponse><serverdone></serverdone></xcatresponse>";
$pattern = "<serverdone>";
$pos = strpos($response,$pattern);
if($pos){
$cleanexit = 1;
}
if ($cleanexit) {
$pattern = "</xcatresponse>";
$pos = strpos($currline,$pattern);
}
if (is_numeric($pos)) {
#$response = substr($response, 0, $pos);
#var_dump($response);
$response = "<xcat>$response</xcat>";
#$response = preg_replace('/<xcatresponse>\s+<\/xcat>/','', $response);
#$response .= "</xcat>";
#echo htmlentities($response);
$rsp = simplexml_load_string($response,'SimpleXMLElement', LIBXML_NOCDATA);
$moreresponses=0;
break;
}
}
fclose($fp);
}else{
echo "xCAT Submit request ERROR: $errno - $errstr<br/>\n";
}
if(! $cleanexit){
if(!$skipVerify){
echo "Error in xCAT response<br>";
$rsp = 0;
}
}
return $rsp;
}
?>

View File

@ -1,52 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>xCAT WebUI</title>
<link rel="stylesheet" type="text/css" href="theme.css" />
<link rel="stylesheet" type="text/css" href="xcatwebui.css" />
<link rel="stylesheet" type="text/css" href="tree_component.css" />
<script type="text/javascript" src="css.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.listen.js"></script>
<script type="text/javascript" src="tree_component.js"></script>
<script type="text/javascript" src="jquery.ui.js"></script>
<script type="text/javascript" src="xcatauth.js"></script>
<script type="text/javascript" src="noderangetree.js"></script>
<script type="text/javascript" src="contents.js"></script>
</head>
<body>
<!-- Log out control -->
<!-- The omnipresent login dialog, waiting to be called forth by javascript -->
<div id="logdialog">
<form id="loginform" method="post" action="login.php">
<label for="username">Username:</label><input id="username" type="text" name="username"><br/>
<label for="password">Password:</label><input id="password" type="password" name="password"></form>
<span class="logstatus" id="logstatus"><br/></span>
</div>
<div id="header">xCAT
<div id="logout" class="xcatbutton"><button>Log Out</button></div>
</div>
<div id="alltabs">
<ul>
<li><a href="#nodepanels" title="actionpane"><span>Nodes</span></a></li>
<li><a href="tables.html" title="actionpane"><span>Tables</span></a></li>
</ul>
</div>
<div id="actionpane"></div>
<div id="nodepanels">
<!-- To place/constrain the noderange tree -->
<div id="nrtree"></div>
<div id="nodearea">
<div id="nodetabs">
<ul>
<li><a href="vitals.html" title="nodepane">Sensors</a></li>
<li><a href="eventlog.html" title="nodepane">Eventlog</a></li>
<li><a href="inventory.html" title="nodepane">Inventory</a><li>
</ul>
</div>
<div id="nodepane"></div>
</div>
</div>
</body>
</html>

View File

@ -1,11 +0,0 @@
<script type="text/javascript">
$(document).ready(function() {
$("#rinvbutton").click(function() {
$("#mydisp").text("Would have queried inv from "+noderange);
});
});
</script>
<body>
<div id="mydisp"></div>
<button id="rinvbutton">Get Inventory</button>
</body>

View File

@ -1,44 +0,0 @@
<?php
session_start();
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
include "functions.php";
$successfullogin=0;
if (isset($_GET["logout"]) or isset($_POST["logout"])) {
logout();
}
if (isset($_POST["password"])) {
$_SESSION=array(); #Clear data from session. prevent session data from migrating in a hijacking?
session_regenerate_id(true);#Zap existing session entirely..
setpassword($_POST["password"]);
$_SESSION["xcatpassvalid"]=-1; #unproven password
}
if (isset($_POST["username"])) {
$_SESSION["username"]=$_POST["username"];
$_SESSION["xcatpassvalid"]=-1; #unproven password
}
if (is_logged()) {
if ($_SESSION["xcatpassvalid"] != 1) {
$testcred=docmd("authcheck","","");
if (isset($testcred->{'xcatresponse'}->{'data'})) {
$result="".$testcred->{'xcatresponse'}->{'data'};
if (is_numeric(strpos("Authenticated",$result))) {
$_SESSION["xcatpassvalid"]=1; #proven good
} else {
$_SESSION["xcatpassvalid"]=0; #proven bad
}
}
}
}
$jdata=array();
if (isset($_SESSION["xcatpassvalid"]) and $_SESSION["xcatpassvalid"]==1) {
$jdata["authenticated"]="yes";
} else {
$jdata["authenticated"]="no";
}
echo json_encode($jdata);
?>

View File

@ -1,79 +0,0 @@
<?php
session_start();
include "functions.php";
$attemptedlogin=0;
$successfullogin=0;
if (isset($_GET["logout"])) {
logout();
}
if (isset($_POST["password"])) {
$_SESSION=array(); #Clear data from session. prevent session data from migrating in a hijacking?
session_regenerate_id(true);#Zap existing session entirely..
setpassword($_POST["password"]);
}
if (isset($_POST["username"])) {
$_SESSION["username"]=$_POST["username"];
$attemptedlogin=1;
}
if (is_logged()) {
$testcred=docmd("authcheck","","");
if (isset($testcred->{xcatresponse}->{data})) {
$result="".$testcred->{xcatresponse}->{data};
if (is_numeric(strpos("Authenticated",$result))) {
$successfullogin=1;
}
}
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>xCAT WebUI</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
<? if (isset($_SESSION["username"])) { ?>
$("#password").focus();
<? } else { ?>
$("#username").focus();
<? } ?>
$("#username").keydown(function(event) {
if (event.keyCode==13) {
$("#password").focus();
}
});
$("#password").keydown(function(event) {
if (event.keyCode==13) {
$("#loginform").submit();
}
});
$("#login").click(function(event) {
$("#loginform").submit();
});
});
</script>
</head>
<body>
<?
if ($successfullogin != 1) {
if ($attemptedlogin) {
?>Login Failed<?
}
?>
<form id="loginform" method="post" action="login.php">
Username:<input id="username" type="text" name="username"<?if (isset($_SESSION["username"])) { echo 'value="'.$_SESSION["username"].'"'; } ?>><BR>
Password:<input id="password" type="password" name="password">
<button id="login" type="button" name="Login" value="Login">Login</button>
</form>
<?
} else {
echo "Login Success <a href=\"login.php?logout=1\">Logout</a>";
}
?>
</body>
</html>

View File

@ -1,47 +0,0 @@
<?php
session_start();
include "functions.php";
if (isset($_GET['id'])) {
$id = $_GET['id'];
}
if ($id == "0") {
$id = '/.*';
} else {
$id=preg_replace('/^,/','',$id);
}
$rvals=docmd('extnoderange',$id,'subgroups');
$parents=array();
$root=1;
if ($id == '/.*') {
$id=',';
} else {
$parents=split("@",$id);
$id=",$id@";
$root=0;
}
unset($rvals->xcatresponse->serverdone[0]);
$numsubgroups=count($rvals->xcatresponse->intersectinggroups);
$numnodes=count($rvals->xcatresponse->node);
$jdata=array();
if ($numnodes >= $numsubgroups) { #If there are few enough subgroups to be helpful filters, add them in
foreach ($rvals->xcatresponse->intersectinggroups as $group) {
if (! in_array("$group",$parents)) {
$jdata[]= array("data"=>"$group",
"attributes"=>array("id"=>"$id$group",
"rel"=>'group'),
"state"=>'closed');
}
}
} #If there were more groups than nodes, leave the signal to noise ratio down
if ($root==0) {
foreach ($rvals->xcatresponse->node as $node) {
$jdata[] = array("data"=>"$node",
"attributes"=>array("id"=>",$node",
"rel"=>'node'));
}
}
# header('Content-type: text/html');
echo json_encode($jdata);
?>

View File

@ -1,30 +0,0 @@
var noderange="";
function updatenoderange() {
myselection=nrtree.selected_arr;
noderange="";
for (node in myselection) {
noderange+=myselection[node][0].id;
}
noderange=noderange.substring(1);
}
$(document).ready(function() {
nrtree = new tree_component(); // -Tree begin
nrtree.init($("#nrtree"),{
rules: {
multiple: "Ctrl"
},
ui: {
animation: 250
},
callback : {
onchange : updatenoderange
},
data : {
type : "json",
async : "true",
url: "noderangesource.php"
}
}); //Tree finish
});

View File

@ -1 +0,0 @@
This would be some sort of table oriented pane I suppose...

View File

@ -1,68 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>xCAT web UI experiments</title>
<link rel="stylesheet" type="text/css" href="tree_component.css" />
<script type="text/javascript" src="css.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.listen.js"></script>
<script type="text/javascript" src="tree_component.js"></script>
<script type="text/javascript">
$(function() {
var nrtree = new tree_component();
nrtree.init($("#nrlist"),{
rules: {
multiple: "Ctrl"
},
ui: {
animation: 250
},
callback : {
onchange : printtree
},
data : {
type : "json",
async : "true",
url: "noderangesource.php",
}
});
});
function printtree (node,nrtree) {
myselection=nrtree.selected_arr;
var noderange="";
for (node in myselection) {
noderange+=myselection[node][0].id;
}
$("#rangedisplay").text("Noderange: "+noderange.substring(1));
}
</script>
</head>
<body>
<div id="rangedisplay">
</div>
<hr>
<div class="demo">
<div id="nrlist" class="dots"></div>
</div>
<hr>
<!-- <div class="demo">
<div id="htlist" class="dots">
<ul>
<li id="storage"><a>storage</a>
<ul>
<li id="node1"><a>node1</a></li>
<li id="node2"><a>node2</a></li>
</ul>
<li id="compute" class="open"><a>compute</a>
<ul>
<li id="node3"><a>node3</a></li>
<li id="node4"><a>node4</a></li>
<li id="node5"><a>node5</a></li>
</ul>
</li>
</ul>
</div>
</div> -->
</body>
</html>

View File

@ -1,11 +0,0 @@
<script type="text/javascript">
$(document).ready(function() {
$("#vitality").click(function() {
$("#mydisp").text("Would have rvitals against "+noderange);
});
});
</script>
<body>
<div id="mydisp"></div>
<button id="vitality">Get Vitals</button>
</body>

View File

@ -1,86 +0,0 @@
/* xCAT WebUI authentication handling functions/setup */
/* IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html */
function openlogdialog (data, textstatus) { //open the log in dialog if not logged in
if (data.authenticated == "no") {
logdialog.dialog("open");
}
}
function onlogin (data, textstatus) {
$("#password").val(""); //clear the password field regardless of what happens
if (data.authenticated == "yes") {
$("#logstatus").text("Logged in successfully");
nrtree.refresh(); // Fix tree potentiall broken through attempts to operate without auth
logdialog.dialog("close");
} else {
$("#logstatus").text("Authentication failure");
$("#logstatus").css("color","#ff0000");
}
}
function logout () {
$.post("log.php",{logout:1})
$("#logstatus").html("");
logdialog.dialog("open");
}
function authenticate() {
$("#logstatus").css("color","#000000");
$("#logstatus").html('Authenticating...<img src="images/throbber.gif"/>');
var passwd=$("#password").val();
$.post("log.php",{
username: $("#username").val(),
password: passwd
},onlogin,"json");
}
$(document).ready(function() {
logdialog=$("#logdialog").dialog({
modal: true,
closeOnEscape: false,
closebutton: false,
overlay: {
backgroundColor: "#000",
opacity: 1
},
height: 200,
width: 350,
autoOpen: false,
buttons: {
"Log In": authenticate
},
open: function(type, dialog) {
if (document.location.protocol == "http:") {
$("#logstatus").html("Unencrypted Session!");
$("#logstatus").css("color","#ff0000");
}
if ($("#username").val() == "") {
$("#username").focus();
} else {
$("#password").focus();
}
},
});
$("#username").keydown(function(event) { //When 'enter' is hit while in username, advance to password
if (event.keyCode==13) {
$("#password").focus();
}
});
$("#password").keydown(function(event) { //Submit authentication if enter is pressed in password field
if (event.keyCode==13) {
authenticate();
}
});
$("#login").click(function(event) { //Also authenticate when 'log in' button is activated
authenticate();
});
$("#logout").click(function(event) { //Bind the button with logout id to our logout function
logout();
});
$.post("log.php",{},openlogdialog,"json"); //Determine if authentication dialog is currently needed on load
});

View File

@ -1,68 +0,0 @@
span.logstatus {
margin-left: 5.5em;
}
label {
text-align: right;
width: 5em;
float: left;
margin-right: 0.5em;
display: block;
}
div#header {
border-bottom: 1px solid #d3d3d3;
vertical-align: middle;
top:0;
left:0;
width:100%;
height:1.8em;
z-index:2;
}
#nodetabs {
float: left;
}
#nodearea {
float: left;
right: 0;
}
#nodepane: {
float: left;
clear: left;
}
#nrtree {
float: left;
clear: left;
border-right: 1px solid #d3d3d3;
border-top: 1px solid #d3d3d3;
height:100%;
width:9.5em;
}
#logout {
position:absolute;
top:0;
right:0;
margin-left:1em;
text-align: center;
vertical-align: top;
}
.xcatbutton button {
margin: .5em .5em .5em 8px;
color: #555555;
background: #e6e6e6 url(images/e6e6e6_40x100_textures_02_glass_75.png) 0 50% repeat-x;
font-size: 0.7em;
border: 1px solid #d3d3d3;
cursor: pointer;
padding: .2em .6em .3em .6em;
line-height: 1.4em;
}
.xcatbutton button:hover {
color: #212121;
background: #dadada url(images/dadada_40x100_textures_02_glass_75.png) 0 50% repeat-x;
border: 1px solid #999999;
}
.xcatbutton button:active {
color: #222222;
background: #ffffff url(images/ffffff_40x100_textures_02_glass_65.png) 0 50% repeat-x;
border: 1px solid #dddddd;
}