Archive for June 2009


Concatenar o separar segmentos de documentos PDF

June 30th, 2009 — 9:55pm

Cómo concatenar archivos PDF ?

$ pdftk (<archivos a concatenar>)+ cat output <archivo resultante>

$ pdftk a.pdf b.pdf c.pdf cat output all.pdf

Cómo extraer un segmento de un archivo PDF ?

$ pdftk (NOMBRE=archivo.pdf)+ cat (NOMBRE{RangoInicial}-{RangoFinal})+ output <archivo resultante>

$ pdftk A=one.pdf B=two.pdf cat A1-5 B10-20 output section.pdf

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Linux/Solaris/BSD, Software

“Entrepreneurs can change the world”

June 30th, 2009 — 9:02pm

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Personal

Los componentes en Yii

June 30th, 2009 — 4:30pm

Introducción.

  • Son objetos escritos basados en una especificación.
  • Heredan de la clase CComponent.
  • Es posible acceder y modificar sus propiedades así como lanzar y manejar sus eventos.

Propiedades.

  • Son atributos públicos de lectura y escritura.
  • Pueden definirse de dos maneras.
    • Declarando un atributo público en el componente.
      • En este caso el nombre de la propiedad es sensible a mayúsculas.
    • Definiendo los métodos setter y getter correspondientes.
      • En este caso el nombre de la propiedad no es sensible a mayúsculas.
      • Para implementar la propiedad imageType es necesario implementar los siguientes métodos.
        public function getImageType()
        {
            return $this -> _imageType;
        }
        
        public function setImageType($value)
        {
            $this -> _imageType = $value;
        }
      • Este método es mas flexible ya que permite definir una lógica del negocio que condicione el acceso a las propiedades.
      • De igual manera es posible implementar propiedades de sólo lectura (sin setter) o de sólo escritura (sin getter).

Eventos.

  • Los eventos del componente son propiedades que toman referencias a métodos (event handlers) como valores.
  • Estos métodos son invocados automáticamente cuando sucede el evento asociado.
  • Un evento del componente es definido por la implementación de un método cuyo nombre empieza por on y termina con el nombre del evento asociado (no es sensible a mayúsculas).
    • Para el evento click -> el método deberá ser entonces: onClicked.
      public function onClicked($event)
      {
          // ...
      }
  • Los eventos ($event) son instancias de la clase CEvent.
  • Los manejadores de evento se asginan de la siguiente manera.
    $component -> onClicked = $callback;
    • $callback deberá ser una referencia válida en PHP según las siguientes opciones.
      • El nombre de una función global.
      • Un método de una clase, para este caso deberá ser de la forma array($objeto, ‘nombreMétodo’).
  • Varios manejadores de evento pueden asociarse a un mismo evento, estos se ejecutarán en el orden en que fueron creados.
  • Un manejador de eventos puede evitar que se invoquen los demás manejadores de eventos al realizar la siguiente modificación.
    $event -> handled = true;

Comportamientos.

  • Un comportamiento es un objeto cuyos métodos pueden ser transferidos a los componentes que se le agreguen.
  • Es decir, reune funcionalidades en lugar de realizar una especialización como lo hace la herencia convencional.
  • Es posible agregar múltiples comportamientos lo que se asemeja a la herencia múltiple.
  • Son análogos a los mixins que incluyen otros lenguajes orientados a objetos (como Ruby) o que implementan otros frameworks (como Symfony).
  • Existen varias maneras de implementar un comportamiento.
    • Como una clase que implementa a la interfaz IBehavior.
    • Como una clase que hereda de CBehavior.
    • Si va a ser agregado a un modelo puede ser una clase que herede de CModelBehavior o CActiveRecordBehavior según corresponda.
  • Para utilizar un comportamiento primero debe ser agregado a un componente.
    $comportamiento -> attach($nombre, $componente);
    $componente -> métodoDelComportamiento();
  • Los comportamientos pueden ser activados y desactivados según se desee en cada componente.
    $componente -> enableBehavior($nombre);
    $componente -> disableBehavior($nombre);
  • Si dos o mas comportamientos agregados a un componente entran en conflicto porque tienen métodos con igual nombre, la precedencia la tendrá el comportamiento que haya sido agregado primero.

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

