Generar un zip de backup del servidor FTP

basandome en el código
he modificado la clase para añadirle seguridad (*):

Para ello partimos de una estructura de servidor:

Donde colocamos el fichero zip.php en el raiz

Dentro del fichero configuramos la ruta donde se van a guardar los archivos y las exclusiones que queremos hacer, en este caso los directorios dir2 y dir4 y el propio fichero de generar el zip.

Una vez que invocamos el fichero desde navegador


obtenemos un zip como:


<?php
	//funciones
	function show($str){
		echo $str . "<br/>\n";
		flush();
		ob_flush();
	}
	function secured($nombre,$directorio){
		return str_replace($directorio."/backup",$directorio."/secured_backup",$nombre);
	}
	
	//configuracion
	ini_set('max_execution_time', 5000);
	$maxFilePerArchive = 20000;
	$directorio="zipBk";
	$debug=false;
	//directorios y ficheros que no quieres que se añadan al archivo
	$excludes=array("dir2","dir4","zip.php");
	
	
	//parametros recibidos
	if (isset($_REQUEST['pass'])){
		$password=$_REQUEST['pass'];
	}else{
		$password="";
	}
	if (isset($_REQUEST['delete'])){
		$delete=true;
	}else{
		$delete=false;
	}
	if (isset($_REQUEST['ver'])){
		$ver=true;
	}else{
		$ver=false;
	}
	if (isset($_REQUEST['dias'])){
		$dias=$_REQUEST['dias'];
	}else{
		$dias=2;
	}
	if (isset($_REQUEST['help'])){
		show("Puedes pasar los parametros<br>
		<strong>pass</strong> Para poner password al zip<br>
		<strong>ver</strong> Para ver los archivos que son, pero sin crear el zip<br>
		<strong>delete</strong> Para borrar los archivos zip anteriores, se puede pasar un parametro dias ( indicando el numero de dias de margen para borrar )<br>
		");
		die;
	}
	
	// increase script timeout value
	
	if ($directorio!="" && $directorio!="." && !file_exists($directorio)) {
		mkdir($directorio, 0777, true);
		if($debug){show("Se ha creado el directorio $directorio porque no existia");}
	}
	if ($delete){
		
		show("Borramos los archivos anteriores a 2 dias");
		$ficheros=0;
		$borrados=0;
		$ahora=time();
		foreach (glob($directorio."/*.zip") as $file) {
			if (is_file($file)){
				$ficheros++;
				
				if ($ahora - filemtime($file) >= 60*60*24*$dias){ // 1 days
					$borrados++;
					echo $file;
					unlink($file);
				}
				echo "<br>";
			}
		}
		show("Hemos borrado $borrados archivos");die;
	}
	
	$numFiles = 0;
	$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("./"));
	foreach ($iterator as $key=>$value){
		$key=substr($key,2,strlen($key)-1);
		if (! preg_match('/'.$directorio.'\/backup_'.'/', $key) && !preg_match('/'.$directorio.'\/secured_backup_'.'/', $key)){
			if (!(substr($key,-2)==".." || substr($key,-1)==".")){
				if ($excludes){
					$puede=true;
					foreach ($excludes as $exclude)
					{
						if (preg_match('/^'.$exclude.'/', $key))
						{
							$puede = false;
						} 
					}
				}else{
					$puede=true;
				}
				if ($puede){
					$numFiles += 1;
					if ($ver){
						show("Se insertara el archivo $key");
					}
				}
			}
		}
	}
	show( "Comprimiremos $numFiles archivos" );
	if (!$ver){
		$date = getdate();
		$enlaces=array();
		$splitNum = 0;
		$archive = $directorio."/backup_" . $date[0];
		$currentArchive = $archive . "_" . $splitNum . ".zip";
		$enlaces[]=$currentArchive;
		$zip = new ZipArchive();
		if ($zip->open($currentArchive, ZIPARCHIVE::CREATE) !== TRUE) {
			die ("No se puede abrir el archivo");
		}
		
		
		$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("./"));
		$numFiles = 0;
		$counter = 0;
		
		foreach ($iterator as $key=>$value){
			$counter += 1;
			if ($counter >= $maxFilePerArchive) {
				$zip->close();
				if ($password!=""){
					try{
						system('zip -P '.$password.' '.secured($currentArchive).' '.$currentArchive);
						unlink($currentArchive);
					}catch(Exception $ex){
					
					}
				}
				$currentArchive = $archive . "_" . $splitNum++ . ".zip";
				$enlaces[]=$currentArchive;
				show( "Limite de ficheros: partimos el archivo, Nuevo archivo es $currentArchive" ); 
				
				$zip = new ZipArchive();
				if ($zip->open($currentArchive, ZIPARCHIVE::CREATE) !== TRUE) {
					die ("No se puede crear el archivo");
				}
				
				$counter = 0;
			}
			$key=substr($key,2,strlen($key)-1);
			if (! preg_match('/'.$directorio.'\/backup_'.'/', $key) && !preg_match('/'.$directorio.'\/secured_backup_'.'/', $key)){
				if (substr($key,-2)==".." || substr($key,-1)=="."){
					if ($debug){show( "Excluimos $key" );}
				}else{
					if ($excludes){
						$puede=true;
						foreach ($excludes as $exclude)
						{
							if (preg_match('/^'.$exclude.'/', $key))
							{
								$puede = false;
							} 
						}
					}else{
						$puede=true;
					}
					if ($puede){
						$zip->addFile(realpath($key), $key) or die ("ERROR: No se puede añadir el fichero: $key");
						$numFiles += 1;
						if ($debug){show( "Añadimos $key" );}
					}
				}
				
			} else {
				if($debug){show( "No se comprime el archivo,por ser una copia previa-> $key" );}
			}
		}
		// close and save archive
		$zip->addFromString("LEEME_".time().".txt", "#1 Fichero generado automaticamenta\nPor un proceso para realizar backup de todo el FTP. ");
		$zip->close();
		if ($password!=""){
			try{
				system('zip -P '.$password.' '.secured($currentArchive).' '.$currentArchive);
				unlink($currentArchive);
			}catch(Exception $ex){
			
			}
		}
		
		if ($password=="" ){
			show( "El fichero no tiene clave, llama al script pasando el parametro ?pass=xxxx para mayor seguridad" );
		}
		if ($password!=""){$enlaces=secured($enlaces);}
		echo "<br>";
		if($enlaces){
			foreach($enlaces as $enlace){
				if (file_exists($enlace)){
					echo "<a href='".$enlace."'>".$enlace."</a><br>";
				}else{
					echo "No se pudo generar el fichero $enlace <br>";
				}
			}
		}
	}
