• Category Archives Programari
  • Actualitzar automàticament la revisió/data/autor en fer commit a subversion

    Si recentment escrivia l’entrada sobre la comanda find amb la possibilitat de fer diferents cerques simultànies, avui explico un cas on ho he usat.

    Alguna vegada haureu vist en fitxers amb codi font (siguin del llenguatge de programació que siguin), que a la part superior apareix informació sobre què conté el fitxer, la seva llicència, o l’autor, la data i el número de revisió dels darrers canvis que ha patit el fitxer en qüestió. En referència a aquestes tres darreres em refereixo a una línia d’aquest estil:

    $Id: codi.php 148 2006-07-28 21:30:43Z jaume $

    Evidentment aquestes dades no són escrites a mà per l’autor cada vegada que fa un canvi al fitxer (una nova revisió), sinó que es realitza automàticament; i concretament aquest és el format que utilitza subversion per la variable Id. En realitat jo havia escrit $Id$ allà on he volgut del fitxer anomenat codi.php, i en fer el commit al dipòsit el sistema ho ha substituït per la línia completa que veieu a dalt. Id és una combinació reduïda de les paraules clau $Author$, $Revision$ i $Date$, que també podeu utilitzar de forma independent. Al manual de subversion (en anglès) podeu llegir més al respecte. Si volem que tots els fitxers del nostre projecte que tinguem al sistema de control de versions subversion incorporin aquesta funcionalitat, hem de configurar el servidor de certa manera. Editem el fitxer /etc/subversion/config (aquest és el camí a Ubuntu, però serà similar a altres distribucions). Per defecte enable-auto-props està comentat, ho deixem així:

    ### Set enable-auto-props to 'yes' to enable automatic properties
    ### for 'svn add' and 'svn import', it defaults to 'no'.
    ### Automatic properties are defined in the section 'auto-props'.
    enable-auto-props = yes
    

    I una mica més avall editem les propietats automàtiques:

    ### Section for configuring automatic properties.
    [auto-props]
    ### The format of the entries is:
    ###   file-name-pattern = propname[=value][;propname[=value]...]
    ### The file-name-pattern can contain wildcards (such as '*' and
    ### '?').  All entries which match (case-insensitively) will be
    ### applied to the file.  Note that auto-props functionality
    ### must be enabled, which is typically done by setting the
    ### 'enable-auto-props' option.
    *.php = svn:eol-style=native;svn:keywords=Author Date Id Revision
    *.txt = svn:eol-style=native;svn:keywords=Author Date Id Revision
    *.sh  = svn:eol-style=native;svn:keywords=Author Date Id Revision;svn:executable
    *.tpl = svn:eol-style=native
    *.css = svn:eol-style=native
    *.js  = svn:eol-style=native
    *.htm = svn:eol-style=native
    *.html = svn:eol-style=native
    *.htaccess = svn:eol-style=native
    *.png = svn:mime-type=image/png
    *.jpg = svn:mime-type=image/jpeg
    *.gif = svn:mime-type=image/gif
    

    Jo he definit que només els fitxers amb l’extensió php, txt i sh tinguin la capacitat de substitució de paraules clau. A més a més els .sh vull que siguin executables (de manera que si algú fa un check out el propi subversion s’encarregui de marcar el bit d’execució per nosaltres). I si us hi fixeu, la resta de fitxers de text tenen una altra propietat: svn:eol-style=native. Això fa referència al final de línia (en anglès, eol = end of line), i serveix per què vàries persones treballin sobre els mateixos fitxers en sistemes operatius diferents (els quals usen diferents caràcters per indicar el final de línia). Les tres darreres línies són pels fitxers d’imatge, cadascun amb el seu tipus mime corresponent.

    Un cop fet això, ens assegurem que els fitxers nous que agreguem al dipòsit tindran aquestes propietats, però què passa amb els fitxers existents? Cal que els donem les propietats nosaltres manualment, i aquí entra la potència de la comanda find. I si ho podem fer tot d’una sola passada millor 🙂 Ens situem al directori arrel del nostre projecte i executem:

    find . \
    \( -name '*.php' -exec svn propset svn:eol-style native {} \; -exec svn propset svn:keywords 'Author Date Id Revision' {} \; \) , \
    \( -name '*.txt' -exec svn propset svn:eol-style native {} \; -exec svn propset svn:keywords 'Author Date Id Revision' {} \; \) , \
    \( -name '*.sh'  -exec svn propset svn:eol-style native {} \; -exec svn propset svn:keywords 'Author Date Id Revision' {} \; -exec svn propset svn:executable {} \; \) , \
    \( -name '*.tpl' -exec svn propset svn:eol-style native {} \; \) , \
    \( -name '*.css' -exec svn propset svn:eol-style native {} \; \) , \
    \( -name '*.js' -exec svn propset svn:eol-style native {} \; \) , \
    \( -name '*.htm' -exec svn propset svn:eol-style native {} \; \) , \
    \( -name '*.html' -exec svn propset svn:eol-style native {} \; \) , \
    \( -name '.htaccess' -exec svn propset svn:eol-style native {} \; \) , \
    \( -name '*.png' -exec svn propset svn:mime-type 'image/png' {} \; \) , \
    \( -name '*.jpg' -exec svn propset svn:mime-type 'image/jpeg' {} \; \) , \
    \( -name '*.gif' -exec svn propset svn:mime-type 'image/gif' {} \; \) > /dev/null
    

    I això és tot, a programar de gust! 😉

    GD Star Rating
    loading...

  • Cerca amb la comanda find de GNU/Linux

    Fins ara, sempre que havia de cercar diferents tipus de fitxers i/o directoris amb la comanda find, executava una comanda de forma independent per a cada cosa. Però això no és gens òptim, perquè cerquem una i altra vegada per tots els fitxers desitjats. Fa uns dies vaig aprendre com cercar vàries coses alhora, en una sola cerca, de manera que se li puguin indicar a find diferents patrons. Aquí mostro l’exemple que apareix al manual (que es pot accedir amb la comanda: man find), escrit en multilínia per fer-lo més entenidor (recordo també que per canviar de línia a la shell abans de pitjar la tecla retorn o enter cal acabar la línia amb un espai i una barra invertida \):

    find / \
    \( -perm -4000 -fprintf /root/suid.txt %#m %u %p\n \) , \
    \( -size +100M -fprintf /root/big.txt %-10s %p\n \)
    

    Recorre el sistema una única vegada, llistant fitxers i directoris amb setuid al fitxer /root/suid.txt i fitxers grans (majors de 100 MB) al fitxer /root/big.txt.

    Un exemple més fàcil d’entendre:

    find . \
    \( -name '*.php' -exec echo "Trobat fitxer PHP:" {} \; \) , \
    \( -name '*.exe' -exec rm -f {} \; -exec echo "Eliminat fitxer .exe:" {} \; \) , \
    \( -name '*.txt' -exec ls -l {} \; \)
    

    Al primer patró busquem els fitxers el nom dels quals acabi amb ‘.php’ i mostrem una frase per la sortida estàndard, al segon eliminem fitxers ‘.exe’ i informem de l’acció, i al tercer llistem informació de fitxers ‘.txt’ en un format llarg.

    Podeu veure que a més a més es poden executar vàries comandes per cada patró de cerca. En el segon patró, executem dues comandes amb l’opció -exec: la primera per eliminar els fitxers trobats i la segona per informar què hem fet.

    Bon profit.

    GD Star Rating
    loading...

  • Error javascript provocat pel plugin Ozh’ Admin Drop Down Menu de WordPress

    No sé si hi ha alguna incompatibilitat entre els plugins RB Internal Linker i Ozh’ Admin Drop Down Menu de WordPress, però ahir vaig actualitzar el primer a la versió 2.0.11 i ara està fallant. El problema l’he detectat amb Firebug (quina eina més meravellosa!), que mostrava el següent error de javascript:

    syntax error
    var oam_toomanypluygins = ;\n

    He cercat directament al directori de plugins quin fitxer contenia aquest nom de variable, des d’una connexió ssh al servidor, així:

    egrep -r oam_toomanypluygins *

    Han sortit tres resultats. El problema es troba al fitxer ozh-admin-drop-down-menu/inc/core.php, a la funció en llenguatge PHP wp_ozh_adminmenu_js().
    A la línia:

    $toomanyplugins = $wp_ozh_adminmenu['too_many_plugins'];

    veiem que la variable PHP $toomanyplugins és assignada i més endavant inserida directament entre codi javascript. Ràpidament ens podem adonar que si la variable és buida s’introduïrà un error al codi javascript perquè faltarà algun valor entre els caràcters = i ;

    var oam_toomanypluygins = ;

    Per resoldre-ho, després de la línia PHP anteriorment esmentada he afegit:

    if (empty($toomanyplugins)) {
        $defaults = wp_ozh_adminmenu_defaults();
        $toomanyplugins = $defaults['too_many_plugins'];
    }
    

    D’aquesta manera comprovem si la variable és buida i li donem el valor per defecte abans d’inserir-la entre codi javascript.

    Resolt! 🙂

    Actualització (01-03-2010): a vegades les coses serveixen per més persones, per això és bo compartir. El desenvolupador del plugin m’ha contestat:

    Hello Jaume
    Nice catch, thanks for this! I’ve updated the plugin to deal with this case
    Cheers,
    Ozh

    GD Star Rating
    loading...

  • Fi de la Drupal Camp Barcelona 2010

    logo drupal camp spain barcelona 2010

    Aquest migdia ha acabat la Drupal Camp Barcelona 2010. Després de les sis ponències que vaig escoltar ahir, avui he decidit assistir a les següents:

    La que més m’ha agradat avui ha estat la primera, d’en Daniel Primo Gorgoso.

    GD Star Rating
    loading...

  • Drupal Camp Barcelona 2010

    Ahir va començar la Drupal Camp Barcelona 2010, el major esdeveniment anual organitzat per i pels amants de Drupal a Espanya. Jo vaig ser dels tres primers en inscriure’m-hi i ahir ja em vaig perdre el primer dia per culpa de passar hores al metge. Però avui, malgrat anar enguixat i amb crosses, sí que assistiré a totes les ponències que pugui. Som-hi!!

    Actualitzo (27-02-2010): finalment he assistit a totes les ponències de la sala auditori, la gran. Han estat:

    La tercera és la que més m’ha agradat, realitzada per César Martin, sobretot pel seu dinamisme i la quantitat d’exemples que ha comentat.

    GD Star Rating
    loading...

  • Com obtenir el Pagerank (PR) d’una uri des de PHP

    Primer de tot, per aquells qui no sapigueu de què parlo, us poso la definició de Pagerank de la Viquipèdia:

    PageRank és l’algorisme que utilitza Google per determinar la posició d’una pàgina web a l’hora de fer una consulta mitjançant el seu motor de cerca. Aquest mètode mesura el seu grau d’importància de forma numèrica i permet situar els resultats més fiables en primer lloc. Alhora, reflecteix la probabilitat que hi ha de que un usuari que navega a través d’enllaços de forma aleatòria arribi a una pàgina web concreta.

    Doncs bé, he trobat un script en el llenguatge de programació PHP que permet obtenir el Pagerank . L’he transformat en una classe i aquí el teniu:

    <?php
    
    /**
     * PageRank Lookup class v1.1 by HM2K (update: 31/01/2007)
     * based on an algorithm found here: http://pagerank.gamesaga.net/
     * @author HM2K
     * @version 1.1
     * @see http://pagerank.gamesaga.net/
     */
    class Pagerank
    {
        //settings - host and user agent
        private static $googlehost = 'toolbarqueries.google.com';
        private static $googleua   = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5';
    
        /**
         * Convert a string to a 32-bit integer
         */
        private function strToNum($Str, $Check, $Magic)
        {
            $Int32Unit = 4294967296;  // 2^32
    
            $length = strlen($Str);
            for ($i = 0; $i < $length; $i++) {
                $Check *= $Magic;
                //If the float is beyond the boundaries of integer (usually +/- 2.15e+9 = 2^31),
                //  the result of converting to integer is undefined
                //  refer to http://www.php.net/manual/en/language.types.integer.php
                if ($Check >= $Int32Unit) {
                    $Check = ($Check - $Int32Unit * (int) ($Check / $Int32Unit));
                    //if the check less than -2^31
                    $Check = ($Check < -2147483648) ? ($Check + $Int32Unit) : $Check;
                }
                $Check += ord($Str{$i});
            }
            return $Check;
        }
    
        /**
         * Genearate a hash for a url
         * @param string $String
         */
        private function hashURL($string)
        {
            $check1 = self::strToNum($string, 0x1505, 0x21);
            $check2 = self::strToNum($string, 0, 0x1003F);
    
            $check1 >>= 2;
            $check1 = (($check1 >> 4) & 0x3FFFFC0 ) | ($check1 & 0x3F);
            $check1 = (($check1 >> 4) & 0x3FFC00 ) | ($check1 & 0x3FF);
            $check1 = (($check1 >> 4) & 0x3C000 ) | ($check1 & 0x3FFF);
    
            $T1 = (((($check1 & 0x3C0) << 4) | ($check1 & 0x3C)) <<2 ) | ($check2 & 0xF0F );
            $T2 = (((($check1 & 0xFFFFC000) << 4) | ($check1 & 0x3C00)) << 0xA) | ($check2 & 0xF0F0000 );
    
            return ($T1 | $T2);
        }
    
        /**
         * Genearate a checksum for the hash string
         * @param string $hashnum
         */
        private function checkHash($hashnum)
        {
            $checkByte = 0;
            $flag = 0;
    
            $HashStr = sprintf('%u', $hashnum) ;
            $length = strlen($HashStr);
    
            for ($i = $length - 1;  $i >= 0;  $i --) {
                $Re = $HashStr{$i};
                if (1 === ($flag % 2)) {
                    $Re += $Re;
                    $Re = (int)($Re / 10) + ($Re % 10);
                }
                $checkByte += $Re;
                $flag ++;
            }
    
            $checkByte %= 10;
            if (0 !== $checkByte) {
                $checkByte = 10 - $checkByte;
                if (1 === ($flag % 2) ) {
                    if (1 === ($checkByte % 2)) {
                        $checkByte += 9;
                    }
                    $checkByte >>= 1;
                }
            }
    
            return '7'.$checkByte.$HashStr;
        }
    
        /**
         * Return the pagerank checksum hash
         * @param string $url
         */
        private function getCh($url)
        {
            return self::checkHash(self::hashURL($url));
        }
    
        /**
         * Return the pagerank figure
         * @param string $url
         */
        public function getPagerank($url)
        {
            $googlehost = self::$googlehost;
            $googleua   = self::$googleua;
            $ch         = self::getCh($url);
            $fp         = fsockopen($googlehost, 80, $errno, $errstr, 30);
            if ($fp) {
                $out = "GET /search?client=navclient-auto&ch=$ch&features=Rank&q=info:$url HTTP/1.1\r\n";
                //echo "<pre>$out</pre>\n"; //debug only
                $out .= "User-Agent: $googleua\r\n";
                $out .= "Host: $googlehost\r\n";
                $out .= "Connection: Close\r\n\r\n";
    
                fwrite($fp, $out);
    
                //$pagerank = substr(fgets($fp, 128), 4); //debug only
                //echo $pagerank; //debug only
                while (!feof($fp)) {
                    $data = fgets($fp, 128);
                    //echo $data;
                    $pos = strpos($data, "Rank_");
                    if($pos === false){} else{
                        $pr=substr($data, $pos + 9);
                        $pr=trim($pr);
                        $pr=str_replace("\n",'',$pr);
                        return $pr;
                    }
                }
                //else { echo "$errstr ($errno)<br />\n"; } //debug only
                fclose($fp);
            }
        }
    
        /**
         * Generate the graphical pagerank
         * @param $url
         * @param $width
         * @param $method
         */
        public function getGraphicalPagerank($url,$width=40,$method='style')
        {
            if (!preg_match('/^(http:\/\/)?([^\/]+)/i', $url))
            {
                $url='http://'.$url;
            }
            $pr=self::getPagerank($url);
            $pagerank="PageRank: $pr/10";
    
            //The (old) image method
            if ($method == 'image') {
                $prpos=$width*$pr/10;
                $prneg=$width-$prpos;
                $html='<img src="http://www.google.com/images/pos.gif" width='.$prpos.' height=4 border=0 alt="'.$pagerank.'"><img src="http://www.google.com/images/neg.gif" width='.$prneg.' height=4 border=0 alt="'.$pagerank.'">';
            }
            //The pre-styled method
            if ($method == 'style') {
                $prpercent=100*$pr/10;
                $html='<div style="position: relative; width: '.$width.'px; padding: 0; background: #D9D9D9;"><strong style="width: '.$prpercent.'%; display: block; position: relative; background: #5EAA5E; text-align: center; color: #333; height: 4px; line-height: 4px;"><span></span></strong></div>';
            }
    
            $out='<a href="'.$url.'" title="'.$pagerank.'">'.$html.'</a>';
            return $out;
        }
    
    }
    

    Per usar-la només cal el següent:

    require 'Pagerank.php';
    
    echo Pagerank::getPagerank('google.com');
    

    L’exemple mostrarà: 10

    Podeu baixar-vos el fitxer amb el codi font fent clic aquí.

    Que aprofiti!

    GD Star Rating
    loading...

  • Actualització a WordPress 2.9.1

    L’altre dia va ocórrer algun problema en actualitzar automàticament —des de la zona d’administració— el blog de WordPress de la versió 2.9.0 en català a la 2.9.1 també en català. Apareixia un missatge tot indicant que tornés a intentar-ho, però en repetir el procés es quedava igual, el problema persistia.

    Avui he baixat la versió 2.9.1 completa de WordPress en català (http://ca.wordpress.org/), l’he pujada al servidor on allotjo el blog per sftp, m’hi he connectat per ssh, i l’he descomprimida. A continuació he seguit els passos que indiquen a http://codex.wordpress.org/Upgrading_WordPress_Extended i ara sí, ja tinc la darrera versió sense cap error.

    GD Star Rating
    loading...

  • Compilació de ffmpeg

    Avui he compilat el programa ffmpeg per habilitar el suport de mp3 i amr amb el gcc 4.4.1. El que ve per defecte a Kubuntu no inclou aquests còdecs perquè no són lliures. Després de baixar el seu codi font primer he hagut d’instal·lar alguns paquets extres tot teclejant a la consola:

    sudo apt-get install libmp3lame-dev libamrnb-dev libamrwb-dev

    I a continuació:

    ./configure --extra-version=4:0.5+svn2010122-jau --prefix=/usr --enable-avfilter --enable-avfilter-lavf --enable-vdpau --enable-bzlib --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --disable-stripping --disable-vhook --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdc1394 --extra-cflags=-I/build/buildd/ffmpeg-0.5+svn2010122-jau/debian/include --enable-shared --disable-static --disable-mmx --enable-nonfree --enable-libamr-nb --enable-libamr-wb  --enable-libmp3lame --enable-libxvid --enable-libx264
    
    make

    Com podeu veure he aprofitat per incloure el còdec xvid. I ja tinc la versió: FFmpeg 0.5-4:0.5+svn2010122-jau 🙂

    GD Star Rating
    loading...

  • Hack al header.php del tema de WordPress Mandingo

    El tema per a WordPress Mandingo té la funcionalitat de poder excloure certes pàgines del menú superior; aquestes es poden configurar des de l’administrador, a la secció del tema. El que no permet és triar quines en volem incloure al menú. Per no haver de marcar cada nova pàgina que creem, i evitar així que aparegui al menú superior, podem fer un petit canvi de funcionalitat: en lloc de marcar les que no volem, marcarem les que sí que volem.

    A més a més hem de fer un petit canvi al codi font del tema. Editem el fitxer:

    themes/mandigo/header.php

    Busquem la crida a la funció PHP:

    wp_list_pages

    I a la línia

    'exclude' => @implode(',', $mandigo_options['header_navigation_exclude_pages']),

    canviem ‘exclude’ per ‘include‘. Desem el fitxer i ja hem acabat.

    D’aquesta manera, només haurem de treballar quan vulguem modificar el menú superior, i no sempre que creem pàgines noves 🙂

    GD Star Rating
    loading...