2 comments » | Desarrollo de software, Web

Los módulos en Yii

June 30th, 2009 — 11:03am

Introducción.

  • Son unidades autocontenidas de software.
  • Tienen sus propios modelos, vistas, controladores y demás componentes de soporte.
  • Se asemejan a una aplicación pero no pueden ser desplegados individualmente, deben residir como parte de  una aplicación.
  • Los usuarios acceeden a los controladores de los módulos de la misma forma como se acceden los controladores convencionales.
  • Son útiles para dividir el desarrollo y mantenimiento de aplicaciones muy grandes en módulos independientes.
  • Facilitan la reutilización de código a alto nivel.
  • Se utilizan para implementar funcionalidades como autenticación, manejo de usuarios, manejo de comentarios, etc.

Estructura.

  • Cada módulo tiene una clase principal que hereda de CWebModule.
  • El nombre de la clase se determina de la siguiente manera: ucfirst(IdentificadorMódulo) . ‘Module’.
    • Ejemplo, la clase del módulo gallery debe llamarse GalleryModule.
  • Esta clase se utiliza para almacenar información y características que son comúnes a todo el módulo.
    • CWebModule::params almacena los parámetros del módulo.
    • CWebModule:: components comparte componentes de aplicación a nivel del módulo.

Creación.

Utilizando yiic.

yiic permite crear fácilmente un esqueleto básico del módulo para empezar a trabajar sobre él.

$ cd WebRoot/MiAplicacion
$ protected/yiic shell

Yii Interactive Tool v1.0
Please type ‘help’ for help.  Type ‘exito’ to quit.

>> module gallery

Uso.

  • Copie el directorio del módulo en el directorio modules de la aplicación.
  • Declare el módulo (con su identificador) en la propiedad modules de la configuración de la aplicación de la siguiente manera.
    return array (
        // ...
        'modules' => array('gallery', /* ... */),
        // ...
    );
  • Es posible especificar valores iniciales para las propiedades del módulo de la siguiente manera.
    return array (
        // ...
        'modules' => array(
            'gallery' => array(
                'fileType' => 'png',
                'rows' => 10,
                'cols' => 3
            ),
            /* ... */
         ),
        // ...
    );
  • La instancia del módulo puede ser accedida a través de la propiedad module del controlador acrivo.
    $rows = Yii::app() -> controller -> module -> rows;
  • Los módulos se acceden con la ruta módulo/controlador/acción.
    • Para el ejemplo, gallery/image/add corresponderá entonces con el URL http://www.servidor.com/index.php?r=gallery/image/add.
  • Un módulo puede contener a su vez a otros módulos los cuales pueden ser accedidos de manera similar: móduloPadre/móduloHijo/controlador/acción.

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Desarrollo de software, Web

Plantillas para documentos XHTML y otros recursos web

June 29th, 2009 — 12:43am

En el sitio de WebStandards se puede encontrar un listado con las plantillas base para los documentos XHTML 1.0/1.1 y HTML4.

Además de estos documentos encontré otros recursos interesantes relacionados con el desarrollo web.

http://www.webstandards.org/learn/tutorials/accessible-forms/

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Desarrollo de software, Web

Remover estilos CSS por defecto

June 28th, 2009 — 10:08pm

Introducción.

El primer paso para desarrollar cualquier interfaz de usuario basada en HTML debería ser el remover los estilos introducidos por defecto por el navegador web, con esto podríamos estar [un poco mas] seguros que los estilos implementados van a tener un igual comportamiento entre los diferentes tipos de navegadores web.

Hacer esto es muy fácil, sólo es necesario incluír el siguiente estilo provisto por Yahoo! al inicio de la hoja de estilos principal (la primera que se carga).

/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:

http://developer.yahoo.net/yui/license.txt

version: 2.7.0
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}

Otra forma de hacerlo es simplemente hacer una referencia a esta hoja de estilos desde los servidores de Yahoo!.

<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/reset-fonts-grids/reset-fonts-grids.css">

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Desarrollo de software, Web