?>

(*) Como la clase ZipArchive de php no soporta clave, se genera un segundo zip mediante llamada al sistema operativo que si que pone contraseña al original y lo borra.

Nociones de economia

Llevo unos días con ganas de aprender algo de economía con la intención de invertir.

Por lo que he leido términos totalmente desconocidos para mi como pueden ser commodities, forwards, los swaps, las OTC, tipos de derivados financieros o los CFDs entre otros.

Entonces esto no parece un tema sencillo, por lo que vamos a intentar ir por partes:

Macroeconomía vs. Microeconomía.

La Macroeconomía estudia el funcionamiento económico a gran escala, así como la repercusión de las políticas económicas en un país, por ejemplo. Se ocupa de analizar:

– La evolución en el corto plazo de la producción, del empleo y de los precios, es decir, de los ciclos económicos.

– La evolución en el largo plazo de la producción y del nivel de vida, es decir, del crecimiento económico.

La Microeconomía estudia el comportamiento de las unidades económicas individuales: individuos, familias, empresas y los mercados en los que operan. Analiza:

– La formación de los precios a partir del cruce entre Oferta y Demanda.

– La asignación de los recursos escasos entre finalidades alternativas.

Hay varias premisas que tenemos que tener clara desde el comienzo:
– Toda inversión tiene un riesgo ( que nadie intente venderte un producto con riesgo 0 )
– Cuanto menor es el riesgo menor será la rentabilidad, o visto de otra forma, cuanto mayor sea el riesgo, mayor tiene a ser su beneficio, aunque también la posibilidad de perder mucho o todo.

Cuando hablamos de riesgo tenemos que ser conscientes de que se puede perder una parte , todo y con algunos productos se puede perder mas de lo invertido.

Otro de los puntos a tener en cuenta es el tiempo que vas a tener la inversión bloqueada, con la imposibilidad de utilizar ese capital. Por lo que necesitas un remanente de dinero con el que no puedes contar en el tiempo que vas a invertir.

Productos de bajo riesgo
Aquí se incluyen los depósitos y las cuentas bancarias de plazo fijo, que a dia de hoy tienen unos intereses muy bajos, por ejemplo ( y según esta web), el valor mas alto es 2% .

Con esto la ganancia que se consigue es bastante baja si tenemos en cuenta que el coste de la vida crece mientras tenemos el dinero bloqueado.

