Formas de validar un correo electrónico

Una de las cosas que habitualmente es necesario hacer es validar cuentas de correo. Hay muchas cosas a hacer, pero una de las primeras es saber si la cuenta de correo está “bien formada”. Un artículo muy interesante sobre distintas formas de verificar cuentas, basadas en una serie de expresiones que sí han de validar, y otras que no han de hacerlo.

La expresión que en principio se ajusta más a todas las posibilidades es la siguiente:

/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i

Con esto tendríamos un código similar a este:
<?php
$texto = "prueba@ejemplo.com";
$expresion = "/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i";
preg_match($expresion , $texto , $encuentros);
print_r($encuentros);
?>

De todas formas, quizá habría que hacer otra cosa, que es verificar si realmente la cuenta existe… y es que una cosa es que la cuenta de correo esté bien formada y otra es que pueda hacer una prueba de envío de correo sin necesidad de enviar. Para eso podríamos usar una clase como esta que se conecta a la máquina remota para verificar la existencia de la cuenta…

<?php
class SMTP_validateEmail {
  var $sock;
  var $user;
  var $domain;
  var $domains;
  var $port = 25;
  var $max_conn_time = 30;
  var $max_read_time = 5;
  var $from_user = 'pruebas@ejemplo.com';
  var $from_domain = 'localhost';
  var $nameservers = array(
    '192.168.0.1'
  );
  var $debug = false;
  function SMTP_validateEmail($emails = false, $sender = false) {
    if ($emails) {
      $this->setEmails($emails);
    }
    if ($sender) {
      $this->setSenderEmail($sender);
    }
  }
  function _parseEmail($email) {
    $parts = explode('@', $email);
    $domain = array_pop($parts);
    $user= implode('@', $parts);
    return array($user, $domain);
  }
  function setEmails($emails) {
    foreach($emails as $email) {
      list($user, $domain) = $this->_parseEmail($email);
      if (!isset($this->domains[$domain])) {
        $this->domains[$domain] = array();
      }
      $this->domains[$domain][] = $user;
    }
  }
  function setSenderEmail($email) {
    $parts = $this->_parseEmail($email);
    $this->from_user = $parts[0];
    $this->from_domain = $parts[1];
  }
  function validate($emails = false, $sender = false) {
    $results = array();
    if ($emails) {
      $this->setEmails($emails);
    }
    if ($sender) {
      $this->setSenderEmail($sender);
    }
    foreach($this->domains as $domain=>$users) {
      $mxs = array();
      list($hosts, $mxweights) = $this->queryMX($domain);
      for($n=0; $n < count($hosts); $n++) {
        $mxs[$hosts[$n]] = $mxweights[$n];
      }
      asort($mxs);
      array_push($mxs, $this->domain);
      $this->debug(print_r($mxs, 1));
      $timeout = $this->max_conn_time/count($hosts);
      while(list($host) = each($mxs)) {
        $this->debug("try $host:$this->port\n");
        if ($this->sock = fsockopen($host, $this->port, $errno, $errstr, (float) $timeout)) {
          stream_set_timeout($this->sock, $this->max_read_time);
          break;
        }
      }
      if ($this->sock) {
        $reply = fread($this->sock, 2082);
        $this->debug("< <<\n$reply");
        preg_match('/^([0-9]{3}) /ims', $reply, $matches);
        $code = isset($matches[1]) ? $matches[1] : '';
        if($code != '220') {
          foreach($users as $user) {
            $results[$user.'@'.$domain] = false;
          }
          continue;
        }
        $this->send("HELO ".$this->from_domain);
        $this->send("MAIL FROM: < ".$this->from_user.'@'.$this->from_domain.">");
        foreach($users as $user) {
          $reply = $this->send("RCPT TO: < ".$user.'@'.$domain.">");
          preg_match('/^([0-9]{3}) /ims', $reply, $matches);
          $code = isset($matches[1]) ? $matches[1] : '';
          if ($code == '250') {
            $results[$user.'@'.$domain] = true;
          } elseif ($code == '451' || $code == '452') {
            $results[$user.'@'.$domain] = true;
          } else {
            $results[$user.'@'.$domain] = false;
          }
        }
        $this->send("quit");
        fclose($this->sock);
      }
    }
    return $results;
  }
  function send($msg) {
    fwrite($this->sock, $msg."\r\n");
    $reply = fread($this->sock, 2082);
    $this->debug(">>>\n$msg\n");
    $this->debug("< <<\n$reply");
    return $reply;
  }
  function queryMX($domain) {
    $hosts = array();
    $mxweights = array();
    if (function_exists('getmxrr')) {
      getmxrr($domain, $hosts, $mxweights);
    } else {
      require_once 'Net/DNS.php'; // http://pear.php.net/package/Net_DNS/
      $resolver = new Net_DNS_Resolver();
      $resolver->debug = $this->debug;
      $resolver->nameservers = $this->nameservers;
      $resp = $resolver->query($domain, 'MX');
      if ($resp) {
        foreach($resp->answer as $answer) {
          $hosts[] = $answer->exchange;
          $mxweights[] = $answer->preference;
        }
      }
    }
    return array($hosts, $mxweights);
  }
  function microtime_float() {
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
  }
  function debug($str) {
    if ($this->debug) {
      echo htmlentities($str);
    }
  }
}
?>

