Archive for the Programming and Scripting Category

A Nautilus shell

We do a lot of development in PHP here at Easytech. Many times you need to test a bit of PHP code. If you played around with python you surely used the python shell. Fortunately the people at Facebook have created a similar shell for PHP (ironically written in python!). You can find it here: http://www.phpsh.org/. From there you can access the GIT repository or download a tgz or zip file.

Currently I couldn’t find a DEB package for Ubuntu. If you want to install it just follow the following steps (you need python installed)

$ cd ~/Devel/PHP (o donde lo quieran tirar)
$ wget http://github.com/facebook/phpsh/tarball/master
$ tar zxvf facebook-phpsh-*
$ cd facebook-phpsh-*
$ sudo python setup.py install

thats it! To test some PHP weirdness…

$ phpsh
Starting php
type ‘h’ or ‘help’ to see instructions & features
php> var_dump( 1 == ‘1′ )
bool(true)
 
php>

Very often when I review other peoples PHP code I come across an old problem: generating a list of comma separated values from a list of things. This happens often when you want to, say, write an SQL query with a WHERE field IN (a,b,c,…,x) and you have an array with a, b, etc.

Another example is when you want to create an include path by concatenating a list of directories with the PATH_SEPARATOR. Yet another example is when you want to build a path concatenating them with the DIRECTORY_SEPARATOR.

The usual code to accomplish looks something like this:

<?php
     // loop through list an generate string
    $line = ;
    foreach( $list as $el ) {
        $line .= $el . ‘,’;
    }

    $line = substr( $line, 0, strlen( $line ) - 1 );
?>
 

(more…)

If you are developing a module for Drupal you might need to use tabs to simplify a bit a screen which has too much functionality. Typically a settings page that might need too many options to comfortably fit on a single screen. Since I had to search and experiment a bit to find out how to do it I decided to write a short post with my findings. In this article I assume you have a basic understanding on writing Drupal modules.

(more…)

Today I needed to generate source code documentation for a webservice APIs we are in coding. One of the guys in the office suggested I take a look at Zend_Reflection. It turns out its quite simple to write PHP code to parse source files and extract the documentation from them. I took a little time to write this sample program.

This program is quite simple: it has a single class called TestClass with one method: addIntegers(). Below this class I wrote a little code which parses the file and then outputs the information. You can use this and a templating system to generate doc. I used it to write the documentation so that we can easily add it to our Wiki.

The script I wrote parses the documentation style used in Zend Framework. Here’s a sample class:

<?php

/**
 * This is a sample test class.
 *
 * This class has only one method: addIntegers() which adds
 * two integers. Its a sample class for our test.
 *
 */

class TestClass
{
    /**
     * This method adds two integers.
     *
     * This method adds the two given integers and returns
     * its sum. If only one integer is given it sums zero.
     *
     * @param int $number1  The first integer
     * @param int $number2  The second integer
     * @return int The sum of $number1 and $number2.
     *
     */

    public function addIntegers( $number1, $number2 = 0 ) {
         return $number1 + $number2;
    }
}

 

Read the rest of the post to see how to easily parse this code…
(more…)

Zend Framework recently introduced the concept of modules so that your applications become more manegable. The application on startup will load the resources defined in the main application.ini file. To configure each module there is a resource called modules that calls the bootstraping code for each module on every request. If you want to load resources on a per module basis you need to write a bootstrap for each module. This can also generate clashes if two modules try to load the same resource. Additionally this process can have a negative impact on your applications performance.

In this blog I propose a different strategy: I created a controller action plugin that will load resources dynamically using the main bootstraping code. The idea is that after the routes are parsed and before the action is executed this code will load the module’s config file and call the bootstrap again so that it will load the resources defined in this config.

This method has several advantages: only the resources for the module that is being called are loaded. Becuase only one config file is read there is no possiblity of clashes.

Here’s the code:

<?php