Otro de los productos es la deuda pública, que en el momento de escribir esto tiene valores incluso negativos (web), por lo que no solo no ganamos dinero, sino que nos cuesta.

Productos de alto riesgo
Comprar deuda privada, es el equivalente al punto anterior, pero cambiando la administración por una empresa. Esto tiene un riesgo mayor, pues la empresa puede quebrar y al final quedarnos sin el dinero. Pero también es posible ganar mas dinero si al final todo sale bien.

Otro de los productos que podemos encontrar como de alto riesgo son las acciones. Que son participaciones del capital de una empresa. Si compramos acciones al final lo que obtenemos es una pequeña ( en algunos casos minúscula) parte de la empresa. En este punto podemos hacer referencia a la bolsa y ver unos de los indicadores principales ( que no el único) que es el IBEX

Uno de los ejemplos que mas me gustan es el de las acciones de amazon:

Donde en el año 1997 las acciones valían 1,5 dolares, para pasar en el año 2007 a cerrar con un valor de 97, que podríamos decir que es muy grande, pero es que si lo comparamos con el valor de 2017, donde han pasado la barrera de los 1000 dolares, es casi irrisorio, pero cuantos de nosotros en el año 1997 podríamos pensar en lo que llegaría a ser….

Como caso contrario podemos mostrar el del banco popular,

Donde la gente que invirtiera en 2008 ha visto como sus acciones han pasado de 25 a 0, por lo que han perdido todo su dinero.

Raiola manda y no el panda

Esta mañana repasando los rss de las distintas web que sigo me ha llamado la atención que en varias paginas hablaban de raiola manda y no el panda, pero ¿ Qué es raiola manda y no el panda?

Pues básicamente un concurso SEO organizado por David Ayala y Deam Romero.
Podeis encontrar el enlace aqui

Pero eso tampoco cuenta nada, por lo que os explico un poco mas.

Todo empezó aproximadamente hace un mes, David & Dean, presentaron mediante un vídeo hace aproximadamente un mes, concretamente el 8 de mayo, lo que iba a acontecer durante el mes de junio, este gran concurso SEO al que pusieron el nombre raiola manda y no panda, y en el que ponían todos sus esfuerzos para que todos los SEOs pudiésemos ponernos a prueba, y lo hacían mediante el siguiente vídeo:

Aquí ya nos dejaron con las ganas a todos, y estábamos deseando que llegará el 1 de junio para empezar a enfrentarnos al concurso SEO de los 5.000. ¡ahí es nada!

Actualmente el concurso lo ganara quien tenga más autoridad, es decir si hoy busco en Google La Raiola manda y no el panda obviamente van a salir sitios que tienen mucho tiempo online y por ende con autoridad, por lo que es complicado que un dominio nuevo pueda hacerles frente.

Es súper interesante como se puede sacar mucho provecho de estos concursos, una de las fuentes de más valor son las oportunidades de en laces que podemos conseguir con el concurso de La Raiola manda y no el panda muchos usuarios sacan esos enlaces “escondidillos” permitiendo que pueda hacerme de una base de datos nueva de sitios donde dejar enlaces para futuros proyectos.

Por qué quieren dar 5000 euros a un ganador

Es fácil. Los packs SEO han dañado el sector y cada vez vemos más anuncios en adwords anunciando top 1 en keywords sin competencia como hoteles, etc.. por sólo 50 euros. Y esto ha hecho mucho daño.

Los SEO que antes cobraban 500 euros por una campaña SEO (al mes), han acabado comprando en Primark por culpa de este nuevo tipo de SEOs. Los SEO destroyers les llaman.

Debido a esta cantidad de bajada en los presupuestos, la compañia Raiola ha decidido donar 5000 euros al sector SEO para que alguien pueda irse de vacaciones este año.

Por otro lado el sector del SEM se ha quejado de la iniciativa. “Nunca hacéis un concurso para nosotros, estamos hasta los huevos y nos posicionamos más rápido” dicen…

¿Estamos ante la próxima guerra de sectores? ¿El Taxi y Cabify/Uber pasarán a un segundo plano? Si los SEO y los SEM quieren, sí. Sin duda.

Y el panda que tiene que ver en esto
El panda ha sido usado como parte de la campaña para causar ternura y facilitar que la gente caiga y participe. El panda siempre ha sido un animal adorable hasta que Google lo uso para nombrar a su algoritmo y desde entonces la gente le tiene manía. Las búsquedas en Youtube de videos sobre panda han bajado, les han cambiado el bambú por cebollinos y ya no saben que hacer con su vida. Están tristes y cabreados.