Buscando desarrollador web

Hoy comenzamos el día con una oferta de trabajo, que tal y como está la cosa, no es moco de pavo. El perfil es de desarrollador PHP y MySQL.

Quién se incorpore estará bajo mi supervisión y se dedicará principalmente a la continuidad de un proyecto que he estado elaborando estos últimos meses, por lo que si le gusta la emoción no ha podido caer en un sitio mejor…

También es interesante que tenga las ideas claras y que le guste Internet, ya que este proyecto se mueve a una velocidad bastante rápida y la evolución puede necesitar ir a la misma velocidad.

Con respecto a la jornada laboral, puede ser media jornada (si fuera de mañanas sería de 09:30 a 13:30; en caso de ser de tardes sería de 15:00 a 19:00) o jornada completa (de lunes a jueves de 09:30 a 19:30 y los viernes de 09:30 a 14:30). La zona de trabajo es Plaça de les Glories en Barcelona.

La retribución ahora mismo no la sé, pero lo más probable es que sea por convenio (que si no recuerdo mal, está por encima de lo mileurista).

Para enviar el curriculum y lo que queráis (algún proyecto que hayáis hecho de ejemplo o similar si os parece conveniente) podéis hacerlo en la cuenta de correo simple@kisslab.com donde una amable secretaria os atenderá (NOTA: la amable secretaria puede no ser tan amable, puede no ser secretaria, puede ser un tío e incluso diría que podría ser yo mismo).

Ethek integra Live Messenger

He de reconocer que si hay un software que todo el mundo utiliza es Windows Live Messenger y no cabe duda de que cualquier integración de un sitio web sólo puede levar a ser un acierto.

Llevo varios meses planteándome integrar algún sistema de estos tan de moda ahora, y aposté en Ethek y en Windows Live ID, más concretamente en Windows Live Messenger Web. Estos días atrás alguien hizo que la chispa saltara y que mis pruebas en una máquina perdida del universo se acabasen convirtiendo en una versión beta que ha durado tan sólo 2 horas, para pasar a producción en cuanto tenía todas las funcionalidades en línea.

¿Qué es lo que he hecho?

Básicamente se resumen en 3 elementos:

  1. Integrar la Windows Live Messenger Bar (al pie de página).
  2. Integrar el Compartir elementos con los contactos.
  3. Añadir Windows Live Alerts.

Messenger Login