/**
 * Bootstraps the module used in the current request
 * It merges the options from main application.ini with the options from a
 * module specific application.ini.
 * I’m using the fact that a resources are loaded only once, so a resource
 * declared in main application.ini is initialized there. If you wish to use some resource
 * in every module use the key default (see bellow).
 *
 * The keys default and disable in the main application.ini have a special meaning.
 * default: It is merged initally so a key default.resources.xxx is added as resource.xxx
 *          so it load the resource xxx as a default for all modules
 * disable: It is used to disable keys after merging so a key disable.resources.xxx disables
 *          this resource in all modules.
 */

class Easytech_Controller_Plugin_ModuleBootstrap extends Zend_Controller_Plugin_Abstract
{
    const MODULE_APPLICATION_INI = "configs/application.ini";

    protected $_bootstrap;

    protected $_autoloader;

    public function dispatchLoopStartup( Zend_Controller_Request_Abstract $request )
    {
        $moduleName = $request->getModuleName();
        if ( empty( $moduleName ) ) {
            $moduleName = ‘default’;
        }

        $front = Zend_Controller_Front::getInstance();
        $moduleDir = $front->getModuleDirectory( $moduleName );
        if ( empty( $moduleDir ) ) {
            $moduleDir = APPLICATION_PATH;
        }
       
        // Para ser usado en los ini.
        define(‘MODULE_PATH’, $moduleDir );
        define(‘MODULE_NAME’, $moduleName );

        // Create a autoloader for this module
        $autoloader = new Zend_Application_Module_Autoloader(array(
            ‘namespace’ => $moduleName,
            ‘basePath’  => $moduleDir,
            ));

        $this->_bootstrap = $front->getParam(‘bootstrap’);
        $globalOptions = $this->_bootstrap->getOptions();

        // Default options from main application.ini
        $options = array();
        if ( isset( $globalOptions[‘default’] ) ) {
            $options = $globalOptions[‘default’];
        }
        if ( isset( $globalOptions[ $moduleName ] ) ) {
            $options = $this->_bootstrap->mergeOptions($options, $globalOptions[ $moduleName ]);
        }

        $applicationFile = $moduleDir . DIRECTORY_SEPARATOR . self::MODULE_APPLICATION_INI;
        if ( isset( $globalOptions[ ‘application_file’ ] ) ) {
            $applicationFile  = $moduleDir . DIRECTORY_SEPARATOR . $globalOptions[ ‘application_file’ ];
        }
        $options = $this->_bootstrap->mergeOptions( $options, $this->_loadConfig( $applicationFile ) );
        if ( isset( $globalOptions[‘disable’] ) ) {
            $options = $this->unsetOptions($options, $globalOptions[‘disable’] );
        }
        $this->_bootstrap->setOptions( $options );
        $this->_bootstrap->bootstrap();
    }

    /**
     * Unset options recursively.
     *
     * @param  array $array1
     * @param  mixed $array2
     * @return array
     */

    public function unsetOptions(array $array1, $array2 = null)
    {
        if (is_array($array2)) {
            foreach ($array2 as $key => $val) {
                if ( ! isset( $array1[ $key ] ) ) {
                    continue;
                }
                if ( is_array( $array2[ $key ] ) ) {
                    $array1[ $key ] = $this->unsetOptions( $array1[ $key ], $array2[ $key ]);
                } else {
                    unset( $array1[ $key ] );
                }
            }
        }
        return $array1;
    }

   /**
     * Based heavily on Zend_Application->_loadConfig
     * Load configuration file of options
     *
     * @param  string $file
     * @throws Zend_Application_Exception When invalid configuration file is provided
     * @return array
     */

    protected function _loadConfig($file)
    {
        if (! Zend_Loader::isReadable($file) ) {
            return;
        }
        $environment = $this->_bootstrap->getApplication()->getEnvironment();
        $suffix      = strtolower(pathinfo($file, PATHINFO_EXTENSION));

        switch ($suffix) {
            case ‘ini’:
                $config = new Zend_Config_Ini($file, $environment);
                break;

            case ‘xml’:
                $config = new Zend_Config_Xml($file, $environment);
                break;

            case ‘php’:
            case ‘inc’:
                $config = include $file;
                if (!is_array($config)) {
                    throw new Zend_Application_Exception(‘Invalid configuration file provided; PHP file does not return array value’);
                }
                return $config;
                break;

            default:
                throw new Zend_Application_Exception(‘Invalid configuration file provided; unknown config type’);
                break;
            }
            return $config->toArray();
        }

    }
 