Ignorar ficheros y directorios en SVN

Crea un fichero de texto donde indicas los ficheros y carpetas que quieres que SVN no tenga en cuenta cuando compara el respositorio. (ignore.txt)

.classpath
.project
target
bin
build

ahora establecemos la propiedad ignore mediante fichero

svn propset svn:ignore -F ignore.txt directorioproyectoquequieresignorar

Una vez establecida la propiedad podemos borrar el fichero.

Patron observer en un comando JONIC desde Bean

En la estructura de JONIC, no podemos crear el comando que extienda de Observable (porque ya extiende de ResultCommand), por lo que creamos una clase interna que si lo haga.

 

public class ConsultaMasivaCMD extends ResultCommand&lt;List&gt;

public PorcentajeMasivoObservable myobs = new PorcentajeMasivoObservable();

public class PorcentajeMasivoObservable extends Observable
{
private int porcentaje = 0;
public int getPorcentaje()
{
return porcentaje;
}
public void setPorcentaje(int porcentaje)
{
this.porcentaje=porcentaje;
setChanged();
notifyObservers();
}

}

 

Y dentro de nuestro comando en el runcommand:

@Override
public ResultCommand&lt;List&lt;Resultado&gt;&gt; runCommand() throws Exception {

      for (int i = 0; i &lt;=array.size() - 1; i++) {

          ... 
          myobs.setPorcentaje(porcentaje);
      }

}

Ahora que ya tenemos la clase observable nos vamos al bean:

public class ConsultaFicherosBean extends RequestAbstractBean implements Serializable, Observer {

private ConsultaMasivaCMD.PorcentajeMasivoObservable pmo =null;

private Integer progress;

public String acConsultar() {

ConsultaMasivaCMD cmd = (ConsultaMasivaCMD)createCommand(ConsultaMasivaCMD.class);
cmd.setObj(this);
pmo=cmd.myobs;
pmo.addObserver(this);
cmd = (ConsultaMasivaCMD) runCommand(cmd);
if (cmd != null &amp;&amp; cmd.getResult() != null)
result.addAll(cmd.getResult());

return "donde sea";
}

@Override
public void update(Observable o, Object arg) {
if (o==pmo){
progress=pmo.getPorcentaje();
}

}

En el xhtml ponemos una barra de progreso con un poll para indicar el estado del progreso.

&lt;h:form id="dataForm"&gt;

&lt;p:commandButton id="viewButton" value="Enviar Petición"
action="#{consultaFicherosBean.acConsultar}"

onclick="PF('pb').start();PF('poll').start();"
onstart="PF('dlg').show()"
oncomplete="PF('dlg').hide();PF('pb').cancel();PF('poll').stop();"
update=":dataForm :prg"

icon="ui-icon-pin-s" /&gt;

&lt;/h:form&gt;

&lt;p:dialog widgetVar="dlg"
appendTo="@(body)"
modal="true"
width="400"
height="100"
header="Progreso"
draggable="false"
closable="false"
closeOnEscape="false"
resizable="false"
minimizable="false"&gt;
&lt;h:form id="prg"&gt;