De todas las cosas, la más compleja ha sido la primera. El sistema necesita la instalación y configuración de la máquina de una forma especial, pero que permite navegar por toda la web sin perder las charlas abiertas. Además, nosotros no tenemos control en absoluto sobre el usuario o clave, de forma que es totalmente transparente para el usuario, ya que utiliza y puede dar permiso o quitarlo para que al acceder al sitio se conecte o no.

Barra de Messenger

Un elemento que, desde el punto de vista de marketing mola bastante, es lo de compartir. Con un clic, te permite seleccionar a los que están conectados y enviarles un mensaje diciéndoles que estás leyendo un artículo en Ethek. Además, se abre la ventana en ese momento y puedes mantener la charla allí mismo.

Compartir con contactos de Messenger

Lo último, lo de las alertas, está bien, ya que es el feed integrado en el messenger, de forma que, cuando se publique algo en la web le aparecerá una alerta a los usuarios que lo hayan aceptado.

Windows Live Alertas

Este es un primer paso que creo interesante dentro del ecosistema Ethek, y, aunque aún quedan dudas en este lanzamiento, pronto, seguro, que os cuento más detalles sobre como va avanzando.

Por cierto, no puedo poner la mano en el fuego, pero me atrevería a decir que esta es la primera web en España que utiliza este sistema… aunque, no puedo confirmarlo, ya que no parece haber ningún sitio donde haya un listado.

oEmbed, WordPress 2.9 y el editor de imágenes

Como muchos ya sabréis soy aficionado a tener una versión “alpha” de WordPress en mi blog personal, y de esa forma ir probando en tiempo real cómo es de estable el sistema antes de hacer las actualizaciones pertinentes en el resto de sitios de los que soy responsable… Y ahora que no creo que tarde mucho en salir esta nueva versión, me gustaría hacer un repaso de algunas características interesantes.

Antes de nada, he de decir que en muchos casos (no sé si es el autoguardado o qué) cuando voy a guardar un borrador o similar se pierde como el ID o algo y acaba fallando, total, que hay que volver a la lista y reabrir esa entrada (habiendo perdido el título y tags, normalmente).

El primero de los detalles que quiero comentar es el editor de imágenes que incluye. No es una barbaridad de editor, porque la verdad es que no supera al Scissors, pero es lo suficientemente sencillo y útil (sobretodo a la hora de redimensionar imágenes). Además, también permite gestionar cómo será el thumbnail por defecto de la entrada, que de eso ahora os hablo.

Wordpress 2.9 - Editor de Imágenes

Como decía, existe otra novedad que es la de los “thumbnails”. Se supone que se puede asignar una pequeña imagen por defecto a las entradas, creándola en base a una de las imágenes que subamos (como se puede ver en la imagen de arriba, en la parte inferior derecha). Para ello ha aparecido una nueva función:

the_post_image(); // Miniatura
the_post_image('thumbnail'); // Miniatura
the_post_image('medium'); // Mediana

Además de esto, quiero hacer referencia al oEmbed, que a muchos les va a ser muy útil, aunque todavía estoy investigando al 100% cómo funciona. La idea era que se utilizasen unos tags específicos, pero parece que se puede poner una dirección URL directa (y seguro que aparecerán plugins que ayuden a ello).

Por ejemplo, si ponemos una dirección de Flickr, la imagen debería aparecer automáticamente, sin necesidad de indicar el código HTML correspondiente (el <img src…> de toda la vida, vaya).

http://www.flickr.com/photos/juancasares/3562950871/

Si se pone esa dirección, a mi, personalmente, ahora mismo me falla la vista previa, como si no pudiera acceder a la imagen…

Según la documentación de Flickr, el código que habría que usar realmente es:

http://flickr.com/services/oembed?url=http://www.flickr.com/photos/juancasares/3562950871/&format=json&maxwidth=200

En este caso se puede omitir el “format”, y el “maxwidth”, si no se indica, es el que se haya configurado en las opciones del WordPress (que hay una pestaña donde se puede configurar esto).

