<?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>Jorge Albaladejo</title>
	<atom:link href="http://jorgealbaladejo.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jorgealbaladejo.com</link>
	<description>Hard &#38; Soft design...</description>
	<lastBuildDate>Mon, 06 Sep 2010 19:37:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>ActionScript 3 and cross-domain problem</title>
		<link>http://jorgealbaladejo.com/2010/09/06/actionscript-and-cross-domain-problem/</link>
		<comments>http://jorgealbaladejo.com/2010/09/06/actionscript-and-cross-domain-problem/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 19:37:27 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[Flash]]></category>
		<category><![CDATA[Php]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[actionscript 3]]></category>
		<category><![CDATA[cross-domain]]></category>
		<category><![CDATA[proxy php]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=664</guid>
		<description><![CDATA[One of the most typical problems when coding AS3 to, let&#8217;s say, read data from an external XML source, is the cross-domain problem. According to security policies, not an url outside the domain where the AS application is being executed can be read, and different subdomains (such as www.yourdomain.com and yourdomain.com) are considered as different [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:justify">One of the most typical problems when coding AS3 to, let&#8217;s say, read data from an external XML source, is the cross-domain problem. According to security policies, not an url outside the domain where the AS application is being executed can be read, and different subdomains (such as www.yourdomain.com and yourdomain.com) are considered as different ones.</p>
<p style="text-align:justify">If the external resources you are trying to use come from your own application in another domain / server that you manage, then it can be fixed by adding a <a href="http://kb2.adobe.com/cps/142/tn_14213.html#main_Cross_domain_policy_files" title="Cross-domain policy files" target="_blank" rel="external">cross-domain policy file</a>. This file must be defined on the content source server, and your AS application has to explicitly <a href="http://stackoverflow.com/questions/1638641/how-do-i-fix-this-cross-domain-actionscript-3-error" title="ActionScript 3 cross-domain problem" target="_blank" rel="external">declare</a> this server as allowed.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p664code6'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p6646"><td class="code" id="p664code6"><pre class="actionscript" style="font-family:monospace;">Security.<span style="color: #0066CC;">allowDomain</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;domainone.com&quot;</span><span style="color: #66cc66;">&#41;</span>;
Security.<span style="color: #0066CC;">allowDomain</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;domaintwo.com&quot;</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>&nbsp;</p>
<p style="text-align:justify">But if this is not the case and the content source is on a different remote server like, for instance, when implementing an RSS news reader which grabs content from sources like online news sites, then this problem can be worked out with a PHP proxy file.</p>
<p><span id="more-664"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p664code7'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p6647"><td class="code" id="p664code7"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'url'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/readfile" rel="external"><span style="color: #990000;">readfile</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>&nbsp;</p>
<p style="text-align:justify">Since PHP is not affected by this policy, all the RSS feeds would be read through this small script, by calling it like &#8216;proxy.php?url=http://rss.thedomain.com&#8217;. Being this file exactly on the same domain than the AS application, the cross-domain problem is solved.</p>
<p style="text-align:justify">However, I have also found an odd behavior regarding this proxy PHP file: it works perfectly when opening the SWF compiled application directly on the browser (http://yourdomain.com/app.swf), but not when it is loaded as a part of the HTML code (embedded into an HTML page like http://yourdomain.com/app.html). The SWF application just doesn&#8217;t find the file (but it <strong>is</strong> there!), despite it reads without any problem a test text file on the same folder. So it seems as if the question mark &#8216;?&#8217; changed the way the SWF application looks for files or executes url addresses. I don&#8217;t have a reason for this yet, but I guess that it is related to the way the Flash plugin manages the security, by using different <a href="http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7c5a.html" target="_blank" title="Security Sandbox in AS3" rel="external">sandboxes</a> for direct and embedded executions of the application.</p>
<p style="text-align:justify">The solution for this second collateral problem is passing the domain name as a parameter, so that the full path to the proxy file can be constructed inside the AS application.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p664code8'); return false;">View Code</a> HTML4STRICT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p6648"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code" id="p664code8"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html" rel="external"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span>
	<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html" rel="external"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span>
		<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/style.html" rel="external"><span style="color: #000000; font-weight: bold;">style</span></a> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span>&gt;</span>
			...
		<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/style.html" rel="external"><span style="color: #000000; font-weight: bold;">style</span></a>&gt;</span>
		<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html" rel="external"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;</span>
			...
		<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html" rel="external"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html" rel="external"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span>
	<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html" rel="external"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span>
		<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html" rel="external"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;flash&quot;</span>&gt;</span>
			<span style="color: #009900;">&lt;? $basepath <span style="color: #66cc66;">=</span> getBasePath<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> ?&gt;</span>
			<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/object.html" rel="external"><span style="color: #000000; font-weight: bold;">object</span></a> <span style="color: #000066;">classid</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&quot;</span> <span style="color: #000066;">codebase</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://download.macromedia.com/&quot;</span> <span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;960&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;610&quot;</span>&gt;</span>
		    	<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/param.html" rel="external"><span style="color: #000000; font-weight: bold;">param</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;allowScriptAccess&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;always&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
		    	<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/param.html" rel="external"><span style="color: #000000; font-weight: bold;">param</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;movie&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;main.swf?basepath=&lt;?=$basepath?&gt;</span></span>&quot; /&gt;
		    	<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/param.html" rel="external"><span style="color: #000000; font-weight: bold;">param</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;quality&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;high&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
		    	<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/param.html" rel="external"><span style="color: #000000; font-weight: bold;">param</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;bgcolor&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;#ffffff&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
				<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/param.html" rel="external"><span style="color: #000000; font-weight: bold;">param</span></a> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;basepath&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?=$basepath?&gt;</span></span>&quot; /&gt;
				<span style="color: #009900;">&lt;embed <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;main.swf?basepath=&lt;?=$basepath?&gt;</span></span>&quot; 
				    quality=high bgcolor=#FFFFFF width=&quot;960&quot; height=&quot;610&quot; name=&quot;main&quot;
				    type=&quot;application/x-shockwave-flash&quot; 
				    pluginspace=&quot;http://www.macromedia.com/go/getflashplayer&quot;&gt;
				<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span>embed&gt;</span>
			<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/object.html" rel="external"><span style="color: #000000; font-weight: bold;">object</span></a>&gt;</span>
		<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html" rel="external"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html" rel="external"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html" rel="external"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p664code9'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p6649"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p664code9"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">function</span> getBasePath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://'</span><span style="color: #339933;">.</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_HOST'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$aPath</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/split" rel="external"><span style="color: #990000;">split</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <a href="http://www.php.net/eregi" rel="external"><span style="color: #990000;">eregi</span></a> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'\.php'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$aPath</span><span style="color: #009900;">&#91;</span><a href="http://www.php.net/sizeof" rel="external"><span style="color: #990000;">sizeof</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$aPath</span><span style="color: #009900;">&#91;</span><a href="http://www.php.net/sizeof" rel="external"><span style="color: #990000;">sizeof</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/join" rel="external"><span style="color: #990000;">join</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span><span style="color: #000088;">$aPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$path</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>&nbsp;</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p664code10'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p66410"><td class="code" id="p664code10"><pre class="actionscript" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> proxyPath:<span style="color: #0066CC;">String</span> = <span style="color: #0066CC;">this</span>.<span style="color: #006600;">loaderInfo</span>.<span style="color: #006600;">parameters</span>.<span style="color: #006600;">basepath</span> + <span style="color: #ff0000;">'proxy.php'</span>; <span style="color: #808080; font-style: italic;">// proxy for cross-domain problems</span></pre></td></tr></table></div>

<p>&nbsp;</p>
<p style="text-align:justify">In any case, these problems only arise in online mode, I have not had any issue while working from my development suite, so it is when moving to a production environment when the pain in the ass can show out. Finally, this is nothing new, but handy and interesting not to forget.</p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/09/06/actionscript-and-cross-domain-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Basic web mapper</title>
		<link>http://jorgealbaladejo.com/2010/08/21/basic-web-mapper/</link>
		<comments>http://jorgealbaladejo.com/2010/08/21/basic-web-mapper/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 08:00:15 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[Web Crawlers]]></category>
		<category><![CDATA[web crawler]]></category>
		<category><![CDATA[web robot]]></category>
		<category><![CDATA[web spider]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=554</guid>
		<description><![CDATA[Sometimes it is useful to have an automated tool to get the full web map of your site. Perhaps not your own web site, since you have already implemented some kind of automatic generation and notification to Google (have not yet?), but a client&#8217;s one. There are a few tools to map an external web [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Sometimes it is useful to have an automated tool to get the full web map of your site. Perhaps not your own web site, since you have already implemented some kind of automatic generation and notification to Google (have not yet?), but a client&#8217;s one.</p>
<p style="text-align: justify;">There are a few tools to map an external web site, I tried some in my particular case. They were just adware, or demos, or they obscured the links in the final report&#8230; Yeah, of course, sometimes a $30 license is worth it, but you might not want to acquire a new piece of proprietary software every time you need a new feature, might you?</p>
<p style="text-align: justify;">So I decided to write it myself in PHP, not for the money, but for the fun <img src='http://jorgealbaladejo.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3><span id="more-554"></span></h3>
<h3 style="margin-top: 30px">The architecture</h3>
<p>First of all, a bit of planning the application:</p>
<div id="attachment_557" class="wp-caption aligncenter" style="width: 465px"><img src="http://jorgealbaladejo.com/wp-content/uploads/2010/08/web_mapper.png" alt="Web mapper work flow" class="size-full wp-image-557" style="border: 5px solid white;" title="Web mapper work flow" width="455" height="942" /><p class="wp-caption-text">Web mapper work flow diagram</p></div>
<p style="text-align: center;"><a href="http://jorgealbaladejo.com/wp-content/uploads/2010/08/web_mapper.zip">Web mapper work flow diagram (Visio)</a>.</p>
<p style="text-align: justify;">&nbsp;</p>
<p style="text-align: justify;">Let&#8217;s take a look at this work flow diagram. First of all, the mapper reads the entry url address in search of links. The blue color represents the entry and exit points of the application.</p>
<p style="text-align: justify;">Then it reads the HTML code, parses it in search for links, and if found, it runs a loop on each one of them. The green color means the actions taken within the loop. Basically, this involves saving the link into the database, and, if the address is not external (that means, it points to a page within the same domain name), then reading it and starting the process again for this new url.</p>
<p style="text-align: justify;">This practice is commonly known as &#8216;recursion&#8217;, and is represented in orange. When a link within a page is followed, the application has just entered a new recursion level, then reads the  HTML code and seeks for links, starting again a new loop. Think of it like a set of <a href="http://en.wikipedia.org/wiki/Russian_dolls" title="Russian dolls" target="_blank" rel="external">Russian dolls</a>: every link of a page contains a page with more links, so there we start a new entire loop from an iteration of the previous one, and so on.</p>
<p style="text-align: justify;">The recursion will end when a page has no links, or all its links are external. Then the application has found a leaf page, nothing to do deeper than that, and can return one level up. When all the leaf pages are read, this algorithm will return to the main entry level, when, after going through all links found, will finish.</p>
<p style="text-align: justify;">This, depending on the web site structure, can take a few minutes to complete all the mapping, so that is better to use a fast and reliable programming language. In my case, I have used PHP for simplicity&#8217;s sake, since is the language I am using daily, but on a test server where I can increase execution time. For more intensive uses of this script, I would recommend to have it translated into another language, or to run it from console with the PHP interpreter, not from the web server itself.</p>
<p style="text-align: justify;">In addition, this architecture is really basic, that means that a lot of things can be improved. For instance, a check has been added to avoid following links twice. This, however, is not so easy to implement, since inner links can follow different conventions (&#8220;www.domain.com&#8221;, &#8220;domain.com&#8221;, &#8220;sub.domain.com&#8221;, &#8220;/&#8221;, &#8220;./&#8221;). Thus, the code presented below should be used for academic and learning purposes, I can not guarantee that it is going to work perfectly at all.</p>
<h3 style="margin-top: 30px">The code</h3>
<p style="text-align: justify;">Let&#8217;s present the code now. It has been written for the Code Igniter framework, but can be easily ported to no matter what architecture or language. A few conventions:</p>
<ul>
<li>It is based on the class &#8216;spider&#8217;, whose main method &#8216;crawl()&#8217; launches the initial entry point, and the inner and protected method &#8216;_crawl()&#8217; implements the recursion.</li>
<li>All inner and protected methods are preceded by an underscore (_).</li>
<li>A few configuration attributes allow a sandbox definition, limiting the recursion levels and the domains to be crawled.</li>
<li>As said before, it is based on Code Igniter, but in this case that is only to provide an easy interface with the database. You can just replace all instances of $this->ci->db with your own <a href="http://jorgealbaladejo.com/2007/05/24/clase-dbhandler-para-manejar-datos-de-una-base-de-datos/" title="Reading data from a MySQL database">MySQL connection class</a>.</li>
</ul>
<p style="text-align: justify;">Using the class is very simple:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p554code13'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p55413"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p554code13"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$spider</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> spider<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$spider</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">crawl</span><span style="color: #009900;">&#40;</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>  <span style="color: #0000ff;">'entry'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'http://jorgealbaladejo.com'</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'domains'</span>	<span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>	<span style="color: #0000ff;">'jorgealbaladejo.com'</span> <span style="color: #339933;">,</span>
							<span style="color: #0000ff;">'www.jorgealbaladejo.com'</span><span style="color: #339933;">,</span>
							<span style="color: #0000ff;">'jorgealbaladejo.ch'</span><span style="color: #339933;">,</span>
							<span style="color: #0000ff;">'jorgealbaladejo.es'</span>	<span style="color: #009900;">&#41;</span> 
			<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$spider</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">printResults</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>&nbsp;</p>
<p>And finally, the core class code. It is commented so it may be easy to understand, eventually. However, comments, improvements and doubts are welcome, so if you find I am doing something not clearly enough, or you would have just done it in another way, please share your comments! <img src='http://jorgealbaladejo.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p554code14'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p55414"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
</pre></td><td class="code" id="p554code14"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Class spider
 * Creates a spider which crawls the internet
 * 
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> spider
<span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * @var Code Igniter object for database access
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$ci</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * @var maximum recursivity depth
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$max_depth</span> 	<span style="color: #339933;">=</span> <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * @var default domains to restrict crawling
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$domains</span> 	<span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jorgealbaladejo.com'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'vwww.jorgealbaladejo.com'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * @var indentation level
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$indent</span> 	<span style="color: #339933;">=</span> <span style="color: #cc66cc;">20</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * @var internal links array
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$links</span> 	<span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Constructor
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> spider<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ci</span> <span style="color: #339933;">=&amp;</span> get_instance<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
		<span style="color: #666666; font-style: italic;">// load links in database to internal list</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_loadLinks<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Entry point for recursive function crawl
	 * 
	 * @param object 	$params
	 * @param array 	$params['domains']
	 * @param string	$params['entry']
	 * 
	 * @return boolean
	 *  
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> crawl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset" rel="external"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'domains'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">domains</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'domains'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>	
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset" rel="external"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'entry'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_crawl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'entry'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>		
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/** 
	 * Recursive crawling function
	 * 
	 * @param string	$page
	 * @param int 		$parent [optional]
	 * @param int 		$depth of current page [optional]
	 * 
	 * @return void
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _crawl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$depth</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// vars</span>
		<span style="color: #000088;">$doc</span> 	<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$title</span> 	<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$desc</span>  	<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$out</span> 	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$links</span> 	<span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$link</span> 	<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">//</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// correct url</span>
		<span style="color: #000088;">$page</span> 	<span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_buildUrl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #000088;">$parent</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// avoid reading the same url twice</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/array_key_exists" rel="external"><span style="color: #990000;">array_key_exists</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">links</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// only read info for inner pages</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/in_array" rel="external"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getDomain<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">domains</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>			
			<span style="color: #666666; font-style: italic;">// read page content</span>
			<span style="color: #000088;">$doc</span> 	<span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getHTTPRequest<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #666666; font-style: italic;">// get page meta data</span>
			<a href="http://www.php.net/list" rel="external"><span style="color: #990000;">list</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #339933;">,</span> <span style="color: #000088;">$desc</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_analyzePage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$doc</span><span style="color: #339933;">,</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// log into inner array</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">links</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>	<span style="color: #0000ff;">'url'</span> 		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$page</span> <span style="color: #339933;">,</span>
						<span style="color: #0000ff;">'title'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$title</span> <span style="color: #339933;">,</span>
						<span style="color: #0000ff;">'description'</span> 	<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$desc</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// write into database		</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ci</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'INSERT INTO web.map VALUES(&quot;&quot;,'</span> <span style="color: #339933;">.</span>
					<span style="color: #0000ff;">'&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$page</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;,'</span> <span style="color: #339933;">.</span>
					<span style="color: #0000ff;">'&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$title</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;,'</span> <span style="color: #339933;">.</span>
					<span style="color: #0000ff;">'&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$desc</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;,'</span> <span style="color: #339933;">.</span>
					<span style="color: #0000ff;">'&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$parent</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;) '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$parent</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ci</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">insert_id</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_printLine<span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #339933;">,</span><span style="color: #000088;">$desc</span><span style="color: #339933;">,</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #000088;">$depth</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
&nbsp;
		<span style="color: #666666; font-style: italic;">// avoid recursion for external domains</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/in_array" rel="external"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getDomain<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">domains</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// now get links and launch recursively</span>
		<span style="color: #000088;">$links</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getInnerLinks<span style="color: #009900;">&#40;</span><span style="color: #000088;">$doc</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$links</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span> 
		<span style="color: #009900;">&#123;</span> 
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$depth</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">max_depth</span><span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_crawl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</span><span style="color: #339933;">,</span><span style="color: #000088;">$parent</span><span style="color: #339933;">,</span><span style="color: #000088;">$depth</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
			<span style="color: #009900;">&#125;</span>				
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>		
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Prints the current links array
	 * 
	 *  
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> printResults<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<a href="http://www.php.net/ksort" rel="external"><span style="color: #990000;">ksort</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">links</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">links</span> <span style="color: #b1b100;">AS</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_printLine<span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'url'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Preloads the existent links in database 
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _loadLinks<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ci</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT url,title,description FROM web.map ORDER BY url ASC'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">num_rows</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$r</span><span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">links</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$r</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>	<span style="color: #0000ff;">'url'</span> 		<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$r</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span> <span style="color: #339933;">,</span>
								<span style="color: #0000ff;">'title'</span> 	<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$r</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span> <span style="color: #339933;">,</span>
								<span style="color: #0000ff;">'description'</span> 	<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$r</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">description</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>		 
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Reads a document for html links
	 * 
	 * @param string $doc [optional]
	 * 
	 * @return array of links
	 *  
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _getInnerLinks<span style="color: #009900;">&#40;</span><span style="color: #000088;">$doc</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$return</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$regexp</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&lt;a\s[^&gt;]*href=(<span style="color: #000099; font-weight: bold;">\&quot;</span>??)([^<span style="color: #000099; font-weight: bold;">\&quot;</span> &gt;]*?)<span style="color: #000099; font-weight: bold;">\\</span>1[^&gt;]*&gt;(.*)&lt;\/a&gt;&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$match</span>  <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/preg_match_all" rel="external"><span style="color: #990000;">preg_match_all</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/<span style="color: #006699; font-weight: bold;">$regexp</span>/siU&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$doc</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #339933;">,</span> PREG_SET_ORDER<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> 
		<span style="color: #009900;">&#123;</span> 	
			<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#41;</span> 
			<span style="color: #009900;">&#123;</span> 
				<span style="color: #000088;">$return</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span> 
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$return</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Prints a line for the current url
	 * 
	 * @param int
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _printLine<span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$desc</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$depth</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// do not indent at this time</span>
		<span style="color: #000088;">$depth</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">//</span>
&nbsp;
		<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;p&gt;'</span> <span style="color: #339933;">.</span>
				<span style="color: #0000ff;">'&lt;h3 style=&quot;margin-left:'</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$depth</span><span style="color: #339933;">*</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">indent</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'px&quot;&gt;'</span> <span style="color: #339933;">.</span> 
					<a href="http://www.php.net/stripslashes" rel="external"><span style="color: #990000;">stripslashes</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> 
				<span style="color: #0000ff;">'&lt;/h3&gt;'</span> <span style="color: #339933;">.</span> 
				<span style="color: #0000ff;">'&lt;span style=&quot;margin-left:'</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$depth</span><span style="color: #339933;">*</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">indent</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'px&quot;&gt;'</span> <span style="color: #339933;">.</span>
					<a href="http://www.php.net/substr" rel="external"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><a href="http://www.php.net/stripslashes" rel="external"><span style="color: #990000;">stripslashes</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$desc</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">100</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span>
				<span style="color: #0000ff;">'&lt;/span&gt;'</span> <span style="color: #339933;">.</span> 
				<span style="color: #0000ff;">'&lt;h4 style=&quot;margin-left:'</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$depth</span><span style="color: #339933;">*</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">indent</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'px&quot;&gt;'</span> <span style="color: #339933;">.</span> 
					<span style="color: #000088;">$page</span> <span style="color: #339933;">.</span> 
				<span style="color: #0000ff;">'&lt;/h4&gt;'</span> <span style="color: #339933;">.</span>
			<span style="color: #0000ff;">'&lt;/p&gt;'</span><span style="color: #339933;">;</span>	
	<span style="color: #009900;">&#125;</span>	
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Analyzes a page to get meta information
	 * 
	 * @param string $doc(cument)
	 * @param string $page
	 * 
	 * @return list($title,$description);
	 *  
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _analyzePage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$doc</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//</span>
		<span style="color: #000088;">$title</span> 	<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$desc</span> 	<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">//</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/eregi" rel="external"><span style="color: #990000;">eregi</span></a> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&lt;title&gt;(.*)&lt;/title&gt;&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$doc</span><span style="color: #339933;">,</span> <span style="color: #000088;">$out</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> 
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/addslashes" rel="external"><span style="color: #990000;">addslashes</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$out</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/strlen" rel="external"><span style="color: #990000;">strlen</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$out</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/substr" rel="external"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">50</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
			<span style="color: #009900;">&#125;</span>			
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$out</span> 	<span style="color: #339933;">=</span> <span style="color: #339933;">@</span><a href="http://www.php.net/get_meta_tags" rel="external"><span style="color: #990000;">get_meta_tags</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset" rel="external"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$out</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$desc</span> 	<span style="color: #339933;">=</span> <a href="http://www.php.net/addslashes" rel="external"><span style="color: #990000;">addslashes</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$out</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #339933;">,</span><span style="color: #000088;">$desc</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Completes a page link with the domain if needed
	 * 
	 * @param string $page
	 * @param int 	 $parent
	 * 
	 * @return string corrected url
	 *  
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _buildUrl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #000088;">$parent</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// prepare url if relative</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/eregi" rel="external"><span style="color: #990000;">eregi</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://'</span><span style="color: #339933;">,</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #666666; font-style: italic;">// root relative path</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/strpos" rel="external"><span style="color: #990000;">strpos</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">domains</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$page</span><span style="color: #339933;">;</span>	
			<span style="color: #009900;">&#125;</span>
			<span style="color: #666666; font-style: italic;">// page relative path</span>
			<span style="color: #b1b100;">else</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/strpos" rel="external"><span style="color: #990000;">strpos</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'mailto:'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&lt;</span><span style="color: #cc66cc;">0</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.php.net/strpos" rel="external"><span style="color: #990000;">strpos</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'javascript:'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&lt;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
				<span style="color: #009900;">&#123;</span>
					<span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getUrlByID<span style="color: #009900;">&#40;</span><span style="color: #000088;">$parent</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$page</span><span style="color: #339933;">;</span>	
				<span style="color: #009900;">&#125;</span>				
			<span style="color: #009900;">&#125;</span>			
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// trim final slash</span>
		<span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/trim" rel="external"><span style="color: #990000;">trim</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$page</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Gets url for a given ID
	 * 
	 * @param int url id
	 * 
	 * @return string the url
	 *  
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _getUrlByID<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ci</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT url FROM web.map WHERE ID = &quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$id</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">num_rows</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$results</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Gets domain name from a URL
	 * 
	 * @param string url
	 * 
	 * @return string domain name
	 * 
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _getDomain<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// get host name from URL</span>
		<a href="http://www.php.net/preg_match" rel="external"><span style="color: #990000;">preg_match</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@^(?:http://)?([^/]+)@i'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset" rel="external"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>	
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * HTTP helper function.&lt;br /&gt;
	 * Loads an http request and returns result.
	 *
	 * @param string $url to request
	 *
	 * @return string the result
	 *
	 */</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _getHTTPRequest<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// vars</span>
		<span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$old</span>  <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>	
		<span style="color: #666666; font-style: italic;">//</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//configuration</span>
		<span style="color: #000088;">$timeout</span> 			<span style="color: #339933;">=</span> <span style="color: #cc66cc;">15</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">//</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// execution</span>
		try
		<span style="color: #009900;">&#123;</span>
&nbsp;
  			<span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><a href="http://www.php.net/fopen" rel="external"><span style="color: #990000;">fopen</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'rb'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/stream_get_contents" rel="external"><span style="color: #990000;">stream_get_contents</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<a href="http://www.php.net/fclose" rel="external"><span style="color: #990000;">fclose</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>						
&nbsp;
		<span style="color: #009900;">&#125;</span>
		catch<span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'error'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #666666; font-style: italic;">//</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/08/21/basic-web-mapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scrum / agile development</title>
		<link>http://jorgealbaladejo.com/2010/07/29/scrum-agile-development/</link>
		<comments>http://jorgealbaladejo.com/2010/07/29/scrum-agile-development/#comments</comments>
		<pubDate>Thu, 29 Jul 2010 19:53:25 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[Project Management]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[agile development]]></category>
		<category><![CDATA[project management]]></category>
		<category><![CDATA[scrum]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=411</guid>
		<description><![CDATA[Some resources and useful information about this development technique: About Scrum (Spanish) http://www.proyectosagiles.org/ Agile Software Development http://www.agile-software-development.com/ Good Agile Project Management software, community / free version available http://www.rallydev.com/ Scrum project management software, for Windows (Desktop) http://www.scrumdesk.com MoSCoW method to prioritize tasks http://en.wikipedia.org/wiki/MoSCoW_Method Basic concepts: Sprints (iterations) last from 2 to 4 weeks, and they are [...]]]></description>
			<content:encoded><![CDATA[<p>Some resources and useful information about this development technique:</p>
<ul>
<li>About Scrum (Spanish) <a href="http://www.proyectosagiles.org/" target="_blank" rel="external">http://www.proyectosagiles.org/</a></li>
<li>Agile Software Development <a href="http://www.agile-software-development.com/" target="_blank" rel="external">http://www.agile-software-development.com/</a></li>
<li>Good Agile Project Management software, community / free version available <a href="http://www.rallydev.com/" target="_blank" rel="external">http://www.rallydev.com/</a></li>
<li>Scrum project management software, for Windows (Desktop) <a href="http://www.scrumdesk.com" target="_blank" rel="external">http://www.scrumdesk.com</a></li>
<li>MoSCoW method to prioritize tasks <a href="http://en.wikipedia.org/wiki/MoSCoW_Method" target="_blank" rel="external">http://en.wikipedia.org/wiki/MoSCoW_Method</a></li>
</ul>
<p><span id="more-411"></span><br />
Basic concepts:</p>
<ul>
<li>Sprints (iterations) last from 2 to 4 weeks, and they are released so that the client can test and provide feedback
<ul>
<li>Every iteration is divided into small tasks planned to be achieved in less than 2 days work</li>
</ul>
</li>
<li>The specifications for a started sprint should not change, the client has the responsibility to define carefully the priorities; they are defined as user stories</li>
<li>There is a project owner which interacts with the client, and a facilitator which helps the development team to achieve the goals</li>
<li>From 5 to 9 people in every development team</li>
<li>Daily meetings (about 15 min) with all the team to discuss about:
<ul>
<li>The work done the day before</li>
<li>The problems faced when doing it</li>
<li>The work to be done the same day</li>
<li>Only &#8216;pigs&#8217; can talk, &#8216;chickens&#8217; can listen, though</li>
</ul>
</li>
<li>&#8216;Pigs&#8217; are: developers, project owner and project facilitator; chickens are: clients, users, marketing people</li>
<li>Finish every new feature (sprint) at 100%; it is better off having 80% features at 100% than 100% features at 80%</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/07/29/scrum-agile-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL clean reinstall</title>
		<link>http://jorgealbaladejo.com/2010/07/27/mysql-clean-reinstall/</link>
		<comments>http://jorgealbaladejo.com/2010/07/27/mysql-clean-reinstall/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 19:08:14 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=397</guid>
		<description><![CDATA[To perform a clean reinstall of the MySQL server (which regenerates start scripts, databases and config files) use: ?View Code BASH1 2 3 4 sudo apt-get install mysql-server&#60;/li&#62; sudo apt-get remove --purge mysql-server&#60;/li&#62; sudo apt-get autoremove mysql-server&#60;/li&#62; sudo apt-get install mysql-server&#60;/li&#62; Some times is useful!]]></description>
			<content:encoded><![CDATA[<p>To perform a clean reinstall of the MySQL server (which regenerates start scripts, databases and config files) use:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p397code16'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39716"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p397code16"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> mysql-server<span style="color: #000000; font-weight: bold;">&lt;/</span>li<span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> remove <span style="color: #660033;">--purge</span> mysql-server<span style="color: #000000; font-weight: bold;">&lt;/</span>li<span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> autoremove mysql-server<span style="color: #000000; font-weight: bold;">&lt;/</span>li<span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> mysql-server<span style="color: #000000; font-weight: bold;">&lt;/</span>li<span style="color: #000000; font-weight: bold;">&gt;</span></pre></td></tr></table></div>

<p>Some times is useful!</p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/07/27/mysql-clean-reinstall/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FTP server on Ubuntu</title>
		<link>http://jorgealbaladejo.com/2010/07/06/ftp-server-on-ubuntu/</link>
		<comments>http://jorgealbaladejo.com/2010/07/06/ftp-server-on-ubuntu/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 20:12:11 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[FTP server]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[web server]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=372</guid>
		<description><![CDATA[This is the excerpt]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">I write this post more as a reminder for myself than as a generic tutorial. Anyway, it is about a precise FTP server configuration on Ubuntu that might or might not be useful for other people. It is just useful in the environment I am using (web server, just one Unix user, some FTP accounts). Here we go:</p>
<p style="text-align: justify;">The server that I&#8217;ve used in several cases, and which I prefer just because it is simple enough to have it running quickly, is <a href="https://help.ubuntu.com/6.06/ubuntu/serverguide/C/ftp-server.html" target="_blank" rel="external">VSFTP</a> (Very Simple FTP). It works in integration with the machine&#8217;s users so that we only need to add users to the server in order to have them available for the FTP daemon.  Once the server is installed, a few configurations must be done. In file <strong><em>/etc/vsftpd.conf</em></strong>:</p>
<p style="text-align: justify;"><span id="more-372"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p372code17'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37217"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p372code17"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Allow anonymous FTP? (Beware - allowed by default if you comment this out).</span>
<span style="color: #007800;">anonymous_enable</span>=NO
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Uncomment this to allow local users to log in.</span>
<span style="color: #007800;">local_enable</span>=YES
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Uncomment this to enable any form of FTP write command.</span>
<span style="color: #007800;">write_enable</span>=YES
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># You may restrict local users to their home directories.  See the FAQ for</span>
<span style="color: #666666; font-style: italic;"># the possible risks in this before using chroot_local_user or</span>
<span style="color: #666666; font-style: italic;"># chroot_list_enable below.</span>
<span style="color: #007800;">chroot_local_user</span>=YES</pre></td></tr></table></div>

<p style="text-align: justify;">So, let&#8217;s take a look at this configuration. First of all, it makes no sense having anonymous users on this machine. Then, we allow local users to connect to the FTP server, and give them write permissions. Finally, they are going to be confined to their local home directory, to make the server safe enough. But, what&#8217;s the point in that? After all, this is a web server, so we want the users to be able to update some web sites.</p>
<p style="text-align: justify;">The solution to this is to mount the specific folders of the Apache webroot directory into the user&#8217;s home page, depending on the right access it should have. A symbolic link is just not enough, since the system prevents FTP clients to follow them as they are outside the home root. A command line like:</p>
<p style="text-align: justify;">

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p372code18'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37218"><td class="code" id="p372code18"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #660033;">--bind</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>username<span style="color: #000000; font-weight: bold;">/</span>mountpoint<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>user_website<span style="color: #000000; font-weight: bold;">/</span></pre></td></tr></table></div>

<p style="text-align: justify;">would do the trick.</p>
<p style="text-align: justify;">A potential security risk is related to the use of this server. As long as FTP clients have to have a user in the machine, they potentially can log in into the server and execute code. First of all, one must ensure that these users do have just the essential access rights, but in addition, we can go further on protecting the server. In my case, the web server is a virtual machine in a cloud of computers, so there is not possible local access. Then, about SSH access, it is enough to specify the users that can log into the machine, so that we can have no matter how many users &#8211; allowed to access their home page through FTP &#8211; which cannot just execute anything on the machine. To do this, let&#8217;s edit <strong><em>/etc/ssh/sshd_config</em></strong>:</p>
<p style="text-align: justify;">

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p372code19'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37219"><td class="code" id="p372code19"><pre class="bash" style="font-family:monospace;">AllowUsers user1 user2 user3 ...</pre></td></tr></table></div>

<p style="text-align: justify;">With this setting, only the selected users can log in the machine via SSH access; the others are just confined to their home folders via the FTP server. And that&#8217;s all, just remember to restart both FTP and SSH services.</p>
<p>It is not the best FTP server I can have installed, but it is simple enough <img src='http://jorgealbaladejo.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/07/06/ftp-server-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Start a service or execute a script on boot on Ubuntu/Fedora</title>
		<link>http://jorgealbaladejo.com/2010/05/27/start-a-service-or-execute-a-script-on-boot-on-ubuntufedora/</link>
		<comments>http://jorgealbaladejo.com/2010/05/27/start-a-service-or-execute-a-script-on-boot-on-ubuntufedora/#comments</comments>
		<pubDate>Thu, 27 May 2010 19:25:14 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[bootstrap]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[run levels]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=365</guid>
		<description><![CDATA[I have a couple of servers with different Linux distributions (Ubuntu/Fedora) on my hands, which normally work continuously well. However, from time to time they reboot as they are hosted in a shared farm of virtual servers. It was in the first of those reboots when we noticed that neither Apache, neither MySQL servers were [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">I have a couple of servers with different Linux distributions (Ubuntu/Fedora) on my hands, which normally work continuously well. However, from time to time they reboot as they are hosted in a shared farm of virtual servers. It was in the first of those reboots when we noticed that neither Apache, neither MySQL servers were automatically launched on start-up, which should be the default configuration in an environment like ours.</p>
<p style="text-align: justify;">So, I&#8217;d like to add another new trick to my the knowledge pool, which I expect to be useful for others as well: <strong>how to configure scripts and services to run after the system boots</strong>?</p>
<h3 style="text-align: justify;"><span id="more-365"></span>Run levels</h3>
<p style="text-align: justify;">First of all, we need to know something about run levels in Linux systems. The numbers and their meaning <a href="http://en.wikipedia.org/wiki/Runlevel"title="Wikipedia: Runlevels"  target="_blank" rel="external">differ from one system to another</a>, but their main purpose remains:</p>
<ol style="text-align: justify;">
<li>Single-user mode</li>
<li>Multi-user mode</li>
<li>Multi-user mode with networking</li>
<li>Reserved for special purposes</li>
<li>Adds display manager to level 3</li>
</ol>
<p style="text-align: justify;">Thus, the &#8216;normal&#8217; run level we should use in a server environment is 3, which starts all the services, but does not care about X11 &#8211; which makes sense. This can be a first source of error if the default run level is not correctly selected, or it is tweaked to mimic another one which is the one that should be used instead. Anyway, to change this parameter we can go through: <strong><em>/etc/inittab</em></strong> and edit the line</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p365code23'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p36523"><td class="code" id="p365code23"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">id</span>:<span style="color: #000000;">3</span>:initdefault:</pre></td></tr></table></div>

</p>
<p style="text-align: justify;">After verifying this setting, we can go for the unit configurations for every service on every level.</p>
<h3 style="text-align: justify;">Services, daemons and servers</h3>
<p style="text-align: justify;">We can use the tool <em><strong>sysv-rc-conf</strong></em> under Ubuntu to easily mark or unmark the installed services that should run automatically with every run level. Normally, these configurations are correct, but it is no harm to double check, right? Under Fedora we can use <strong><em>chkconfig </em></strong>for the same purpose.</p>
<h3 style="text-align: justify;">Custom scripts and applications</h3>
<p style="text-align: justify;">There is still another way to configure the services and software that we want to be auto-executed on system start. Under <em><strong>/etc/rcX.d</strong></em> (where X is the run level) there are some simbolic links to all the commands, scripts and applications that should run with every run level. Then, an advanced way to configure the servers that we want to launch with the machine, or even better, the custom scripts that we want to execute with a wide range of purposes (maintenance, a specific folder mount, whatever), is to create a symbolic link under one of these folders.</p>
<p style="text-align: justify;">To create the link, the naming Sxx or Syy must be respected, where xx and yy are numbers which complement 100 (like K36mysqld and S64mysqld). The number is the order in which the command will be executed, and the letter (well &#8216;S&#8217;, well &#8216;K&#8217;) tells the system whether is a <strong>S</strong>tart or a <strong>K</strong>ill action, that&#8217;s to say, if the command specified should be executed when entering or when exiting the selected run level.</p>
<p style="text-align: justify;">As an example:</p>
<p style="text-align: justify;">

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p365code24'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p36524"><td class="code" id="p365code24"><pre class="text" style="font-family:monospace;">/etc/rc3.d/S99custom_mount -&gt; /etc/init.d/custom_mount.sh</pre></td></tr></table></div>

</p>
<h3 style="text-align: justify;">Alternatives</h3>
<p style="text-align: justify;">There are other possibilities to get the same result, like editing <em><strong>/etc/rc.local file</strong></em>, where we can write the commands we want to execute when the system has finished booting. Taking a look to the run level bootstrap default configuration, we may find:</p>
<p style="text-align: justify;">

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p365code25'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p36525"><td class="code" id="p365code25"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>rc3.d<span style="color: #000000; font-weight: bold;">/</span>S99rc.local -<span style="color: #000000; font-weight: bold;">&gt;</span> ..<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>rc.local</pre></td></tr></table></div>

</p>
<p style="text-align: justify;">Which means that the commands stated in this file will be executed at the very end of the system load in run level 3, that&#8217;s to say, after MySQL, Apache and the rest of servers and services.  Despite the simplicity of this alternative, I prefer the one exposed above, since it gives a full control on what is being executed, where, and when. And, of course, it gives a better comprehension of Linux environments, which is one of the primary targets of this article.</p>
<p style="text-align: justify;">Did you enjoy it? Leave a comment!</p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/05/27/start-a-service-or-execute-a-script-on-boot-on-ubuntufedora/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing a database cubes system on MySQL</title>
		<link>http://jorgealbaladejo.com/2010/05/11/implementing-a-database-cubes-system-on-mysql/</link>
		<comments>http://jorgealbaladejo.com/2010/05/11/implementing-a-database-cubes-system-on-mysql/#comments</comments>
		<pubDate>Tue, 11 May 2010 09:22:01 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[cubes]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[hourly averages]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=321</guid>
		<description><![CDATA[I&#8217;ve already talked about how I solved the problem of managing huge amounts of data in my last post. Now, I&#8217;m going to explain how to implement one of the solutions found in order to comfortably face this continuously increasing avalanche of information. Let&#8217;s imagine that, as I explained before, I have separated data input [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">I&#8217;ve already talked about how I solved the problem of managing huge amounts of data in <a href="http://jorgealbaladejo.com/?p=319" title="Managing big data sets with MySQL">my last post</a>. Now, I&#8217;m going to explain how to implement one of the solutions found in order to comfortably face this continuously increasing avalanche of information.</p>
<p style="text-align: justify;">Let&#8217;s imagine that, as I explained before, I have separated data input into tables coded by a station ID. All of them are stored in the same database for maintenance simplicity sake. So, we have the &#8216;database&#8217; in which there are hundreds of tables called &#8216;Station_XYZ&#8217;. Every table has the same structure: to simplify, SensorID, Time (UNIX), Value. All right then, time to make cubes!</p>
<p style="text-align: justify;"><span id="more-321"></span>First of all, I define a MySQL stored procedure to extract maximum, minimum and average values from these tables and to save them in a second &#8216;database_cubes_1h&#8217;, named so because this process will run every hour. Also, there is a table Stations in &#8216;database_main&#8217; (a third database to keep other application&#8217;s configurations), where all the stations ever installed are registered. We will use this table to know if a station exists and therefore its related table in database. A first draft would look like this:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p321code31'); return false;">View Code</a> MYSQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p32131"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code" id="p321code31"><pre class="mysql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
<span style="color: #808080; font-style: italic;">-- Procedure `fill_cubes_1h`</span>
<span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DROP" rel="external"><span style="color: #990099; font-weight: bold;">DROP</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=PROCEDURE" rel="external"><span style="color: #990099; font-weight: bold;">PROCEDURE</span></a> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=EXISTS" rel="external"><span style="color: #990099; font-weight: bold;">EXISTS</span></a> fill_cubes_1h<span style="color: #000033;">;</span>
&nbsp;
DELIMITER <span style="color: #CC0099;">//</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=CREATE" rel="external"><span style="color: #990099; font-weight: bold;">CREATE</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=PROCEDURE" rel="external"><span style="color: #990099; font-weight: bold;">PROCEDURE</span></a> fill_cubes_1h<span style="color: #FF00FF;">&#40;</span>$StationID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=INT" rel="external"><span style="color: #999900; font-weight: bold;">INT</span></a><span style="color: #FF00FF;">&#41;</span>
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=BEGIN" rel="external"><span style="color: #990099; font-weight: bold;">BEGIN</span></a>
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a> Station_ID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=IN" rel="external"><span style="color: #990099; font-weight: bold;">IN</span></a> <span style="color: #FF00FF;">&#40;</span><a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SELECT" rel="external"><span style="color: #990099; font-weight: bold;">SELECT</span></a> StationID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=FROM" rel="external"><span style="color: #990099; font-weight: bold;">FROM</span></a> <span style="color: #008000;">`database`</span>.<span style="color: #008000;">`Stations`</span><span style="color: #FF00FF;">&#41;</span>
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">THEN</span></a>
    <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> @strSQL <span style="color: #CC0099;">=</span> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/string-functions.html" rel="external"><span style="color: #000099;">CONCAT</span></a><span style="color: #FF00FF;">&#40;</span><span style="color: #008000;">'
      INSERT INTO `database<span style="color: #008080; font-weight: bold;">_</span>cubes<span style="color: #008080; font-weight: bold;">_</span>1h`.`Station<span style="color: #008080; font-weight: bold;">_</span>'</span><span style="color: #000033;">,</span>$StationID<span style="color: #000033;">,</span><span style="color: #008000;">'`
      SELECT
        SensorID,
        UNIX<span style="color: #008080; font-weight: bold;">_</span>TIMESTAMP(DATE<span style="color: #008080; font-weight: bold;">_</span>FORMAT(FROM<span style="color: #008080; font-weight: bold;">_</span>UNIXTIME(Time),&quot;<span style="color: #008080; font-weight: bold;">%</span>Y-<span style="color: #008080; font-weight: bold;">%</span>m-<span style="color: #008080; font-weight: bold;">%</span>d <span style="color: #008080; font-weight: bold;">%</span>H:00:00&quot;)) AS Hour,
        AVG(Value) AS Value,
        MAX(Value) AS ValueMax,
        MIN(Value) AS ValueMin
      FROM `database`.`Station<span style="color: #008080; font-weight: bold;">_</span>'</span><span style="color: #000033;">,</span>$StationID<span style="color: #000033;">,</span><span style="color: #008000;">'`
      WHERE
        Time &amp;gt;= UNIX<span style="color: #008080; font-weight: bold;">_</span>TIMESTAMP(DATE<span style="color: #008080; font-weight: bold;">_</span>FORMAT(NOW() - INTERVAL 1 HOUR,&quot;<span style="color: #008080; font-weight: bold;">%</span>Y-<span style="color: #008080; font-weight: bold;">%</span>m-<span style="color: #008080; font-weight: bold;">%</span>d <span style="color: #008080; font-weight: bold;">%</span>H:00:00&quot;))
      GROUP BY
        HOUR, SensorID
      ORDER BY
        HOUR ASC
    '</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span>
&nbsp;
    PREPARE statement <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=FROM" rel="external"><span style="color: #990099; font-weight: bold;">FROM</span></a> @strSQL<span style="color: #000033;">;</span>
    EXECUTE statement <span style="color: #000033;">;</span>
    DEALLOCATE PREPARE statement <span style="color: #000033;">;</span>
&nbsp;
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">ELSE</span></a>
    <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> @foo <span style="color: #CC0099;">=</span> <span style="color: #008000;">&quot;&quot;</span><span style="color: #000033;">;</span>
&nbsp;
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a><span style="color: #000033;">;</span>
&nbsp;
<a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a><span style="color: #000033;">;</span><span style="color: #CC0099;">//</span>
&nbsp;
DELIMITER <span style="color: #000033;">;</span></pre></td></tr></table></div>

<p style="text-align: justify;">Basically, it composes a query to extract averages from one table and insert into another at once. This query is run as a prepared statement so that we can reuse the function for all the stations in our database, as long as tables are always named as Station_XYZ. But, what does exactly it do?</p>
<ol style="text-align: justify;">
<li>Use a statement like &#8216;INSERT INTO table SELECT * FROM another_table. It will copy data automatically if the number and format of columns of the SELECT output and the INSERT INTO input are the same.</li>
<li>As Time is stored in UNIX EPOCH time, it is converted to ISO time, then only the hour is extracted, then it is converted back to UNIX. The result of this process is be able to group the result set by hour, getting rid off minutes and seconds. &#8220;UNIX_TIMESTAMP(DATE_FORMAT(FROM_UNIXTIME(Time),&#8221;%Y-%m-%d %H:00:00&#8243;)) AS Hour&#8221;</li>
<li>A WHERE condition filters the results for the last hour: &#8216;Time &gt;= UNIX_TIMESTAMP(DATE_FORMAT(NOW() &#8211; INTERVAL 1 HOUR,&#8221;%Y-%m-%d %H:00:00&#8243;))&#8217;.</li>
<li>Finally, the whole result set is grouped by Time, to be able to calculate averages, maximums and minimums. This statement does the grouping by respecting the different sensors that might have sent data on the same hourly interval &#8220;GROUP BY HOUR, SensorID&#8221; and the following ones perform calculations &#8220;AVG(Value) AS Value, MAX(Value) AS ValueMax, MIN(Value) AS ValueMin&#8221;.</li>
</ol>
<p style="text-align: justify;">Up to now we seem to have resolved the performance problem. Hourly cubes can be constructed and we only would need to add a sort of cron job. But, it is not so easy&#8230; I haven&#8217;t mentioned yet that data is not received synchronously. That means, within a time frame of three or four hours we could receive the data from a lazy or out of range station. That may be problematic, so&#8230;</p>
<p style="text-align: justify;">I&#8217;ve changed my stored procedure to do as follows:</p>
<ol style="text-align: justify;">
<li>Calculate the whole last day in hourly tranches, while keep running every hour. &#8220;WHERE Time &gt;= UNIX_TIMESTAMP(DATE_FORMAT(NOW() &#8211; INTERVAL 1 DAY,&#8221;%Y-%m-%d %H:00:00&#8243;)) AND Time &lt;= UNIX_TIMESTAMP(DATE_FORMAT(NOW() &#8211; INTERVAL 1 HOUR,&#8221;%Y-%m-%d %H:59:59&#8243;))&#8221;</li>
<li>Modify the query to allow update in case that a hourly cube was already calculated. &#8220;ON DUPLICATE KEY UPDATE `Value` = VALUES(`Value`)&#8221;</li>
</ol>
<p style="text-align: justify;">Please note that in order to get it correctly running, there should be an effective way to detect a duplicate key. In my case, I&#8217;ve used all fields but the value as primary keys, instead of defining a new artificial key field. Thus, SensorID and Time are primary keys, so there should never be more than one value for each combination of both. Doing so, MySQL detects duplicate and updates the third column, value, by throwing no errors. The whole stored procedure would look like this:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p321code32'); return false;">View Code</a> MYSQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p32132"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code" id="p321code32"><pre class="mysql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
<span style="color: #808080; font-style: italic;">-- Procedure `fill_cubes_1h`</span>
<span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DROP" rel="external"><span style="color: #990099; font-weight: bold;">DROP</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=PROCEDURE" rel="external"><span style="color: #990099; font-weight: bold;">PROCEDURE</span></a> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=EXISTS" rel="external"><span style="color: #990099; font-weight: bold;">EXISTS</span></a> fill_cubes_1h<span style="color: #000033;">;</span>
&nbsp;
DELIMITER <span style="color: #CC0099;">//</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=CREATE" rel="external"><span style="color: #990099; font-weight: bold;">CREATE</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=PROCEDURE" rel="external"><span style="color: #990099; font-weight: bold;">PROCEDURE</span></a> fill_cubes_1h<span style="color: #FF00FF;">&#40;</span>$StationID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=INT" rel="external"><span style="color: #999900; font-weight: bold;">INT</span></a><span style="color: #FF00FF;">&#41;</span>
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=BEGIN" rel="external"><span style="color: #990099; font-weight: bold;">BEGIN</span></a>
&nbsp;
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a> Station_ID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=IN" rel="external"><span style="color: #990099; font-weight: bold;">IN</span></a> <span style="color: #FF00FF;">&#40;</span><a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SELECT" rel="external"><span style="color: #990099; font-weight: bold;">SELECT</span></a> StationID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=FROM" rel="external"><span style="color: #990099; font-weight: bold;">FROM</span></a> <span style="color: #008000;">`database`</span>.<span style="color: #008000;">`Stations`</span><span style="color: #FF00FF;">&#41;</span>
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">THEN</span></a>
    <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> @strSQL <span style="color: #CC0099;">=</span> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/string-functions.html" rel="external"><span style="color: #000099;">CONCAT</span></a><span style="color: #FF00FF;">&#40;</span><span style="color: #008000;">'
      INSERT INTO `database<span style="color: #008080; font-weight: bold;">_</span>cubes<span style="color: #008080; font-weight: bold;">_</span>1h`.`Station<span style="color: #008080; font-weight: bold;">_</span>'</span><span style="color: #000033;">,</span>$StationID<span style="color: #000033;">,</span><span style="color: #008000;">'`
      SELECT
        SensorID,
        UNIX<span style="color: #008080; font-weight: bold;">_</span>TIMESTAMP(DATE<span style="color: #008080; font-weight: bold;">_</span>FORMAT(FROM<span style="color: #008080; font-weight: bold;">_</span>UNIXTIME(Time),&quot;<span style="color: #008080; font-weight: bold;">%</span>Y-<span style="color: #008080; font-weight: bold;">%</span>m-<span style="color: #008080; font-weight: bold;">%</span>d <span style="color: #008080; font-weight: bold;">%</span>H:00:00&quot;)) AS Hour,
        AVG(Value) AS Value,
        MAX(Value) AS ValueMax,
        MIN(Value) AS ValueMin
        FROM `database`.`Station<span style="color: #008080; font-weight: bold;">_</span>'</span><span style="color: #000033;">,</span>$StationID<span style="color: #000033;">,</span><span style="color: #008000;">'`
      WHERE
        Time &amp;gt;= UNIX<span style="color: #008080; font-weight: bold;">_</span>TIMESTAMP(DATE<span style="color: #008080; font-weight: bold;">_</span>FORMAT(NOW() - INTERVAL 1 DAY,&quot;<span style="color: #008080; font-weight: bold;">%</span>Y-<span style="color: #008080; font-weight: bold;">%</span>m-<span style="color: #008080; font-weight: bold;">%</span>d <span style="color: #008080; font-weight: bold;">%</span>H:00:00&quot;)) AND
        Time &amp;lt;= UNIX<span style="color: #008080; font-weight: bold;">_</span>TIMESTAMP(DATE<span style="color: #008080; font-weight: bold;">_</span>FORMAT(NOW() - INTERVAL 1 HOUR,&quot;<span style="color: #008080; font-weight: bold;">%</span>Y-<span style="color: #008080; font-weight: bold;">%</span>m-<span style="color: #008080; font-weight: bold;">%</span>d <span style="color: #008080; font-weight: bold;">%</span>H:59:59&quot;))
      GROUP BY
        HOUR, SensorID
      ORDER BY
        HOUR ASC
      ON DUPLICATE KEY UPDATE `Value` = VALUES(`Value`)
    '</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span>
&nbsp;
    PREPARE statement <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=FROM" rel="external"><span style="color: #990099; font-weight: bold;">FROM</span></a> @strSQL<span style="color: #000033;">;</span>
    EXECUTE statement <span style="color: #000033;">;</span>
    DEALLOCATE PREPARE statement <span style="color: #000033;">;</span>
&nbsp;
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">ELSE</span></a>
    <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> @foo <span style="color: #CC0099;">=</span> <span style="color: #008000;">&quot;&quot;</span><span style="color: #000033;">;</span>
&nbsp;
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a><span style="color: #000033;">;</span>
&nbsp;
<a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a> <span style="color: #000033;">;</span><span style="color: #CC0099;">//</span>
&nbsp;
DELIMITER <span style="color: #000033;">;</span></pre></td></tr></table></div>

<p style="text-align: justify;">The next step is to get this procedure running every hour for all the stations in the database. Now we are going to use our Stations table. The steps to follow are:</p>
<ol style="text-align: justify;">
<li>Request the highest station ID in Stations table</li>
<li>Since station ID&#8217;s are not sequential, get a way to determine if related table should exist</li>
<li>Tell the procedure to keep going if any exception raises</li>
<li>Run the loop until reach final station ID, and call the previous procedure passing current index as a parameter</li>
</ol>
<p style="text-align: justify;">The final result looks like:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p321code33'); return false;">View Code</a> MYSQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p32133"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code" id="p321code33"><pre class="mysql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
<span style="color: #808080; font-style: italic;">-- Procedure `climaps_main`.`fill_all_cubes_1h`</span>
<span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DROP" rel="external"><span style="color: #990099; font-weight: bold;">DROP</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=PROCEDURE" rel="external"><span style="color: #990099; font-weight: bold;">PROCEDURE</span></a> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=EXISTS" rel="external"><span style="color: #990099; font-weight: bold;">EXISTS</span></a> fill_all_cubes_1h<span style="color: #000033;">;</span>
&nbsp;
DELIMITER <span style="color: #CC0099;">//</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=CREATE" rel="external"><span style="color: #990099; font-weight: bold;">CREATE</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=PROCEDURE" rel="external"><span style="color: #990099; font-weight: bold;">PROCEDURE</span></a> fill_all_cubes_1h<span style="color: #FF00FF;">&#40;</span><span style="color: #FF00FF;">&#41;</span>
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=BEGIN" rel="external"><span style="color: #990099; font-weight: bold;">BEGIN</span></a>
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DECLARE" rel="external"><span style="color: #990099; font-weight: bold;">DECLARE</span></a> v <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=INTEGER" rel="external"><span style="color: #999900; font-weight: bold;">INTEGER</span></a><span style="color: #000033;">;</span>
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DECLARE" rel="external"><span style="color: #990099; font-weight: bold;">DECLARE</span></a> m <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=INTEGER" rel="external"><span style="color: #999900; font-weight: bold;">INTEGER</span></a><span style="color: #000033;">;</span>
&nbsp;
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DECLARE" rel="external"><span style="color: #990099; font-weight: bold;">DECLARE</span></a> CONTINUE <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=HANDLER" rel="external"><span style="color: #990099; font-weight: bold;">HANDLER</span></a> FOR SQLEXCEPTION <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=BEGIN" rel="external"><span style="color: #990099; font-weight: bold;">BEGIN</span></a> <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a><span style="color: #000033;">;</span>
&nbsp;
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> v <span style="color: #CC0099;">=</span> <span style="color: #008080;">0</span><span style="color: #000033;">;</span>
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> m <span style="color: #CC0099;">=</span> <span style="color: #FF00FF;">&#40;</span><a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SELECT" rel="external"><span style="color: #990099; font-weight: bold;">SELECT</span></a> StaID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=FROM" rel="external"><span style="color: #990099; font-weight: bold;">FROM</span></a> climaps_main.Stations <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=ORDER%20BY" rel="external"><span style="color: #990099; font-weight: bold;">ORDER BY</span></a> StaID <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DESC" rel="external"><span style="color: #990099; font-weight: bold;">DESC</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=LIMIT" rel="external"><span style="color: #990099; font-weight: bold;">LIMIT</span></a> <span style="color: #008080;">1</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span>
&nbsp;
  WHILE v <span style="color: #CC0099;">&amp;</span>lt<span style="color: #000033;">;</span><span style="color: #CC0099;">=</span> m <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DO" rel="external"><span style="color: #990099; font-weight: bold;">DO</span></a>
&nbsp;
    <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=CALL" rel="external"><span style="color: #990099; font-weight: bold;">CALL</span></a> fill_cubes_1h<span style="color: #FF00FF;">&#40;</span>v<span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span>
    <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=SET" rel="external"><span style="color: #990099; font-weight: bold;">SET</span></a> v <span style="color: #CC0099;">=</span> v <span style="color: #CC0099;">+</span> <span style="color: #008080;">1</span><span style="color: #000033;">;</span>
&nbsp;
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a> WHILE<span style="color: #000033;">;</span>
&nbsp;
<a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a><span style="color: #000033;">;</span><span style="color: #CC0099;">//</span>
&nbsp;
DELIMITER <span style="color: #000033;">;</span></pre></td></tr></table></div>

<p style="text-align: justify;">We&#8217;ve nearly finished! We have a way to build hourly cubes for a variable number of stations, and solving the problem of asynchronous data. We just need to create an event to run this last procedure, as we have stated above, every hour. This should work on MySQL 5.1</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p321code34'); return false;">View Code</a> MYSQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p32134"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code" id="p321code34"><pre class="mysql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
<span style="color: #808080; font-style: italic;">-- Event `database_main`.`fill_cubes_1h`</span>
<span style="color: #808080; font-style: italic;">-- -----------------------------------------------------</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DROP" rel="external"><span style="color: #990099; font-weight: bold;">DROP</span></a> EVENT <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">IF</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=EXISTS" rel="external"><span style="color: #990099; font-weight: bold;">EXISTS</span></a> fill_cubes_1h<span style="color: #000033;">;</span>
&nbsp;
DELIMITER <span style="color: #CC0099;">//</span>
&nbsp;
<a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=CREATE" rel="external"><span style="color: #990099; font-weight: bold;">CREATE</span></a> EVENT fill_cubes_1h
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=ON" rel="external"><span style="color: #990099; font-weight: bold;">ON</span></a> SCHEDULE EVERY <span style="color: #008080;">1</span> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=HOUR" rel="external"><span style="color: #9900FF; font-weight: bold;">HOUR</span></a>
  <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=DO" rel="external"><span style="color: #990099; font-weight: bold;">DO</span></a> <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=BEGIN" rel="external"><span style="color: #990099; font-weight: bold;">BEGIN</span></a>
      <a href="http://search.mysql.com/search?site=refman-%35%31&amp;q=CALL" rel="external"><span style="color: #990099; font-weight: bold;">CALL</span></a> fill_all_cubes_1h<span style="color: #FF00FF;">&#40;</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span>
  <a href="http://dev.mysql.com/doc/refman/%35%2E%31/en/control-flow-functions.html" rel="external"><span style="color: #009900;">END</span></a> <span style="color: #CC0099;">//</span>
&nbsp;
DELIMITER <span style="color: #000033;">;</span></pre></td></tr></table></div>

<p style="text-align: justify;">If for any reason we are not allowed to create events (all this stuff should be run as a user with whole access to the tables involved), or we are running a MySQL version lower than 5.1, a cron job should be run instead. Just get EXECUTE access on the database where the procedures have been created (on my case, database_main), and add this line to crontab:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p321code35'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p32135"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p321code35"><pre class="bash" style="font-family:monospace;"><span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> mysql <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'CALL database_main.fill_all_cubes_1h()'</span></pre></td></tr></table></div>

<p style="text-align: justify;">Please note that to get this statement running without asking for a password, you need to create a .my.cnf file in your home directory (UNIX systems)</p>
<p style="text-align: justify;">And that&#8217;s all!</p>
<p style="text-align: justify;">So, what do you think? What&#8217;s your method? Comments and feedback are much appreciated <img src='http://jorgealbaladejo.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/05/11/implementing-a-database-cubes-system-on-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Managing big data sets with MySQL</title>
		<link>http://jorgealbaladejo.com/2010/05/05/managing-big-data-sets-with-mysql/</link>
		<comments>http://jorgealbaladejo.com/2010/05/05/managing-big-data-sets-with-mysql/#comments</comments>
		<pubDate>Wed, 05 May 2010 15:23:31 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[big data sets]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=319</guid>
		<description><![CDATA[I&#8217;m currently working on a database which stores, literally, a million of new data registers every day. They come from several hundred weather stations spread along the world, and need to be processed on real time. That&#8217;s a huge amount to be managed with a simple &#8211; but powerful &#8211; MySQL server, so I&#8217;ve had [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">I&#8217;m currently working on a database which stores, literally, a million of new data registers every day. They come from several hundred weather stations spread along the world, and need to be processed on real time. That&#8217;s a huge amount to be managed with a simple &#8211; but powerful &#8211; MySQL server, so I&#8217;ve had to design and implement a few tricks in order to succeed.</p>
<p style="text-align: justify;">In this post I&#8217;d like to talk about the main three techniques we&#8217;ve used to engage our high performance database, and the reasons to choose these solutions.</p>
<p style="text-align: justify;">First of all, MySQL innodb tables start <strong>degrading </strong>at some million registers  (7-10M on my current server, but not tested further), so the first though I had was: we need to <strong>divide if we want to conquer</strong>. Then, after some thinking about, I decided to split the big table into small chunks, and use a table for each station. That made the whole problem more affordable, and tables smaller enough not to become scary: the new problem was how to store about 5 M registers per year per table in our database.</p>
<p style="text-align: justify;">Of course, some logic in both the application controller and the data input server was needed to correctly place data registers. Additionally, tables get often fragmented so some cron jobs were needed to keep the database running smoothly. But there was still the problem of data growing. As long as registers were separated depending on the station, the scalability problem was solved: more tables can be added, even more servers with ranges of stations and a hash function to calculate what server is a given station hosted in. Once again were we talking about several million registers per year per table, and with a standart MySQL 5.1 server (the main problem with an start-up company tends to be funding, so we didn&#8217;t have anything better).</p>
<p style="text-align: justify;"><span id="more-319"></span></p>
<p style="text-align: justify;">Then a second solution came out: since 80% of queries are performed over the last few years of data, let&#8217;s <strong>move oldest registers to depot tables</strong>! This way, data used most often will be kept on relatively small (affordable, at least) tables, and the rest will be just stored.  So a big problem had turned into a matter of designing some queries over a bunch of tables, in a way that can be easily automated. Great! And it&#8217;s been so for a while, until we&#8217;ve realized that even with small tables, we are handing huge sets of data to represent evolution of physical variables along time. I&#8217;m talking about high resolution data, let&#8217;s say a measure every minute for some types of sensor, which makes sense to study minor variations along the day.</p>
<p style="text-align: justify;">It&#8217;s now when we start thinking about cubes &#8211; resumes. The real headache with big data sets starts when comparing a whole month range of values, which will produce several thousand registers to represent on a 800px wide plot graph&#8230; that&#8217;s basically a waste of server processor and memory resources, since we are providing a resolution which is not adapted to the circumstances.</p>
<p style="text-align: justify;">So now we have a third solution which is based on <strong>averages</strong>. MySQL &#8211; as other database engines &#8211; allows creating averages on the fly which is further better than relying these operations on the application layer. The problem beneath is that a big data set must be evaluated on demand, and this for every user on the website (we barely can cache MySQL responses because values change every 10 minutes). To fix it, we&#8217;ve decided to run these operations just once every hour, and store the results on cubes &#8211; tables with resumes &#8211; which would be consulted instead of the high density original ones. The algorithm to determine the table to look is simple: if the range of data is larger than several days, just use the hourly resolution instead. To automate this, we&#8217;ve added some naming convention, let&#8217;s say, all data tables are named the same way (based on the station ID), and only the database name (based on the data resolution) changes.</p>
<p style="text-align: justify;">To finish with, I&#8217;d like to advance the construction of this cubes generation process:</p>
<ol style="text-align: justify;">
<li> A stored procedure calculates averages for a given period for a given table</li>
<li>Another stored procedure launches the first one for all the tables; it is defined to be called from whatever time event handler we use</li>
<li>The event handler is defined, well in MySQL engine, well as a cron job</li>
</ol>
<p style="text-align: justify;">I&#8217;ll talk about the implementation details in further posts&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/05/05/managing-big-data-sets-with-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tunneling a multipart POST message through PHP and CURL</title>
		<link>http://jorgealbaladejo.com/2010/05/05/tunneling-a-multipart-post-message-through-php-and-curl/</link>
		<comments>http://jorgealbaladejo.com/2010/05/05/tunneling-a-multipart-post-message-through-php-and-curl/#comments</comments>
		<pubDate>Wed, 05 May 2010 14:50:51 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Php]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[post]]></category>
		<category><![CDATA[tunneling]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=347</guid>
		<description><![CDATA[Tunneling a multipart POST message through PHP and CURL]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">In this post I&#8217;m going to cover a particular solution to a given problem we&#8217;ve faced up in our last project. Let&#8217;s set the background: there is a complex web application under development on a shared virtual machine, installed on a subdomain of a public network that will change when going to production. We have also a commercial website hosted in a shared server under a domain that should not change, since it is our first step out of this virtual farm.</p>
<p style="text-align: justify;">For this project, we require to integrate some cameras which send pictures via GPRS connections to the server, and we want to provide some user authentication to avoid having anybody posting whatever to this web service. So, we have developed a controller in Code Igniter which gets a camera ID / password from POST, and also the bytes for the image, and proceeds to do some filtering. For instance, camera ID and password should match with the values previously registered in the database, and the picture should be MIME image/jpeg, with a limit of 2MBs. Up to now, nothing special, tested and working with POSTS from the within the website.</p>
<p style="text-align: justify;">The problem came when we found out that cameras only allow to send their information to a root domain, to a particular file, let&#8217;s say upload.php. So, we would only need to put this file in the root path and it&#8217;s done. Unfortunately, doing so in the application virtual server would result on flashing again all the cameras once we move to a new server and set up a final domain name. We might be able to install this receiver in the commercial website root path, but then we would require to send the message back to the application server in any way, so it is not the best solution we want to solve this issue.</p>
<p style="text-align: justify;">&#8216;Just add a domain that points to this subdomain and you are done&#8217; would you say. Well, yes, that would have done the trick. Unfortunately, we cannot host this domain in the machine since we have no administrator rights on the servers farm. Nor can we just use this external domain because it produces an HTTP redirection which, to make things worse, is not supported by the camera. We&#8217;ve even tried with cloaking the url of the receiver with an external subdomain, with no success &#8211; since cloaking wraps the real content inside an iframe and it breaks the POST message.</p>
<p style="text-align: justify;">What a headache! it seemed there was no way to implement the system with the full functionality we wanted&#8230;</p>
<p style="text-align: justify;"><span id="more-347"></span>At thas moment we were a bit puzzled because we had to choose between two main options, which in any case took us away from the initial implementation design:</p>
<ul style="text-align: justify;">
<li>hosting the receiver script in a subdomain that would change</li>
<li>hosting it in a fixed external domain (the commercial website) and try to send the messages back to the application server</li>
<li>in any case, we would have to implement the features planned for the Code Igniter controller in this new stand-alone script, which would produce extra work and remove some built-in capabilities</li>
</ul>
<p style="text-align: justify;">How to fix this problem? Well, he have chosen a variant of #2: try to send the messages back to the application server. But how exactly? Well, by <strong>tunneling the multipart POST message with <a href="http://ch2.php.net/manual/en/book.curl.php"title="PHP CURL"  target="_blank" rel="external">CURL</a></strong>.</p>
<p style="text-align: justify;">To achieve our goal we have written a script which is hosted in the domain root of the commercial website, with does the following:</p>
<ol style="text-align: justify;">
<li>Reads the serial number sent by the camera</li>
<li>Reads the temporary upload file, and moves it to a specified folder</li>
<li>Initializes and configures PHP-CURL to generate a new POST message with the data recovered and the image content as multipart form</li>
<li>Deletes the temporary file created</li>
</ol>
<p style="text-align: justify;">And<strong> the code</strong>:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?" rel="external"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p347code36'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p34736"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code" id="p347code36"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * @file upload.php
 * This pipeline grabs a POST message and sends it back to a processing server
 * It is meant to solve a particular problem where the sender device has limited
 *  HTTP functionalities like being unable to deal with Apache redirections
 *
 * This code is just an example, you may use for learning purposes
 *
 */</span>
<span style="color: #666666; font-style: italic;">// camera serial number, it is barely filtered because the real processing</span>
<span style="color: #666666; font-style: italic;">//  is to be done in the final server</span>
<span style="color: #000088;">$csn</span>	<span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span> <a href="http://www.php.net/isset" rel="external"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'CSN'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'CSN'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// we need to locally store the file to resend it</span>
<span style="color: #000088;">$file</span> 	<span style="color: #339933;">=</span> <span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'userfile'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tmp</span> 	<span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;tmp/&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/move_uploaded_file" rel="external"><span style="color: #990000;">move_uploaded_file</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;tmp_name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tmp</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// post information is rebuilt</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array" rel="external"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'CSN'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$csn</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'userfile'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'@'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$tmp</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// note the @ which tells CURL that this field is a file</span>
<span style="color: #666666; font-style: italic;">// this will be automatically interpreted as a application/multipart form</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// init and configure curl</span>
<span style="color: #000088;">$ch</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/curl_init" rel="external"><span style="color: #990000;">curl_init</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/curl_setopt" rel="external"><span style="color: #990000;">curl_setopt</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_URL<span style="color: #339933;">,</span> <span style="color: #0000ff;">'http://the-application-server/path/controller/method'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/curl_setopt" rel="external"><span style="color: #990000;">curl_setopt</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_POST<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/curl_setopt" rel="external"><span style="color: #990000;">curl_setopt</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_POSTFIELDS<span style="color: #339933;">,</span> <span style="color: #000088;">$data</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// finally, send</span>
<a href="http://www.php.net/curl_exec" rel="external"><span style="color: #990000;">curl_exec</span></a> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// and delete the locally stored file</span>
<a href="http://www.php.net/unlink" rel="external"><span style="color: #990000;">unlink</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2010/05/05/tunneling-a-multipart-post-message-through-php-and-curl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Managing a web development project</title>
		<link>http://jorgealbaladejo.com/2009/05/07/managing-a-web-development-project/</link>
		<comments>http://jorgealbaladejo.com/2009/05/07/managing-a-web-development-project/#comments</comments>
		<pubDate>Thu, 07 May 2009 12:02:16 +0000</pubDate>
		<dc:creator>Jorge Albaladejo</dc:creator>
				<category><![CDATA[Project Management]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[project management]]></category>
		<category><![CDATA[web develop]]></category>

		<guid isPermaLink="false">http://jorgealbaladejo.com/?p=303</guid>
		<description><![CDATA[There are many types of websites, as well as sizes and complexity. At the beginning, most of my creations were constructed &#8216;on the fly&#8217;, without much planning &#8211; in the end, a &#8216;news&#8217; module is not scary enough to need a project. But recently I&#8217;ve started working on more ambitious jobs (like http://climaps.com), and feeling [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">There are many types of websites, as well as sizes and complexity. At the beginning, most of my creations were constructed &#8216;on the fly&#8217;, without much planning &#8211; in the end, a &#8216;news&#8217; module is not scary enough to need a project.</p>
<p style="text-align: justify;">But recently I&#8217;ve started working on more ambitious jobs (like <a href="http://climaps.com" title="Climaps" target="_blank" rel="external">http://climaps.com</a>), and feeling the need of a strongly defined method to apply to web applications design. Some tools are almost mandatory, like <a href="http://en.wikipedia.org/wiki/Use_case_diagram" target="_blank" rel="external">Use Case Diagrams</a> which become really helpful in order to translate what every user can do into <a href="http://en.wikipedia.org/wiki/Access_control_list" title="access control lists" target="_blank" rel="external">ACL</a>&#8216;s, methods, controllers, etc; or like <a href="http://dev.mysql.com/workbench/"  title="MySQL WorkBench" target="_blank" rel="external">modeling tools</a> to graphically represent the application&#8217;s database.</p>
<p style="text-align: justify;">But the best way &#8211; according to my experience &#8211; to successfully manage a web project is following a detailed planning. Determining what the steps are and what order should they be executed in, is a good starting point to know were exactly we are on each development stage.</p>
<p style="text-align: justify;"><span id="more-303"></span></p>
<p style="text-align: justify;">Thus, I want to clarify that I&#8217;m not talking about software, applications or techniques to effectively manage big web projects; I don&#8217;t have this experience to talk about. Instead, I&#8217;m referring to the main steps I&#8217;ve followed in the past to handle the web projects I&#8217;ve worked on, steps which have proved to be effective. This article does not describe a rule but a personal way of doing things, and I&#8217;ll be glad to know your thoughts about it. What tools do you use to build your websites? Comments are welcome <img src='http://jorgealbaladejo.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: justify;">The following diagram shows an overview of the entire process:</p>
<p style="text-align: justify;">
<div id="attachment_304" class="wp-caption aligncenter" style="width: 433px"><img class="size-full wp-image-304" title="web_project_flow" src="http://jorgealbaladejo.com/wp-content/uploads/2009/05/web_project_flow.png" alt="Web project management flow" width="423" height="685" /><p class="wp-caption-text">Web project management flow</p></div>
<p style="text-align: justify;">
<p style="text-align: justify;"><!-- 	 	 --></p>
<h2>Chronological steps to follow</h2>
<ol>
<li><strong>Business</strong>: 	<em>Analysis of requirements</em></li>
<li><strong>Business</strong>: 	<em>Get data model</em></li>
<li><strong>Database</strong>: 	<em>Design</em>
<ul>
<li>get to 3FN and study going beyond</li>
</ul>
</li>
<li><strong>Database</strong>: 	<em>Implementation</em>
<ul>
<li>select a database engine</li>
<li>determine storage engine</li>
<li>develop triggers, views, and additional features</li>
<li>develop maintenance and backup scripts</li>
</ul>
</li>
<li><strong>Database</strong>: 	<em>Life time </em>(*)
<ul>
<li>design plan for durability</li>
<li>implement and estimate 	performance</li>
<li>develop triggers, views, and additional features</li>
<li>design libraries to make it transparent for the 	application</li>
</ul>
</li>
<li><strong>Application</strong>: 	<em>Use Case Diagrams</em>
<ul>
<li>represent different user profiles</li>
<li>review with client</li>
</ul>
</li>
<li><strong>PHP</strong>: 	<em>Develop initial system </em>(*)
<ul>
<li>choose a framework</li>
<li>set up initial libraries and systems</li>
<li>design template&#8217;s system</li>
<li>unitary tests system</li>
</ul>
</li>
<li><strong>PHP</strong>: 	<em>Core develop for all functionalities</em>
<ul>
<li>programming all functions needed for cases of use</li>
<li>generation of a initial HTML view</li>
</ul>
</li>
<li><strong>PHP</strong>: 	<em>Tests and bug fixing</em>
<ul>
<li>use unitary tests</li>
<li>use functional tests</li>
</ul>
</li>
<li><strong>HTML</strong>: 	<em>Finish structure</em>
<ul>
<li>use semantic code</li>
<li>define attributes for accessibility</li>
<li>run Hera, eXaminator, w3c and other tools and make adjustments</li>
</ul>
</li>
<li><strong>CSS</strong>: 	<em>Definition </em>(*)
<ul>
<li>design a CSS files structured system</li>
<li>start filling with some initial design</li>
<li>run W3C CSS test</li>
</ul>
</li>
<li><strong>Design</strong>: 	<em>External outsource </em>(*)
<ul>
<li>slice design in usable blocks</li>
<li>apply design through HTML images and CSS</li>
</ul>
</li>
<li><strong>Standards 	compliance</strong>: <em>Tests and adjustments</em>
<ul>
<li>multi platform: 	check browsers compliance: check IE, Firefox, safari</li>
<li>run again 	W3C tests for HTML and CSS</li>
<li>run again Hera, eXaminator and 	other accessibility checks</li>
<li>layout adjustments</li>
</ul>
</li>
<li><strong>Ajax</strong>: 	<em>Analysis of requirements</em>
<ul>
<li>cases of use diagram, with different user profiles</li>
<li>determine functionalities to be available</li>
</ul>
</li>
<li><strong>Ajax</strong>: 	<em>Setting up </em>(*)
<ul>
<li>determining a framework to work with</li>
<li>establishing folder distribution</li>
<li>determine unitary and functional tests systems</li>
</ul>
</li>
<li><strong>Ajax</strong>: 	<em>Implementation</em>
<ul>
<li>develop all functionalities</li>
<li>add necessary PHP back ends in XML 	/ HTML format</li>
</ul>
</li>
<li><strong>Ajax</strong>: 	<em>Test</em>
<ul>
<li>apply test cases</li>
<li>make adjustments</li>
</ul>
</li>
<li><strong>Summary</strong>: 	<em>Final review</em>
<ul>
<li>presentation of website to client</li>
<li>getting feedback</li>
<li>taking notes for a new wheel&#8217;s spin</li>
</ul>
</li>
</ol>
<p><!-- 	 	 --></p>
<p><strong>Note</strong>: sections marked with (*) can be avoided when adding new modules to a previously developed application.</p>
]]></content:encoded>
			<wfw:commentRss>http://jorgealbaladejo.com/2009/05/07/managing-a-web-development-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
