Archivo de la etiqueta: Wordpress

Migración de WordPress a Hugo

[blog]

Desde hace ya un tiempo he querido abandonar WordPress como motor para mi blog. Las razones para ello son múltiples, pero las más destacadas serían:

  • Realizar copias de seguridad de manera más sencilla.
  • Tener los artículos en un formato más exportable.
  • Despreocuparme de las actualizaciones.
  • Mejor seguridad.

Hace un tiempo estuve leyendo sobre Jekyll que te permite crear blogs como páginas estáticas a partir de documentos en Markdown. Me gustó mucho el concepto así que he investigado que otras alternativas similares existen. La alternativa más fuerte es Hugo. La verdad es que ambos sistemas son excelentes, y no creo que ahora mismo exista un claro vencedor entre los dos, y dependerá más de otras circunstancias a la hora de elegir. En mi caso me he decantado por Hugo por un motivo, y es que la migración automática WordPress-Jekyll estaba llena de errores, mientras que la WordPress-Hugo fue mucho mejor, reduciendo considerablemente las correcciones a realizar.

Podría haber lanzado los cambios tal cual, pero ya que hacía esta migración quería dejar los ficheros con un código Markdown lo más limpio posible, y me he pegado una buena paliza revisando todos los artículos del blog desde sus inicios. Ha sido un tanto agotador, pero también ha sido divertido releer mis ideas de los últimos 8 años. Además me ha venido bien para limpiar un buen número de enlaces que han muerto a lo largo de los años.

SPAM Fight – Round 4!

[blog] [programación]

Cuando pensaba que había encontrado el método definitivo anti-spam, resultó no ser eficaz ni durante un día entero. Algunos de los comentarios se estaban marcando correctamente como SPAM, que deben ser los que atacan directamente a wp-comments-post.php. Sin embargo seguían llegando algunos comentarios de SPAM, y no tengo ni idea de como lo están haciendo. Debe haber otra manera de hacer un POST de un comentario, pero por el momento no la he encontrado.

Lo que sí que me he dado cuenta, es que estos comentarios nunca tienen establecido un correo electrónico (al menos de momento). Utilizando ese dato, he complementado el método de identificación de SPAM con el requerimiento de un correo. En wp-includes/comment.php:

if(strpos($comment_content, '[THIS#IS#SPAAAM!]') !== false
    || !is_email($comment_author_email)){
    $comment_approved = 'spam';
}

De momento con esto estoy cazando todo el SPAM. ¡Veremos si dura!

El SPAM contraataca!

[blog] [programación]

El método que implementé contra el SPAM, que comenté en esté articulo, ha estado funcionando bien, pero en los últimos 2 meses ha dejado de cazar todo el SPAM. Los últimos comentarios que están llegando sí que  traen el campo de email cumplimentado, por lo que ya no es efectivo. Dándole vueltas al asunto, se me ha ocurrido hacer mi propia base de datos anti-spam. La idea es que cada vez que llega un nuevo comentario, se comprueba con la base de datos si es SPAM, y en caso que lo sea, añadir sus datos para futuras comprobaciones. El código es el siguiente:

En wp_includes/comment.php en el método wp_insert_comment, justo antes de insertar el comentario hago esta comprobación:

if(!is_email($comment_author_email)){
    $comment_approved = 'spam';
}
else{
    $spam_query = "SELECT * FROM spam_data "
    ."WHERE data = '".$comment_author_IP
    ."' OR data = '".$comment_author_email
    ."' OR data = '".$comment_author_url."'";

    /*$spam_query = "SELECT * FROM spam_data "
    ."WHERE 1";*/

    $spam_results = $wpdb->get_results($spam_query);

    /*if(count($spam_results) <= 0){ // It's SPAM
        $comment_approved = 'spam';
    }*/

    if(count($spam_results) > 0){ // It's SPAM
        $comment_content .= " count: ".count($spam_results);
        $comment_approved = 'spam';

        insert_into_spam_data($comment_author_IP);
        insert_into_spam_data($comment_author_email);
        insert_into_spam_data($comment_author_url);
    }    
}

Y para añadir los datos a la BD he añadido este método:

function insert_into_spam_data($spam_data){
    global $wpdb;

    $spam_query = "SELECT * FROM spam_data "
    ."WHERE data = '".$spam_data."'";

    $spam_results = $wpdb->get_results($spam_query);

    if(count($spam_results) <= 0){
        $wpdb->insert(
            'spam_data',
            array(
                'data' => $spam_data
            ),
            array(
                '%s'
            )
        );
    }
}

Esto debería parar una buena parte del SPAM. El siguiente paso será que cuando yo marque manualmente un comentario como SPAM, sus datos también sean incluidos en la tabla con la información de SPAM. Para ello en el metodo wp_spam_comment, tras marcar el comentario como SPAM, añadimos este código:

insert_into_spam_data($comment->comment_author_IP);
insert_into_spam_data($comment->comment_author_email);
insert_into_spam_data($comment->comment_author_url);

Ahora faltará ver como de efectivas son las medidas. Me estoy planteando introducir algún otro tipo de comprobación anti-spam, viendo que el captcha no está funcionando. Pero eso para otro artículo más adelante 🙂

Sigue la lucha contra el Spam

[blog] [programación]

Ya comenté en un post anterior los problemas que estaba teniendo con el Spam.

Como tuve los problemas de indexación en Google, dejaron de bonbardearme, pero ahora que está resuelto, vuelvo a ver una buena cantidad de comentarios Spam nuevos cada vez que me paso por el blog. Dije la última vez que WordPress no traía un sistema anti-spam integrado, y era mentira. Tras investigar un poco veo que trae Akismet, que parece ser una solución muy robusta anti-spam. El problema es que al igual que me pasaba con ReCaptcha, el plugin de Akismet intenta hacer una conexión externa y parece ser el servidor gratuito de FreeHostia no lo permite, por lo que sigo sin poder usar esa opción.

Algo que veo que tienen en común todos los comentarios spam es que no tienen especificado un correo electrónico, cuando es indispensable para mandar un comentario. Por más pruebas que hago no consigo replicar la creación de un comentarios sin correo, lo que me hace pensar que de alguna manera deben estar saltándose alguna de las comprobaciones de wordpress, aunque no intuyo como.

Buscando el momento exacto en el que se guardan los comentarios en la base de datos, parece ser que es en el fichero /wp-includes/comment.php, en el método wp_insert_comment. No se siquiera si es posible que estén llegando hasta este punto evitando algún paso intermedio, pero por si acaso he añadido aquí una comprobación adicional para verificar que el correo del comentario existe y es correcto:

if(!is_email($comment_author_email)){
  return -1;
}

Ahora toca esperar y ver si ha sido efectivo…

ACTUALIZACIÓN 12/12/2011

Aunque el código anterior parecía efectivo, al impedir por completo la creación del nuevo comentario, no había manera de comprobarlo. Si tras unas semanas no aparecía nuevo spam, se podría decir que ha funcionado, pero como quería algo más definitivo, he modificado el código por lo siguiente:

if(!is_email($comment_author_email)){
  $comment_approved = 'spam';
}

Así, lo que hago es permitir que se inserte en la base de datos, pero marcado directamente como spam, y ya ha dado sus frutos, acabo de ver un nuevo comentario de spam etiquetado automáticamente como tal. Se confirma entonces que de alguna manera están evitando el método normal de añadir un comentario en wordpress, y que este código es efectivo en contrarrestarlo mientras no rellenen el campo de correo.

WordPress Error 403 – Forbidden: Access is denied

[internet]

Ayer por la noche terminé de ver el último anime que tenía pendiente de esta temporada, así que me metí en el blog para terminar el artículo con las recomendaciones. Lo escribí sin problemas, pero cuando intentaba previsualizarlo me llevaba a la página principal de Leadhoster. Se que algunos hostings gratuitos no soportan las páginas de error, así que imaginé que debía de estar dando algún error, y aunque me extrañó, no le di mayor importancia.

Termino el artículo, lo publico, y voy a la página principal para ver como ha quedado…. cuando para mi sorpresa me redirige de nuevo a la página del hoster. Claro, la primera impresión es “algo he tocado”. Antes funcionaba y después de publicar, ya no va. Intento mirar si hay algo raro con el artículo, pero es todo normal. Pienso que tal vez es algún plugin, ya que he instalado un par recientemente y los desactivo. Nada, sigue fallando. Tal vez es mi propio plugin, el acordeón de artículos, que con el cambio de mes (coincide que es 1 de octubre) puede estar dando algún error. Lo desactivo pero nada. Pienso en desactivar el resto, pero no veo como pueden estar afectando a la página principal.

Vuelvo a los articulos e intento previsualizar uno de ellos, ¡y funciona! Empiezo a visualizar el resto de artículos y todos funcionan. Puedo mostrar las categorías, puedo moverme por los artículos y el panel de control sigue funcionando sin problemas. El problema afecta únicamente a la página principal.

En la consola de errores de javascript no hay nada, y si es un error de php, no tengo forma de detectarlo. En ese momento me acuerdo del mejor complemento del mundo mundial, ¡el Firebug!

Abro la función de red para ver que peticiones se realizan, y veo que al cargar la página principal salta un error y hace una redirección. Demasiado rápido para leerlo. Reintento y esta vez detengo la carga.

Error 403 – Forbidden: Access is denied WTF! Empiezo a pensar que no va a ser culpa mía…..

