<?php
/**
 * Clases que definen la red y los elementos que la componen
 *
 * @author Jesús Algeciras <jes.algeciras@gmail.com>
 * @version 2010-10-24
 *
 * @author Alberto Martín <betolapalma@gmail.com>
 * @version 
 *
 */
require_once('func_comunes.php');
// Para la comunicación con los PCs
require_once('xmlrpc.inc');
// Para la comunicación con los Conmutadores
require_once ('PHPTelnet.php');

/**
 * Clase para los elementos que conforman la red
 *
 * Clase abstracta que define los métodos y las propiedades
 * de los elemnetos de la red (PC y Conmutadores).
 */
abstract class ElementoRed {

	/**
	 * Identificador
	 * @var int
	 */
	protected $id;

	/**
	 * Dirección IP de administración
	 * @var string
	 */
	protected $ip;

	/**
	 * Configuración actual
	 * @var mixed
	 */
	protected $config;

	/**
	 * Ultima configuración valida
	 * @var mixed
	 */
	protected $lastConfig;

	function __construct($id, $ip, $config = NULL) {
		$this->id = $id;
		$this->ip = $ip;
		$this->config = $config;
		$this->lastConfig = $config;
	}

	function getID() {
		return $this->id;
	}

	function setConfig($config) {
		$this->config = $config;
	}

	function getConfig() {
		return $this->config;
	}

	/**
	 * Envia la configuración al PC/Conmutador
	 * @return array información sobre errores
	 */
	abstract function sendConfig();

	/**
	 * Carga la configuración de la base de datos
	 * @param $idconfig id de la configuración
	 * @return boolean
	 */
	abstract function loadConfig($idconfig);

	/**
	 * Almacena la configuración en la base de datos
	 * @param $idconfig id de la configuración
	 * @return boolean
	 */
	abstract function storeConfig($idconfig);
}

/**
 * Clase que define propiedades y métodos para el PC
 */
class PC extends ElementoRed {

	/**
	 * Puerto de administración
	 * @var int
	 */
	protected $port;

	function __construct($id, $ip, $port, $config = NULL) {
		$this->port = $port;
		parent::__construct($id, $ip, $config = NULL);
	}
	
