I have a Nokia 770. It's a nice Linux-based PDA, with a Debian core plus some proprietary bits and bobs (e.g. Flash, RealPlayer) incorporated. I use it at home if I leave my laptop at work for simple web browsing and checking email. The main bonus being I can use it lying down :).
A couple of days ago, the latest firmware was released. As there were major improvements (e.g. fingertip input support, password saving in the web browser, GoogleTalk integration), I thought it was worthwhile to upgrade. And there my troubles began.
At the weekend, I had installed a Windows 2000 VMware image, so at least I had the tools available without having to take home a different laptop. But as soon as I tried to install the Nokia 770 firmware update wizard, I encountered a hulking, rusty chain of dependencies:
On my home machine, it took about an hour (over slow ADSL) to download all the bits of software, find my CD case with serial number, and install everything. The Nokia update took another 20 minutes on top of that. Hmmm, don't think I'll be switching to Windows any time soon. Granted, I am running an ancient version of Windows, but so are lots of businesses who, like me, can't afford to upgrade. It's so much easier on Ubuntu, with a nifty apt-get install. Anyhow, I suppose it's worth the effort to upgrade the Nokia, as the improvements make a big difference to usability.
Update: to add insult to injury, when I tried to follow the same procedure to update Jono's 770, it completely screwed the firmware, so it won't even boot. What is wrong with treating the 770 as a big USB hard drive and dropping the new firmware into a specially-named folder? (This is how I upgrade the firmware on my iAUDIO M3 - nice piece of kit, by the way, except I think the headphone jack socket is wearing out through over-use, and I get occasional wierd freezes which require a reset.)
A while ago I write a thing called WAML, a small library for writing an HTTP client in Ruby, with support for tidying HTML, simple XML parsing, creating RSS feeds, and sending files over SSH (I wrote it to screen scrape pages, push them into RSS files, then send the output files to a website).
Like a good Rubyist, I included a whole bank of tests, including a few for the HTTP client stuff. However, at the time, I just pointed at pages on the internet, and my HTTP client tests would dutifully march out into the wilds to pick up web pages. This is not ideal: what if a website is down? or it changes? or I don't have a network connection?
I found a really neat solution called FakeWeb, which solved all my problems. This interposes between your testing code and the Net::HTTP libraries (the main HTTP libraries for Ruby). So you can run your test code against a "fake web": any HTTP requests sent through Net::HTTP are intercepted by FakeWeb and handled by it instead. Any pages you want to "mock up" are registered with FakeWeb using the register_uri method, and you can attach arbitrary headers, cookies, and page content to each registered URI. Here's an example of how I applied it, starting with my original test, which checks whether my HTTP client correctly sets cookies on redirected requests:
class TestHTTPClient < Test::Unit::TestCase
def setup
@client = Client.new :user_agent => 'Firefox'
end
# test passing of cookies gathered from one response to subsequent request
def test_cookie_passing
response = @client.post(:absolute_url => 'http://bloglines.com/login',
:post_parameters => { 'r' => '/myblogs', 'email' => 'elliot at townx.org',
'password' => 'notmyrealpassword', 'Sign In' => 'Log In'})
assert_equal 'http://bloglines.com/myblogs', response.url
assert_equal 'elliot@townx.org', response.cookies['BloglinesEmail']
assert response.body.include?('<frame src="/info/myfeeds" name="basefrm" scrolling="yes" />')
end
end
(I've left out all the requires to keep it neat.)
Note that this code physically logs into BlogLines by sending a post request, then checks that the client correctly follows the redirect to the /myblogs page and has a cookie set. There are a couple of problems with this:
Here is the test, rewritten using FakeWeb, which fixes these issues. More verbose, yes, but friendly. Plus I can test any kind of arbitrary series of web pages without having to setup a special website to do so:
class TestHTTPClient < Test::Unit::TestCase
def setup
@client = Client.new :user_agent => 'Firefox'
login_setup
end
# setup fakeweb to emulate login procedure
def login_setup
base_url = 'http://pretend.web.com/'
# URL where the agent will try to login
@login_url = base_url + 'login'
# URL to redirect to after login page
@bloglist_url = base_url + 'myblogs'
@bloglist_content = '<title>Logged In</title>'
# email address to use during login and in cookie
@email = 'elliot at townx.org'
# custom build response from the login page, to redirect to the bloglist and set a cookie
redirect_response = Net::HTTP::HTTPResponse.new('1.1', '302', 'Found')
redirect_response['Location'] = @bloglist_url
redirect_response['Set-Cookie'] = 'email=' + @email +
'; expires=Sun, 31-Jul-07 15:22:12 GMT; path=/'
# register the two URIs with FakeWeb and attach their content
FakeWeb.register_uri(@login_url, :response => redirect_response)
FakeWeb.register_uri(@bloglist_url, :string => @bloglist_content)
end
# test passing of cookies gathered from one response to subsequent request
def test_cookie_passing
response = @client.post(:absolute_url => @login_url,
:post_parameters => { 'r' => '/blog_list', :username => @email,
'Sign In' => 'Log In'})
assert_equal @bloglist_url, response.url
assert_equal @email, response.cookies['email']
assert response.body.include?(@bloglist_content)
end
end
Note the quick and dirty way I setup the response returned by the login page, to emulate a redirect with a cookie (I deserve a slapped wrist for that baby, especially the manual date setting). I will probably extend FakeWeb to do this better. Plus I had to add a new method to Net::HTTPResponse to allow me to manually set a response body. But it works pretty nice now. It would also make sense for me to rewrite my FlickrLilli tests like this (they currently use Flickr directly, which means the tests can take a while).
The WAML gem is attached to the bottom of this post, for anyone interested. I haven't updated it for a while, but it still does its job.
Can anyone recommend me an HTTP client library for Ruby? I know about Net::HTTP, but that's pretty low level: I'm looking for something like Apache Commons HTTPClient. I've written my own, but it's primitive. I basically need stuff like:
If there's nothing out there, I'll carry on building my own (codenamed: WAML [Web Automation Macro Language]). But it would be interesting to find out if anyone else is working on this already before I go too far.
I'm still trying to get my thoughts in order for a forthcoming seminar on making money because of open source. I found this short article on RFID, which encapsulates the arguments for standardisation and its effects on the market really concisely:
...standards won't turn RFID into a commodity. Standardization will increase competition, drive innovation and lead to products with meaningful differences.
We've seen the same thing happen with the web server market, and currently happening with content management. Not that there are meaningful standards among content management systems (at least, not PHP ones), but the fact that most CMSs provide equivalent base functionality has meant differentiation has had to move to other areas of the market: e.g. better user interfaces and better integration with external systems.
I enjoyed OSBC last week, though I thought it was a bit pricey for what we got. Simon Phipps' presentation was very good indeed (plus he attacked IP indemnification firms as pointless scare-mongers); I enjoyed Trolltech's Eirik Chambe-Eng laying into Symbian, stating that Linux can scale down better and is more attractive for low-end phones (some bloke from Symbian stood up at the end, a bit miffed); Ian Howells from Alfresco had some interesting points about how the Enterprise Content Management market is ripe for exploitation by open source (monolithic, 15 year old code bases in existing systems are the opposite of agile); Mark Fleury bristled through the panel sessions; and Brian Behlendorf said some interesting stuff about using open source style development in large software houses (though the audience wasn't particularly responsive). Also met a couple of nice chaps from Sun.
A few observations:
That's all I have to say on the matter. And no, I will neither forgive nor forget Hazard.
Update: This has mostly been superseded by my full-on s33r project, hosted on RubyForge. It contains a Rails application as an example, but far more functionality than this early effort. I'd go so far as to say it outstrips the Amazon Ruby sample code for S3, as it provides object wrappers around the bucket listing, logging and acl functionality, making it much easier to utilise them than it is with the Amazon samples. Give it a try, why don't you?
There's no support for resource prefixes, so the storage is fairly flat at the moment.
It incorporates the S3 sample Ruby code from Amazon, the HMAC-SHA1 library, and the MIME::Types libraries. I haven't included the licences, but believe they are all under MIT. My S3 code is a Rails plugin in vendor/plugins/S3Client. The Rails code is hastily hacked together and badly organised, but I got carried away. I haven't frozen the Rails gems in, but for reference I used Rails 1.0.
If you want to try installing it, the package is attached to the end of this blog entry. Untar and install as you would any other Rails app.. You will need to fix the shebang lines (they point at one of my many custom Rails environments!). Then you will need an S3 account. Once you have this, edit config/s3_config.yaml with your AWS access key details. Change bucket_prefix to something sensible for you. Then start it up (WEBrick or Lighttpd), browse to localhost (port 3333 if you use the included Lighttpd config.), and away you go!
There is a SQLite database attached to the app., but it isn't used at present. Not sure if this will break if you try to use the package without SQLite being installed. I tested under Lighttpd, and there's a Lighttpd config. file in the config. directory if you want to use that.
The whole thing will be released under the MIT Licence eventually, and I will put it up on RubyForge once I get a minute. But I was too excited to wait before releasing it :) Any feedback would be great.
This software comes with no warranty. I am happy to answer informal queries, though.
I am in old skool Detroit techno heaven: I found out about Detroit Digital Vinyl yesterday, and downloaded a few tracks last night by the mighty Underground Resistance (Death Star - what a classic of brooding, disorientating acid that is), plus the compilation Interstellar Fugitives. It worked out at £7.50 for the lot, which is about right for me, given that this stuff is pretty hard to get your hands on otherwise. I've been hankering after this stuff since reading some time in the '90s that the Aphex Twin is a big fan; plus I had a lot of old acid tracks (DJ Pierre, Phuture, Tyree, Mr. Fingers, Adonis) on crumpled tapes and needed a fresh acid/house injection. Recommended.
A few things have prompted me to think about how open source is gradually being recognised as "enterprise-ready":
So open source is (slowly) gaining more acceptance in the mainstream (enterprise). My feeling is that it's not so much acceptance as recognition: I reckon most decent/big companies use open source somewhere, whether they know it or not, and this wave of interest is simply highlighting the fact that executives have realised this and are formalising casual use. Open source was there all along: big companies are only just now admitting it.
This is how to install the APC caching extension (I got version 3.0.6) into XAMPP on Linux (for PHP5). You will need the developer package for XAMPP to do this. (You can use the pear command to install it if you're using standard Apache + PHP.)
/opt/lampp/bin/phpize-x.x.x; use the version of phpize which corresponds to the version of PHP you want to install for../configure --enable-apc --with-apxs --with-php-config=/opt/lampp/bin/php-config-5.0.4makemake install
extension=apc.so
phpinfo(), and check that there is a section for APC. If there is, it's working.