curl es un programa que nos permite transferir datos (o archivos) desde o hasta un servidor, a través de distintos protocolos (entre ellos HTTP, FTP, SCP, etc).

hackers usando curl para testear un SQL injection.





hackers usando curl para testear un SQL injection

Lo interesante (y lo más usado entre los code-monkeys de Easytech) es su uso para emular POSTs a ciertas URLs, sin tener que pasar por la página en el browser.

si no lo tienen, pueden bajarlo del link anterior, aunque tiene fama de estar en todos los repos de las distros conocidas.

En mi caso particular, curl me fue muy útil para hacer un POST a una de las webapps que desarrollamos, y poder chequear el XML que devolvía, sin complicaciones ni pasar por un web-browser.

un PM de Easytech le enseña a un junior a probar sus Forms con curl.















un PM de Easytech le enseña a un junior a probar sus Forms con curl.

empecemos por lo más básico, emular un formulario. esto lo hacemos con curl -F, o curl -d (dependiendo del content-type que querramos usar). La sintáxis sería algo como:

curl -d "nombre_campo1=valor_campo1&amp;nombre_campo2=valor_campo2&amp;nombre_campoN=valor_campoN" url_a_donde_hacemos_el_post.com

Otro uso interesante es el de hacer upload de files, emulando un de un form html. La sintáxis:

curl -F "nombre_del_input=@path_al_file_a_subir" url_a_donde_hacemos_el_post.com

o…

curl -F "nombre_del_input=@path_al_file_a_subir;filename=nombre_del_file" url_a_donde_hacemos_el_post.com

… si queremos un nombre específico para el file.

Nótese que la arroba delante del path del file es obligatoria.

Claro que, lo que yo quería, era ver qué me devolvía la aplicación (en este caso es un upload de un file a un servidor que devolvía un XML con datos). Para hacer esto tenemos varias formas, u opciones, para pasarle al comando curl, como ser –verbose, –trace, o –trace-ascii. Cada una muestra distintas cosas, dependiendo lo que necesitemos. En mi caso, el servidor devolvía el XML con un simple fpassthru, para lo que trace-ascii venía perfecto.

La sintáxis, entonces, sería así:

curl –trace-ascii -F "nombre_del_input=@path_al_file_a_subir;filename=nombre_del_file" url_a_donde_hacemos_el_post.com

la aplicación recibió el file a uploadear como si de un form se tratase, y al devolver el XML, curl lo mostró por stdout. Ideal para debuggear desde la terminal en un servidor remoto o sin tener que pasar por la aplicación web.

Dicen por ahí que también es muy útil para testear vulnerabilidades en algunos sitios con poca validación de formularios, pero eso es demasiado oscuro para mí.

hacker sexy tipea un script con 2 joysticks.












hacker sexy tipea un script con 2 joysticks.

Para ver más ejemplos, consulten acá o en el man de curl, por supuesto.

Un problema recurrente con los sistemas grandes y/o multidominio es mantener la sesion de usuarios entre diferentes dominios.

Es imposible hacerlo con las cookies ya que por cuestiones de seguridad los browser no dejan leer o escribir cookies con diferente dominio al actual.

Lo mismo pasa con las sesiones, si uno accede a una pagina y genera un sesion cuando pasa a otro dominio pierde esa sesion.

La solucion no es nada simple. En el ultimo web and beer se hablo de una solucion, pero esa solucion no me dejo nada convencido, y me quede pensando en la idea.

Actualmente en Easytech estamos trabajando en un proyecto, que inicialmente iba a tener el mismo problema, pero lo solucionamos usando un unico dominio, ya que no era necesario otro. Solo tuvimos que unir varios sistemas, bajo el mismo dominio, pero esto es mucho mas facil, ya que podemos pasar un hash que nos permita buscar la info del usuario en una base de datos o en el file system a traves de las cookies.