Los parámetros que soporta el oEmbed son:

  • url: que es la dirección del elemento a incrustar (obligatorio)
  • maxwidth: el ancho máximo del objeto.
  • maxheight: la altura máxima del objeto.
  • format: el formato de respuesta

A parte de Flickr, también podríamos incrustar vídeos de Youtube:

Como comentaba antes, simplemente poniendo una dirección como la siguiente debería funcionar, aunque por ahora me falla y no carga la página… de todas formas, el código correcto sería:

http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=HJEoNtN7j04

Algunos de los proveedores que ofrecen ya el servicio de oEmbed son:

  • Clearspring Widgets: http://widgets.clearspring.com/widget/v1/oembed/
  • Flickr: http://www.flickr.com/services/oembed/
  • Hulu: http://www.hulu.com/api/oembed.{ext}
  • My Opera: http://my.opera.com/service/oembed
  • oohEmbed: http://oohembed.com/oohembed/
  • Poll Everywhere:http://www.polleverywhere.com/services/oembed/
  • Qik: http://qik.com/api/oembed.{ext}
  • Revision3: http://revision3.com/api/oembed/
  • Viddler: http://lab.viddler.com/services/oembed/
  • Vimeo: http://www.vimeo.com/api/oembed.{ext}
  • YouTube: http://www.youtube.com/oembed

Por cierto, para los geeks que quieran implementar esto del oEmbed en su propio CMS o servicio, existe una librería en PHP además de soporte PHP.

Nota final: parece que para que todo funcione correctamente hay que instalar este plugin llamado oohEmbed y se supone que, junto a WordPress 2.9, la cosa funciona… (aunque a mi me sigue sin ir).

Parsear el robots.txt con PHP

Cuando construyes un robots de Internet has de tener en cuenta dos elementos:

  • Tener tu propio “User-Agent”
  • Cumplir el estándar de robots.txt

Para el primer elemento hay una forma muy sencilla de ejecutar un código en PHP:

ini_set("user_agent", "Agente 1.0 (http://www.agente.dom)");

Con esto ya consigues que, cuando se haya una petición desde PHP hacia cualquier sitio, en vez de llevar el agente del propio PHP se genere uno con los datos que tú indiques.

Aunque, quizá lo más interesante es tener un sistema de parseo de los ficheros de robots.txt. Para ello hemos de leer todas las líneas del fichero y procesarlas, sobretodo si coinciden con nuestro agente.

La idea es crear una función que consulte si tenemos acceso o no a esa dirección URL. Se puede mejorar con un sistema de caché y similar, pero lo pondré sencillo para dar unos primeros pasos.

function robots($url, $useragent=false) {
 
  // leemos la URL a revisar y sacamos la info
  $parseado = parse_url($url);
 
  // creamos un array de agentes posibles, incluyendo siempre el *
  $agentes = array(preg_quote('*'));
 
  // Si enviamos unos agentes por parámetro los revisamos
  // los agentes se pueden pasar por parámetro separados por "pipelines"
  if($useragent) $agentes[] = preg_quote($useragent);
  $agentes = implode('|', $agentes);
 
  // leemos el fichero robots.txt
  $robotstxt = @file("http://{$parsed['host']}/robots.txt");
  // y si no existe, se acabó todo
  if(!$robotstxt) return true;
 
  $reglas = array();
  $aplicadas = false;
  foreach($robotstxt as $linea) {
    if(!$linea = trim($linea)) continue;
 
    // Comprobamos si la línea hace referencia a un Agente
    if(preg_match('/User-agent:(.*)/i', $linea, $coincidencia)) {
      $aplicadas = preg_match("/($agentes)/i", $coincidencia[1]);
    }
 
    // Comprobamos si la línea hace referencia a una Regla
    if($aplicadas && preg_match('/Disallow:(.*)/i', $linea, $registro)) {
      if(!$registro[1]) return true;
      $reglas[] = preg_quote(trim($registro[1]), '/');
    }
  }
 
  // Comprobamos cada una de las reglas para la dirección que estamos revisando
  foreach($reglas as $regla) {
    if(preg_match("/^$regla/", $parseado['path'])) return false;
  }
 
  // Si no hay que filtrar nada, devolvemos "true" sino, ya habremos devuelto "false"
  return true;
}

