<?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>Softcore software development &#187; programming</title>
	<atom:link href="http://tea.cesaroliveira.net/archives/category/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://tea.cesaroliveira.net</link>
	<description>It&#039;s all about the cycles</description>
	<lastBuildDate>Tue, 24 Jan 2012 04:31:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A breakdown of building Firefox</title>
		<link>http://tea.cesaroliveira.net/archives/389</link>
		<comments>http://tea.cesaroliveira.net/archives/389#comments</comments>
		<pubDate>Tue, 24 Jan 2012 04:31:50 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[bungineer]]></category>
		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=389</guid>
		<description><![CDATA[John Ford posted an interesting post on improving the build times of mac minis. This largely turned out to be a hardware solution (spend enough money on solid state drives and more cores and things are likely to improve). But that is expensive. What is interesting to me though is the build times. 2 hours [...]]]></description>
			<content:encoded><![CDATA[<p>John Ford posted an interesting post on <a href="http://blog.johnford.info/new-mac-builders-ssds-j-settings/" onclick="pageTracker._trackPageview('/outgoing/blog.johnford.info/new-mac-builders-ssds-j-settings/?referer=');">improving the build times of mac minis</a>. This largely turned out to be a hardware solution (spend enough money on solid state drives and more cores and things are likely to improve). But that is expensive. What is interesting to me though is the build times. 2 hours for a dual core set-up?</p>
<p>For a long time the only really thing you can do is pass -jN. -j merely parallelized the process. It was a good idea to have -j2 even on a single core just so that the CPU was busy doing something. That was often the weak point, you just couldn&#8217;t compile fast enough.</p>
<p>Of course, now we have dual-tri-quad cores, so now it wasn&#8217;t how fast you can compile but how fast you can write to disk. Solid state drives can help close that gap.</p>
<p>But Firefox is a huge project. At some point the cost of hardware to compile it in 10 seconds is just too significant, even for <a href="http://blog.mozilla.com/blog/2011/12/20/mozilla-and-google-sign-new-agreement-for-default-search-in-firefox/" onclick="pageTracker._trackPageview('/outgoing/blog.mozilla.com/blog/2011/12/20/mozilla-and-google-sign-new-agreement-for-default-search-in-firefox/?referer=');">Mozilla with it&#8217;s fancy new Google-deal</a>.</p>
<p>I wondered where the build was spending most of its time. I couldn&#8217;t find anything to profile make (at least not through the man page, and the name is not google friendly, and people don&#8217;t call it gmake anymore <img src='http://tea.cesaroliveira.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ). Since what I want to do is pretty simple, I downloaded the source and made a few changes to log the <a href="http://pubs.opengroup.org/onlinepubs/009604499/functions/time.html" onclick="pageTracker._trackPageview('/outgoing/pubs.opengroup.org/onlinepubs/009604499/functions/time.html?referer=');">seconds since epoch</a> when we enter/leave a directory. A crappy python script later, and here is the broken results:</p>
<p>Total time for accessible is 77 seconds. Project was entered 3 times<br />
Total time for b2g is 0 seconds. Project was entered 0 times<br />
Total time for browser is 13 seconds. Project was entered 3 times<br />
Total time for build is 0 seconds. Project was entered 3 times<br />
Total time for caps is 6 seconds. Project was entered 3 times<br />
Total time for chrome is 6 seconds. Project was entered 3 times<br />
Total time for config is 0 seconds. Project was entered 3 times<br />
Total time for content is 572 seconds. Project was entered 3 times<br />
Total time for db/sqlite3/src is 7 seconds. Project was entered 3 times<br />
Total time for dbm is 0 seconds. Project was entered 0 times<br />
Total time for docshell is 16 seconds. Project was entered 3 times<br />
Total time for dom is 223 seconds. Project was entered 3 times<br />
Total time for editor is 56 seconds. Project was entered 3 times<br />
Total time for embedding is 23 seconds. Project was entered 3 times<br />
Total time for gfx is 106 seconds. Project was entered 3 times<br />
Total time for hal is 6 seconds. Project was entered 3 times<br />
Total time for image is 18 seconds. Project was entered 3 times<br />
Total time for intl is 31 seconds. Project was entered 3 times<br />
Total time for ipc is 186 seconds. Project was entered 3 times<br />
Total time for js/ductwork/debugger is 1 seconds. Project was entered 3 times<br />
Total time for js/examples is 0 seconds. Project was entered 0 times<br />
Total time for js/ipc is 3 seconds. Project was entered 3 times<br />
Total time for js/jsd is 3 seconds. Project was entered 3 times<br />
Total time for js/public is 0 seconds. Project was entered 0 times<br />
Total time for js/src is 17 seconds. Project was entered 4 times<br />
Total time for js/xpconnect is 61 seconds. Project was entered 3 times<br />
Total time for layout is 378 seconds. Project was entered 3 times<br />
Total time for media/libjpeg is 3 seconds. Project was entered 3 times<br />
Total time for media/libnestegg is 0 seconds. Project was entered 3 times<br />
Total time for media/libogg is 1 seconds. Project was entered 3 times<br />
Total time for media/libpng is 1 seconds. Project was entered 3 times<br />
Total time for media/libsydneyaudio is 0 seconds. Project was entered 3 times<br />
Total time for media/libtheora is 2 seconds. Project was entered 3 times<br />
Total time for media/libtremor is 0 seconds. Project was entered 0 times<br />
Total time for media/libvorbis is 2 seconds. Project was entered 3 times<br />
Total time for media/libvpx is 3 seconds. Project was entered 3 times<br />
Total time for memory/jemalloc is 0 seconds. Project was entered 3 times<br />
Total time for memory/mozalloc is 0 seconds. Project was entered 3 times<br />
Total time for mfbt is 0 seconds. Project was entered 3 times<br />
Total time for mobile is 0 seconds. Project was entered 0 times<br />
Total time for modules/freetype2 is 0 seconds. Project was entered 0 times<br />
Total time for modules/libbz2 is 1 seconds. Project was entered 3 times<br />
Total time for modules/libjar is 6 seconds. Project was entered 3 times<br />
Total time for modules/libmar is 1 seconds. Project was entered 3 times<br />
Total time for modules/libpref is 7 seconds. Project was entered 3 times<br />
Total time for modules/zlib is 1 seconds. Project was entered 3 times<br />
Total time for mozglue is 0 seconds. Project was entered 3 times<br />
Total time for netwerk is 126 seconds. Project was entered 3 times<br />
Total time for nsprpub is 2 seconds. Project was entered 2 times<br />
Total time for other-licenses is 0 seconds. Project was entered 0 times<br />
Total time for parser is 29 seconds. Project was entered 3 times<br />
Total time for probes is 0 seconds. Project was entered 3 times<br />
Total time for profile is 3 seconds. Project was entered 3 times<br />
Total time for rdf is 14 seconds. Project was entered 3 times<br />
Total time for security/coreconf is 0 seconds. Project was entered 0 times<br />
Total time for security/dbm is 0 seconds. Project was entered 0 times<br />
Total time for security/manager is 109 seconds. Project was entered 3 times<br />
Total time for security/nss/lib is 0 seconds. Project was entered 0 times<br />
Total time for services is 2 seconds. Project was entered 3 times<br />
Total time for startupcache is 3 seconds. Project was entered 3 times<br />
Total time for storage is 28 seconds. Project was entered 3 times<br />
Total time for testing is 0 seconds. Project was entered 0 times<br />
Total time for toolkit is 88 seconds. Project was entered 3 times<br />
Total time for tools is 0 seconds. Project was entered 0 times<br />
Total time for uriloader is 19 seconds. Project was entered 3 times<br />
Total time for view is 2 seconds. Project was entered 3 times<br />
Total time for widget is 40 seconds. Project was entered 3 times<br />
Total time for xpcom is 85 seconds. Project was entered 3 times<br />
Total time for xpfe/appshell is 8 seconds. Project was entered 3 times<br />
Total time for xpfe/components is 3 seconds. Project was entered 3 times<br />
Total time for xpfe/test is 0 seconds. Project was entered 0 times<br />
Total time for xulrunner is 0 seconds. Project was entered 0 times<br />
The total time calculated is 2398</p>
<p>The total time is off. Firstly, you&#8217;ll see NSS is not being tracked. What usually happens is that the Makefile is generated in the object directory. In the case of NSS, it comes with a Makefile already. This is breaking my script, but it takes approx. 72 seconds.</p>
<p>Secondly, The totally time since I ran &#8220;make -f client.mk build&#8221; is approx 2662 seconds. Even factoring in the NSS time, that still leaves 3 minutes unaccounted for. So I still might be missing some projects. Part of that time was spent traversing the tree and running configure.</p>
<p>In the past, when we only had single-core computers, we tried fixing the problem by using tools like distcc to distribute the load to slave machines. With multi-core machines, this is less and less ideal since the overhead is quite substantial (a preprocessed file would go through and object files come back). However, I wonder if we can achieve better build times by distributing projects across machines. That would present some challenges (like dependencies), but it might give better results.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/389/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image prefetching</title>
		<link>http://tea.cesaroliveira.net/archives/371</link>
		<comments>http://tea.cesaroliveira.net/archives/371#comments</comments>
		<pubDate>Thu, 01 Dec 2011 05:45:59 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[derp]]></category>
		<category><![CDATA[prefetch]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=371</guid>
		<description><![CDATA[As part of a personal website I am doing, I transition between several large (1920 pixels wide) images. It is beneficial for me to do two things : Cache the images so they don&#8217;t keep taking up my bandwidth Prefetch the images so that a noticeable lag isn&#8217;t taking place while the image loads. Caching [...]]]></description>
			<content:encoded><![CDATA[<p>As part of a personal website I am doing, I transition between several large (1920 pixels wide) images. It is beneficial for me to do two things :</p>
<ol>
<li>Cache the images so they don&#8217;t keep taking up my bandwidth</li>
<li>Prefetch the images so that a noticeable lag isn&#8217;t taking place while the image loads.</li>
</ol>
<p>Caching is a bit tricky. While I want the names to stay consistant, I also want to be able to change the images at anytime. What I want is the browser to cache <a href="http://kittenwar.com/c_images/2008/08/06/162954.2.jpg" onclick="pageTracker._trackPageview('/outgoing/kittenwar.com/c_images/2008/08/06/162954.2.jpg?referer=');">kitten.jpg</a> until next year, or until I decide that I want a different kitten image and it should pick the new <a href="http://kittenwar.com/c_images/2006/08/10/84180.1.jpg" onclick="pageTracker._trackPageview('/outgoing/kittenwar.com/c_images/2006/08/10/84180.1.jpg?referer=');">kitten.jpg</a> (almost) immediately.</p>
<p>I have seen this problem solved in <a href="http://rubyonrails.org/" onclick="pageTracker._trackPageview('/outgoing/rubyonrails.org/?referer=');">Ruby on Rails</a>. What they did is append some query string identifier as part of the image. So instead of retrieving kitten.jpg, you would retrieve kitten.jpg?mittens. When the image changed, so did the identifier to something like kitten.jpg?bucket. This lets you cache aggressively, while still being able to change the image fairly regularly. (I am aware of other headers such as Last-Modified that might be a better solution. But from my understanding that only works with documents and not images. If an image is cached, the browser will use it until it expires as opposed to doing a HEAD request to see whether the Last-Modified date changed. I could be wrong about this).</p>
<p>I decided to do something similar, in that the md5 of the file will be appended.</p>
<p>The other thing I was missing was prefetching. I understand I could easily do this by hiding a bunch of images in the HTML page, or dynamically creating an Image object and setting the source. But this is 2011 dammit. We have standards that were promised, and behold <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#link-type-prefetch" onclick="pageTracker._trackPageview('/outgoing/www.whatwg.org/specs/web-apps/current-work/multipage/links.html_link-type-prefetch?referer=');">link prefetching</a>! It turns out only Mozilla and Webkit support this, which is lame. But that&#8217;s fine considering this website is only for my use.</p>
<p>I put in a pretch link using this method and used Firebug&#8217;s net panel to see whether it was working. And apparently it didn&#8217;t. I found out much later on that Firebug doesn&#8217;t capture it. You have to look at the server&#8217;s access log so see whether the image was retrieved.</p>
<p>Next, I checked out <a href="https://developer.mozilla.org/en/Link_prefetching_FAQ" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/en/Link_prefetching_FAQ?referer=');">Mozilla link prefetching FAQ</a>, which informed me that URLS with query strings are not prefetched. I found out much later that this is a lie (<a href="https://developer.mozilla.org/index.php?title=en/Link_prefetching_FAQ&#038;action=diff&#038;revision=27&#038;diff=28" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/index.php?title=en/Link_prefetching_FAQ_038_action=diff_038_revision=27_038_diff=28&amp;referer=');">and removed it</a>). This was actually fixed back in <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=185692" onclick="pageTracker._trackPageview('/outgoing/bugzilla.mozilla.org/show_bug.cgi?id=185692&amp;referer=');">2003</a> by someone who also thought it was stupid.</p>
<p>So here I am, also at 01:00. Reheated a plate of pasta and now enjoying some lukewarm soup. I promised myself yesterday I would be in bed by 23:00 at the latest. Tomorrow will be unpleasant, but at least this feels accomplishing.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/371/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing a django project</title>
		<link>http://tea.cesaroliveira.net/archives/363</link>
		<comments>http://tea.cesaroliveira.net/archives/363#comments</comments>
		<pubDate>Wed, 30 Nov 2011 02:29:53 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[mess]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=363</guid>
		<description><![CDATA[I have been working on a Django application for a few weeks and want to put it on my website. Tom suggested that I put it on bitbucket as a private repository and then pull it from my server since there is no direct way to pull it from my computer. I&#8217;ve decided to just [...]]]></description>
			<content:encoded><![CDATA[<p>I have been working on a Django application for a few weeks and want to put it on my website. <a href="http://blog.tom.aratyn.name/" onclick="pageTracker._trackPageview('/outgoing/blog.tom.aratyn.name/?referer=');">Tom</a> suggested that I put it on bitbucket as a private repository and then pull it from my server since there is no direct way to pull it from my computer.</p>
<p>I&#8217;ve decided to just zip up the thing and ftp it. But I found it interesting that Django projects are actually not trivial to share. For example, what files would you include?</p>
<p>It actually seems like you are not supposed to share settings.py (nor manage.py, or urls.py really. These are auto-generated for you). At least, the secret_key should be secret. But you also have a bunch of settings such as database information that should not be public either. If you change the file, any version control system will declare it as a changed file. If you .(git|hg)ignore it, what happens if you need to add a new setting to settings.py?</p>
<p>So I thought maybe you share django apps instead of the project? That&#8217;s stupid. My project has templates, static files. Are those supposed to be a separate project?</p>
<p>So it looks like a fucking mess and I&#8217;m zipping this shit up and calling it a day.</p>
<p>After seeing what <a href="https://github.com/jbalogh/zamboni/commit/f5588504343d80c3ceead07c69f7867a51c05788#diff-1" onclick="pageTracker._trackPageview('/outgoing/github.com/jbalogh/zamboni/commit/f5588504343d80c3ceead07c69f7867a51c05788_diff-1?referer=');">Zamboni does</a>, it appears they modified the manage.py to load a settings_local.py file instead of settings. So you would copy settings.py to settings.local.py and use it. That&#8217;s actually a pretty good idea.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/363/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thoughts on Rails</title>
		<link>http://tea.cesaroliveira.net/archives/319</link>
		<comments>http://tea.cesaroliveira.net/archives/319#comments</comments>
		<pubDate>Fri, 09 Sep 2011 01:30:16 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=319</guid>
		<description><![CDATA[I have been working the past few weeks on Ruby on Rails web development framework. My experience with Ruby is minimal, so there was a large amount of learning and re-learning that was required. Working on it full-time for the past week or two, I reflected on some of the pros and cons of the [...]]]></description>
			<content:encoded><![CDATA[<p>I have been working the past few weeks on <a href="http://rubyonrails.org/" onclick="pageTracker._trackPageview('/outgoing/rubyonrails.org/?referer=');">Ruby on Rails</a> web development framework. My experience with Ruby is minimal, so there was a large amount of learning and re-learning that was required. Working on it full-time for the past week or two, I reflected on some of the pros and cons of the language and framework:</p>
<ul>
<li>Ruby blocks are *fantastic*. If you ever had to work with generating XML, I highly suggest <a href="http://nokogiri.org/" onclick="pageTracker._trackPageview('/outgoing/nokogiri.org/?referer=');">Nokogiri</a> to generate and parse XML documents. XPATH? Yes please! (Ok, XML sucks but when you have to use it, this library makes it painless)</li>
<li>Rails has a ton of shortcuts that make development easier. They have a ton of <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html" onclick="pageTracker._trackPageview('/outgoing/api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html?referer=');">HTML helpers</a> to auto-generate HTML. The framework takes some getting used, but it works quite well.</li>
<li>Rails expects you to develop a certain way. IMO, this a very negative attribute until you get used to it. Your controllers names MUST be plural (cashiers, merchants, etc). Your models MUST be singular (cashier, merchant, etc). Breaking the rules leads to frustration and headache.</li>
<li>Rails expects you to build a certain way. In my application, I did not need to use a database (everything is done using a REST service). But Rails makes this difficult to do.</li>
<li>The Rails installation procedure is easy, but a bit too easy <img src='http://tea.cesaroliveira.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  I managed to screw up a few times (shame on me) and just did <code>gem install rails</code>. That will install the latest Ruby on Rails on your machine. The problem is when I had to move my code to the server. Between development, rails went up a few versions (from 3.0.x to 3.1.x) and a lot of stuff broke. I wish at the time I knew I can install a specific version. Which leads me to&#8230;</li>
<li>Rails is difficult to update. Well, so are most frameworks. I think we need to get better at this developers&#8230;</li>
</ul>
<p>It is difficult to say whether I enjoy Rails or <a href="https://www.djangoproject.com/" onclick="pageTracker._trackPageview('/outgoing/www.djangoproject.com/?referer=');">Django</a>. I am definitely more comfortable with Django, but it is great getting to know both. I am still a newbie at Rails, so hopefully things get easier as I do more work on this.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/319/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Beatport and Beatport5</title>
		<link>http://tea.cesaroliveira.net/archives/301</link>
		<comments>http://tea.cesaroliveira.net/archives/301#comments</comments>
		<pubDate>Mon, 22 Aug 2011 04:10:15 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[beatport5]]></category>
		<category><![CDATA[beatport]]></category>
		<category><![CDATA[html5]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=301</guid>
		<description><![CDATA[Beatport has recently unveiled their HTML version of their website. They then proceeded to launch a quasi job recruitment video explaining the benefits of the new website. Some of the points are valid (the site load time has really improved), but other points are really stretched or moot or misleading. For example they made a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://beatport.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/beatport.com/?referer=');">Beatport</a> has <a href="https://twitter.com/#!/beatport/status/91603983810039808" onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/beatport/status/91603983810039808?referer=');">recently</a> unveiled their HTML version of their website. They then proceeded to launch a <a href="http://www.youtube.com/watch?v=dNVjf8nOtMM" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.youtube.com/watch?v=dNVjf8nOtMM&amp;referer=');">quasi job recruitment video explaining the benefits of the new website</a>. Some of the points are valid (the site load time has really improved), but other points are really stretched or moot or misleading. For example they made a point of the new website containing the <acronym title="Beats per Minute">BPM</acronym> of a track. That&#8217;s just silly because their <a href="http://api.beatport.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/api.beatport.com/?referer=');">API</a> has that information, so there is no technical reason why they cannot have it on their flash website. Interestingly, the BPM only appears on the JSON version of the API and not the XML version and that&#8217;s just terrible. I expected more from people sporting impressive facial hair.</p>
<p>Overall I do like their new website. It is fast, clean, <a href="https://twitter.com/#!/Quextal/status/91867897806327809" target="_blank" onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/Quextal/status/91867897806327809?referer=');">hackable</a>. I thought they were using the audio tag and doing some neat stuff to get the <a href="http://en.wikipedia.org/wiki/Waveform" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Waveform?referer=');">waveform</a> but it turned out that was an image and they are still using flash. Which is probably the wisest thing to do but not very HTML5ish <img src='http://tea.cesaroliveira.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Having a HTML version of the website was also something I thought would be an interesting project (back when they only had a flash-only site). A few weeks ago, I decided to do one anyways, and launched <a href="http://beatport5.cesaroliveira.net/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/beatport5.cesaroliveira.net/?referer=');">beatport5</a> &#8211; a HTML5 version of the website (I may end up renaming it). It has a few caveats:</p>
<ul>
<li>It&#8217;s pretty much not optimized for screens with a resolution under 1920&#215;1080 oops</li>
<li>It works best in Gecko browsers, needs improvement for webkit, and pretty terrible under trident browsers. Don&#8217;t even ask about anything under IE8</li>
<li>The playlist is not working yet</li>
<li>The search functionality is very simple. You can search for tracks, releases, artists or a global search. But you are not able to search for x track by y artist.</li>
<li>The landing page needs improvements</li>
<li>I am not working on this full-time</li>
</ul>
<p>Some interesting stuff:</p>
<ul>
<li>We both use DOM local storage. They seems to use it for their playlist queue. Neat!</li>
</ul>
<p>Some wishlist that I need to put on their mailing list:</p>
<ol>
<li>I would like to avoid hitting my server, so it would be great if their website enabled <a href="https://developer.mozilla.org/En/HTTP_access_control" target="_blank" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/En/HTTP_access_control?referer=');">HTTP access controls</a> for their API and mp3 files</li>
<li>Maybe a way to add stuff to their shopping cart?</li>
<li>There&#8217;s more but I&#8217;m drawing a blank&#8230;</li>
</ol>
<p>I haven&#8217;t really worked in what value I would add that isn&#8217;t already in the beatport site. I would like to incorporate the <a href="http://tea.cesaroliveira.net/archives/256">beatport flac converter</a> somehow. Likely anything meaningful I want to do would have to stored on my server. One experiment I would like to attempt is a way to discover music, much like the beatbot, but maybe less like it, and more awesome.</p>
<p>Why release this now? Release early, release often! It&#8217;s not complete, but I hope to spend time on it and be useful to me and others as well. My main concern right now is making this work cross-browser. Next is screen resolution fix, and an appropriate landing page.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/301/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Firefox extension logging</title>
		<link>http://tea.cesaroliveira.net/archives/238</link>
		<comments>http://tea.cesaroliveira.net/archives/238#comments</comments>
		<pubDate>Tue, 26 Oct 2010 19:36:45 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[addons]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[logging]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=238</guid>
		<description><![CDATA[Last week, I was tasked at work to create a quick prototype extension. This machine had a few other extensions, including the very verbose SmartSwipe extension. SmartSwipe extension logs almost everything to the error console as messages. Which in turns makes it a pretty bad choice for any other extension who wants to use the [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, I was tasked at work to create a quick prototype extension. This machine had a few other extensions, including the very verbose SmartSwipe extension. SmartSwipe extension logs almost everything to the error console as messages. Which in turns makes it a pretty bad choice for any other extension who wants to use the error console as a logging service (incidentally, I am the main developer of the SmartSwipe extension, so this is entirely my fault).</p>
<p>Despite Firefox extensions growing more complex, there are two areas of extension development that are still a pain to deal with: debugging and logging.</p>
<p>What pains me is that extensions have a pretty crappy choice of methods to use for logging purposes. There is <a href="https://developer.mozilla.org/en/DOM/window.dump" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/en/DOM/window.dump?referer=');">dump()</a>, <a href="https://developer.mozilla.org/en/Components.utils.reportError" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/en/Components.utils.reportError?referer=');">Components.utils.reportError()</a>, FUEL’s <a href="https://developer.mozilla.org/en/Toolkit_API/extIConsole#log.28.29" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/en/Toolkit_API/extIConsole_log.28.29?referer=');">Application.console.log()</a>, and maybe some others I am missing (ChromeBug is another possibility, but I haven&#8217;t used it). But these methods of logging don’t scale very well. If you have more than 1 extension using the same logging service, you introduce noise that can be difficult to sort through.</p>
<p>It striked me that there was nothing simple to capture and filter your logging information. Since this problem was annoying me, I decided to create an extension to deal with this.</p>
<h2>Introducing Debug Log</h2>
<p>The extension is uncreatively called Debug Log (unrelated to Jeremy Gillick&#8217;s <a href="https://addons.mozilla.org/en-US/firefox/addon/3983/" onclick="pageTracker._trackPageview('/outgoing/addons.mozilla.org/en-US/firefox/addon/3983/?referer=');">DebugLogger</a>). It shows a <a href="http://en.wikipedia.org/wiki/Event_Viewer" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Event_Viewer?referer=');">Windows-style event viewer</a> with basic filtering. To use it is really easy. First I will show how it is used, and next how to use it when the Debug Log extension isn’t installed:</p>
<p><code>
<pre>
var log = {};
(function() {
        var modules = {};
        Components.utils.import("chrome://debuglog/content/DebugLog.jsm",
        modules);
        log = new modules.DebugLog("my_extension_slug_name");
        log.info("Hello")
        log.warn("Trimming to 8 characters. String : " + s);
        log.error("MyTerribleFunction", exception);
        log.assert(foo != null, "foo should never be null");
})();
</pre>
<p></code></p>
<p>Which results in the following:<br />
<img src="http://media.cesaroliveira.net/images/debuglog-example0.png" alt="screenshot"/></p>
<p>Assert is a bit different from typical assertion in other languages. It will not quit the application, nor would it throw an exception (unless you passed a wrong parameter to assert).</p>
<p>To use it properly, you must also account for times when DebugLog is not installed.<br />
<code>
<pre>
var logging = {};
(function() {
        try
        {
                var modules = {};
                Components.utils.import("chrome://debuglog/content/DebugLog.jsm",
                modules);
                logging = new modules.DebugLog("JavascriptPlusPlus");
        }
        catch (e)
        {
                logging.assert = logging.warn = logging.info = logging.error = function() {}
        }
})()
logging.info("Starting...");
</pre>
<p></code></p>
<p>The extension still has a lot of work to be done, but it&#8217;s useable now. So now is the time to release and it is available at <a href="https://addons.mozilla.org/en-US/firefox/addon/246799/" onclick="pageTracker._trackPageview('/outgoing/addons.mozilla.org/en-US/firefox/addon/246799/?referer=');">https://addons.mozilla.org/en-US/firefox/addon/246799/</a>. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/238/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Endianness, how I loathe you</title>
		<link>http://tea.cesaroliveira.net/archives/172</link>
		<comments>http://tea.cesaroliveira.net/archives/172#comments</comments>
		<pubDate>Thu, 13 May 2010 05:26:21 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[do'h]]></category>
		<category><![CDATA[endian]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[sha1]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=172</guid>
		<description><![CDATA[(originally posted in February, but got lost in time) I have been busy making my own implementation of SHA-1. To better learn about why so many people depend on it for basically everything from SSL to tamper detection mechanism. I have a bigger project idea, but that is not important right now. What is important [...]]]></description>
			<content:encoded><![CDATA[<p>(originally posted in February, but got lost in time)</p>
<p>I have been busy making my own implementation of SHA-1. To better learn about why so many people depend on it for basically everything from SSL to tamper detection mechanism. I have a bigger project idea, but that is not important right now. What is important is that SHA-1 does everything in big endian, and I am on x86-64 which is a little endian machine.</p>
<p>Remember that a big endian machine has the most significant byte first, and little endian has the most significant byte last.</p>
<p>For example, let&#8217;s say I want a 64-bit integer to hold the number 1. This is how it&#8217;ll be stored:<br />
Big endian:<br />
1 = 0000 0000 0000 0000 0000 0000 0000 0001<br />
Little endian:<br />
1 = 0001 0000 0000 0000 0000 0000 0000 0000</p>
<p>SHA-1 stores the size of the message as a 64-bit integer in the last block during padding (each block is 512 bits). Since I have a little-endian machine, I wrote a function that correctly switches endian and now, the 1 appears as the as it should.</p>
<p>However, SHA-1 loops through each block in 32-bit integers.</p>
<p>*((unsigned int*)0000 0000 0000 0000) = 0<br />
*((unsigned int*)0000 0000 0000 0001) = 16 million and change on little endian machine instead of 1 as I expect</p>
<p>so the second time, I have to do another endian change, this time a 32-bit endian change, so that it appears as :<br />
0001 0000 0000 0000</p>
<p>so I get back 1.</p>
<p>This is a PITA, and a frustrating one. Mainly because I couldn&#8217;t figure it out for a few days. But feel so accomplished for figuring it out. Accomplished and embarrassed.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/172/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AES and CBC</title>
		<link>http://tea.cesaroliveira.net/archives/156</link>
		<comments>http://tea.cesaroliveira.net/archives/156#comments</comments>
		<pubDate>Tue, 22 Dec 2009 05:21:06 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[crypto]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=156</guid>
		<description><![CDATA[If you ever want to use a crypto library in Python, you&#8217;ll be sad to note that there isn&#8217;t one built into Python impressive repertoire of modules. In fact, you&#8217;ll most likely hit pycrypt on your Google search to find one. And there is some dirty work you&#8217;ll have to do if you want to [...]]]></description>
			<content:encoded><![CDATA[<p>If you ever want to use a crypto library in Python, you&#8217;ll be sad to note that there isn&#8217;t one built into Python impressive repertoire of modules. In fact, you&#8217;ll most likely hit <a href="http://www.dlitz.net/software/pycrypto/" onclick="pageTracker._trackPageview('/outgoing/www.dlitz.net/software/pycrypto/?referer=');">pycrypt</a> on your Google search to find one. And there is some dirty work you&#8217;ll have to do if you want to use symmetric cryptography using this library. And one of the hard/easy parts is knowing the difference between ECB and CBC.</p>
<p>Here, we start initializing the AES object using CBC mode:</p>
<p><code>&gt;&gt;&gt; from Crypto.Cipher import AES;<br />
&gt;&gt;&gt; aes = AES.new('some key here', AES.MODE_CBC, 'INIT_VECTOR')<br />
Traceback (most recent call last):<br />
  File "&lt;console&gt;", line 1, in &lt;module&gt;<br />
ValueError: IV must be 16 bytes long</code></p>
<p>oops. You&#8217;ll have to make you&#8217;re initialization vector 16 bytes long. Also, your key has to be 16, 24, or 32 bytes long as well. Let&#8217;s do something better :</p>
<p><code>&gt;&gt;&gt; aes = AES.new('J2-+sfd%932mIt:{', AES.MODE_CBC, 'wir&amp;/&gt;H54mgd9a";')</code></p>
<p>ah! much better. Even if it was me smashing my hand against the keyboard. Now let&#8217;s encrypt/decrypt something important.</p>
<p><code>&gt;&gt;&gt; aes.encrypt('the answer to life the universe and everything is 42')<br />
Traceback (most recent call last):<br />
  File "&lt;console&gt;", line 1, in &lt;module&gt;<br />
ValueError: Input strings must be a multiple of 16 in length</code></p>
<p>You&#8217;ll have to do the dirty work remember:</p>
<p><code>>&gt;&gt;&gt; ciphertext = aes.encrypt('the answer to life the universe and everything is 42195479204957')<br />
>>> ciphertext<br />
'f0\xa9\xf9f&#038;X)\x0e\x08=\x06\x97\xcbF\xddK\x1a\xa6i\x1d\x02"}\xd9\\\xaa\xb6\xd9J\xe3Q\x07\xaev\x012\xbf\rPN\xd2\xf9\xf7$\x93\xe0/\xcb\xae9\x91K\xd01\xab\xb7\xdb\reR\xff\xef\x1c'</code></p>
<p>Much better. Now lets decrypt it:</p>
<p><code>&gt;&gt;&gt; aes.decrypt(ciphertext)<br />
'\xc8\xaf.\x97\x05\x80\n\xe9\xe6\xc4Ju\x04\xbe\xa1Nfe the universe and everything is 42195479204957'</code></p>
<p>Woah! That isn&#8217;t the whole message! So what&#8217;s going on?</p>
<p>Remember that initialization vector you set in the beginning? That sets the stage for the first block. But each block becomes the initialization vector for the second block, and so on. So when you decrypt, it is using the initialization vector from the block before. That&#8217;s why the first 16 bytes are screwed up. This is a feature of CBC, but not ECB:</p>
<p><code>&gt;&gt;&gt; aes = AES.new('J2-+sfd%932mIt:{', AES.MODE_ECB, 'wir&amp;/&gt;H54mgd9a";')<br />
&gt;&gt;&gt; ciphertext = aes.encrypt('the answer to life the universe and everything is 42195479204957')<br />
&gt;&gt;&gt; aes.decrypt(ciphertext)'the answer to life the universe and everything is 42195479204957'</code></p>
<p>And yes, this is a feature. Read the <a href="http://en.wikipedia.org/wiki/Cipher_block_chaining" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cipher_block_chaining?referer=');">block cipher modes wikipedia article</a> for a better explination. So what&#8217;s the answer? Simply, to call aes.new() again before calling decrypt!</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/156/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps and geolocation</title>
		<link>http://tea.cesaroliveira.net/archives/61</link>
		<comments>http://tea.cesaroliveira.net/archives/61#comments</comments>
		<pubDate>Fri, 10 Jul 2009 05:37:34 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[hugs]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[browser compatibility]]></category>
		<category><![CDATA[google chrome]]></category>

		<guid isPermaLink="false">http://tea.cesaroliveira.net/?p=61</guid>
		<description><![CDATA[I was first made aware of the fact that maps.google.com now uses geolocation by sdwilsh, which is new in Firefox 3.5. But when I loaded maps, I was surprised to see that it didn&#8217;t work when I visited the site. And I was using something even more recent than Firefox 3.5, Minefield. Surely, it has [...]]]></description>
			<content:encoded><![CDATA[<p>I was first made aware of the fact that <a href="http://maps.google.com" onclick="pageTracker._trackPageview('/outgoing/maps.google.com?referer=');">maps.google.com</a> now uses <a href="https://developer.mozilla.org/En/Using_geolocation" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/En/Using_geolocation?referer=');">geolocation</a> by <a href="http://twitter.com/sdwilsh/status/2553543365" onclick="pageTracker._trackPageview('/outgoing/twitter.com/sdwilsh/status/2553543365?referer=');">sdwilsh</a>, which is new in <a href="http://www.spreadfirefox.com" onclick="pageTracker._trackPageview('/outgoing/www.spreadfirefox.com?referer=');">Firefox 3.5</a>. But when I loaded maps, I was surprised to see that it didn&#8217;t work when I visited the site. And I was using something even more recent than Firefox 3.5, Minefield. Surely, it has geolocation, so what is going on?</p>
<p>The reason maps doesn&#8217;t support Minefield is because of  *<a href="http://www.youtube.com/watch?v=NNaZedAWmlE" onclick="pageTracker._trackPageview('/outgoing/www.youtube.com/watch?v=NNaZedAWmlE&amp;referer=');">drumrolls</a>* &#8230; browser sniffing. Developers&#8230; no wait&#8230; GOOGLE web developers, I thought we moved on?</p>
<p>The actual bit of code is here unminimized and tidied up ;<br />
<code>
<pre>
function isBrowserGeolocationSupported(){
    if (window.navigator &#038;&#038;
        navigator.userAgent.search("Firefox") != -1 &#038;&#038;
        navigator.geolocation)
        return true;
    if (window.navigator &#038;&#038;
        navigator.userAgent.search("Chrome") != -1)
        return Number(String(/Chrome\/[0-9]+/.exec(navigator.userAgent)).substr(7))>=2;
    var gearsFactory=null;
</pre>
<p></code></p>
<p>The hell? Ok, so I understand they do a bit of browser sniffing because it looks like Chrome had a old/broken implementation of geolocation. But I wish there was a more graceful way of doing this (maybe something like navigator.geolocation.version < 1). One that didn't break every application that may implement geolocation that isn't named Firefox. Because, those <a href="http://flock.com/" onclick="pageTracker._trackPageview('/outgoing/flock.com/?referer=');">exist</a> <a href="http://www.getsongbird.com/" onclick="pageTracker._trackPageview('/outgoing/www.getsongbird.com/?referer=');">too</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/61/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Not even bytecode can save me now&#8230;</title>
		<link>http://tea.cesaroliveira.net/archives/35</link>
		<comments>http://tea.cesaroliveira.net/archives/35#comments</comments>
		<pubDate>Tue, 16 Sep 2008 07:57:18 +0000</pubDate>
		<dc:creator>Cesar</dc:creator>
				<category><![CDATA[addons]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[seneca]]></category>

		<guid isPermaLink="false">http://www.cesaroliveira.net/?p=35</guid>
		<description><![CDATA[I&#8217;ve been spending a few days on trying to develop a few tools for editors to use to quickly reject addons for obvious defects, such as loading remote scripts. But I wanted to get deeper into the javascript stuff mainly because it&#8217;s a) it&#8217;s harder and b) it&#8217;s where the real problems lie. But as [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been spending a few days on trying to develop a few tools for editors to use to quickly reject addons for obvious defects, such as loading remote scripts. But I wanted to get deeper into the javascript stuff mainly because it&#8217;s a) it&#8217;s harder and b) it&#8217;s where the real problems lie.</p>
<p>But as anyone can tell you, it&#8217;s not an easy task (going towards damn near impossible). Firstly, you can&#8217;t really use a lexical parser. Well, you can, but it won&#8217;t be dependable. Let&#8217;s take an example out of the Reviewer&#8217;s guide :</p>
<p><code>document["crea" + "teElement"]("s" + "c" + "r" + ["i", "p", "t"].join(""));</code></p>
<p>Which is sneaky way of creating a script element, though I question the competence of someone who will use this as their main line of attack (it&#8217;s practically spelled out for you). But taking this as a use case, and ignoring the fact that they can use document[cheese] instead, I wondering if parsing the javascript would make figuring this stuff out any better.</p>
<p>Happily, I have spidermonkey and a <a href="http://developer.mozilla.org/en/Introduction_to_the_JavaScript_shell" onclick="pageTracker._trackPageview('/outgoing/developer.mozilla.org/en/Introduction_to_the_JavaScript_shell?referer=');">js shell</a> to do any parsing I wish. But I found out some cool things that you can do in the shell, such as looking at the bytecode for an entire function using the dis() command.</p>
<p>This was interesting. Certainly, there are some optimizations you can do for :<br />
<code>document["crea" + "teElement"]("s" + "c" + "r" + ["i", "p", "t"].join("")); </code><br />
I would be shocked if it didn&#8217;t end up spelling out :<br />
<code>document["createElement"]("script"); </code></p>
<p>I had a few hurdles to overcome. Firstly, document is not defined in the javascript shell. Thinking it was defined in the xpcshell (owww. I was misled by some apparently <a href="http://mxr.mozilla.org/mozilla-central/search?find=%2Fjs%2Fsrc%2Fxpconnect%2Ftests%2F&amp;string=document" onclick="pageTracker._trackPageview('/outgoing/mxr.mozilla.org/mozilla-central/search?find=_2Fjs_2Fsrc_2Fxpconnect_2Ftests_2F_amp_string=document&amp;referer=');">unused tests</a> and my general ignorance that xpcshell tests went into unit/ and not js/ directory) I went through the added trouble of coping dis() and related functions from <a href="http://mxr.mozilla.org/mozilla-central/source/js/src/js.cpp#1373" onclick="pageTracker._trackPageview('/outgoing/mxr.mozilla.org/mozilla-central/source/js/src/js.cpp_1373?referer=');">js.cpp</a> to xpcshell.cpp. Once I realized that document wasn&#8217;t defined, I made a document mock object just to see what the blasted bytecode would look like.</p>
<p>I was a little disappointed. This source:<br />
<!--start_raw--><code>
<pre>var document = {
createElement : function(s) {
print("damn");
}
};

function foo() {
document["crea" + "teElement"]("s" + "c" + "r" + ["i", "p", "t"].join(""));
}

dis(foo);</pre>
<p></code><!--end_raw--></p>
<p>Ended up being this bytecode :<br />
<!--start_raw--><br />
<code style="font-size:smaller;">
<pre>
00000:  name "document"
00003:  string "createElement"
00006:  callelem
00007:  string "s"
00010:  string "c"
00013:  add
00014:  string "r"
00017:  add
00018:  newinit 3
00020:  zero
00021:  string "i"
00024:  initelem
00025:  one
00026:  string "p"
00029:  initelem
00030:  int8 2
00032:  string "t"
00035:  initelem
00036:  endinit
00037:  callprop "join"
00040:  string ""
00043:  call 1
00046:  add
00047:  call 1
00050:  pop
00051:  stop

Source notes:
  0:     0 [   0] newline
  1:     6 [   6] pcbase   offset 6
  3:    37 [  31] xdelta
  4:    37 [   0] pcbase   offset 19
  6:    43 [   6] pcbase   offset 25
  8:    47 [   4] pcbase   offset 47</pre>
<p></code><!--end_raw--></p>
<p>So, almost. The document["createElement"] part was correct, but the .join() wasn&#8217;t optimized. Although I wasn&#8217;t overly estatic, I knew that this was just one (somewhat lame) use case in the countless of possible others.</p>
<p>This is making me rethink whether lexical tools <em>are</em> the way to go. While they don&#8217;t give you any definitive proof that there is a possible security hole, they can still be useful. For example, if you want to use XMLHttpRequest, then you have to call it at least once in your program (even if you say <code>var Widget = XMLHttpRequest</code>). And at least that can bring up warning flags, or at least give editors a place to look.</p>
<p>I don&#8217;t think any tool can completely replace a human being. But hopefully, tools will help make the review process easier because you can start looking at high-risk areas first rather than starting from a arbitrary point and not coming across something until 10 minutes later.</p>
]]></content:encoded>
			<wfw:commentRss>http://tea.cesaroliveira.net/archives/35/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