Agregar soporte de MP3 en Ubuntu 9.04

June 24th, 2009 — 12:14pm

Introducción.

Por defecto, la instalación de Ubuntu no incluye el soporte para el formato MP3 así que sólo es posible codificar archivos en formato OGG que es mejor pero la gran mayoría de los reproductores [físicos] de audio aún no lo soportan.  Por suerte la instalación del soporte para el formato es muy sencilla.

Instalación.

$ sudo aptitude install gstreamer0.10-plugins-ugly-multiverse

Extracción y codificación de MP3.

Iniciar Applications > Sound & Video > Rhythmbox Music Player.

Configurar a Rhythmbox para que se utilice a MP3 como formato por defecto.

Seleccionar el menú Edit > Preferences y seleccione la etiqueta Music.

En el campo Preferred format elija la opción CD Quality, MP3 (.mp3 type).

MusicPreferences

Si desea modificar la calidad del archivo MP3 generado realice los siguientes pasos adicionales.  Por defecto se generan con un bitrate de 128 Kbps.

Presione el botón Edit para modificar el formato seleccionado: MP3.

Seleccione el perfil CD Quality, MP3 o cree uno nuevo.  Presione el botón Edit del diálogo.

Modifique el campo GStreamer pipeline con la siguiente cadena.

audio/x-raw-int,rate=44100,channels=2 ! lame name=enc mode=0 vbr-quality=6 bitrate=192 ! id3v2mux

Edite los valores de las variables rate, channels y bitrate según sus preferencias.

Seleccione las canciones que se desean codificar.

Presione el botón de extracción: ExtractButton

Los archivos de las canciones codificadas se almacenan en la ubicación especificada en las preferencias bajo Library Location > Music files are placed in, cuya ruta es por defecto: ~/Music.

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

1 comment » | Linux/Solaris/BSD, Software

Creación de contenido traducido en Drupal 6

June 24th, 2009 — 10:42am

Introducción.

Este procedimiento permite mantener diferentes tipos de contenido en Drupal 6 traducido en los diferentes idiomas que soporta el Portal.  En esta versión, a diferencia de la versión 5, el módulo que permite esto se incluye en la distribución de core.

Configuración.

Activar el módulo de traducción de contenido.

  • Acceder a http://www.servidor.com/?q=admin/build/modules.
  • Activar el módulo Content translation encontrado en la sección opcional de core.

Asignar los permisos de traducción.

  • Acceder a http://www.servidor.com/?q=admin/user/permissions.
  • Asignar el permiso Translation > traducir contenido a los roles que estarán encargados de realizar la traducción de los contenidos.

Determinar los idiomas soportados por el portal.

  • Acceder a http://www.servidor.com/?q=admin/settings/language.
  • Agregar los idiomas necesarios además del idioma predefinido para el sitio.

Determinar cuales tipos de contenido tendrán traducción.

  • Acceder a http://www.servidor.com/?q=admin/content/types.
  • Elegir los tipos que tendrán contenido traducido.
  • Editar los tipos.
  • En la sección Workflow settings > Multilingual support seleccionar la casilla de verificación Habilitado con traducción.
  • Guardar.

En mi caso personal elegí los siguientes tipos de contenido para tener traducción: Evento, Noticia, Página, Página de grupo, Tema de foro y Enlaces web.

Activar el bloque para cambio de idiomas (opcional).

  • Acceder a http://www.servidor.com/?q=admin/build/block.
  • Activar y ubicar donde se desee al bloque Language switcher.

Utilización.

Después de realizado este el procedimiento de configuración, los tipos de contenido configurados para tal fin tendrán un nuevo campo llamado Idioma el cual permitirá elegir entre Lenguaje neutral y Español (o el idioma predeterminado elgido anteriormente).

Para acceder a la traducción del contenido es necesario editar el contenido inicial y seleccionar a Español como idioma.  Al guardar este contenido aparece una nueva opción llamada Traducción (Translate) a través de la cual es posible seleccionar cualquiera de los demás idiomas configurados para crear la traducción del contenido inicial.