Ahora sólo faltaría hacer un llamada:

$url = "http://www.ejemplo.ext/preba.html";
if(robots($url, "Agente")) {
  $contenido = file_get_contents($url);
}

Publicado en PHP

phpBB, contenidos duplicados y etiqueta Canonical

Siempre he defendido phpBB como un buen sistema de foros, pero a veces creo que está pensando más en la Edad Media que para la era Internet. Y es que si hay una cosa que no me gusta absolutamente nada, es que las URL puede cambiar de forma estrepitosa según el navegante que venga, o buscador, además de poder generarse una de combinaciones bestiales.

Hace unas semanas tuve que actualizar un foro muy antiguo (versión 2 algo) a la nueva versión (la 3 algo), y me encontré con que, hace unos 4-5 años, le hice unos cambios por temas de SEO en el que las URL quedaban “chulas”. El problema es “deshacer todo el SEO que había hecho” para así, a partir de ahora, poder actualizar el software sin necesidad de ningún MOD raro de esos que se pueden montar…

Total, que tras la actualización han empezado a salir decenas de contenidos duplicados que no sabía cómo arreglar… hasta hoy que he encontrado una forma “razonable”. Lógicamente, esta forma razonable va a depender mucho de cada uno y de lo que pretenda con su foro, pero creo que para la mayoría de mortales servirá.

Y la forma razonable que planteo es sólo indexar estas 2 cosas:

  • Foros: sólo la primera página de cada foro.
  • Temas: indexar todos los temas y sus paginaciones

El resto (fichas de usuarios, combinaciones raras de foros o temas, paneles de gestión, ayudas, y demás) quedarían fuera de este sistema, ya que, a priori, no sirven para mucho, a la hora de aparecer en los resultados de búsqueda.

Lo bueno de este sistema, es que sirve para cualquier “style” (diseño) del phpBB, así que cualquiera lo debería de poder utilizar sin problema. Para ello, lo primero que hemos de hacer es activar las capacidades PHP del phpBB en los “style”. Para ello hay que:

  1. Entrar en el panel de Administradores
  2. Ir a la pestaña General -> Configuración del servidor -> Configuración de seguridad
  3. Permitir PHP en plantillas (Si se habilita esta opción, PHP e INCLUDEPHP serán convertidos en las plantillas) activar a SÍ.
  4. Aceptamos y ya tenemos el primero de los pasos… ya que ahora podemos programar dentro de los “diseños”.

Ahora hemos de ir al “diseño” que tengamos activo… para ello entraremos en Estilos -> Plantillas -> Editar (de la plantilla actual) -> overall_header.html. Allí buscaremos la línea del <title>...</title> y la sustituiremos por esto siguiente:

Descargar directamente como TXT (es posible que haya un problema con las comillas en el código siguiente y en el TXT funcionará correctamente).


