<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>easytech blog</title>
	<atom:link href="http://blog.easytech.com.ar/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.easytech.com.ar</link>
	<description>sharing knowledge</description>
	<lastBuildDate>Tue, 05 Feb 2013 06:41:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Testing webservices circa 2013</title>
		<link>http://blog.easytech.com.ar/2013/02/05/testing-webservices-circa-2013/</link>
		<comments>http://blog.easytech.com.ar/2013/02/05/testing-webservices-circa-2013/#comments</comments>
		<pubDate>Tue, 05 Feb 2013 06:40:56 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=834</guid>
		<description><![CDATA[google_ad_client = "pub-5177142273878832"; google_ad_channel =""; google_ad_width = 468; google_ad_height = 60; google_ad_format = "468x60_as"; google_ad_type = "text_image"; google_color_border = "CCCCCC"; google_color_link = "000000"; google_color_text = "333333"; google_color_bg = "CCCCCC"; google_color_url = "666666"; Back in 2009, our Leandro (a.k.a TatooKa) wrote an awesome post on how to use curl to do POSTs and other HTTP magic. [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2013/02/05/testing-webservices-circa-2013/' data-shr_title='Testing+webservices+circa+2013'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2013/02/05/testing-webservices-circa-2013/' data-shr_title='Testing+webservices+circa+2013'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Back in 2009, our Leandro (a.k.a TatooKa) wrote an <a href="http://blog.easytech.com.ar/2009/01/12/haciendo-posts-con-curl/">awesome post</a> on how to use curl to do POSTs and other HTTP magic. Back then curl was the way to go when you wanted to do command line HTTP GET/POST/PUT. Nowadays there&#8217;s a simpler and more modern variation: <a href="https://github.com/jkbr/httpie">httpie</a>.</p>
<p>To install on Ubuntu just do: </p>
<p><code>$ sudo apt-get install httpie</code></p>
<p>Once installed, you can do a simple HTTP POST with form variables like so:</p>
<p><code>$ http --form POST api.myservice.com/auth/login username=guest password=secretpassword<br />
</code><br />
as a response you would get something like this (a JSON response in this case):</p>
<p><a href="http://blog.easytech.com.ar/wp-content/uploads/httpie-sample.png" rel="thumbnail"><img src="http://blog.easytech.com.ar/wp-content/uploads/httpie-sample.png" alt="" title="A sample output of a Webservice returning a JSON object." width="620" height="446" class="aligncenter size-full wp-image-838" /></a></p>
<p>As you can see the response is much cleaner: there&#8217;s color coding showing you the response headers, the body is detected to be a JSON object and its nicely formatted. To see many other cool examples go to its page on Github: <a href="https://github.com/jkbr/httpie">https://github.com/jkbr/httpie</a></p>
<div class="shr-publisher-834"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2013/02/05/testing-webservices-circa-2013/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Script to read Drupal Planet RSS</title>
		<link>http://blog.easytech.com.ar/2012/09/20/script-read-drupal-planet-rss/</link>
		<comments>http://blog.easytech.com.ar/2012/09/20/script-read-drupal-planet-rss/#comments</comments>
		<pubDate>Fri, 21 Sep 2012 02:54:54 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=817</guid>
		<description><![CDATA[google_ad_client = "pub-5177142273878832"; google_ad_channel =""; google_ad_width = 120; google_ad_height = 240; google_ad_format = "120x240_as"; google_ad_type = "text_image"; google_color_border = "CCCCCC"; google_color_link = "000000"; google_color_text = "333333"; google_color_bg = "CCCCCC"; google_color_url = "666666"; I was playing around and wanted to have a command line interface script to see the latest titles from Drupal Planet. I wipped [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2012/09/20/script-read-drupal-planet-rss/' data-shr_title='Script+to+read+Drupal+Planet+RSS'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2012/09/20/script-read-drupal-planet-rss/' data-shr_title='Script+to+read+Drupal+Planet+RSS'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>I was playing around and wanted to have a command line interface script to see the latest titles from Drupal Planet. I wipped this Python script to read and display the RSS feed. You need to install feedparser (in Ubuntu: <code>$ <strong>sudo aptitude install python-feedparser</strong></code>). Here&#8217;s the code:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> feedparser<br />
&nbsp; &nbsp;<br />
<span class="kw1">def</span> color<span class="br0">&#40;</span>this_color, <span class="kw3">string</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&quot;<span class="es0">\0</span>33[&quot;</span> + this_color + <span class="st0">&quot;m&quot;</span> + <span class="kw3">string</span> + <span class="st0">&quot;<span class="es0">\0</span>33[0m&quot;</span><br />
&nbsp; <br />
<span class="kw1">print</span><br />
<span class="kw1">print</span> color<span class="br0">&#40;</span><span class="st0">&#8217;34&#8242;</span>, <span class="st0">&#8216;-&#8217;</span> * <span class="nu0">70</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> color<span class="br0">&#40;</span><span class="st0">&#8217;1;34&#8242;</span>, <span class="st0">&#8216; &#8216;</span> * <span class="nu0">10</span> + <span class="st0">&#8216;D R U P A L &nbsp; &nbsp;/ &nbsp; P L A N E T&#8217;</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> color<span class="br0">&#40;</span><span class="st0">&#8217;34&#8242;</span>, <span class="st0">&#8216;-&#8217;</span> * <span class="nu0">70</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span><br />
&nbsp; <br />
python_wiki_rss_url = <span class="st0">&quot;http://drupal.org/planet/rss.xml/&quot;</span> <br />
feed = feedparser.<span class="me1">parse</span><span class="br0">&#40;</span> python_wiki_rss_url <span class="br0">&#41;</span><br />
&nbsp; <br />
<span class="kw1">for</span> item <span class="kw1">in</span> feed<span class="br0">&#91;</span><span class="st0">&#8216;items&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> color<span class="br0">&#40;</span><span class="st0">&#8217;30&#8242;</span>, <span class="st0">&#8216; &gt;&gt; &#8216;</span><span class="br0">&#41;</span> + color<span class="br0">&#40;</span><span class="st0">&#8217;1;37&#8242;</span>, item<span class="br0">&#91;</span><span class="st0">&#8216;title&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> + <span class="st0">&#8216;<span class="es0">\n</span> &nbsp; &nbsp;&#8217;</span> + color<span class="br0">&#40;</span><span class="st0">&#8217;32&#8242;</span>, item<span class="br0">&#91;</span><span class="st0">&#8216;link&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <br />
&nbsp;</div>
<p>To run it:</p>
<p><code>$ python planet.py</code></p>
<p>You can save it in <code>~/bin</code> and create an alias with: <code>$ alias planet='python ~/bin/planet.py'</code> and execute it simply from the CLI with: <code>$ planet</code></p>
<p>Here&#8217;s how it looks:</p>
<p><a href="http://blog.easytech.com.ar/wp-content/uploads/drupal_planet1.png" rel="thumbnail"><img src="http://blog.easytech.com.ar/wp-content/uploads/drupal_planet1.png" alt="" title="drupal_planet" width="908" height="423" class="aligncenter size-full wp-image-821" /></a></p>
<div class="shr-publisher-817"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2012/09/20/script-read-drupal-planet-rss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The &#8216;drush cc all&#8217; syndrome</title>
		<link>http://blog.easytech.com.ar/2012/06/07/drush-cc-all-syndrome/</link>
		<comments>http://blog.easytech.com.ar/2012/06/07/drush-cc-all-syndrome/#comments</comments>
		<pubDate>Thu, 07 Jun 2012 04:21:29 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=798</guid>
		<description><![CDATA[If you use drush and code modules/templates in Drupal you know the symptom: add a new template file, add a hook to your module, pretty much change a few things in your code and you issue a drush cc all &#8216;just in case&#8217;. Drupal has an extensive cache system which is your friend but unfortunately when [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2012/06/07/drush-cc-all-syndrome/' data-shr_title='The+%27drush+cc+all%27+syndrome'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2012/06/07/drush-cc-all-syndrome/' data-shr_title='The+%27drush+cc+all%27+syndrome'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><img class="alignleft size-full wp-image-807" style="border: 1px solid #C0C0C9; border-radius: 5px;" title="d7-contributor-cloud-huge" src="http://blog.easytech.com.ar/wp-content/uploads/d7-contributor-cloud-huge1.png" alt="" width="280" height="322" />If you use drush and code modules/templates in Drupal you know the symptom: add a new template file, add a hook to your module, pretty much change a few things in your code and you issue a <strong>drush cc all</strong> &#8216;just in case&#8217;. Drupal has an extensive cache system which is your friend but unfortunately when coding you often have to clear it so that the new changes can be detected. This constant &#8216;clear all caches&#8217; can really slow you down. On large sites a drush cc all can take as long as 15-20 seconds to complete. If you are not sure your overriding the correct template or hook then it can become a little annoying  to waste so much time.</p>
<p>As you probably know, Drupal has more than one cache. Wouldn&#8217;t it be great if you could just clear the cache which you know needs to be cleared and avoid clearing the others which don&#8217;t have an impact? It turns out you can! The only problem is knowing what modifications go into what cache. You could spend some time going through core but it&#8217;s probably easier to do it by trial and error. Because of this issue I decided to experiment a little in my latest projects and waste a little more time to compile a list of drush cc commands and when you should issue them. Here&#8217;s what I have so far:</p>
<div>$ <strong>drush cc menu</strong>&nbsp;</p>
<ul>
<li>modify or add your  <em>hook_menu()</em> module function</li>
<li>modify or add your  <em>hook_menu_alter()</em></li>
</ul>
<p>$ <strong>drush cc registry</strong></p>
<ul>
<li>modify or add your <em>hook_form_alter()</em></li>
<li>Add a new hook to your module. For example: <em>hook_node_save()</em></li>
</ul>
<p>$ <strong>drush cc theme_registry</strong></p>
<ul>
<li>Add a new <em>.tpl.php</em> file to a theme theme</li>
</ul>
</div>
<p>$ <strong>drush cc css-js</strong></p>
<ul>
<li>If you have turned on CSS and JS aggregation you can use this to regenerate the aggregated CSS and JS.</li>
</ul>
<p>That&#8217;s what I have so far. It&#8217;s been a real time saver for me. If you have other <strong>drush cc xxxx</strong> commands to share leave a note and I&#8217;ll add them to the post. Maybe later I&#8217;ll add a page to the drush page at drupal.org</p>
<h4>Credits</h4>
<ul>
<li>Thanks to Hjalmar from <a href="http://nodeone.se">Nodeone</a> for the <em>drush cc css-js</em> tip!</li>
</ul>
<div class="shr-publisher-798"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2012/06/07/drush-cc-all-syndrome/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ssh tunnel and a half</title>
		<link>http://blog.easytech.com.ar/2011/07/11/ssh-tips/</link>
		<comments>http://blog.easytech.com.ar/2011/07/11/ssh-tips/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 20:20:24 +0000</pubDate>
		<dc:creator>lucas</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[tunnel]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=658</guid>
		<description><![CDATA[&#160; As you all might know ssh is a very popular protocol used to connect to remote shells. I mostly use OpenSSH as a client (I think most of you to). SSH has a lot of cool options but in this post i&#8217;m going to write about how to use it to create a secure [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2011/07/11/ssh-tips/' data-shr_title='ssh+tunnel+and+a+half'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2011/07/11/ssh-tips/' data-shr_title='ssh+tunnel+and+a+half'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>&nbsp;</p>
<div id="attachment_702" class="wp-caption alignleft" style="width: 291px"><a href="http://blog.easytech.com.ar/wp-content/uploads/trinity-nmapscreen-hd-crop-1200x728.jpg" rel="thumbnail"><img class="size-full wp-image-702    " title="trinity-nmapscreen-hd-crop-1200x728" src="http://blog.easytech.com.ar/wp-content/uploads/trinity-nmapscreen-hd-crop-1200x728.jpg" alt="" width="281" height="262" /></a><p class="wp-caption-text">Using ssh to shut down lights <img src='http://blog.easytech.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p></div>
<p>As you all might know ssh is a very popular protocol used to connect to remote shells. I mostly use <a href="http://www.openssh.org/" target="_blank">OpenSSH</a> as a client (I think most of you to). SSH has a lot of cool options but in this post i&#8217;m going to write about how to use it to create a secure tunnel.</p>
<p><strong>What is a tunnel?</strong></p>
<p>A tunnel specifies a given port on the local (client) host that is to be forwarded to the given host and port on the remote side. How it works? This works by allocating a socket to listen to a port on the local side, optionally bound to the specified bind_address.  Whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to the port from the remote machine.<span id="more-658"></span><strong> </strong></p>
<p><strong>Making the tunnel</strong></p>
<p>Before type the command line to create the ssh tunnel I&#8217;m assuming the following topology</p>
<p><a href="http://blog.easytech.com.ar/wp-content/uploads/ssh_tunnel1.png" rel="thumbnail"><img class="aligncenter size-full wp-image-687" title="ssh_tunnel" src="http://blog.easytech.com.ar/wp-content/uploads/ssh_tunnel1.png" alt="" width="478" height="213" /></a>If I would like to connect to 192.168.0.2 db server and the database is a postgresql, then the default port is 5432 and the tunnel command line is:</p>
<pre>$ ssh -L 5432:192.168.0.2:5432 &lt;user&gt;@&lt;web server&gt;
     _____^______     ______^______
    / local port \   / remote port \</pre>
<p>If you are running a postgresql in your own machine you can chose another port to listen in your loop back. I always have a pgsql running in my laptop because I use it in most of my developments and I use port 5435.</p>
<pre>$ ssh -L <strong>5435</strong>:192.168.0.2:5432 &lt;user&gt;@&lt;web server&gt;

============================================================
 from other terminal
============================================================

$ psql -h localhost -p 5435 -U db_user -d db_name
Welcome to psql 7.3.4, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
 \h for help with SQL commands
 \? for help on internal slash commands
 \g or terminate with semicolon to execute query
 \q to quit

db_bame=#</pre>
<p>You can make a tunnel to many ports at the same time.</p>
<pre>$ ssh -L 543<strong>5</strong>:192.168.0.2:5432 -L 543<strong>6</strong>:192.168.0.3:5432 &lt;user&gt;@&lt;web server&gt;

or

$ ssh -L 543<strong>5</strong>:192.168.0.2:5432 -L 2222:192.168.0.2:22 &lt;user&gt;@&lt;web server&gt;

then try to connect to ssh remote service using the tunnel

$ ssh -p 2222 user@localhost</pre>
<p>SSH tunnel is something very useful in my life. I hope this post helps you to make it useful for you to.</p>
<p><strong>and a half &#8230;</strong></p>
<p>Many router or firewall (statefuls for example)  try to clean up dead connections, that means that they are looking  if no data was trasmited in the last N secs, and then asumes that connection is no longer in use. For example I go to get some cofe and when I come back to my desk I see this in my monitor:</p>
<pre>lucas@megara:~$ Read from remote host megara.easytech.com.ar:
Connection reset by peer
Connection to megara.easytech.com.ar closed.  

%$#&amp;*@#$^!@#&amp;*$#%^!#@<strong> &lt;- my thoughts</strong></pre>
<p>I hate when this happens and more if I have all my tunnels created. I way to fix this is enabling the keep-alive option. What this does, essentially is every N seconds, the client sends a small  <a href="http://tools.ietf.org/html/rfc1122#page-101">keep-alive</a> packet to the server to make it look like the ssh connection  is being actively used.</p>
<p>To enable  all your ssh connections to send a keep-alive packet you just have to add the following lines to your ~/.ssh/config file:</p>
<pre>KeepAlive <span style="color: #3366ff;">yes</span>
<span style="color: #808000;">ServerAliveInterval</span> <span style="color: #ff0000;">60</span></pre>
<p>In most cases this option is very useful but if the connection is down and the keep-alive packet is sent the SSH will disconnect you, so you have to be careful in witch scenarios use this option.</p>
<p>There are many other options to play with but I would like to recommending you take a look at ssh multiplexing and how to use ssh as a proxy ( see the <a href="http://store.2600.com/summer2011.html" target="_blank">2600 summer 2011</a> for a very good article about this).</p>
<p><a href="http://twitter.com/lucasmingarro" target="_blank">@lucasmingarro</a></p>
<div class="shr-publisher-658"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2011/07/11/ssh-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>nice to meet you</title>
		<link>http://blog.easytech.com.ar/2011/05/31/lanubecita-nuevo-blog/</link>
		<comments>http://blog.easytech.com.ar/2011/05/31/lanubecita-nuevo-blog/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 02:56:57 +0000</pubDate>
		<dc:creator>lucas</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=660</guid>
		<description><![CDATA[Hace aproximadamente un año atras decidimos que en algún momento ibamos a arrancar con un nuevo emprendimiento, al cual bautizamos a modo de juego, lanubecita. El tiempo fue pasando y lanubecita se fue haciendo cada vez más real. La diferencia puntual entre lo que hacemos en easytech vs lanubecita es que en el primero hacemos [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class=\'shareaholic-fblike\' data-shr_layout=\'button_count\' data-shr_showfaces=\'false\' data-shr_href=\'http://blog.easytech.com.ar/2011/05/31/lanubecita-nuevo-blog/\' data-shr_title=\'nice+to+meet+you\'></a><a class=\'shareaholic-googleplusone\' data-shr_size=\'medium\' data-shr_count=\'true\' data-shr_href=\'http://blog.easytech.com.ar/2011/05/31/lanubecita-nuevo-blog/\' data-shr_title=\'nice+to+meet+you\'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://blog.easytech.com.ar/wp-content/uploads/Screen-shot-2011-05-31-at-7.16.11-PM.png" rel="thumbnail"><img class="alignleft size-full wp-image-664" title="Screen shot 2011-05-31 at 7.16.11 PM" src="http://blog.easytech.com.ar/wp-content/uploads/Screen-shot-2011-05-31-at-7.16.11-PM.png" alt="" width="266" height="266" /></a>Hace aproximadamente un año atras decidimos que en algún momento ibamos a arrancar con un nuevo emprendimiento, al cual bautizamos a modo de juego, lanubecita.</p>
<p>El tiempo fue pasando y lanubecita se fue haciendo cada vez más real.</p>
<p>La diferencia puntual entre lo que hacemos en easytech vs lanubecita es que en el primero hacemos desarrollos a medida para nuestros clientes y en lanubecita desarrollamos aplicaciones web que  vamos a comercializar como servicios (SaaS).</p>
<p><span id="more-660"></span>Con la intención de compartir nuestros pensamientos y lo que vayamos experimentando mientras transitamos por este nuevo startup, es que anoche creé un blog usando posterus, el cual me convenció por los lindos themes que tiene y  cuyo url es <a title="blog de la nubecita" href="http://blog.lanubecita.com" target="_blank">http://blog.lanubecita.com</a></p>
<p>nice to meet you.</p>
<div style="padding:7px; display: block; margin-left: auto; margin-right: auto; text-align: center;"><script type="text/javascript">
    	google_ad_client = "pub-5177142273878832"; 
    	google_ad_channel ="";
    	google_ad_width = 728; google_ad_height = 90;
		google_ad_format = "728x90_as"; google_ad_type = "text_image";
		google_color_border = "CCCCCC";
		google_color_link = "000000";
		google_color_text = "333333";
		google_color_bg = "CCCCCC";
		google_color_url = "666666"; 
		</script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></div><div class="shr-publisher-660"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2011/05/31/lanubecita-nuevo-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing with TermKit in Linux with Chrome</title>
		<link>http://blog.easytech.com.ar/2011/05/21/playing-with-termkit-with-chrome/</link>
		<comments>http://blog.easytech.com.ar/2011/05/21/playing-with-termkit-with-chrome/#comments</comments>
		<pubDate>Sat, 21 May 2011 16:36:58 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=607</guid>
		<description><![CDATA[TermKit is graphical replacement for the old Unix terminal developed by Steven Wittens. It is based on the WebKit HTML rendering engine used in Safari and Chrome. The only &#8216;problem&#8217; with TermKit is that you need a Mac with OS X to use it. Since we are Linux users we wanted to at least give [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class=\'shareaholic-fblike\' data-shr_layout=\'button_count\' data-shr_showfaces=\'false\' data-shr_href=\'http://blog.easytech.com.ar/2011/05/21/playing-with-termkit-with-chrome/\' data-shr_title=\'Playing+with+TermKit+in+Linux+with+Chrome\'></a><a class=\'shareaholic-googleplusone\' data-shr_size=\'medium\' data-shr_count=\'true\' data-shr_href=\'http://blog.easytech.com.ar/2011/05/21/playing-with-termkit-with-chrome/\' data-shr_title=\'Playing+with+TermKit+in+Linux+with+Chrome\'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://acko.net/blog/on-termkit"></a><a href="http://blog.easytech.com.ar/wp-content/uploads/termkit2.png" rel="thumbnail"><img class="alignleft size-full wp-image-626" title="termkit2" src="http://blog.easytech.com.ar/wp-content/uploads/termkit2.png" alt="" width="336" height="203" /></a><a href="http://acko.net/blog/on-termkit">TermKit</a> is graphical replacement for the old Unix terminal developed by <a href="http://acko.net/">Steven Wittens</a>. It is based on the WebKit HTML rendering engine used in Safari and Chrome. The only &#8216;problem&#8217; with TermKit is that you need a Mac with OS X to use it. Since we are Linux users we wanted to at least give it a try and found that you can test it using Chrome. In this post I cleaned up the instructions for testing TermKit on a machine with Ubuntu.</p>
<p><span id="more-607"></span>The idea is detailed in this fork at Github: <a href="https://github.com/Floby/TermKit/commit/2e18c8d622443a671a626a7815006ce187743ea2">https://github.com/Floby/TermKit/commit/2e18c8d622443a671a626a7815006ce187743ea2</a>.</p>
<p>Make sure you have <strong>git, libssl-dev </strong>and <strong>Google Chrome</strong> installed. To install git and libssl-dev do: <strong>sudo aptitude install git libssl-dev</strong> and <strong>sudo aptitude install google-chrome-beta</strong> will install Google Chrome.</p>
<p>With those two installed (most developers already have them) then follow these commands to build <strong>Node.js</strong>, <strong>npm</strong> and finally run TermKit. To compile this you may need to include other dependencies but in my machine they were already installed.</p>
<p>The following steps will create a directory called TermKitProj in your home directory and install everything you need inside it.</p>
<pre>$ cd ~
$ mkdir TermKitProj
$ cd TermKitProj
$ git clone https://github.com/joyent/node.git
$ cd node
$ ./configure
$ make</pre>
<p>wait a while until Node compiles &#8230;</p>
<pre>$ sudo make install
$ cd ..
$ git clone http://github.com/isaacs/npm.git
$ cd npm
$ sudo make install</pre>
<p>wait a little more &#8230;</p>
<pre>$ cd ..
$ git clone https://github.com/Floby/TermKit.git --recursive
$ cd TermKit/
$ npm install
$ node Node/nodekit.js</pre>
<p>The last command starts the backend in your terminal. You should see something like this:</p>
<pre>miquel@inspire:~/Develop/TermKitProj/TermKit$ <strong>node Node/nodekit.js</strong>
21 May 13:10:27 - Your node instance does not have root privileges. This means that the flash XML policy file will be served inline instead of on port 843. This will slow down initial connections slightly.
21 May 13:10:27 - socket.io ready - accepting connections
server listening at http://localhost:2222
21 May 13:10:41 - Initializing client with transport "websocket"
21 May 13:10:41 - Client 8840208831243217 connected
worker:  config @{}@</pre>
<p>Once this is running fireup Chrome and open this URL: <a href="http://localhost:2222">http://localhost:2222</a> and you should see something like this:</p>
<p style="text-align: center;"><a href="http://blog.easytech.com.ar/wp-content/uploads/termkit1.png" rel="thumbnail"><img class="size-full wp-image-622 aligncenter" title="TermKit running in Chome in Linux" src="http://blog.easytech.com.ar/wp-content/uploads/termkit1.png" alt="" width="595" height="372" /></a></p>
<div class="shr-publisher-607"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2011/05/21/playing-with-termkit-with-chrome/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Guick Support Ticket System &#124; First Shot</title>
		<link>http://blog.easytech.com.ar/2011/05/19/guick-support-ticket-system-first-shot/</link>
		<comments>http://blog.easytech.com.ar/2011/05/19/guick-support-ticket-system-first-shot/#comments</comments>
		<pubDate>Thu, 19 May 2011 06:57:15 +0000</pubDate>
		<dc:creator>lucas</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Help Desk]]></category>
		<category><![CDATA[lanubecita]]></category>
		<category><![CDATA[mesa de ayuda]]></category>
		<category><![CDATA[soporte]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=561</guid>
		<description><![CDATA[Some time ago we begin to need something to manage our clients requirements because it was  already a very high entropy. After some research (that means google) we were unable to find a simple app that fit our needs. At this point  Cesar decided to implement Drupal + Support Ticket System module. As always this module had not [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2011/05/19/guick-support-ticket-system-first-shot/' data-shr_title='Guick+Support+Ticket+System+%7C+First+Shot'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2011/05/19/guick-support-ticket-system-first-shot/' data-shr_title='Guick+Support+Ticket+System+%7C+First+Shot'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><div class="jLanguage">
<ul>
<li><a href="?lan=english"><img alt="english" src="http://blog.easytech.com.ar/wp-content/plugins/jLanguage/icons/en.png" /></a></li>
<li><a href="?lan=spanish"><img alt="spanish" src="http://blog.easytech.com.ar/wp-content/plugins/jLanguage/icons/es.png" /></a></li>
</ul>
</div>
<p>Some time ago we begin to need something to manage our clients requirements because it was  already a very high entropy. After some research (that means google) we were unable to find a simple app that fit our needs. At this point  <a href="http://www.linkedin.com/in/cesarmiquel">Cesar</a> decided to implement Drupal + Support Ticket System module.</p>
<p><a href="http://blog.easytech.com.ar/wp-content/uploads/screen-shot-2011-05-19-at-41105-am.png" rel="thumbnail"><img class="size-full wp-image-576 alignnone" style="margin-top: 10px; margin-bottom: 10px;" title="screen-shot-2011-05-19-at-41105-am" src="http://blog.easytech.com.ar/wp-content/uploads/screen-shot-2011-05-19-at-41105-am.png" alt="" width="707" height="324" /></a>As always this module had not all we needed and as always we finished  changing the module&#8217;s code, creating new views and a lot of Drupal <a href="http://drupal.org/documentation/theme" target="_blank">theming</a> to get a better functionality and a better UI to the way we work. Since then  we have been using it (2 years actually) we very good results.</p>
<p><span id="more-561"></span>Check out how guick looks like right now.</p>
<p style="text-align: left;"><a href="http://blog.easytech.com.ar/wp-content/uploads/guickapp-01.png" rel="thumbnail"><img class="aligncenter size-full wp-image-651" title="guickapp-01" src="http://blog.easytech.com.ar/wp-content/uploads/guickapp-01.png" alt="" width="853" height="736" /></a><a href="http://blog.easytech.com.ar/wp-content/uploads/guickapp-02.png" rel="thumbnail"><img class="aligncenter size-full wp-image-652" title="guickapp-02" src="http://blog.easytech.com.ar/wp-content/uploads/guickapp-02.png" alt="" width="848" height="794" /></a>After a lot of iterations and improvements over the this time and seeing that our clients (we also) are very happy with this app we started thinking about selling it. For this purpose we called this application <strong>guick </strong>and we build a pre-launch page in the following url <a href="http://guickapp.com" target="_blank">http://guickapp.com</a> to collect some email addresses. btw I thought it would take 4 or 5 hours but as always I was wrong (3 days actually).</p>
<p>&nbsp;Some feedback will be welcome and not be shy and type your email address if you are interested</p>
<p><a href="https://twitter.com/lucasmingarro">@lucasmingarro</a></p>
<div class="shr-publisher-561"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2011/05/19/guick-support-ticket-system-first-shot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Error reporting in PHP scripts</title>
		<link>http://blog.easytech.com.ar/2010/12/02/error-reporting-in-php-scripts/</link>
		<comments>http://blog.easytech.com.ar/2010/12/02/error-reporting-in-php-scripts/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 03:50:41 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming and Scripting]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=542</guid>
		<description><![CDATA[It often happens that you are trying to debug a PHP script running from command line or a part of your code and the script mysteriously dies. Depending on your server configuration (or command line) errors may be being silently being hidden. In those cases I recommend you add the following lines to your code [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2010/12/02/error-reporting-in-php-scripts/' data-shr_title='Error+reporting+in+PHP+scripts'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2010/12/02/error-reporting-in-php-scripts/' data-shr_title='Error+reporting+in+PHP+scripts'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>It often happens that you are trying to debug a PHP script running from command line or a part of your code and the script mysteriously dies. Depending on your server configuration (or command line) errors may be being silently being hidden. In those cases I recommend you add the following lines to your code to guarantee that all errors, notices, etc will be printed. </p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">&lt;?php</span></p>
<p>&nbsp;<span class="co1">// set error reporting para que reporte TODO</span><br />
&nbsp;<a href="http://www.php.net/error_reporting"><span class="kw3">error_reporting</span></a><span class="br0">&#40;</span><span class="kw2">E_ALL</span><span class="br0">&#41;</span>;<br />
&nbsp;<a href="http://www.php.net/ini_set"><span class="kw3">ini_set</span></a><span class="br0">&#40;</span><span class="st0">&#8216;display_errors&#8217;</span>, <span class="st0">&#8216;On&#8217;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp;<span class="co1">// The rest of your code &#8230;</span><br />
&nbsp;</div>
<p>This post is really for reference since most PHP developers already know this &#8230; </p>
<div class="shr-publisher-542"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2010/12/02/error-reporting-in-php-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A PHP Shell</title>
		<link>http://blog.easytech.com.ar/2010/07/02/a-php-shell/</link>
		<comments>http://blog.easytech.com.ar/2010/07/02/a-php-shell/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:34:37 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming and Scripting]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=515</guid>
		<description><![CDATA[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: [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class=\'shareaholic-fblike\' data-shr_layout=\'button_count\' data-shr_showfaces=\'false\' data-shr_href=\'http://blog.easytech.com.ar/2010/07/02/a-php-shell/\' data-shr_title=\'A+PHP+Shell\'></a><a class=\'shareaholic-googleplusone\' data-shr_size=\'medium\' data-shr_count=\'true\' data-shr_href=\'http://blog.easytech.com.ar/2010/07/02/a-php-shell/\' data-shr_title=\'A+PHP+Shell\'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://blog.easytech.com.ar/wp-content/uploads/20080426-perfect-halved-nautilus-shell.jpg" rel="thumbnail"><img class="size-full wp-image-525   alignleft" style="margin: 0 15px 0 0;" title="A Nautilus shell" src="http://blog.easytech.com.ar/wp-content/uploads/20080426-perfect-halved-nautilus-shell.jpg" alt="A Nautilus shell" width="128" height="108" /></a></p>
<p>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.</p>
<p>Currently I couldn&#8217;t find a DEB package for Ubuntu. If you want to install it just follow the following steps (you need python installed)</p>
<div class="dean_ch" style="white-space: wrap;">$ cd ~/Devel/PHP (o donde lo quieran tirar)<br />
$ wget http://github.com/facebook/phpsh/tarball/master<br />
$ tar zxvf facebook-phpsh-*<br />
$ cd facebook-phpsh-*<br />
$ sudo python setup.py install</div>
<p>thats it! To test some PHP weirdness&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">$ phpsh<br />
Starting php<br />
type &#8216;h&#8217; or &#8216;help&#8217; to see instructions &amp;amp; features<br />
php&gt; var_dump( 1 == &#8217;1&#8242; )<br />
bool(true)<br />
&nbsp;<br />
php&gt;</div>
<div class="shr-publisher-515"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2010/07/02/a-php-shell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exploding and imploding&#8230;</title>
		<link>http://blog.easytech.com.ar/2010/04/24/exploding-and-imploding/</link>
		<comments>http://blog.easytech.com.ar/2010/04/24/exploding-and-imploding/#comments</comments>
		<pubDate>Sat, 24 Apr 2010 04:42:05 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming and Scripting]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=496</guid>
		<description><![CDATA[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,&#8230;,x) and you have an array with a, b, etc. Another [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class=\'shareaholic-fblike\' data-shr_layout=\'button_count\' data-shr_showfaces=\'false\' data-shr_href=\'http://blog.easytech.com.ar/2010/04/24/exploding-and-imploding/\' data-shr_title=\'Exploding+and+imploding...\'></a><a class=\'shareaholic-googleplusone\' data-shr_size=\'medium\' data-shr_count=\'true\' data-shr_href=\'http://blog.easytech.com.ar/2010/04/24/exploding-and-imploding/\' data-shr_title=\'Exploding+and+imploding...\'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://blog.easytech.com.ar/wp-content/uploads/php_src.png" rel="thumbnail"><img class="size-full wp-image-506 alignright" title="PHP source icon" src="http://blog.easytech.com.ar/wp-content/uploads/php_src.png" alt="" width="128" height="128" /></a>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 <em>WHERE field IN (a,b,c,&#8230;,x)</em> and you have an array with a, b, etc.</p>
<p>Another example is when you want to create an include path by concatenating a list of directories with the <em>PATH_SEPARATOR</em>. Yet another example is when you want to build a path concatenating them with the <em>DIRECTORY_SEPARATOR</em>.</p>
<p>The usual code to accomplish looks something like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; &nbsp;<span class="co1">// loop through list an generate string</span><br />
&nbsp; &nbsp; <span class="re0">$line</span> = <span class="st0">&#8221;</span>;<br />
&nbsp; &nbsp; <span class="kw1">foreach</span><span class="br0">&#40;</span> <span class="re0">$list</span> <span class="kw1">as</span> <span class="re0">$el</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$line</span> .= <span class="re0">$el</span> . <span class="st0">&#8216;,&#8217;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="re0">$line</span> = <a href="http://www.php.net/substr"><span class="kw3">substr</span></a><span class="br0">&#40;</span> <span class="re0">$line</span>, <span class="nu0">0</span>, <a href="http://www.php.net/strlen"><span class="kw3">strlen</span></a><span class="br0">&#40;</span> <span class="re0">$line</span> <span class="br0">&#41;</span> &#8211; <span class="nu0">1</span> <span class="br0">&#41;</span>;<br />
<span class="kw2">?&gt;</span><br />
&nbsp;</div>
<p><span id="more-496"></span></p>
<p>There is really nothing wrong with this code snippet. The last line is kind of &#8216;ugly&#8217;: while you are looping over the array and are concatenating a string with &#8216;,&#8217; you don&#8217;t know which is the last element in the list. This means that when the loop is done you have an extra &#8216;,&#8217; character. The solution: use substring to remove the final &#8216;,&#8217;. Another alternative is:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; &#8230;<br />
&nbsp; &nbsp; <span class="re0">$line</span> = <a href="http://www.php.net/preg_replace"><span class="kw3">preg_replace</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;/,$/&#8217;</span>, <span class="st0">&#8221;</span>, <span class="re0">$line</span> <span class="br0">&#41;</span>;<br />
<span class="kw2">?&gt;</span><br />
&nbsp;</div>
<p>This way we use a regular expression to replace the last &#8216;,&#8217; with a blank. A bit nicer than the <em>substr()</em> example. Both ways are ok but PHP has a really nice function called <em>implode()</em>. What <em>implode()</em> does is it takes a list or array and joins it with whatever character/s you want. So, the code we just wrote can be replaced with the much cleaner:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; &#8230;<br />
&nbsp; &nbsp; <span class="re0">$line</span> = <a href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;,&#8217;</span>, <span class="re0">$list</span> <span class="br0">&#41;</span>;<br />
<span class="kw2">?&gt;</span><br />
&nbsp;</div>
<p>With <em>implode()</em> you don&#8217;t need to do weird stuff to remove the last &#8216;,&#8217; or whatever char/chars you used to concatenate the string. Another advantage is that the code is much faster since <em>implode()</em> is implemented in C code.</p>
<p>The <em>implode()</em> function has another useful and related function: <em>explode()</em>. This function takes a delim delimiter and a subject string and returns an array of strings which is obtained by splitting the subject using the delimiter. I&#8217;m quite sure you&#8217;ve used <em>explode()</em>. It&#8217;s used when you want to, for example take a comma separated list and parse it to obtain the fields. Of course if you want to parse a CSV file you should use another PHP function: <em>fgetcsv()</em>; but that is for another post&#8230;</p>
<p>So, the moral of this post should be: before embarking on doing weird things first take a look at the PHP library of functions. Chances are that someone has come across the same problem and have solved it and included it as a PHP function or library. The advantage is that these functions not only execute faster since they are straight C code but also have been tested by thousands of programmers and, in most cases, are known to work. This is often the case when you have to do operations on dates. For example: calculate what day of the month is next Friday, etc. This functions are quite tricky to write because there are a lot of border cases: leap years, change of month / year, etc. If you write<br />
them your are quite likely to forget about some border case. You should always use library functions and particularly PHP library functions which have been extensively tested and used for years.</p>
<div class="shr-publisher-496"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2010/04/24/exploding-and-imploding/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating a page with tabs in Drupal</title>
		<link>http://blog.easytech.com.ar/2010/01/18/creating-a-page-with-tabs-in-drupal/</link>
		<comments>http://blog.easytech.com.ar/2010/01/18/creating-a-page-with-tabs-in-drupal/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 20:44:08 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=478</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2010/01/18/creating-a-page-with-tabs-in-drupal/' data-shr_title='Creating+a+page+with+tabs+in+Drupal'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2010/01/18/creating-a-page-with-tabs-in-drupal/' data-shr_title='Creating+a+page+with+tabs+in+Drupal'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>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.</p>
<div style="width: 700px; clear: both; float: left;"><a href="http://blog.easytech.com.ar/wp-content/uploads/post01.png" rel="thumbnail"><img class="alignnone size-full wp-image-485" title="Resulting page in Drupal" src="http://blog.easytech.com.ar/wp-content/uploads/post01.png" alt="" width="663" height="370" /></a></div>
<p><span id="more-478"></span></p>
<p>Basically you define what content goes in what tab in your modules <em>hook_menu()</em> function defining menu items which are called <strong>MENU_LOCAL_TASK</strong>. Suppose I want a page which has two tabs: Company and Mail as seen on the screen shot. This is the corresponding <em>hook_menu()</em> code:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="coMULTI">/**<br />
&nbsp;* Implementation of hook_menu()<br />
&nbsp;*/</span><br />
<span class="kw2">function</span> my_module_menu<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p>&nbsp; <span class="re0">$items</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; <span class="co1">// definition for main page</span><br />
&nbsp; <span class="re0">$items</span><span class="br0">&#91;</span><span class="st0">&#8216;settings&#8217;</span><span class="br0">&#93;</span> =<br />
&nbsp; &nbsp; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;title&#8217;</span> =&gt; t<span class="br0">&#40;</span><span class="st0">&#8216;Settings&#8217;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;description&#8217;</span> =&gt; t<span class="br0">&#40;</span><span class="st0">&#8216;Settings for Ticket System&#8217;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;page callback&#8217;</span> =&gt; <span class="st0">&#8216;my_module_settings_root&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;access callback&#8217;</span> =&gt; <span class="kw2">true</span>,<br />
&nbsp; &nbsp; <span class="br0">&#41;</span>;<br />
&nbsp; <span class="co1">// definition for default tab.</span><br />
&nbsp; <span class="re0">$items</span><span class="br0">&#91;</span><span class="st0">&#8216;settings/company&#8217;</span><span class="br0">&#93;</span> =<br />
&nbsp; &nbsp; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;title&#8217;</span> =&gt; t<span class="br0">&#40;</span><span class="st0">&#8216;Company&#8217;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;description&#8217;</span> =&gt; t<span class="br0">&#40;</span><span class="st0">&#8216;Settings for Ticket System&#8217;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;type&#8217;</span> =&gt; MENU_DEFAULT_LOCAL_TASK,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;weight&#8217;</span> =&gt; <span class="nu0">0</span>,<br />
&nbsp; &nbsp; <span class="br0">&#41;</span>;<br />
&nbsp; <span class="co1">// definition for additional tab.</span><br />
&nbsp; <span class="re0">$items</span><span class="br0">&#91;</span><span class="st0">&#8216;settings/mail&#8217;</span><span class="br0">&#93;</span> =<br />
&nbsp; &nbsp; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;title&#8217;</span> =&gt; t<span class="br0">&#40;</span><span class="st0">&#8216;Mail&#8217;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;description&#8217;</span> =&gt; t<span class="br0">&#40;</span><span class="st0">&#8216;Settings for Ticket System&#8217;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;access callback&#8217;</span> =&gt; <span class="kw2">true</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;page callback&#8217;</span> =&gt; <span class="st0">&#8216;my_module_settings_mail&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;type&#8217;</span> =&gt; MENU_LOCAL_TASK,<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&#8216;weight&#8217;</span> =&gt; <span class="nu0">2</span>,<br />
&nbsp; &nbsp; <span class="br0">&#41;</span>;</p>
<p>&nbsp; <span class="kw1">return</span> <span class="re0">$items</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw2">function</span> my_module_settings_root<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">return</span> <span class="st0">&#8216;page root&#8217;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw2">function</span> my_module_settings_mail<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">return</span> <span class="st0">&#8216;page mail&#8217;</span>;<br />
<span class="br0">&#125;</span></div>
<p>Here are the main highlights of how this works:</p>
<ul>
<li>The first item should be a standard menu item and its route should be shared with the other tabs. In this case, the route is &#8216;settings&#8217;.</li>
<li>Each additional tab should be of type <strong>MENU_LOCAL_TASK</strong>.</li>
<li>You need at least two tabs. If you only have one child route then you will not see a tab.</li>
<li>If you add more than one <strong>MENU_LOCAL_TASK</strong>, you must single out one as required by setting its type to <strong>MENU_DEFAULT_LOCAL_TASK</strong>. The default local task doesn&#8217;t need a &#8216;page callback&#8217; since it is handled by the root item.</li>
<li>Additional tabs should be of type <strong>MENU_LOCAL_TASK</strong> and should have a page callback function assigned to them.</li>
<li>The &#8216;title&#8217; of the standard item appears a the top of the tab bar. The title of the <strong>MENU_LOCAL_TASK</strong> and <strong>MENU_DEFAULT_LOCAL_TASK</strong> are used as the titles on the individual tabs.</li>
<li>You can change the order of the tabs by adding a &#8216;weight&#8217; item to each menu<br />
item.</li>
<li>You need to specify an &#8216;access callback&#8217; item and have permissions to view the corresponding tab.</li>
</ul>
<p>Finally, remember that each time you change an item in <em>hook_menu()</em> you need to flush your cache so that the items are re-read. This can be achived by going to admin-&gt;settings-&gt;performance and hitting clear cache or by using drush and doing &#8216;drush cache clear&#8217;.</p>
<div class="shr-publisher-478"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2010/01/18/creating-a-page-with-tabs-in-drupal/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Drupal Tip &#8211; How to determine what module handles a given path</title>
		<link>http://blog.easytech.com.ar/2009/11/18/drupal-tip-how-to-determine-what-module-handles-a-given-path/</link>
		<comments>http://blog.easytech.com.ar/2009/11/18/drupal-tip-how-to-determine-what-module-handles-a-given-path/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 18:48:18 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Modules]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=460</guid>
		<description><![CDATA[Drupal has a sophisticated module system that allows developers to extend the CMSs functionality very easily. Each module &#8220;hooks&#8221; into Drupal by implementing hook functions. On way to use this feature is to hook different URLs to module functions. Essentially the developer in his module declares an array of url paths and what function should [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2009/11/18/drupal-tip-how-to-determine-what-module-handles-a-given-path/' data-shr_title='Drupal+Tip+-+How+to+determine+what+module+handles+a+given+path'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2009/11/18/drupal-tip-how-to-determine-what-module-handles-a-given-path/' data-shr_title='Drupal+Tip+-+How+to+determine+what+module+handles+a+given+path'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Drupal has a sophisticated module system that allows developers to extend the CMSs functionality very easily. Each module &#8220;hooks&#8221; into Drupal by implementing hook functions. On way to use this feature is to hook different URLs to module functions. Essentially the developer in his module declares an array of url paths and what function should be called when that path is requested. This small post will show you how you can determine which module handles a specific URL. This can be quite useful for debugging and/or browsing other peoples source code to learn how to do something.</p>
<p>Every module in Drupal that hooks to a URL path needs to implement the <strong>hook_menu</strong> function. This hook basically tells Drupal what paths will be handled by this module. This information is read when the module is enabled and stored in a database table. In Drupal 6 this information is cached so if you modify the array returned by the <strong>hook_menu</strong> function you need to clear the cache. To determine what module is handling what path you simply need to query the <strong>menu_router</strong> table. A simple query to do this is:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">SELECT</span><br />
&nbsp; path<br />
&nbsp; , file<br />
&nbsp; , page_callback<br />
&nbsp; , type<br />
&nbsp; , title<br />
<span class="kw1">FROM</span><br />
&nbsp; menu_router m<br />
<span class="kw1">ORDER</span> <span class="kw1">BY</span><br />
&nbsp; path</div>
<p><span id="more-460"></span></p>
<p>This table has more information that might be useful: <strong>access_callback</strong> and <strong>access_arguments</strong> store information related to what access function is called to determine who has access to that path, <strong>page_arguments</strong> stores information related to what arguments to pass to the callback function. This is specially relevant when the page_callback function is <strong>drupal_get_form</strong> in which case Drupal will render a form and this field stores the name of the form to render.</p>
<p>An example usage might be:</p>
<pre>$ drush sql cli
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1859
Server version: 5.0.77 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql&gt; SELECT path, file, page_callback FROM menu_router ORDER BY path;

+-----------------------------------+---------------------------------+------------------------------+
| path                              | file                            | page_callback                |
+-----------------------------------+---------------------------------+------------------------------+
| admin                             | modules/system/system.admin.inc | system_main_admin_page       |
| admin/build                       | modules/system/system.admin.inc | system_admin_menu_block_page |
| admin/build/block                 | modules/block/block.admin.inc   | block_admin_display          |
| admin/build/block/add             | modules/block/block.admin.inc   | drupal_get_form              |
| admin/build/block/configure       | modules/block/block.admin.inc   | drupal_get_form              |
| admin/build/block/delete          | modules/block/block.admin.inc   | drupal_get_form              |
| admin/build/block/list            | modules/block/block.admin.inc   | block_admin_display          |
| admin/build/block/list/bluemarine | modules/block/block.admin.inc   | block_admin_display          |
| admin/build/block/list/chameleon  | modules/block/block.admin.inc   | block_admin_display          |
| admin/build/block/list/donline    | modules/block/block.admin.inc   | block_admin_display          |
  .....

mysql&gt;</pre>
<div class="shr-publisher-460"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2009/11/18/drupal-tip-how-to-determine-what-module-handles-a-given-path/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Zend_Reflection to generate API docs</title>
		<link>http://blog.easytech.com.ar/2009/08/08/using-zend_reflection-to-generate-api-docs/</link>
		<comments>http://blog.easytech.com.ar/2009/08/08/using-zend_reflection-to-generate-api-docs/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 05:24:26 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=439</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2009/08/08/using-zend_reflection-to-generate-api-docs/' data-shr_title='Using+Zend_Reflection+to+generate+API+docs'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2009/08/08/using-zend_reflection-to-generate-api-docs/' data-shr_title='Using+Zend_Reflection+to+generate+API+docs'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>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 <a href="http://framework.zend.com/manual/en/zend.reflection.html">Zend_Reflection</a>. 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. </p>
<p>This program is quite simple: it has a single class called <strong>TestClass</strong> with one method: <strong>addIntegers()</strong>. 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.</p>
<p>The script I wrote parses the documentation style used in Zend Framework. Here&#8217;s a sample class:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">&lt;?php</span></p>
<p><span class="coMULTI">/**<br />
&nbsp;* This is a sample test class.<br />
&nbsp;*<br />
&nbsp;* This class has only one method: addIntegers() which adds<br />
&nbsp;* two integers. Its a sample class for our test.<br />
&nbsp;*<br />
&nbsp;*/</span><br />
<span class="kw2">class</span> TestClass<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp;* This method adds two integers.<br />
&nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp;* This method adds the two given integers and returns <br />
&nbsp; &nbsp; &nbsp;* its sum. If only one integer is given it sums zero.<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param int $number1 &nbsp;The first integer<br />
&nbsp; &nbsp; &nbsp;* @param int $number2 &nbsp;The second integer<br />
&nbsp; &nbsp; &nbsp;* @return int The sum of $number1 and $number2.<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> addIntegers<span class="br0">&#40;</span> <span class="re0">$number1</span>, <span class="re0">$number2</span> = <span class="nu0">0</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span> <span class="re0">$number1</span> + <span class="re0">$number2</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>&nbsp;</p></div>
<p>Read the rest of the post to see how to easily parse this code&#8230;<br />
<span id="more-439"></span></p>
<p>Below is the complete sample code. Fire up your text editor, copy-and-paste this code into it, save it as <em>test_zend_reflection.php</em> and run it. Hope this helps!</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">&lt;?php</span></p>
<p><span class="co1">// setup Zend auto loader</span><br />
<span class="kw1">require_once</span> <span class="st0">&#8216;Zend/Loader/Autoloader.php&#8217;</span>;<br />
<span class="re0">$autoloader</span> = Zend_Loader_Autoloader::<span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><span class="coMULTI">/**<br />
&nbsp;* This is a sample test class.<br />
&nbsp;*<br />
&nbsp;* This class has only one method: addIntegers() which adds<br />
&nbsp;* two integers. Its a sample class for our test.<br />
&nbsp;*<br />
&nbsp;*/</span><br />
<span class="kw2">class</span> TestClass<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp;* This method adds two integers.<br />
&nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp;* This method adds the two given integers and returns <br />
&nbsp; &nbsp; &nbsp;* its sum. If only one integer is given it sums zero.<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param int $number1 &nbsp;The first integer<br />
&nbsp; &nbsp; &nbsp;* @param int $number2 &nbsp;The second integer<br />
&nbsp; &nbsp; &nbsp;* @return int The sum of $number1 and $number2.<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> addIntegers<span class="br0">&#40;</span><span class="re0">$number1</span>, <span class="re0">$number2</span> = <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span> <span class="re0">$number1</span> + <span class="re0">$number2</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="co1">// use this file</span><br />
<span class="re0">$file</span> = <span class="kw2">__FILE__</span>;</p>
<p><span class="co1">// Zend Reflection require that you load the file. If you are loading</span><br />
<span class="co1">// another file then you need the following line:</span><br />
<span class="co1">// require_once( $file );</span><br />
<span class="re0">$zr</span> = <span class="kw2">new</span> Zend_Reflection_File<span class="br0">&#40;</span> <span class="re0">$file</span> <span class="br0">&#41;</span>;</p>
<p><span class="co1">// Get all classes defined in this file and parse each one</span><br />
<span class="re0">$classDoc</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">foreach</span><span class="br0">&#40;</span> <span class="re0">$zr</span>-&gt;<span class="me1">getClasses</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">as</span> <span class="re0">$class</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="re0">$classDoc</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = parseClass<span class="br0">&#40;</span> <span class="re0">$zr</span>, <span class="re0">$class</span> <span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
<a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span> <span class="re0">$classDoc</span> <span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">// parses a Zend_Reflection_Class object</span><br />
<span class="kw2">function</span> parseClass<span class="br0">&#40;</span> <span class="re0">$zr</span>, <span class="re0">$class</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span>&nbsp; &nbsp; </p>
<p>&nbsp; &nbsp; <span class="co1">// read class docs</span><br />
&nbsp; &nbsp; <span class="re0">$docBlock</span> &nbsp; &nbsp; &nbsp; = <span class="re0">$class</span>-&gt;<span class="me1">getDocblock</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$fileName</span> &nbsp; &nbsp; &nbsp; = <span class="re0">$zr</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$classShortComment</span> &nbsp;= <span class="re0">$docBlock</span>-&gt;<span class="me1">getShortDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$classLongComment</span> &nbsp; = <span class="re0">$docBlock</span>-&gt;<span class="me1">getLongDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// load class info</span><br />
&nbsp; &nbsp; <span class="re0">$classDoc</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;fileName&#8217;</span>&nbsp; &nbsp; &nbsp; =&gt; <span class="re0">$fileName</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;className&#8217;</span>&nbsp;&nbsp; &nbsp; =&gt; <span class="re0">$class</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;shortComment&#8217;</span>&nbsp; =&gt; <span class="re0">$classShortComment</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;longComment&#8217;</span>&nbsp; &nbsp;=&gt; <span class="re0">$classLongComment</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// Read methods</span><br />
&nbsp; &nbsp; <span class="re0">$methods</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$class</span>-&gt;<span class="me1">getMethods</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">as</span> <span class="re0">$methodObj</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$methods</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = parseMethod<span class="br0">&#40;</span> <span class="re0">$methodObj</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="re0">$classDoc</span><span class="br0">&#91;</span><span class="st0">&#8216;methods&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$methods</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$classDoc</span>;<br />
<span class="br0">&#125;</span>&nbsp; &nbsp;</p>
<p><span class="co1">// parses a Zend_Reflection_Method object</span><br />
<span class="kw2">function</span> parseMethod<span class="br0">&#40;</span> <span class="re0">$methodObj</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p>&nbsp; &nbsp; <span class="re0">$return</span> = <span class="st0">&#8216;void&#8217;</span>;</p>
<p>&nbsp; &nbsp; <span class="re0">$docBlock</span> &nbsp;= <span class="re0">$methodObj</span>-&gt;<span class="me1">getDocblock</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$shortDesc</span> = <span class="re0">$docBlock</span>-&gt;<span class="me1">getShortDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$longDesc</span> &nbsp;= <span class="re0">$docBlock</span>-&gt;<span class="me1">getLongDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// read method tags</span><br />
&nbsp; &nbsp; <span class="re0">$tags</span> = <span class="re0">$docBlock</span>-&gt;<span class="me1">getTags</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// parse them</span><br />
&nbsp; &nbsp; <span class="re0">$paramDoc</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">foreach</span><span class="br0">&#40;</span> <span class="re0">$tags</span> <span class="kw1">as</span> <span class="re0">$tag</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$tag</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == <span class="st0">&#8216;return&#8217;</span> <span class="br0">&#41;</span> &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$return</span> &nbsp; &nbsp; = <span class="re0">$tag</span>-&gt;<span class="me1">getType</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$returnDesc</span> = <span class="re0">$tag</span>-&gt;<span class="me1">getDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$tag</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == <span class="st0">&#8216;param&#8217;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$paramDoc</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;name&#8217;</span> =&gt; <span class="re0">$tag</span>-&gt;<span class="me1">getVariableName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="re0">$tag</span>-&gt;<span class="me1">getType</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;desc&#8217;</span> =&gt; <a href="http://www.php.net/trim"><span class="kw3">trim</span></a><span class="br0">&#40;</span> <span class="re0">$tag</span>-&gt;<span class="me1">getDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="re0">$method</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$method</span><span class="br0">&#91;</span> <span class="st0">&#8216;name&#8217;</span> <span class="br0">&#93;</span> &nbsp; &nbsp; &nbsp; = <span class="re0">$methodObj</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$method</span><span class="br0">&#91;</span> <span class="st0">&#8216;shortDesc&#8217;</span> <span class="br0">&#93;</span>&nbsp; = <span class="re0">$shortDesc</span>;<br />
&nbsp; &nbsp; <span class="re0">$method</span><span class="br0">&#91;</span> <span class="st0">&#8216;longDesc&#8217;</span> <span class="br0">&#93;</span>&nbsp; &nbsp;= <span class="re0">$longDesc</span>;<br />
&nbsp; &nbsp; <span class="re0">$method</span><span class="br0">&#91;</span> <span class="st0">&#8216;returnType&#8217;</span><span class="br0">&#93;</span> &nbsp;= <span class="re0">$return</span>;<br />
&nbsp; &nbsp; <span class="re0">$method</span><span class="br0">&#91;</span> <span class="st0">&#8216;returnDesc&#8217;</span><span class="br0">&#93;</span> &nbsp;= <span class="re0">$returnDesc</span>;<br />
&nbsp; &nbsp; <span class="re0">$method</span><span class="br0">&#91;</span> <span class="st0">&#8216;params&#8217;</span> <span class="br0">&#93;</span> &nbsp; &nbsp; = <span class="re0">$paramDoc</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$method</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>If you run our PHP code you get:</p>
<div class="dean_ch" style="white-space: wrap;">
$ php test_zend_reflection.php</p>
<p>Array<br />
(<br />
&nbsp; [fileName] =&gt; /var/www/html/soa/doc/test_zend_reflection.php<br />
&nbsp; [className] =&gt; TestClass<br />
&nbsp; [shortComment] =&gt; This is a sample test class.<br />
&nbsp; [longComment] =&gt; This class has only one method: addIntegers() which adds<br />
two integers. Its a sample class for our test.<br />
&nbsp; [methods] =&gt; Array<br />
&nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; [0] =&gt; Array<br />
&nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [name] =&gt; addIntegers<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [shortDesc] =&gt; This method adds two integers.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [longDesc] =&gt; This method adds the two given integers and returns <br />
its sum. If only one integer is given it sums zero.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [returnType] =&gt; int<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [returnDesc] =&gt; The sum of $number1 and $number2.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [params] =&gt; Array<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] =&gt; Array<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [name] =&gt; $number1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [type] =&gt; int<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [desc] =&gt; The first integer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [1] =&gt; Array<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [name] =&gt; $number2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [type] =&gt; int<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [desc] =&gt; The second integer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br />
&nbsp; &nbsp; &nbsp; &nbsp; )<br />
&nbsp; &nbsp; )<br />
)<br />
&nbsp;</div>
<div class="shr-publisher-439"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2009/08/08/using-zend_reflection-to-generate-api-docs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Initializing only one module per request in Zend_Framework.</title>
		<link>http://blog.easytech.com.ar/2009/08/04/initializing-only-one-module-per-request-in-zend_framework/</link>
		<comments>http://blog.easytech.com.ar/2009/08/04/initializing-only-one-module-per-request-in-zend_framework/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 15:46:57 +0000</pubDate>
		<dc:creator>adji</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=421</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2009/08/04/initializing-only-one-module-per-request-in-zend_framework/' data-shr_title='Initializing+only+one+module+per+request+in+Zend_Framework.'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2009/08/04/initializing-only-one-module-per-request-in-zend_framework/' data-shr_title='Initializing+only+one+module+per+request+in+Zend_Framework.'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>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.</p>
<p>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&#8217;s config file and call the bootstrap again so that it will load the resources defined in this config.</p>
<p>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.</p>
<p>Here&#8217;s the code:</p>
<p><span id="more-421"></span></p>
<div class="dean_ch" style="white-space: wrap;">&lt;!&#8211;?php</p>
<p><span class="coMULTI">/**<br />
&nbsp;* Bootstraps the module used in the current request<br />
&nbsp;* It merges the options from main application.ini with the options from a<br />
&nbsp;* module specific application.ini.<br />
&nbsp;* I&#8217;m using the fact that a resources are loaded only once, so a resource<br />
&nbsp;* declared in main application.ini is initialized there. If you wish to use some resource<br />
&nbsp;* in every module use the key default (see bellow).<br />
&nbsp;*<br />
&nbsp;* The keys default and disable in the main application.ini have a special meaning.<br />
&nbsp;* default: It is merged initally so a key default.resources.xxx is added as resource.xxx<br />
&nbsp;* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;so it load the resource xxx as a default for all modules<br />
&nbsp;* disable: It is used to disable keys after merging so a key disable.resources.xxx disables<br />
&nbsp;* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this resource in all modules.<br />
&nbsp;*/</span><br />
<span class="kw2">class</span> Easytech_Controller_Plugin_ModuleBootstrap <span class="kw2">extends</span> Zend_Controller_Plugin_Abstract<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; const MODULE_APPLICATION_INI = <span class="st0">&quot;configs/application.ini&quot;</span>;</p>
<p>&nbsp; &nbsp; protected <span class="re0">$_bootstrap</span>;</p>
<p>&nbsp; &nbsp; protected <span class="re0">$_autoloader</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> dispatchLoopStartup<span class="br0">&#40;</span> Zend_Controller_Request_Abstract <span class="re0">$request</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$moduleName</span> = <span class="re0">$request</span>&#8212;&gt;<span class="me1">getModuleName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span> <span class="re0">$moduleName</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$moduleName</span> = <span class="st0">&#8216;default&#8217;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$front</span> = Zend_Controller_Front::<span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$moduleDir</span> = <span class="re0">$front</span>-&gt;<span class="me1">getModuleDirectory</span><span class="br0">&#40;</span> <span class="re0">$moduleName</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span> <span class="re0">$moduleDir</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$moduleDir</span> = APPLICATION_PATH;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Para ser usado en los ini.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st0">&#8216;MODULE_PATH&#8217;</span>, <span class="re0">$moduleDir</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st0">&#8216;MODULE_NAME&#8217;</span>, <span class="re0">$moduleName</span> <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Create a autoloader for this module</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$autoloader</span> = <span class="kw2">new</span> Zend_Application_Module_Autoloader<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;namespace&#8217;</span> =&gt; <span class="re0">$moduleName</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;basePath&#8217;</span> &nbsp;=&gt; <span class="re0">$moduleDir</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_bootstrap = <span class="re0">$front</span>-&gt;<span class="me1">getParam</span><span class="br0">&#40;</span><span class="st0">&#8216;bootstrap&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$globalOptions</span> = <span class="re0">$this</span>-&gt;_bootstrap-&gt;<span class="me1">getOptions</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Default options from main application.ini</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$options</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span> <span class="re0">$globalOptions</span><span class="br0">&#91;</span><span class="st0">&#8216;default&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$options</span> = <span class="re0">$globalOptions</span><span class="br0">&#91;</span><span class="st0">&#8216;default&#8217;</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span> <span class="re0">$globalOptions</span><span class="br0">&#91;</span> <span class="re0">$moduleName</span> <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$options</span> = <span class="re0">$this</span>-&gt;_bootstrap-&gt;<span class="me1">mergeOptions</span><span class="br0">&#40;</span><span class="re0">$options</span>, <span class="re0">$globalOptions</span><span class="br0">&#91;</span> <span class="re0">$moduleName</span> <span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$applicationFile</span> = <span class="re0">$moduleDir</span> . DIRECTORY_SEPARATOR . self::<span class="me2">MODULE_APPLICATION_INI</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span> <span class="re0">$globalOptions</span><span class="br0">&#91;</span> <span class="st0">&#8216;application_file&#8217;</span> <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$applicationFile</span> &nbsp;= <span class="re0">$moduleDir</span> . DIRECTORY_SEPARATOR . <span class="re0">$globalOptions</span><span class="br0">&#91;</span> <span class="st0">&#8216;application_file&#8217;</span> <span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$options</span> = <span class="re0">$this</span>-&gt;_bootstrap-&gt;<span class="me1">mergeOptions</span><span class="br0">&#40;</span> <span class="re0">$options</span>, <span class="re0">$this</span>-&gt;_loadConfig<span class="br0">&#40;</span> <span class="re0">$applicationFile</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span> <span class="re0">$globalOptions</span><span class="br0">&#91;</span><span class="st0">&#8216;disable&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$options</span> = <span class="re0">$this</span>-&gt;<span class="me1">unsetOptions</span><span class="br0">&#40;</span><span class="re0">$options</span>, <span class="re0">$globalOptions</span><span class="br0">&#91;</span><span class="st0">&#8216;disable&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_bootstrap-&gt;<span class="me1">setOptions</span><span class="br0">&#40;</span> <span class="re0">$options</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_bootstrap-&gt;<span class="me1">bootstrap</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp;* Unset options recursively.<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;array $array1<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;mixed $array2<br />
&nbsp; &nbsp; &nbsp;* @return array<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> unsetOptions<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a> <span class="re0">$array1</span>, <span class="re0">$array2</span> = <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/is_array"><span class="kw3">is_array</span></a><span class="br0">&#40;</span><span class="re0">$array2</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$array2</span> <span class="kw1">as</span> <span class="re0">$key</span> =&gt; <span class="re0">$val</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> ! <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span> <span class="re0">$array1</span><span class="br0">&#91;</span> <span class="re0">$key</span> <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/is_array"><span class="kw3">is_array</span></a><span class="br0">&#40;</span> <span class="re0">$array2</span><span class="br0">&#91;</span> <span class="re0">$key</span> <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$array1</span><span class="br0">&#91;</span> <span class="re0">$key</span> <span class="br0">&#93;</span> = <span class="re0">$this</span>-&gt;<span class="me1">unsetOptions</span><span class="br0">&#40;</span> <span class="re0">$array1</span><span class="br0">&#91;</span> <span class="re0">$key</span> <span class="br0">&#93;</span>, <span class="re0">$array2</span><span class="br0">&#91;</span> <span class="re0">$key</span> <span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span> <span class="re0">$array1</span><span class="br0">&#91;</span> <span class="re0">$key</span> <span class="br0">&#93;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$array1</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp;<span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp;* Based heavily on Zend_Application-&gt;_loadConfig<br />
&nbsp; &nbsp; &nbsp;* Load configuration file of options<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string $file<br />
&nbsp; &nbsp; &nbsp;* @throws Zend_Application_Exception When invalid configuration file is provided<br />
&nbsp; &nbsp; &nbsp;* @return array<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; protected <span class="kw2">function</span> _loadConfig<span class="br0">&#40;</span><span class="re0">$file</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>! Zend_Loader::<span class="me2">isReadable</span><span class="br0">&#40;</span><span class="re0">$file</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$environment</span> = <span class="re0">$this</span>-&gt;_bootstrap-&gt;<span class="me1">getApplication</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">getEnvironment</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$suffix</span> &nbsp; &nbsp; &nbsp;= <a href="http://www.php.net/strtolower"><span class="kw3">strtolower</span></a><span class="br0">&#40;</span><a href="http://www.php.net/pathinfo"><span class="kw3">pathinfo</span></a><span class="br0">&#40;</span><span class="re0">$file</span>, PATHINFO_EXTENSION<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span><span class="re0">$suffix</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;ini&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$config</span> = <span class="kw2">new</span> Zend_Config_Ini<span class="br0">&#40;</span><span class="re0">$file</span>, <span class="re0">$environment</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;xml&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$config</span> = <span class="kw2">new</span> Zend_Config_Xml<span class="br0">&#40;</span><span class="re0">$file</span>, <span class="re0">$environment</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;php&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;inc&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$config</span> = <span class="kw1">include</span> <span class="re0">$file</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<a href="http://www.php.net/is_array"><span class="kw3">is_array</span></a><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw <span class="kw2">new</span> Zend_Application_Exception<span class="br0">&#40;</span><span class="st0">&#8216;Invalid configuration file provided; PHP file does not return array value&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$config</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">default</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw <span class="kw2">new</span> Zend_Application_Exception<span class="br0">&#40;</span><span class="st0">&#8216;Invalid configuration file provided; unknown config type&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$config</span>-&gt;<span class="me1">toArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="br0">&#125;</span></div>
<div class="shr-publisher-421"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2009/08/04/initializing-only-one-module-per-request-in-zend_framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Filtering table data by user in PostgreSQL</title>
		<link>http://blog.easytech.com.ar/2009/02/19/filtering-table-data-by-user-in-postgresql/</link>
		<comments>http://blog.easytech.com.ar/2009/02/19/filtering-table-data-by-user-in-postgresql/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 02:18:54 +0000</pubDate>
		<dc:creator>Cesar Miquel</dc:creator>
				<category><![CDATA[Database]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=402</guid>
		<description><![CDATA[When developing multi-organization web applications it is of utmost importance that data from one organization is not visible to the other. There are several software aproaches for this. Usually this can be solved by having an organization ID and whenever a query is made a &#8216;where&#8217; clause is added to filter by organization. Although this [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2009/02/19/filtering-table-data-by-user-in-postgresql/' data-shr_title='Filtering+table+data+by+user+in+PostgreSQL'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2009/02/19/filtering-table-data-by-user-in-postgresql/' data-shr_title='Filtering+table+data+by+user+in+PostgreSQL'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>When developing multi-organization web applications it is of utmost importance that data from one organization is not visible to the other. There are several software aproaches for this. Usually this can be solved by having an organization ID and whenever a query is made a &#8216;where&#8217; clause is added to filter by organization. Although this approach works fine it is up to developers to always filter by org_id but its certainly error prone.</p>
<p>To solve this problem there are other approaches. One is that each organization gets a copy of the database and a single database user to log to this database. When the user logs in the application uses the URL to determine the organization (say: <em>http://<strong>organization</strong>.domain.com/login</em>). With the organization name extracted from the URL, the aplication determines which database instance, database user and password to use for the application to use. This obviously solves the problem since, by definition, there is no way data from the two organizations can mix: they live in different databases alltogether.</p>
<p><span id="more-402"></span></p>
<p>The problem with the above approach is that, if you have a large number of organizations that means you have a large number of databases. In the case of thousands of organizations (don&#8217;t think corporations, think small business owners which use your webapp daily) then there might be performance issues in the database since regular databases are not designed to have thousands of small databases. At least the ones I know of.</p>
<p>Chatting about this problem with the nice folks over at the <strong>#postgres</strong> IRC channel on the FreeNode servers they pointed me to two different approaches. One was to use PL/pgSQL code to isolate all access to the data. You have PL/pgSQL code which takes a user as a parameter and uses it to filter or insert the data into tables which have an org_id column.</p>
<p>A second approach which seemed more interesting to me was to create a schema for each organization and encode the organization_id in the schema name. Then you can create an updatable view which uses the schema name to filter the data by organiation_id.</p>
<p>The last approach appealed to me more because I wanted the database to take care of the filtering. The problem with it is that you have to create a schema for each new user. Another setback the guys at #postgres pointed out was that connection spooling is not possible (I don&#8217;t know enough postgres to understand why).</p>
<p>In this article I will point out a slighly different approach our team at Easytech came up with inspired by this last method. The idea is that when the applications logs into the database it sets the organization ID as a kind of &#8216;session parameter&#8217; . All data is accesible through updatable views and this views filter the data using de org_id. When data is updated in the table the org_id is pulled from the &#8216;session&#8217; and inserted in the original table so that it can be marked as beloging to that organization.</p>
<p>The trick here is to create a run-time paramater. To do this you need to modify your <strong>postgres.conf</strong> file and add a parameter. For example:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp;# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&nbsp;# &nbsp;Organization ID <br />
&nbsp;# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&nbsp;custom_variable_classes = &#8216;org&#8217; &nbsp;# list of custom variable class names<br />
&nbsp;org.id = &#8216;private&#8217; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # set initial value<br />
&nbsp;</div>
<p>After re-starting the server you can now connect to the server with psql and set the value of <strong>org.id</strong> with:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">SET</span> SESSION org.id <span class="kw1">TO</span> <span class="st0">&#8216;apple&#8217;</span>;</div>
<p>Lets see how we can use this to create views which display different data to different application users:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2"># su &#8211; postgres</span><br />
$ psql<br />
Welcome <span class="kw1">TO</span> psql <span class="nu0">7.3</span><span class="nu0">.4</span>, the PostgreSQL interactive terminal.</p>
<p>Type: &nbsp;\copyright <span class="kw1">FOR</span> distribution terms<br />
&nbsp; &nbsp; &nbsp; &nbsp;\h <span class="kw1">FOR</span> help <span class="kw1">WITH</span> SQL commands<br />
&nbsp; &nbsp; &nbsp; &nbsp;\? <span class="kw1">FOR</span> help <span class="kw1">ON</span> internal slash commands<br />
&nbsp; &nbsp; &nbsp; &nbsp;\g <span class="kw1">OR</span> terminate <span class="kw1">WITH</span> semicolon <span class="kw1">TO</span> execute query<br />
&nbsp; &nbsp; &nbsp; &nbsp;\q <span class="kw1">TO</span> quit</p>
<p>postgres=<span class="co2"># select &nbsp;version();</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;version<br />
<span class="co1">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</span><br />
&nbsp;PostgreSQL <span class="nu0">8.2</span><span class="nu0">.5</span> <span class="kw1">ON</span> i686-pc-linux-gnu, compiled <span class="kw1">BY</span> GCC gcc <span class="br0">&#40;</span>GCC<span class="br0">&#41;</span> <span class="nu0">3.3</span><span class="nu0">.2</span> <span class="nu0">20031022</span> <span class="br0">&#40;</span>Red Hat Linux <span class="nu0">3.3</span><span class="nu0">.2</span><span class="nu0">-1</span><span class="br0">&#41;</span></p>
<p>postgres=<span class="co2"># &nbsp;create database corp;</span><br />
<span class="kw1">CREATE</span> <span class="kw1">DATABASE</span></p>
<p>postgres=<span class="co2"># \connect corp</span><br />
You are now connected <span class="kw1">TO</span> <span class="kw1">DATABASE</span> corp.</p>
<p>corp=<span class="co2"># create table secret_projects ( org_id varchar, project_name varchar);</span><br />
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span></p>
<p>corp=<span class="co2"># insert into secret_projects values (&#8216;apple&#8217;, &#8216;iPhone&#8217;);</span><br />
corp=<span class="co2"># insert into secret_projects values (&#8216;apple&#8217;, &#8216;iMac&#8217;);</span><br />
corp=<span class="co2"># insert into secret_projects values (&#8216;microsoft&#8217;, &#8216;Zune&#8217;);</span><br />
&#8230;</p>
<p>corp=<span class="co2"># create view secret_projects_v as</span><br />
<span class="kw1">SELECT</span> *<br />
<span class="kw1">FROM</span> secret_projects<br />
<span class="kw1">WHERE</span> org_id = <span class="br0">&#40;</span> <span class="kw1">SELECT</span> current_setting<span class="br0">&#40;</span><span class="st0">&#8216;org.id&#8217;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
<span class="kw1">CREATE</span> <span class="kw1">VIEW</span></p>
<p>corp=<span class="co2"># set session org.id to &#8216;apple&#8217;;</span><br />
<span class="kw1">SET</span></p>
<p>corp=<span class="co2"># select * from secret_projects_v;</span><br />
&nbsp;org_id | project_name<br />
<span class="co1">&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
&nbsp;apple &nbsp;| iPhone<br />
&nbsp;apple &nbsp;| iMac<br />
<span class="br0">&#40;</span><span class="nu0">2</span> rows<span class="br0">&#41;</span></p>
<p>corp=<span class="co2"># set session org.id to &#8216;microsoft&#8217;;</span><br />
<span class="kw1">SET</span></p>
<p>corp=<span class="co2"># select * from secret_projects_v;</span><br />
&nbsp; org_id &nbsp; | project_name<br />
<span class="co1">&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
&nbsp;microsoft | Zune<br />
<span class="br0">&#40;</span><span class="nu0">1</span> row<span class="br0">&#41;</span></div>
<p>As you can see with this approach each application user can see different data from the same table. When a user logs into the application we pull the organization from the URL and use it to setup the session parameter. Once the session paramater is set, all views of sensitive data filter by org_id. Of course if you select from the original tables then you will see all data. It is important that the development team only use this filtered views to access the data.</p>
<p>We still have to investigate how this technique might work in a real application. Another issue to study is how to perform joins with several views and how it performs. We will report how this technique turns out in another posting.</pre>
</pre>
</pre>
</pre>
<div class="shr-publisher-402"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2009/02/19/filtering-table-data-by-user-in-postgresql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using csv data with oracle</title>
		<link>http://blog.easytech.com.ar/2009/01/13/using-csv-data-with-oracle/</link>
		<comments>http://blog.easytech.com.ar/2009/01/13/using-csv-data-with-oracle/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 20:54:35 +0000</pubDate>
		<dc:creator>lucas</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[csv]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=340</guid>
		<description><![CDATA[Sometimes I need to use data from a csv (comma separated values) in an oracle procedure. The best way to do that is inserting the data into a db table using sqlloader and then reading it from the PL/SQL. In this post I will show you how to use sql loader to load a csv [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class=\'shareaholic-fblike\' data-shr_layout=\'button_count\' data-shr_showfaces=\'false\' data-shr_href=\'http://blog.easytech.com.ar/2009/01/13/using-csv-data-with-oracle/\' data-shr_title=\'Using+csv+data+with+oracle\'></a><a class=\'shareaholic-googleplusone\' data-shr_size=\'medium\' data-shr_count=\'true\' data-shr_href=\'http://blog.easytech.com.ar/2009/01/13/using-csv-data-with-oracle/\' data-shr_title=\'Using+csv+data+with+oracle\'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://blog.easytech.com.ar/wp-content/uploads/oracle_logo.gif" rel="thumbnail"><img class="size-full wp-image-342 alignleft" title="oracle_logo" src="http://blog.easytech.com.ar/wp-content/uploads/oracle_logo.gif" alt="" width="94" height="94" /></a><br />
Sometimes I need to use data from a csv (comma separated values) in an oracle procedure. The best way to do that is inserting the data into a db table using sqlloader  and then reading it from the PL/SQL.</p>
<p>In this post I will show you how to use sql loader to load a csv file exported from excel into an oracle table.</p>
<p>Suppose that you got a XLS spreadsheet with contact data: first name, last name, security number, phone number.</p>
<p>First, create a table where the file will be loaded:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">CREATE</span> <span class="kw1">TABLE</span> people_from_csv<br />
&nbsp; &nbsp;<span class="br0">&#40;</span>first_name varchar2<span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;,last_name varchar2<span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;,security_number number<br />
&nbsp; &nbsp;,phone_number varchar2<span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#41;</span>;</div>
<p>In my xls (people.xls) I have the following info:</p>
<table border="1" cellspacing="0" frame="box" rules="groups">
<colgroup>
<col width="86"></col>
</colgroup>
<colgroup>
<col width="86"></col>
</colgroup>
<colgroup>
<col width="86"></col>
</colgroup>
<colgroup>
<col width="86"></col>
</colgroup>
<tbody>
<tr>
<td width="86" height="14" align="left" bgcolor="#e6e6ff"><span style="font-size: xx-small;">First Name</span></td>
<td width="86" align="left" bgcolor="#e6e6ff"><span style="font-size: xx-small;">Last Name</span></td>
<td width="86" align="left" bgcolor="#e6e6ff"><span style="font-size: xx-small;">Secutiry Number</span></td>
<td style="text-align: center;" width="86" bgcolor="#e6e6ff"><span style="font-size: xx-small;">Phone Number</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John </span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000001</span></td>
<td align="right"><span style="font-size: xx-small;">11111123456</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John 01</span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000002</span></td>
<td align="right"><span style="font-size: xx-small;">11111123457</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John 02</span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000003</span></td>
<td align="right"><span style="font-size: xx-small;">11111123458</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John 03</span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000004</span></td>
<td align="right"><span style="font-size: xx-small;">11111123459</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John 04</span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000005</span></td>
<td align="right"><span style="font-size: xx-small;">11111123460</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John 05</span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000006</span></td>
<td align="right"><span style="font-size: xx-small;">11111123461</span></td>
</tr>
</tbody>
<tbody>
<tr>
<td height="13" align="left"><span style="font-size: xx-small;">John 06</span></td>
<td align="left"><span style="font-size: xx-small;">Doe</span></td>
<td align="right"><span style="font-size: xx-small;">00000007</span></td>
<td align="right"><span style="font-size: xx-small;">11111123462</span></td>
</tr>
</tbody>
</table>
<p><span id="more-340"></span></p>
<p>&nbsp;</p>
<p>Save the data as a comma delimited file.</p>
<p>File -&gt; Save As<br />
Change File name to people_csv<br />
Select ‘Text CSV ’ in the File type drop down box.</p>
<p style="text-align: left;"><a href="http://blog.easytech.com.ar/wp-content/uploads/screenshot-2.png" rel="thumbnail"><img class="size-full wp-image-348 aligncenter" title="screenshot-2" src="http://blog.easytech.com.ar/wp-content/uploads/screenshot-2.png" alt="" width="508" height="412" /></a></p>
<p>If you open the people_csv.csv file in a text editor (vi in my case), you will see it in a comma separated format.  Two commas will denote fields without a value, these will be loaded as nulls into the Oracle table.</p>
<p><strong>CSV file</strong>:</p>
<div class="dean_ch" style="white-space: wrap;">First Name,Last Name,Secutiry Number,Phone Number<br />
John ,Doe,00000001,11111123456<br />
John 01,Doe,00000002,11111123457<br />
John 02,Doe,00000003,11111123458<br />
John 03,Doe,00000004,11111123459<br />
John 04,Doe,00000005,11111123460<br />
John 05,Doe,00000006,11111123461<br />
John 06,Doe,00000007,11111123462</div>
<p>Create the following sql loader control file (people_ctrl.txt)</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">LOAD</span> <span class="kw1">DATA</span><br />
<span class="kw1">INFILE</span> <span class="st0">&#8216;people_csv.csv&#8217;</span><br />
<span class="kw1">INTO</span> <span class="kw1">TABLE</span> people_from_csv<br />
<span class="kw1">FIELDS</span> TERMINATED <span class="kw1">BY</span> <span class="st0">&#8216;,&#8217;</span><br />
<span class="br0">&#40;</span> first_name, last_name , security_number, phone_number<span class="br0">&#41;</span></div>
<p>at last  run the sql loader to put the info into the db table.</p>
<div class="dean_ch" style="white-space: wrap;">$ sqlldr usr/<span class="kw3">pwd</span> <span class="re2">control=</span>people_ctrl.txt <span class="re2">log=</span>csvlog</p>
<p>SQL*Loader: Release <span class="nu0">9.2</span><span class="nu0">.0</span><span class="nu0">.8</span><span class="nu0">.0</span> &#8211; Production on Tue Jan <span class="nu0">13</span> <span class="nu0">17</span>:<span class="nu0">26</span>:<span class="nu0">53</span> <span class="nu0">2009</span></p>
<p>Copyright <span class="br0">&#40;</span>c<span class="br0">&#41;</span> <span class="nu0">1982</span>, <span class="nu0">2002</span>, Oracle Corporation. &nbsp;All rights reserved.</p>
<p>Commit point reached &#8211; logical record count <span class="nu0">7</span></div>
<p>Now I can use the data from sql with a simple query:</p>
<div class="dean_ch" style="white-space: wrap;">SQL&gt; <span class="kw1">SELECT</span> phone_number <span class="kw1">FROM</span> people_from_csv;</p>
<p>PHONE_NUMBER<br />
<span class="co1">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
<span class="nu0">11111123456</span><br />
<span class="nu0">11111123457</span><br />
<span class="nu0">11111123458</span><br />
<span class="nu0">11111123459</span><br />
<span class="nu0">11111123460</span><br />
<span class="nu0">11111123461</span><br />
<span class="nu0">11111123462</span></p>
<p><span class="nu0">7</span> rows selected.</div>
<div class="shr-publisher-340"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2009/01/13/using-csv-data-with-oracle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Haciendo POSTs con CURL</title>
		<link>http://blog.easytech.com.ar/2009/01/12/haciendo-posts-con-curl/</link>
		<comments>http://blog.easytech.com.ar/2009/01/12/haciendo-posts-con-curl/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 18:15:09 +0000</pubDate>
		<dc:creator>Leandro</dc:creator>
				<category><![CDATA[Programming and Scripting]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=271</guid>
		<description><![CDATA[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 Lo interesante (y lo más usado entre los code-monkeys de Easytech) es su uso para emular POSTs a ciertas URLs, [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2009/01/12/haciendo-posts-con-curl/' data-shr_title='Haciendo+POSTs+con+CURL'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2009/01/12/haciendo-posts-con-curl/' data-shr_title='Haciendo+POSTs+con+CURL'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://curl.haxx.se/">curl</a> 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).</p>
<p><a href="http://blog.easytech.com.ar/wp-content/uploads/hackers04.jpg" rel="thumbnail"><img class="alignnone size-full wp-image-119" src="http://blog.easytech.com.ar/wp-content/uploads/hackers04.jpg" alt="hackers usando curl para testear un SQL injection." width="280" height="89" /></a><br />
<br/><br/><br/><br/><br/><em>hackers usando curl para testear un SQL injection</em></p>
<p>Lo interesante (y lo más usado entre los <em>code-monkeys</em> de Easytech) es su uso para emular POSTs a ciertas URLs, sin tener que pasar por la página en el browser.</p>
<p>si no lo tienen, pueden bajarlo del link anterior, aunque tiene fama de estar en todos los repos de las distros conocidas.</p>
<p>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.</p>
<p><img class="size-full wp-image-266" src="http://blog.easytech.com.ar/wp-content/uploads/viewerpl.jpeg" alt="un PM de Easytech le enseña a un junior a probar sus Forms con curl." width="400" height="280" /><br />
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><em>un PM de Easytech le enseña a un junior a probar sus Forms con curl.</em></p>
<p>empecemos por lo más básico, emular un formulario. esto lo hacemos con <span style="#008000;">curl -F</span>, o <span style="#008000;">curl -d</span> (dependiendo del content-type que querramos usar). La sintáxis sería algo como:</p>
<div class="dean_ch" style="white-space: wrap;">curl -d &quot;nombre_campo1=valor_campo1&amp;amp;nombre_campo2=valor_campo2&amp;amp;nombre_campoN=valor_campoN&quot; url_a_donde_hacemos_el_post.com</div>
<p>Otro uso interesante es el de hacer upload de files, emulando un  de un form html. La sintáxis:</p>
<div class="dean_ch" style="white-space: wrap;">curl -F &quot;nombre_del_input=@path_al_file_a_subir&quot; url_a_donde_hacemos_el_post.com</div>
<p>o&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">curl -F &quot;nombre_del_input=@path_al_file_a_subir;filename=nombre_del_file&quot; url_a_donde_hacemos_el_post.com</div>
<p>&#8230; si queremos un nombre específico para el file.</p>
<p>Nótese que la arroba delante del path del file es obligatoria.</p>
<p>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 &#8211;verbose, &#8211;trace, o &#8211;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.</p>
<p>La sintáxis, entonces, sería así:</p>
<div class="dean_ch" style="white-space: wrap;">curl &#8211;trace-ascii -F &quot;nombre_del_input=@path_al_file_a_subir;filename=nombre_del_file&quot; url_a_donde_hacemos_el_post.com</div>
<p>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.</p>
<p>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í.</p>
<p><img class="size-full wp-image-264" src="http://blog.easytech.com.ar/wp-content/uploads/hackers2.gif" alt="hacker sexy tipea un script con 2 joysticks." width="350" height="216" /><br />
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><em>hacker sexy tipea un script con 2 joysticks.</em></p>
<p>Para ver más ejemplos, consulten <a href="http://curl.haxx.se/docs/httpscripting.html">acá</a> o en el man de curl, por supuesto.</p>
<div class="shr-publisher-271"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2009/01/12/haciendo-posts-con-curl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Día de Campo</title>
		<link>http://blog.easytech.com.ar/2008/12/12/dia-de-camp/</link>
		<comments>http://blog.easytech.com.ar/2008/12/12/dia-de-camp/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 00:19:23 +0000</pubDate>
		<dc:creator>Leandro</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=252</guid>
		<description><![CDATA[Como es costumbre, todos los veranos Easytech organiza un &#8220;día de campo&#8221; bien merecido por los developers que tanto sufrimos durante el año (no podemos vivir manejando helicópteros de juguete todo el día). Para distendernos, fuimos obligados a hacer deporte (terrestre Y ACUÁTICO). Además, no consultamos nuestros mails en todo el día (Bueno, en realidad [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/' data-shr_title='D%C3%ADa+de+Campo'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/' data-shr_title='D%C3%ADa+de+Campo'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Como es costumbre, todos los veranos Easytech organiza un &#8220;día de campo&#8221; bien merecido por los developers que tanto sufrimos durante el año (no podemos vivir manejando helicópteros de juguete todo el día).</p>
<p>Para distendernos, fuimos obligados a hacer deporte (terrestre Y ACUÁTICO). Además, no consultamos nuestros mails en todo el día (Bueno, en realidad sí, había Wi-Fi).</p>
<p>En agradecimiento por ese exquisito matambrito a la pizza (y por organizar el evento un día laboral), compartimos las fotos que documentan el hecho:</p>

<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0400_new3/' title='img_0400_new3'><img width="112" height="150" src="http://blog.easytech.com.ar/wp-content/uploads/img_0400_new3.jpg" class="attachment-thumbnail" alt="img_0400_new3" title="img_0400_new3" /></a>
<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0402_new3/' title='img_0402_new3'><img width="150" height="112" src="http://blog.easytech.com.ar/wp-content/uploads/img_0402_new3.jpg" class="attachment-thumbnail" alt="img_0402_new3" title="img_0402_new3" /></a>
<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0404_new3/' title='img_0404_new3'><img width="150" height="112" src="http://blog.easytech.com.ar/wp-content/uploads/img_0404_new3.jpg" class="attachment-thumbnail" alt="img_0404_new3" title="img_0404_new3" /></a>
<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0408_new3/' title='img_0408_new3'><img width="150" height="112" src="http://blog.easytech.com.ar/wp-content/uploads/img_0408_new3.jpg" class="attachment-thumbnail" alt="img_0408_new3" title="img_0408_new3" /></a>
<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0409_new3/' title='img_0409_new3'><img width="150" height="112" src="http://blog.easytech.com.ar/wp-content/uploads/img_0409_new3.jpg" class="attachment-thumbnail" alt="img_0409_new3" title="img_0409_new3" /></a>
<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0412_new3/' title='img_0412_new3'><img width="150" height="112" src="http://blog.easytech.com.ar/wp-content/uploads/img_0412_new3.jpg" class="attachment-thumbnail" alt="img_0412_new3" title="img_0412_new3" /></a>
<a href='http://blog.easytech.com.ar/2008/12/12/dia-de-camp/img_0413_new3/' title='img_0413_new3'><img width="150" height="112" src="http://blog.easytech.com.ar/wp-content/uploads/img_0413_new3.jpg" class="attachment-thumbnail" alt="img_0413_new3" title="img_0413_new3" /></a>

<div class="shr-publisher-252"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2008/12/12/dia-de-camp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mantener la sesion entre dominios diferentes</title>
		<link>http://blog.easytech.com.ar/2008/12/12/mantener-la-sesion-entre-dominios-diferentes/</link>
		<comments>http://blog.easytech.com.ar/2008/12/12/mantener-la-sesion-entre-dominios-diferentes/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 19:14:56 +0000</pubDate>
		<dc:creator>Pablo Morales</dc:creator>
				<category><![CDATA[Programming and Scripting]]></category>
		<category><![CDATA[cross domain]]></category>
		<category><![CDATA[multiple dominios]]></category>
		<category><![CDATA[sesiones entre dominios]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=249</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http://blog.easytech.com.ar/2008/12/12/mantener-la-sesion-entre-dominios-diferentes/' data-shr_title='Mantener+la+sesion+entre+dominios+diferentes'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http://blog.easytech.com.ar/2008/12/12/mantener-la-sesion-entre-dominios-diferentes/' data-shr_title='Mantener+la+sesion+entre+dominios+diferentes'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Un problema recurrente con los sistemas grandes y/o multidominio es mantener la sesion de usuarios entre diferentes dominios.</p>
<p>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.</p>
<p>Lo mismo pasa con las sesiones, si uno accede a una pagina y genera un sesion cuando pasa a otro dominio pierde esa sesion.</p>
<p>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.</p>
<p><a href="http://blog.pablo-morales.com/wp-content/uploads/2008/11/pwa-en_us.gif" rel="thumbnail"><img class="alignleft size-full wp-image-384" title="pwa-en_us" src="http://blog.pablo-morales.com/wp-content/uploads/2008/11/pwa-en_us.gif" alt="" width="200" height="33" /></a></p>
<p>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.</p>
<p><a href="http://blog.pablo-morales.com/wp-content/uploads/2008/11/googleaccountslogo.gif" rel="thumbnail"><img class="alignright size-full wp-image-383" title="googleaccountslogo" src="http://blog.pablo-morales.com/wp-content/uploads/2008/11/googleaccountslogo.gif" alt="" width="150" height="58" /></a></p>
<p>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?</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Vamos a ver ahora un ejemplo practico</p>
<p>Yo tengo el dominio www.mail.com, el dominio www.calendar.com, y el dominio de mi empresa que se llama www.cloacas.com.</p>
<p>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.</p>
<p>Con esto tengo que haber logrado autenticarme en www.mail.com. Ahora el usuario, en otro tab de su browser escribe, www.calendar.com.</p>
<p>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</p>
<p><a href="http://blog.pablo-morales.com">fuente</a></p>
<div class="shr-publisher-249"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2008/12/12/mantener-la-sesion-entre-dominios-diferentes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mosquito</title>
		<link>http://blog.easytech.com.ar/2008/11/27/mosquito/</link>
		<comments>http://blog.easytech.com.ar/2008/11/27/mosquito/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 00:51:57 +0000</pubDate>
		<dc:creator>lucas</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.easytech.com.ar/?p=240</guid>
		<description><![CDATA[Sometimes easytech developers need flying lessons. &#160; &#160; &#160; &#160; After that we got a better kung-fu.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class=\'shareaholic-fblike\' data-shr_layout=\'button_count\' data-shr_showfaces=\'false\' data-shr_href=\'http://blog.easytech.com.ar/2008/11/27/mosquito/\' data-shr_title=\'Mosquito\'></a><a class=\'shareaholic-googleplusone\' data-shr_size=\'medium\' data-shr_count=\'true\' data-shr_href=\'http://blog.easytech.com.ar/2008/11/27/mosquito/\' data-shr_title=\'Mosquito\'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://blog.easytech.com.ar/wp-content/uploads/index.jpg" rel="thumbnail"><img class="alignleft size-full wp-image-601" title="index" src="http://blog.easytech.com.ar/wp-content/uploads/index.jpg" alt="" width="200" height="200" /></a>Sometimes easytech developers need flying lessons.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>After that we got a better kung-fu.</p>

<div class="shr-publisher-240"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://blog.easytech.com.ar/2008/11/27/mosquito/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