Pero este problema de los multidominios tiene solucion, de hecho tenemos un google account, que administra las claves de diferentes dominios, ya sea www.gmail.com, www.google.com, www.youtube.com, www.orkut.com, www.picasaweb.com, etc.. Si google lo resolvio porque no nosotros?

Una manera de resolver este probelma, es guardar los datos de sesion en una base de datos, y los enlaces a los diferentes dominios agregarle el hash que hace de indice en esta base para que pueda regenerar los datos de session. El problema es que si yo accedo directamente a un dominio eso no me va a funcionar muy bien.

Una alternativa a este problema es que todo siempre se redireccione a un dominio, cheque si hay una sesion, y despues redirigirlo, como hace google.

Por ejemplo, cada vez que nosotros accedemos a www.orkut.com, este nos redirecciona a https://www.google.com/accounts/ServiceLogin y envia todos los parametros que necesita para identificar al usuario.

Desde este dominio de autenticacion, generamos la cookie correspondiente con el hash necesario. Y lo volvemos a redireccionar al sitio que quiere acceder con un parametro hash, con el indice para que obtenga los datos.

La solucion parece bastante simple, y creo que lo es pero queria compartirla ya que se me quedo colgada en el ultimo web and beer.

Vamos a ver ahora un ejemplo practico

Yo tengo el dominio www.mail.com, el dominio www.calendar.com, y el dominio de mi empresa que se llama www.cloacas.com.

Un usuario ingresa en www.mail.com, ingresa los datos de su cuenta, este formulario envia un post a http://account.cloacas.com/, valido los datos, genero la autenticacion, y lo redirecciono a http://www.mail.com/?id=1231534232, el dominio mail.com, sabe que tiene que generar la sesion con los datos que va a obtener de la base de datos, con el indice que le paso en id.

Con esto tengo que haber logrado autenticarme en www.mail.com. Ahora el usuario, en otro tab de su browser escribe, www.calendar.com.

Calendar.com, hace lo mismo que www.mail.com, y lo redirecciona a account.cloacas.com, este se fija sino tiene ninguna cookie seteada, y si la tiene busca el hash que guardo en la cookie y la compara con el de la base de datos, si todo esta ok, redirecciona al usuario a www.calendar.com/?id=1231534232, sin la necesidad que el usuario ingrese sus datos, porque ya lo habia hecho en www.mail.com

fuente

Sometimes easytech developers need flying lessons.

After that we got a better kung-fu.

free video player & free video platform
video player, online video, video tools
flv player - video editor - video pluginvideo blog + wordpress plugin + video remix




El concepto de cachear contenido es simple. Cada vez que generamos una pagina con contenido dinamicamente con PHP, lo que hacemos desde el lado del servidor es procesar los .php, estos generalmente tienen cierta logica, para generar el contenido que vamos a mostrar, como buscar en la base datos, llamar algun webservice, y depende el sistema mas o menos cosas. Con Zend_Cache nos evitamos de estos pasos.

Lo que hacemos con Zend_Cache, es generar el html(xml, json, etc) final, y almacenarlo en el file system. De esta manera cada vez que hagamos llamen a nuestra web vamos a llamar a nuestro html final, y no volver a generar el html que generamos en peticiones anteriores. Esto sirve para web donde el contenido no cambia constantemente.

Por ejemplo si tuvieramos un diario, como www.clarin.com.ar donde acceden millones de personas mensualmente, pero sabemos que el unico momento donde se cambia la portada es cuando aparece una nueva nota, aunque las paginas internas siguen siendo las mismas.

Para este caso es ideal algo como Zend_Cache, podemos Cachear toda portada, y cada una de las paginas internas, si desde la administracion se carga una nueva nota, se borra el cache anterior y se genera uno nuevo muy facilmente.

Pero hasta ahora solo vimos la teoria.

Manos a la obra