<!-- PHP -->
if( $_SERVER["PHP_SELF"] == "/viewtopic.php" ) {
<!-- ENDPHP -->
<title>{TOPIC_TITLE}</title>
<!-- PHP -->
} elseif( $_SERVER["PHP_SELF"] == "/viewforum.php" ) {
<!-- ENDPHP -->
<title>{SITENAME}: {FORUM_NAME}</title>
<!-- PHP -->
} else {
<!-- ENDPHP -->
<title>{PAGE_TITLE} en {SITENAME}</title>
<!-- PHP -->
}
if( $_GET['p'] || $_GET['sid'] || $_GET['highlight'] ) {
echo "<meta name=\"robots\" content=\"noindex\" />\n";
} elseif( $_GET['f'] && $_GET['t'] && ($_GET['start']!=0) ) {
echo "<link rel=\"canonical\" href=\"http://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF']."?f=".$_GET['f']."&t=".$_GET['t']."&start=".$_GET['start']."\" />\n";
} elseif( $_GET['f'] && $_GET['t'] && ($_GET['start']==0) ) {
echo "<link rel=\"canonical\" href=\"http://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF']."?f=".$_GET['f']."&t=".$_GET['t']."\" />\n";
} elseif( $_GET['f'] && $_GET['t'] ) {
echo "<link rel=\"canonical\" href=\"http://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF']."?f=".$_GET['f']."&t=".$_GET['t']."\" />\n";
} elseif( $_GET['f'] && ($_GET['start']!=0) ) {
echo "<link rel=\"canonical\" href=\"http://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF']."?f=".$_GET['f']."&start=".$_GET['start']."\" />\n";
} elseif( $_GET['f'] && ($_GET['start']==0) ) {
echo "<link rel=\"canonical\" href=\"http://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF']."?f=".$_GET['f']."\" />\n";
} elseif( $_SERVER["PHP_SELF"] == "/" ) {
echo "";
} else {
echo "<meta name=\"robots\" content=\"noindex\" />\n";
}
<!-- ENDPHP -->

Con esto básicamente hacemos varias cosas:

  • Poner un título concreto para los temas (indexable)
  • Poner un título concreto para los foros (indexable)
  • Poner el título genérico para el resto de elementos (no indexable)
  • Controlar parámetros que generan duplicados (p, sid, highlight) y decirle que esas páginas “no las indexe”.
  • Controlar las páginas indexables (con sus parámetros correctos) y darles la URL con el meta-tag Canonical para que siempre tengan el mismo formato.
  • Controlar que el resto de páginas no se indexen.

El hecho de usar la etiqueta Canonical ha sido básicamente porque, aunque el phpBB genera URL del tipo viewtopic.php?f=2&t=100, puede ser que algún listillo ponga los parámetros de otra forma, y que ese enlace genere otros incorrectos…

En fin, como digo, yo lo he probado con el phpBB 3 y me funciona… aunque, lógicamente, se aceptan todo tipo de sugerencias, combinaciones de URL y demás, porque seguro que me he dejado alguna cosa y el código se puede mejorar (si alguien sabe alguna cosa, que lo comente y actualizaré el código encantado).

ACTUALIZACIÓN: faltaba que se pudiera indexar la página principal… así que he añadido un “if” por ahí para controlar esa página…

Herramientas básicas: Gregarius

Una de las preguntas que de tanto en tanto alguien me hace es la de qué lector de feeds utilizo. Y la verdad es que muchas veces no sé si vale la pena contestar o inventármelo.

Habitualmente la gente utiliza Bloglines, Google Reader, Netvibes… pero claro, ¿cómo voy a usar yo una cosa de esas? Yo he de complicarme la vida y usar Gregarius.

Es un lector de feeds que se instala en el servidor, no es de escritorio, sino vía web (algo que facilita que esté actualizado siempre en todos sitios). Y su peculiaridad y lo que hace que lo siga usando es que, a diferencia de otros lectores:

  • Puedo ver todo lo pendiente de lectura en una misma pantalla.
  • Si leo algo no se elimina… eso sí, lo puedo “borrar” (además, con AJAX que desaparece de pantalla) con un simple clic.
  • Permite organizar por carpetas y demás, así que puedo leer “por temas” todo mezclado.
  • La única cosa que no lleva y que yo me he hecho es ponerle un cron para que se actualice cada hora.

Existe una demo de Gregarius por si alguien queire ver como es y funciona… tiene usuario y clave y otras cosas y pijadas, aunque, como digo, sobretodo va bien para cuando has de trabajar con feeds de forma habitual, no simplemente como lector…

Sitios que “roban” contenidos