Cuando se consulta un nodo este muestra con enlaces cuales son las traducciones que se encuentran disponibles y permite acceder a ellas, de igual manera es posible modificar el idioma del sitio utilizando el bloque de cambio de idioma.

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

1 comment » | Software, Web

Las vistas en Yii

June 23rd, 2009 — 12:25am

Introducción.

  • Son archivos PHP convencionales.
  • Pueden incluír elementos de interfaz de usuario basados en Yii.
  • Se recomienda que las vistas accedan a la información de los modelos pero que no los modifiquen.
  • Deben permanecer lo mas simples posibles, lógicas complejas deberían llevarse hasta el controlador.
  • El nombre del archivo donde se almacena la vista corresponde con el identificador junto con la extensión .php.
    • La vista edit se almacenará en el archivo edit.php.
  • Los archivos de las vistas se almacenan bajo la ruta protected/views/<Identificador del controlador>.
  • Desde la vista es posible acceder a los atributos del controlador a través del objeto $this.
  • Para procesar una vista se debe invocar el método CController::render(<Identificador de vista>).
  • Es posible pasar explícitamente información desde el controlador a la vista en el momento de su generación.
    $this -> render('edit', array (
        'variable1' => $valor1,
        'variable2' => $valor2
    ));
    • En la vista edit se podrá acceder a $variable1 y $variable2 como variables convencionales.

Layouts (diseños).

  • El layout permite especificar el diseño común y constante de la interfaz de usuario.
  • Evita la necesidad de agregar elementos comúnes (archivos javascript y css, título, subtítulo, menú izquierdo, pies, etc) a todas las páginas en cada una de ellas.
  • El layout aplica a todo el sitio web y se aplica automáticamente al invocar el método render.
  • Para generar una vista sin el layout es necesario utilizar el método renderPartial.
  • El layout utilizado por defecto se encuentra en views/layouts/main.php.
    • Es posible modificar esto alterando CWebApplication::layout para toda la aplicación o CController::layout para todas las acciones del controlador.
  • En el layout se debe incluír la variable $content para especificar la ubicación en la que se agregará el contenido de la vista específica al controlador/acción ejecutado (parte no constante de la interfaz de usuario).

Widgets.

  • Los widgets son componentes predefinidos para la presentación de la interfaz de usuario.
  • Generalmente agregan una funcionalidad gráfica compleja, específica y autocontenida.
  • Heredan de CWidget.
  • Su forma de invocarlos depende de si tienen o no contenido en su cuerpo.
    • Sin contenido en su cuerpo.
      <? php $this -> widget('ruta.a.la.ClaseWidget'); ?>
    • Con contenido en su cuerpo.
      <? php $this -> beginWidget('ruta.a.la.ClaseWidget'); ?>
      ... contenido del cuerpo del Widget ...
      <? php $this -> endWidget(); ?>
  • Es posible definir valores iniciales para los atributos del Widget durante su invocación con widget o beginWidget.
    $this -> widget('CMaskedTextField', array (
        'mask' => '99/99/9999'
    ));

Creación de nuevos Widgets.

  • El nuevo widget debe heredar de CWidget e implementar los métodos init y run.
    class NuevoWidget extends CWidget
    {
        public function init()
        {
            // Invocado por CController::beginWidget().
        }
    
        public function run()
        {
            // Invocado por CController::endWidget().
        }
    }
  • Tienen sus propias vistas y se ubican por defecto en el directorio views bajo el directorio que contiene la clase del widget.
  • Estas vistas se generan invocando CWidget::render().

Vistas del sistema.

  • Estas vistas se utilizan para mostrar errores del sistema o información de registro.
  • Las excepciones de HTTP (CHTTPException) se despliegan con las vistas errorXXX donde XXX es el código del error HTTP generado.
  • Las vistas por defecto provistas por Yii se ubican en framework/views y pueden personalizarse definiéndolas en protected/views/system.

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Desarrollo de software, Web

Video institucional de Armenia, Quindío, Colombia.

June 22nd, 2009 — 11:43pm

Enlaces.

VN:F [1.8.5_1061]
Rating: 0 (from 0 votes)

Comment » | Personal

Back to top