Me pongo a buscar en Google el error, y parece bastante común. Las soluciones más planteadas fueron 3:

  1. El fichero o directorio no tiene los permisos adecuados. Hice la comprobación y estaban todos a 755, así que descartado.
  2. El fichero .htaccess está mal. Tal vez se había modificado de alguna manera, pero lo comparé con la copia de seguridad y estaba todo correcto. Descartado.
  3. Un problema con el servidor Apache. Ummm, si este es realmente el problema, teniendo en cuenta que no tengo acceso al servidor, estoy en un callejón sin salida.

Como ninguna de estas alternativas me proporcionaba una solución, opte por mi aproximación favorita a los problemas, ¡MATAR MOSCAS A CAÑONAZOS!

Me pongo a buscar un nuevo hosting, encuentro Freehostia que tiene muy buena pinta (además de un nombre gracioso ¡Hostias gratis para todos!). Subo la copia de seguridad por FTP, exporto/importo la base de datos, cambio los DNS del domino y ¡tachán! Migración express. Y oh! sorpresa! El blog vuelve a funcionar.

Así que ya tengo actualizado el artículo con la comparativa de hostings que hice hace un tiempo.

Usando Fancybox y corrigiendo error en CKEditor usando typeof

[fotografía] [programación]

Quiero empezar a poner más imágenes ilustrando los artículos del blog, así que hace unos días me puse a buscar algún plugin que permitiera ampliar las imágenes de los artículos. Encontré unos cuantos, pero todos eran bastante similares y tampoco encontré muchas demos de funcionamiento. Al final, como el que usa Baratijas Blog me gustaba, pues me he puesto el mismo:

Fancybox plugin para Wordpress

Al instalarlo, me he puesto a hacer pruebas, y en la página principal del blog funcionaba sin problemas, pero al pinchar en alguno de los artículos dejaba de funcionar. Pensaba que podía ser problema del tema, pero al mirar la consola de errores de Javascript, he visto que lo que fallaba era un script del plugin para integrar el CKEditor. El error que me daba era “getUserSetting is not defined” en el fichero ckeditor.utils.js. Es posible que este error ya esté solucionado en las nuevas versiones del plugin, pero como era una chorrada he realizado yo la corrección.

La modificación es sustituir esta línea:

if(ckeditorSettings.autostart && getUserSetting('editor') == 'tinymce'){

Por esta otra:

if(ckeditorSettings.autostart && typeof getUserSetting == 'function' && getUserSetting('editor') == 'tinymce'){

Lo que hacemos con la instrucción typeof es comprobar que el método getUserSetting está definido antes de intentar invocarlo.

Y con esto, ya no salta el error y el lightbox vuelve a funcionar. La prueba de concepto:

Una rosa

[ACTUALIZACIÓN] Al abandonar Wordpress, Fancybox ya no está instalado.

Acordeón Javascript para el listado de artículos

[blog]

Esto es algo que tenía en el viejo blog, y me gustaba por la facilidad que da de ir a alguno de los artículos. Estuve buscando a ver si ya existía un plugin o widget que me ofreciera la funcionalidad, pero no encontré nada, así que lo vi como la oportunidad ideal de aprender a crear widgets para WordPress.

Buscando tutoriales, encontré unos cuantos, pero muchos están desfasados y solo cubren versiones anteriores de WordPress. Otros tantos están incompletos o dan información por supuesta, por lo que no son demasiados útiles para empezar. Al final encontré este que explica paso a paso la creación de un widget funcional.

Siguiendo el tutorial, la creación del widget es muy sencilla, y pude reutilizar la mayor parte del código PHP que tenía para el viejo blog (excepto la obtención de los datos de los artículos que ahora pasa a hacerse a través de la API de WordPress). Lo que no es tan inmediato es la carga del Javascript necesario para el acordeón, ya que hay que usar un hook.

Indicando la URL del script de manera relativa al plugin/widget tal y como se explica en el codex de WordPress:

El resultado sería algo similar a esto:

function load_into_head(){
    echo '<script type="text/javascript" src="'.plugins_url('accordion.js', __FILE__).'"></script>'."n";
    echo '<link rel="stylesheet" href="'.plugins_url('acc-styles.css', __FILE__).'" type="text/css" media="screen" />';
}

add_action('wp_head', 'load_into_head');

Donde estoy cargando tanto el script del acordeón como una hoja con sus estilos en la cabecera de la página donde aparezca el widget.

En cuanto tenga un poco de tiempo limpiaré y comentaré el código y compartiré el widget por si alguien lo quiere utilizar. También me hará falta darle un nombre. De momento se llama “Article Accordion” que no es muy original, aunque es bastante autoexplicativo :P. ¿A alguien se le ocurre un buen nombre?