Hace ya un tiempo comenté los problemas que tenía con contenidos duplicados por utilizar Feedburner y la imposibilidad de filtrarlos, y que de ahí comencé a utilizar el plugin de WordPress llamado ©Feed.

La cuestión es que después d un tiempo, tengo una pequeña lista de IP de servicios de esos que almacenan una copia de los contenidos de los feeds para mostrarlos en su sitio web, lo que podría llegar a afectar a la multiplicidad de nuestros contenidos por la red sin que sea una simple mención, sino copia.

ServicioDirección IP ServicioDirección IP
Wikio84.55.184.93Blodico / DigestServices67.212.188.186
Feedshow88.191.13.89Feedage64.34.174.17
UrlFan70.165.48.167MobiType91.121.143.209
Notifixious75.101.147.247Tecnomeme / Webremix64.13.192.34
WASALive88.191.36.95Toluu67.228.53.210
Blogged74.54.159.180flitic78.129.128.90
Hedatu84.20.10.71Portal-seo80.33.138.93
Rssindicato92.243.2.141Multiplica81.19.100.35
Iluminatia69.16.236.104Planet Google64.111.122.23
Xgil66.232.112.166Newsbeet216.86.147.191
Planetaki67.207.138.103WASALive91.121.94.113
Keegy74.52.131.116Dilo Ya!82.146.52.192
Linkandoo91.200.140.50Limlom64.62.174.98
BlogDimension85.31.105.37Blogtok67.43.168.85
DigestServices72.232.181.242UrlFan207.88.140.130
UrlFan70.165.48.162Personalbee67.111.14.203
Jordo Media216.227.208.228Feeddigest75.126.158.42
mytalk.at / Personalbee67.111.14.202RSSmicro209.216.63.55
Newstin195.39.35.193iPlural67.205.3.218
ElPelao67.111.14.204telefonos-moviles.net77.232.72.161
Cognomarket212.227.114.90Fooglesfunny202.106.63.4

La lista de IP y servicios ha sido extraida de una mezcla de blogs que controlo y en los que está el plugin que comentaba, por lo que he podido sacar las direcciones e investigar un poco.

Que conste que hay más sitios que roban contenidos, pero lo hacen a través de otros servicios que, lógicamente, por la repercusión que tienen en lectores reales, no he añadido a la lista…

Cómo saber la IP real del usuario con PHP


<?php
function SacarIP() {
  if($_SERVER) {
    if($_SERVER["HTTP_X_FORWARDED_FOR"]) {
      $realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    } elseif ($_SERVER["HTTP_CLIENT_IP"]) {
      $realip = $_SERVER["HTTP_CLIENT_IP"];
    } else {
      $realip = $_SERVER["REMOTE_ADDR"];
    }
  } else {
    if(getenv("HTTP_X_FORWARDED_FOR")) {
      $realip = getenv("HTTP_X_FORWARDED_FOR");
    } elseif(getenv("HTTP_CLIENT_IP")) {
      $realip = getenv("HTTP_CLIENT_IP");
    } else {
      $realip = getenv("REMOTE_ADDR");
    }
  }
  return $realip;
}
echo SacarIP();
?>

Publicado en PHP

PrestaShop, una solución e-Commerce interesante

PrestaShopHacía bastante tiempo que no revisaba el sistema gratuito de PrestaShop, un software hecho en PHP y MySQL que permite montar una tienda de forma sencilla, de forma similar a OsCommerce, pero mucho más simple.

Me parece interesante por su forma de estar desarrollado y sus posibilidades, como se puede ver en la demo del frontal, y en la demo del backoffice (usuario: demo@prestashop.com; clave: prestashop_demo).

La lista de funcionalidades es muy interesante y viene preconfigurado para poder usarse con PayPal, tiene algunas funciones sociales (top compradores y productos…), facturación por PDF, traducciones, SEO

Si alguien está haciendo un pensamiento de crear una tienda, sin duda es un sistema interesante a instalar y probar.