	// Envia configuración a un PC
	function sendConfig() {
		$error['error'] = FALSE;
		$error['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($this->config['ip']),
		new xmlrpcval($this->config['mascara']),
		new xmlrpcval($this->config['puerta']),
		new xmlrpcval($this->config['dns1']),
		new xmlrpcval($this->config['dns2']));

		$msg = new xmlrpcmsg('config_red',$params);
		// Mensaje para el borrado de ficheros al cerrar
		$msg2 = new xmlrpcmsg('elimina');
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$respuesta = $cliente->send($msg);
		
		// Respuesta del borrado de ficheros al cerrar
		$respuesta2 = $cliente->send($msg2);

		if ($respuesta || $respuesta2) {
			if (!$respuesta->faultcode() || !$respuesta2->faultcode()) {
				$resp = php_xmlrpc_decode($respuesta->value());
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
			if ($error['error']) {
				$this->config = $this->lastConfig;
			} else {
				$this->lastConfig = $this->config;
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $error;
	}
	
	// Carga la configuración de un PC
	function loadConfig($idconfig) {
		$db = Database::conectar();
		$respuesta = $db->query('SELECT INET_NTOA(ip) AS ip,
									INET_NTOA(mascara) AS mascara,
									INET_NTOA(puerta) AS puerta,
									INET_NTOA(dns1) AS dns1,
									INET_NTOA(dns2) AS dns2 FROM pc
									WHERE idconfiguracion="'.$idconfig.'" AND idpc='.$this->id);
		if ($respuesta->num_rows > 0) {
			$datos = $respuesta->fetch_assoc();
			$respuesta->free();
			$this->config = array('ip' => $datos['ip'],
									'mascara' => $datos['mascara'],
									'puerta' => $datos['puerta'],
									'dns1' => $datos['dns1'],
									'dns2' => $datos['dns2']);
			return TRUE;
		} else {
			$respuesta->free();
			return FALSE;
		}
	}
	
	// Almacena la configuración de un PC
	function storeConfig($idconfig) {
		$db = Database::conectar();
		if ($this->config) {
			$respuesta = $db->query('SELECT idpc FROM configuracion NATURAL LEFT JOIN pc
									WHERE usuario='.$_SESSION["idusuario"].'
									AND idconfiguracion='.$idconfig.' AND idpc='.$this->id);
			if ($respuesta->num_rows > 0) {
				$db->query('UPDATE pc SET ip=INET_ATON("'.$this->config["ip"].'"),
									mascara=INET_ATON("'.$this->config["mascara"].'"),
									puerta=INET_ATON("'.$this->config["puerta"].'"),
									dns1=INET_ATON("'.$this->config["dns1"].'"),
									dns2=INET_ATON("'.$this->config["dns2"].'")
									WHERE idconfiguracion='.$idconfig.' AND idpc='.$this->id);
			} elseif (!$this->default) {
				$db->query('INSERT INTO pc VALUES ('.$idconfig.','.$this->id.',
							INET_ATON("'.$this->config["ip"].'"),
							INET_ATON("'.$this->config["mascara"].'"),
							INET_ATON("'.$this->config["puerta"].'"),
							INET_ATON("'.$this->config["dns1"].'"),
							INET_ATON("'.$this->config["dns2"].'"))');
			}
			$respuesta->free();
		}
		return TRUE;
	}

	/**
	 * Petición al servidor XML-RPC de un ping a la dirección indicada
	 * @param $destino ip destino del ping
	 * @param $paquetes número de paquetes enviados por el ping
	 * @return array
	 */
	function ping($destino,$paquetes) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($destino),
		new xmlrpcval($paquetes));
		$msg = new xmlrpcmsg('ping',$params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}

		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de una captura de tráfico del PC especificado
	 * @param $accion acción a realizar
	 * @param $usuario usuario que realiza la captura
	 * @return array
	 */
	function captura($accion, $usuario) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();
		$respuesta['stdfich'] = array();  // Fichero de la captura
		
		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($accion), new xmlrpcval($usuario));
		$msg = new xmlrpcmsg('captura', $params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
				
				if(strlen($resp[2] != 0)){
					// Cuando se obtiene la captura, la almacenamos
					$respuesta['stdfich'] = $resp[2]; 
				}
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de la configuración del PC especificado
	 * @return array
	 */
	function ifconfig() {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$msg = new xmlrpcmsg('ifconfig');
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de la tabla de rutas del PC especificado
	 * @return array
	 */
	function route() {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$msg = new xmlrpcmsg('route');
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de un listado de archivos del PC especificado
	 * @param $rol carpeta que deseamos listar
	 * @return array
	 */
	function ls($rol) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($rol));
		$msg = new xmlrpcmsg('ls', $params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
								if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de la subida de un archivo
	 * @param $ficheroxml fichero a subir, codificado en base64
	 * @param $nombre nombre del fichero a subir
	 * @return array
	 */
	function enviar($ficheroxml, $nombre) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		
		$params = array(new xmlrpcval($ficheroxml),
		new xmlrpcval($nombre));
		$msg = new xmlrpcmsg('crea', $params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC del borrado de archivos del PC especificado
	 * @param $rol carpeta que deseamos borrar
	 * @return array
	 */
	function borrar($rol) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($rol));
		$msg = new xmlrpcmsg('borrar', $params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
								if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de la transferencia TFTP entre dos pc's
	 * @param $servidor ip del servidor tftp
	 * @param $archivo nombre del archivo a transferir
	 * @return array
	 */
	function tftp($servidor, $archivo) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($servidor),
		new xmlrpcval($archivo));
		$msg = new xmlrpcmsg('tftp',$params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
	
	/**
	 * Petición al servidor XML-RPC de la transferencia WGET entre dos pc's
	 * @param $servidor ip del servidor web
	 * @param $archivo nombre del archivo a transferir
	 * @return array
	 */
	function wget($servidor, $archivo) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();

		// Construimos el mensaje XML-RPC y lo enviamos
		$params = array(new xmlrpcval($servidor),
		new xmlrpcval($archivo));
		$msg = new xmlrpcmsg('wget',$params);
		$cliente = new xmlrpc_client('/', $this->ip, $this->port);
		$resp = $cliente->send($msg);

		// Se procesa la respuesta del servidor situado en el PC
		if ($resp) {
			if ($resp->faultcode() == 0) {
				$resp = php_xmlrpc_decode($resp->value());
				$respuesta['stdout'] = $resp[0];
				if (strlen($resp[1][0]) != 0)
					throw new NetworkException('(PC '.$this->id.') '.implode($resp[1]));
			} else {
				throw new NetworkException('(PC '.$this->id.') '.$respuesta->faultString());
			}
		} else {
			throw new NetworkException('(PC '.$this->id.') No ha sido posible establecer la conexión');
		}
		return $respuesta;
	}
}

/**
 * Clase que define propiedades y métodos para el Conmutador
 */
class Conmutador extends ElementoRed {

	/**
	 * Contraseña
	 * @var string
	 */
	protected $password;

	function __construct($id, $ip, $password, $config = NULL) {
		$this->password = $password;
		parent::__construct($id, $ip, $config = NULL);
	}
    
	// Envia configuración al conmutador
	function sendConfig() {
		$error['error'] = FALSE;
		$error['info'] = array();
		global $cnxn_admin_red;

		$telnet = new PHPTelnet();
		$telnet->show_connect_error = 0;

		$respuesta = $telnet->Connect($this->ip, '', $this->password);
		switch ($respuesta) {
			case 0:
				$this->generateConfig();
				$telnet->DoCommand('copy tftp startup-config '.$cnxn_admin_red['ip'].' conm_config.txt', $respuesta);
				$telnet->DoCommand('y', $respuesta);

				// Se eliminan los caracteres de la secuencia de escape ASCII de la respuesta
				$respuesta = preg_replace('/^.*24;1H([^\x1b]*)\r.*$/', "$1", $respuesta);
				$respuesta = preg_replace('/\r/', '', $respuesta);
				if (preg_match('/Corrupted download file/', $respuesta)) {
					// Obtenermos los errores en la configuración del archivo de log del conmutador
					$telnet->DoCommand('copy command-output "log -r" tftp '.$cnxn_admin_red['ip'].' log unix', $respuesta);
					$conmlog = Archivo::lineas(FILES_TFTP.'log');
					$warnings = array();
					// Se obtienen todas las líneas desde la última transferencia
					foreach ($conmlog as $line) {
						if (preg_match('/Transfer completed/', $line))
							break;
						if (preg_match('/^W /', $line))
							$warnings[] = $line;
					}
					$warnings = array_reverse($warnings);
					foreach ($warnings as $i => $warn) {
						$warn = preg_replace('/^.*update: (.*)$/', "$1", $warn);
						$warn = preg_replace('/^line (\d+). /', '', $warn);
						$warn = preg_replace('/Invalid input/', 'Comando / Valor erroneo', $warn);
						$warnings[$i] = $warn;
					}
					Archivo::borrar(FILES_TFTP.'log');
					$error['error'] = 'validacion';
					$error['info']['archivo'] = $warnings;
				}
				$telnet->Disconnect();
				Archivo::borrar(FILES_TFTP."conm_config.txt");
				break;

			case 1:
				throw new NetworkException('(Conmutador '.$this->id.') No ha sido posible establecer la conexión');
				break;
			case 2:
				throw new NetworkException('(Conmutador '.$this->id.') Host desconocido');
				break;
			case 3:
				throw new NetworkException('(Conmutador '.$this->id.') Contraseña invalida');
				break;
			case 4:
				throw new NetworkException('La versión de PHP no soporta la clase PHPTelnet');
				break;
		}

		if ($error['error']) {
			$this->config = $this->lastConfig;
		} else {
			$this->lastConfig = $this->config;
		}
		return $error;
	}
	
	// Obtiene la configuracion actual del conmutador
	function ObtConfig() {
		$error['error'] = FALSE;
		$error['info'] = array();
		global $cnxn_admin_red;
		global $cnxn_red;
		
		$telnet = new PHPTelnet();
		$telnet->show_connect_error = 0;
		
		// Archivo con el que se filtran las lineas de administración de la configuración
		$fichero_admin = $cnxn_red[$_SESSION['idred']]['conmutador'][$this->id]['admin_config'];
		$fichero_admin = str_replace('.txt', 'filtro.txt', $fichero_admin);
		
		$respuesta = $telnet->Connect($this->ip, '', $this->password);
		switch ($respuesta) {
			case 0:
				$telnet->DoCommand('copy running-config tftp '.$cnxn_admin_red['ip'].' conm_config.txt', $respuesta);

				// Se eliminan los caracteres de la secuencia de escape ASCII de la respuesta
				$respuesta = preg_replace('/^.*24;1H([^\x1b]*)\r.*$/', "$1", $respuesta);
				$respuesta = preg_replace('/\r/', '', $respuesta);
				$telnet->Disconnect();
				$config = array();
				$config['archivo'] = FILES_TEMP.'user'.sprintf('%02d',$_SESSION['idusuario']).'conf00conm'.$_POST['id'].'.txt';
				
				// Flitrado del archivo de configuración
				$filtrado = $this->filtrarArchivo(FILES_TFTP.'conm_config.txt', $fichero_admin);
				
				Archivo::copiar($filtrado, $config['archivo']);

				Archivo::borrar(FILES_TFTP."conm_config.txt");
				Archivo::borrar($filtrado);
				return $config;
				break;

			case 1:
				throw new NetworkException('(Conmutador '.$this->id.') No ha sido posible establecer la conexión');
				break;
			case 2:
				throw new NetworkException('(Conmutador '.$this->id.') Host desconocido');
				break;
			case 3:
				throw new NetworkException('(Conmutador '.$this->id.') Contraseña invalida');
				break;
			case 4:
				throw new NetworkException('La versión de PHP no soporta la clase PHPTelnet');
				break;
		}
	}
	
	// Carga la configuración almacenada
	function loadConfig($idconfig) {
		$db = Database::conectar();
		$respuesta = $db->query('SELECT archivo FROM conmutador WHERE idconfiguracion='.$idconfig.' AND idconmutador='.$this->id);
		if ($respuesta->num_rows > 0) {
			$datos = $respuesta->fetch_assoc();
			$file = $datos['archivo'];
			$respuesta->free();
			if (is_file($file)) {
				$this->config['archivo'] = $file;
				return TRUE;
			} else {
				return FALSE;
			}
		} else {
			$respuesta->free();
			return FALSE;
		}
	}
	
	// Realización de la orden SHOW en un conmutador
	function show($accion) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();
		
		$telnet = new PHPTelnet();
		$telnet->show_connect_error = 0;

		$resp = $telnet->Connect($this->ip, '', $this->password);
		switch ($resp) {
			case 0:
				if (strpos($accion,'?')!=0){
					// Muestra todas las opciones permitidas
					$accion = preg_replace('/\?/', '', $accion);
					$telnet->DoCommand2('show '.$accion, $resp);
					// Borrado de la linea de comamdos del conmutador
					$telnet->DoCommand3();
				} else {
					$telnet->DoCommand('show '.$accion, $resp);
				}
				
				// Se eliminan los caracteres de la secuencia de escape ASCII de la respuesta
				$resp = preg_replace('/^.*24;1H([^\x1b]*)\r.*$/', "$1", $resp);
				$resp = preg_replace('/\r/', '', $resp);
				
				// Convertimos a cadenas separadas cada nueva linea
				$resp = preg_split('/\n/',$resp);
				
				// Matener espacios
				$resp = preg_replace('/\s/','&nbsp;', $resp);
		
				$telnet->Disconnect();
				$respuesta['stdout'] = $resp;
				break;

			case 1:
				throw new NetworkException('(Conmutador '.$this->id.') No ha sido posible establecer la conexión');
				break;
			case 2:
				throw new NetworkException('(Conmutador '.$this->id.') Host desconocido');
				break;
			case 3:
				throw new NetworkException('(Conmutador '.$this->id.') Contraseña invalida');
				break;
			case 4:
				throw new NetworkException('La versión de PHP no soporta la clase PHPTelnet');
				break;
		}
		return $respuesta;
	}
	
	// Configura un conmutador mediante lineas introducidas en el formulario
	function configure($accion) {
		$respuesta['stdout'] = array();
		$respuesta['stderr']['error'] = FALSE;
		$respuesta['stderr']['info'] = array();
		
		$telnet = new PHPTelnet();
		$telnet->show_connect_error = 0;

		$resp = $telnet->Connect($this->ip, '', $this->password);
		switch ($resp) {
			case 0:
				if (strpos($accion,'?')!=0){
					// Muestra todas las opciones permitidas
					$accion = preg_replace('/\?/', '', $accion);
					// Entramos en el submenu 'configure del conmutador'
					$telnet->DoCommand('configure', $resp);
					$telnet->DoCommand2($accion, $resp);
					// Borrado de la linea de comamdos del conmutador
					$telnet->DoCommand3();
				} else {
					$telnet->DoCommand('configure', $resp);
					$telnet->DoCommand($accion, $resp);
				}
				
				// Se eliminan los caracteres de la secuencia de escape ASCII de la respuesta
				$resp = preg_replace('/^.*24;1H([^\x1b]*)\r.*$/', "$1", $resp);
				$resp = preg_replace('/.*24;..H([^\x1b]*).*/', "Configuracion realizada", $resp);
			    $resp = preg_replace('/\r/', '', $resp);
				
				// Convertimos a cadenas separadas cada nueva linea
				$resp = preg_split('/\n/',$resp);
				
				// Matener espacios
				$resp = preg_replace('/\s/','&nbsp;', $resp);
		
				$telnet->Disconnect();
				$respuesta['stdout'] = $resp;
				break;

			case 1:
				throw new NetworkException('(Conmutador '.$this->id.') No ha sido posible establecer la conexión');
				break;
			case 2:
				throw new NetworkException('(Conmutador '.$this->id.') Host desconocido');
				break;
			case 3:
				throw new NetworkException('(Conmutador '.$this->id.') Contraseña invalida');
				break;
			case 4:
				throw new NetworkException('La versión de PHP no soporta la clase PHPTelnet');
				break;
		}
		return $respuesta;
	}
	
	// Almacena la configuración de un conmutador
	function storeConfig($idconfig) {
		
		// Obtenemos el archivo de configuración actual del conmutador 
		$config = $this->ObtConfig();
		$this->setConfig($config);
		
		$db = Database::conectar();
		if ($this->config['archivo']) {
			$origen = $this->config['archivo'];
			$destino = FILES_STORAGE.'user'.sprintf('%02d',$_SESSION['idusuario']).'conf'.sprintf('%d', $idconfig).'conm'.$this->id.'.txt';
			if ($origen != $destino) {
				Archivo::copiar($origen, $destino);
				$respuesta = $db->query('SELECT idconmutador FROM configuracion
											NATURAL LEFT JOIN conmutador
											WHERE usuario='.$_SESSION["idusuario"].'
											AND idconfiguracion='.$idconfig.'
											AND idconmutador='.$this->id);
				if ($respuesta->num_rows > 0) {
					$datos = $respuesta->fetch_assoc();
					$db->query('UPDATE conmutador SET archivo="'.$destino.'"
								WHERE idconfiguracion='.$idconfig.'
								AND idconmutador='.$this->id);
				} else {
					$db->query('INSERT INTO conmutador VALUES ('.$idconfig.','.$this->id.',"'.$destino.'")');
				}
				$respuesta->free();
				$this->config['archivo'] = $destino;
			}
		}
		return TRUE;
	}


	/** 
	 * Elimina la parte de administración del archivo de 
     * configuracion
	 * @param ruta del archivo de configuracion completo
	 * @return string ruta del archivo flitrado
	 */
	
	private function filtrarArchivo($completo, $admin){
		$array_filtrado = array_diff(file($completo), file($admin));
		$filtrado = FILES_TFTP."conm_config2.txt";
        $fp = fopen($filtrado, 'a');
		foreach($array_filtrado as $linea){
			fwrite($fp, $linea);
		}
        fclose($fp);
		return $filtrado;
	}
	
	/**
	 * Añade al archivo de configuración creado por el usuario
	 * la configuración de administración
	 * @return string ruta del archivo de configuración
	 */
	private function generateConfig() {
		global $cnxn_red;
		$file = FILES_TFTP."conm_config.txt";
		Archivo::crea($file);
		Archivo::escribir($file, Archivo::leer($cnxn_red[$_SESSION['idred']]['conmutador'][$this->id]['admin_config']));
		Archivo::escribir($file, Archivo::leer($this->config['archivo']));
	}
}

/**
 * Clase que define al conjunto de toda la red
 *
 * Esta clase contendrá los objetos que representan los distintos elementos
 * que conforman la red y los metodos para tratar con ellos de manera general.
 */
class Red {
	/**
	 * Objetos de la clase PC
	 * @var array
	 */
	protected $pc;

	/**
	 * Objetos de la clase Conmutador
	 * @var array
	 */
	protected $conmutador;

	/**
	 * Añade elementos a la red
	 * @param $elementoRed objeto a añadir
	 * @return boolean
	 */
	function add($elementoRed) {
		if ($elementoRed instanceof PC) {
			$this->pc[] = $elementoRed;
		} elseif ($elementoRed instanceof Conmutador) {
			$this->conmutador[] = $elementoRed;
		} else {
			return FALSE;
		}
		return TRUE;
	}

	/**
	 * Devuelve la instancia de la clase PC indicada o todas
	 * @param $id id del elemento
	 * @return mixed
	 */
	function getPC($id = NULL) {
		if ($id) {
			foreach ($this->pc as $pc) {
				if ($pc->getID() == $id)
					return $pc;
			}
		} else {
			return $this->pc;
		}
		return FALSE;
	}

	/**
	 * Devuelve la instancia de la clase Conmutador indicada o todas
	 * @param $id id del elemento
	 * @return mixed
	 */
	function getConmutador($id = NULL) {
		if ($id) {
			foreach ($this->conmutador as $conmutador) {
				if ($conmutador->getID() == $id)
					return $conmutador;
			}
		} else {
			return $this->conmutador;
		}
		return FALSE;
	}

	/**
	 * Devuelve ID de la configuración por defecto de la red
	 * @return int ID de configuración
	 */
	function defaultConfig() {
		$database = Database::conectar();
		$dbdata = $database->query('SELECT default_config FROM red WHERE idred='.$_SESSION['idred']);
		$data = $dbdata->fetch_assoc();
		$dbdata->free();
		return $data['default_config'];
	}

	/**
	 * Invoca a la función sendConfig de todos los elementos de la red
	 * @return array información sobre errores
	 */
	function sendConfig() {
		$error['error'] = FALSE;
		$error['info'] = array();
		$nodos = array_merge($this->pc, $this->conmutador);
		foreach ($nodos as $elementoRed) {
			$errores == $elementoRed->sendConfig();
			if ($errores['error']) {
				$error['error'] = 'aplicacion';
				$error['info'] = array_merge($error['info'], $errorres['info']);
			}
		}
		return $error;
	}

	/**
	 * Invoca a la función loadConfig de todos los elementos de la red
	 * @param $idconfig ID de de la confuración o 'default'
	 * @return array información sobre errores
	 */
	function loadConfig($idconfig) {
		$error['error'] = FALSE;
		$error['info'] = array();
		$loaded = TRUE;
		$nodos = array_merge($this->pc, $this->conmutador);
		foreach ($nodos as $elementoRed)
			$loaded = $loaded && $elementoRed->loadConfig($idconfig);
		if (!$loaded) {
			$error['error'] = 'aplicacion';
			$error['info'] = array('ERROR: La configuración no ha podido ser cargada con exito');
		}
		return $error;
	}

	/**
	 * Almacena los datos de la configuracion e invoca a la
	 * función storeConfig de todos los elementos de la red
	 * @param $nombre Nombre de de la confuración
	 * @param $idconfig ID de de la confuración
	 * @return array información sobre errores
	 */
	function storeConfig($idconfig, $nombre) {
		$error['error'] = FALSE;
		$error['info'] = array();
		$nueva = ($idconfig == 'new') ? TRUE : FALSE;
		$db = Database::conectar();
		if (!$nueva) {
			$db->autocommit(FALSE);
			$db->query('UPDATE configuracion SET modificado="'.date('Y-m-d H:i:s').'",
							nombre="'.$nombre.'" WHERE idconfiguracion='.$idconfig);
		} else {
			$respuesta = $db->query('SELECT COUNT(nombre) FROM configuracion
										WHERE nombre="'.$nombre.'"GROUP BY nombre');
			$datos = $respuesta->fetch_assoc();
			$respuesta->free();
			if($datos['COUNT(nombre)'] != 0){
				$error['error'] = 'aplicacion';
				$error['info'] = array('ERROR: Ya tienes una configuracion con este nombre');
				return $error;
			}
			$respuesta = $db->query('SELECT COUNT(usuario) FROM configuracion
										WHERE usuario='.$_SESSION['idusuario'].' GROUP BY usuario');
			$datos = $respuesta->fetch_assoc();
			$respuesta->free();
			if ($datos['COUNT(usuario)'] >= 20) {
				$error['error'] = 'aplicacion';
				$error['info'] = array('ERROR: El máximo número de configuraciones permitidas por usuario es 20');
				return $error;
			} else {
				$db->autocommit(FALSE);
				$db->query('INSERT INTO configuracion (usuario,nombre,modificado)
								VALUES ('.$_SESSION['idusuario'].',"'.$nombre.'","'.date('Y-m-d H:i:s').'")');
				$respuesta = $db->query('SELECT LAST_INSERT_ID() AS idconfig');
				$datos = $respuesta->fetch_assoc();
				$respuesta->free();
				$idconfig = $datos['idconfig'];
			}
		}
		$nodos = array_merge($this->pc, $this->conmutador);
		try {
			foreach ($nodos as $elementoRed)
				$elementoRed->storeConfig($idconfig);
		}
		catch (Exception $excepcion) {
			// Si se produce un error durante el gurdado de la configuración se borran los archivos
			// creados para evitar archivos residuales
			if ($nueva) {
				$respuesta = $db->query('SELECT * FROM conmutador WHERE idconfiguracion='.$idconfig);
				for ($i = 0; $i < $respuesta->num_rows; $i++) {
					$config = $respuesta->fetch_assoc();
					Archivo::borrar($config['archivo']);
				}
				$respuesta->free();
			}
			throw $excepcion;
		}
		$db->commit();
		$db->autocommit(TRUE);
		return $error;
	}

	/**
	 * Borra la configuracion indicada
	 * @param $idconfig ID de de la confuración
	 * @return boolean
	 */
	function deleteConfig($idconfig) {
		$db = Database::conectar();
		$respuesta = $db->query('SELECT * FROM conmutador WHERE idconfiguracion='.$idconfig);
		for ($i = 0; $i < $respuesta->num_rows; $i++) {
			$config = $respuesta->fetch_assoc();
			Archivo::borrar($config['archivo']);
		}
		$respuesta->free();
		$db->query('DELETE FROM configuracion WHERE usuario='.$_SESSION['idusuario'].' AND idconfiguracion='.$idconfig);
		return TRUE;
	}
}

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es">
	<head>
            <title>e-REdING. Biblioteca de la Escuela Superior de Ingenieros de Sevilla.</title>

                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="description" content="Buscador de proyectos ETSI" />
<meta name="author" content="Daniel Callejo"/>
<meta name="author" content="Federico L&oacute;pez"/>
<meta name="author" content="Juli&aacute;n P&eacute;rez"/>
<meta name="author" content="Jos&eacute; Mar&iacute;a Vidal Vidal"/>
<base href="/bibing/proyectos/" /><link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="./publico/css/estructura.css" type="text/css" />
<link rel="stylesheet" href="./publico/css/bootstrap.css" type="text/css" media="screen"/>
<link rel="stylesheet" href="./publico/css/enlaces-capas.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/pestanas.css" type="text/css"  /> 
<link rel="stylesheet" href="./publico/css/formularios.css" type="text/css" />
<link rel="stylesheet" href="./publico/css/lightbox.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/autocompleter.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/resultados.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/milista.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/explorador.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/ultimos.css" type="text/css"  />
<link rel="stylesheet" href="./publico/css/contactar.css" type="text/css"  />
<!-- <link rel="stylesheet" href="./css/print.css" type="text/css" media="print" /> -->
<script src="./publico/javascript/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="./publico/javascript/bootstrap.js" type="text/javascript"></script>

<script src="./publico/javascript/mootools-1.2.4-core.js" type="text/javascript"></script>
<script src="./publico/javascript/mootools-1-1.2.4.2-more.js" type="text/javascript"></script>
<script src="./publico/javascript/targetbl.js" type="text/javascript"></script>
<script src="./publico/javascript/mensajes.js" type="text/javascript"></script>
<script src="./publico/javascript/form.js" type="text/javascript"></script>
<script src="./publico/javascript/autocompleter/Observer.js" type="text/javascript"></script>
<script src="./publico/javascript/autocompleter/Autocompleter.js" type="text/javascript"></script>
<script src="./publico/javascript/autocompleter/Autocompleter.Request.js" type="text/javascript"></script>
<script src="./publico/javascript/domready.js" type="text/javascript"></script>

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-8T1TSNC1QY"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-8T1TSNC1QY');
</script>



<script type="text/javascript">
function seleccionar_todo(){
   for (i=0;i<document.formulario_marcados.elements.length;i++)
      if(document.formulario_marcados.elements[i].type == "checkbox")
         document.formulario_marcados.elements[i].checked=1
}
function deseleccionar_todo(){
   for (i=0;i<document.formulario_marcados.elements.length;i++)
      if(document.formulario_marcados.elements[i].type == "checkbox")
         document.formulario_marcados.elements[i].checked=0
} 
</script>
	</head>
    <body style="min-width: 960px; background-color: #e2e2e2; height: 100%">	
		<a name="arriba"></a>
<div>
<div id="header">
    <table id="Tabla_01" height="105" border="0" cellpadding="0" cellspacing="0">
    <tr>
        <td>
            <img src="./publico/imagenes/cabecera/banner_new2_01.jpg" width="3" height="105" alt="">
        </td>
        <td>
            <img src="./publico/imagenes/cabecera/banner_new2_02.jpg" width="100" height="105" alt="">
        </td>
        <td width="100%" align="right"  style="min-width: 613px; background-repeat: no-repeat; background-position: top right; font-size: medium; font-weight: bold; color: white;">
            <table width="100%" height="105" border="0">
                <tr>
                    <td style=" vertical-align: top; width: 547px">
                        <!-- <a style="text-decoration: none" href="./"><img src="./publico/imagenes/cabecera/banner_new2_03.jpg"alt=""></a> -->
                        <a style="text-decoration: none" href="/bibing/proyectos/"><img src="./publico/imagenes/cabecera/banner_new2_03.jpg"alt=""></a>
                     </td>
                     <td  background="./publico/imagenes/cabecera/banner_new2_04.jpg" style="background-repeat: no-repeat; background-color: #c6d4e8;"><br><br><br>
                         &nbsp;
                        </td>
                    </tr>
             </table>
        </td>
    </tr>
    <tr style="border-top: 1px solid #ffffff;">
        <td colspan="3" id="menu_sup" style="font-size: small; text-align: right; background-color: #9c1f2f; vertical-align: bottom">
             
					<a href="/bibing/proyectos/" class="enlace " style=" color: #ffffff">Inicio&nbsp;&nbsp;|</a>
					<a href="/bibing/proyectos/acerca/" style=" color: #ffffff" class="enlace ">&nbsp;&nbsp;Acerca de&nbsp;&nbsp;|</a>
					
					<a href="/bibing/proyectos/contactar/" style=" color: #ffffff" class="enlace ">&nbsp;&nbsp;Contactar&nbsp;&nbsp;</a>
			 <!--       <a href="/bibing/proyectos/ayuda/" style=" color: #ffffff" class="enlace  ">&nbsp;&nbsp;Ayuda&nbsp;&nbsp;|</a> -->
					<!-- <form id="idioma" class=""  method="post" action="">
					<div class="inline" style="color: white">
					<input type="submit" class="tipo_letra " style=" color: #ffffff"name="idioma" value="Castellanossss" />&nbsp;&nbsp;
					</div>	
					</form> -->
			        </td>

    </tr>
    </table>
</div>
<br><br>
<div class="colmask rightmenu">
<div class="panel panel-default" style="margin:20px">
            <div class="panel-heading"><h4>DESARROLLO DE UN ENTORNO DE PRÁCTICAS PARA REDES MULTISERVICIO</h4><h5 style="color:grey"><span class="glyphicon glyphicon-user""></span> : <b>MARTÍN REDONDO, ALBERTO JESÚS</b><br><span class="glyphicon glyphicon-book""></span>  :<b> Ingenier&iacute;a Telecomunicación</b></h5></div><div class="panel-body"><div class="contenido_proyecto"><div class="titulo2_explorador">Contenido del proyecto:</div><div class="ruta"><a href="use/abreproy/12106">Directorio ra&iacute;z</a>&nbsp;&nbsp;>&nbsp;&nbsp;<a href="use/abreproy/12106/direccion/ARCHIVOS%252F">ARCHIVOS</a>&nbsp;&nbsp;>&nbsp;&nbsp;<a href="use/abreproy/12106/direccion/ARCHIVOS%252Fredes%252F">redes</a>&nbsp;&nbsp;>&nbsp;&nbsp;<a href="use/abreproy/12106/direccion/ARCHIVOS%252Fredes%252Fadmin%252F">admin</a>&nbsp;&nbsp;>&nbsp;&nbsp;<a href="use/abreproy/12106/direccion/ARCHIVOS%252Fredes%252Fadmin%252Fred.php%252F">red.php</a></div><div class="listing"></div></div></div></div>
</div>
</div>

        
	</body>
 
 
<!-- Inicio Google Analytics -->
<!--
	<script type="text/javascript">
		var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
		document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
	</script>
	
	<script type="text/javascript">
		try {
		var pageTracker = _gat._getTracker("UA-7789620-1");
		pageTracker._trackPageview();
	} 
		catch(err) {}
	</script>
-->
<!-- Fin Google Analytics -->

</html>