Lo primero que tenemos que hacer antes de cachear nuestras paginas es configurar como queremos que funcione Zend_Cache. En este ejemplo le vamos a dar un tiempo de vida determinado, vamos a indicarle donde queremos que almacene las paginas cacheadas, y vamos a decirle que actions y vistas queremos que cachee. Este codigo podemos ponerlo en nuestro bootstrap.

<?php

/**
 * You should avoid putting too many lines before the cache section.
 * For example, for optimal performances, "require_once" or
 * "Zend_Loader::loadClass" should be after the cache section.
 */

$frontendOptions = array(
   ‘lifetime’ => 7200,
   ‘debug_header’ => true, // for debugging
   ‘regexps’ => array(
       // cache the whole IndexController
       ‘^/$’ => array(‘cache’ => true),

       // cache the whole IndexController
       ‘^/index’ => array(‘cache’ => true),

       ‘^/home’ => array(‘cache’ => true),
       // we don’t cache the ArticleController…

       // we don’t cache the ArticleController…
       ‘^/news’ => array(‘cache’ => true),

       // we don’t cache the ArticleController…
       

       // … but we cache the "view" action of this ArticleController
       ‘^/news/list/view’ => array(
           ‘cache’ => true
       )
   ),
   ‘default_options’ => array(
           ‘make_id_with_post_variables’ => true,
           ‘make_id_with_cookie_variables’ => true,
           ‘cache_with_cookie_variables’ => true
    )
   
);

$backendOptions = array(
    ‘cache_dir’ => ‘/tmp/zend_cache’
);

// getting a Zend_Cache_Frontend_Page object
$cache = Zend_Cache::factory(‘Page’,
                             ‘File’,
                             $frontendOptions,
                             $backendOptions);
$cache->start();
?>
 

En este ejemplo estamos cacheando los controller news, home, index. Ademas le indicamos que el directorio para los files es /tmp/zend_cache (hay que crearlo!!)

Los tiempos que se reducen dependen de la cantidad de datos que busquemos en la base de datos, webservice, o que dependa de cierta logica.

Para un blog, o un portal con muchos hits diarios esto es indispensable al menos que tengamos hardware de sobra. En este blog yo uso WP-Cache de Ricardo Galli que hace lo mismo que Zend_Cache.

fuente

Cada vez que instanciamos un Zend_Db_Table, ZF hace un describe de la/las tablas que vamos a usar en nuestros query, recolectar esta info consume tiempo y recurso. ZF nos da la posibilidad de Cachear estos datos, usando Zend_Cache. Esto si bien podria estar como default, para reducir bastante los tiempos, no lo esta debido a que si cambiamos el nombre o datos de nuestra tabla, deberiamos limpiar el cache, y para evitar problemas que pueda llegar a generar esto no viene activo por default.

Si queremos hacerlo en nuestro sistema usando Sqllite la forma es muy simple. Basta habilitar sqllite en nuestro php.ini y crear una carpeta para que guarde este cache, podemos elegir la misma ruta que usamos para guardar nuestras paginas con Zend_Cache, todo esto es totalmente personalizable.

El codigo para que guarde la metada lo tenemos que aplicar antes de instanciar cualquier modelo, esto lo podemos hacer desde el bootstrap, pero tambien hay otras formas, cada uno puede implementar la forma que mas le convenga.

Los datos a continuacion tenemos que guardarlos en nuestro archivo de configuracion, yo uso los .ini en el ejemplo
config.ini
[metadata_cache]
frontend.automatic_serialization = true
frontend.lifetime = 3600
; Lugar donde vamos a guardar el cache
backend.cache_db_complete_path= “/tmp/zend_cache_db”

Y este es el codigo que deberia ir en nuestro bootstrap

bootstrap.php

<?php
// ... Configuracion inicial

// ... Ahora configuramos el cache
$cache = Zend_Cache::factory( 'Core', 'Sqlite', metadata_cache->frontend, $config->metadata_cache->backend );
$cache->clean( Zend_Cache::CLEANING_MODE_ALL );
Zend_Db_Table_Abstract::setDefaultMetadataCache( $cache );
?>

Enlaces

Documentacion oficial de Zend_Db_Table
Documentacion de webinar sobre acceso a la base de datos con Zend Db