  &lt;p:poll interval="1"
  widgetVar="poll"
  autoStart="false"
  async="true"
  update=":prg"
  immediate="true"/&gt;

&lt;!-- progressbar--&gt;
&lt;p:progressBar widgetVar="pb"
ajax="true"
value="#{consultaFicherosBean.progress}"
labelTemplate="{value}%"
styleClass="animated"
global="false"&gt;
&lt;/p:progressBar&gt;
&lt;/h:form&gt;
&lt;/p:dialog&gt;

Con esto el comando avisa en cada iteración del porcentaje, el Bean se entera y actualiza su variable de progreso y la página mediante el poll y la barra de progreso puede informar al usuario de como va la tarea.

Corregir fallo prestashop 1.7 carousel

Una vez que he instalado prestashop 1.7 y accedo a la tienda veo que el componente carousel que viene con el tema por defecto no tiene enlace

Aunque en la parte de administración veo que si que está definido:

 

Para arreglarlo es necesario modificar el fichero:

themes/classic/modules/ps_imageslider/views/templates/hook/slider.tpl

Añadiendo el elemento a, dentro de figure:

Una vez hecho, es necesario vaciar la caché para que podamos ver el resultado:

 

 

 

 

Pensando en cambiar de hosting

Será porque hoy es sábado y voy bien de tiempo con mis proyectos que tengo a medias, pero hoy me apetece escribir una entrada mas larga.

Llevo tiempo con mi pagina web en 1and1, y creo que es el momento de pensar si es el mejor hosting en el que puedo tener no solo el blog, sino todas las paginas correspondientes a mis aplicaciones móviles, tanto de IOS como de Android, ademas de aquellas necesarias para el correcto funcionamiento de varias aplicaciones que he desarrollado a lo largo de los años.

Ultimamente he desarrollado varias aplicaciones como Datercam para Android ( ya existía para IOS) que permite poner información como la fecha, la hora, las coordenadas gps y la ubicación ( obtenida mediante google ) a las fotos, para que no olvides cuando y donde hiciste una foto.

O mi ultima aplicación Emojime publicada hace 3 días, que permite coger una foto, bien sea de la cámara o del carrete, detectar las caras y cargar emoticonos de forma aleatoria, lo que permite “jugar” a encontrar la combinación de caras que mejor se adapte a la foto, una vez tienes el resultado puedes compartirla o guardarla.

Pero volviendo al tema con el que empece, últimamente he tenido problemas con mi pagina en 1and1, momentos en los que no puede acceder, errores internos del servidor ( que luego no dan mas información ) o simplemente que la velocidad no es la deseada.

A eso se junta que hace tiempo me cambiaron la tarifa de forma unilateral, después de 8 años con ellos ya no podían mantenerme el contrato que tenia con ellos, y me pasaban a uno superior ofreciendo cosas que no necesito y con ello un aumento de precio considerable.

Otro de los motivos por los que tengo que pensar en cambiar de hosting es que me gustaría que tuviera acceso a la base de datos de forma nativa mediante host y puerto, mientras que ahora solo puedo acceder mediante phpmyadmin una vez que me he logueado en el panel de control, lo que relentiza bastante el trabajo con base de datos.

Hace unos días que encontré un articulo  donde hablaban de tres hosting baratos y exponían una serie de pruebas que habian hecho para valorar cual era la mejor, los tres candidatos eran: Webempresa, Raiola y Sered, y las pruebas que realizaban eran: benchmark, velocidad de renderización, estabilidad del servidor o load impact entre otros.

Aquí me pilla de novato, pues no tenia ni idea de en que consistían muchas de las pruebas que se realizaban, pero me ha servido para aprender mas acerca de los pasos necesarios para que tu web esté en un hosting capaz de soportar cargas sin que el usuario se vea afectado. Es mas creo que estas pruebas pueden ser aplicadas en mi puesto de trabajo y se lo comentaré a la gente de sistemas para organizar un plan de actuación.

Aunque en el articulo si mostraban un ganador, como en casi todas las comparativas  cada una de ellas destacaba en algún punto por lo que el resultado no era fácil de determinar.

Como en el articulo no hablaban de si el acceso a base de datos era con phpmyadmin o si por el contrario permitían acceso directo no me queda mas remedio que preguntarlo directamente, recurro a llamar por teléfono y quedo a la espera, en unos segundos me atiende un empleado muy amable que me responde a mi gran duda, y la respuesta es afirmativa, CPANEL permite habilitar conexión externa con la base de datos, por lo que acaba de convencerme para tomarlo como claro candidato a ser mi proximo hosting, a ver si el proximo post ya está ahí alojado.

 

 

Modificaciones sobre boton flotante

Partiendo del componente FabOptions

Añadiendo en la clase FabOptions.java el método:

public void changeColorbackground(int color){
Drawable d = mBackground.getBackground();
d = DrawableCompat.wrap(d);
DrawableCompat.setTint(d.mutate(), color);

}
public void changeColor(int color){
mFab.setBackgroundTintList(new ColorStateList(new int[][]{new int[]{0}}, new int[]{color}));

}

y llamandolo pasandole el color:

fabOptions.changeColorBackground((getResources().getColor(R.color.verde));

Podemos obtener resultados como:

Y para cambiar el color del boton principal:

fabOptions.changeColor((getResources().getColor(R.color.verde2));

Ordenar columnas datatable jquery

Hay determinadas columnas que no se ordenan bien de manera nativa utilizando jquery.datatable.js
Por ejemplo las fechas

Las fechas en español no se ordenan bien, para ello tenemos que indicarle un valor con la fecha en formato americano de manera que no se vea pero que le sirva para ordenar:

Donde lo importante es poner un elemento <span style=”display:none”>valor util para ordenar</span> que en el caso de las fechas es con el formato americano.