New blog
If you follow this blog on Tumblr or through a feed reader, please update to the new-and-improved Octopress-powered blog: http://blog.andrewcantino.com
If you follow this blog on Tumblr or through a feed reader, please update to the new-and-improved Octopress-powered blog: http://blog.andrewcantino.com
Suppose you want to build a Rails application for tracking popular links, and you want it to post the most popular links to Twitter automatically. This quick tutorial will show you how to do that using the newest version of the Ruby twitter gem. A little while ago I added the ability for Freebies Finder to tweet popular freebies. I recently had to do this for another site and decided that a tutorial was in order.
We’ll pretend that our website is called AwesomeLinks.com. Signup for two Twitter accounts, AwesomeLinks and AwesomeLinksDev. We need to create a Twitter application through which our website can post to these accounts. Do this by logging into AwesomeLinks and visiting https://dev.twitter.com/apps/new. Select ‘Client’ as the Application Type, skip the Callback URL, and select Read & Write access. Twitter will give you a OAuth Consumer key and secret, which you will soon need.
Now you need to authorize your new Twitter Application to post on both of your Twitter accounts. For this, we use a script:
(If you used the Twitter gem in the past, you may have used authorize_from_access for this, but that no longer works. We now have to require and use oauth separately.)
Fill in your Twitter Application’s Consumer key and secret and run the script. You will be prompted to visit a URL and then to enter the PIN that Twitter provides. Do this for both of your new Twitter accounts and record the results in config/twitter.yml, like so:
Now, create an initializer in config/initializers/twitter.rb and again include your Twitter App’s key and secret:
(If you want to Tweet to multiple accounts, you can do this differently and instead make separate Twitter::Client object, each with their own OAuth tokens.)
Finally, it’s time to augment our Link model so that it can send tweets. I decided to have it tweet the link’s description and a shortened version of its URL using the following code:
The rest is up to you. You could write a cronjob to automatically call tweet! on every link, or only on those with enough popularity. Have fun!
The increasing availability of low profile “wall-wart” plug computers like the SheevaPlug can be viewed as an emerging threat to physical network security. For $99, a budding industrial espionagist could buy the SheevaPlug developer kit or the consumer TonidoPlug, install some easily-available network intrusion testing software, and illicitly “test” the security of a competitor’s network.
While many of these techniques have been known for a while, the low form factor of plug computers and consumer netbooks, coupled with their rapidly decreasing price, could enable disposable intrusion tools and open new avenues for attack. The current $99 SheevaPlug has no wireless capability and limited storage, but the manufacture has just announced an expanded model with wifi, bluetooth, and an internal hard drive. Even without these advances, current generation plug computers can easily be expanded with a USB memory stick or external USB hard drive, USB wireless interface, and more. For little more than $100 one could make a practically undetectable wireless bug that can be deployed in seconds.
In fact, soon you may be able to just buy an all-in-one penetration plug computer, the PlugBot.
edit: as was pointed out to me after posting this article, the described device already exists and can tunnel out over 3G. http://pwnieexpress.com/pwnplug3g.html
With two wireless adapters and some simple software, a plug computer becomes a wireless bridge capable of automatically cracking wireless networks in range (both WEP and WPA are vulnerable these days; see aircrack). Most locations have multiple 3rd party networks overlapping their physical space, which, if cracked, could be used as back channels for the plug computer to phone home. The attacker could then tunnel into the company network undetected and completely bypass the company’s external defenses by routing through an available 3rd party wireless network. From the perspective of the attacked network, even if the intrusion is noticed, it appears to come from within their own physical space.
A number of other uses come to mind for such devices:
- Passive sniffing of internal network traffic using dsniff and sending it back to an attacker. Many networks aren’t sufficiently secured once you’re past the perimeter firewalls.
- Physically connect two ethernet interfaces and use the plug computer as a man-in-the-middle proxy to sniff all traffic entering and leaving a workstation.
- Attach a camera or other sensor payload and use as an over-the-internet video bug.
Again, much of this has been possible for a while, but form factor is everything. Also, I haven’t seen people talking about the possibility of bridging multiple available wireless networks together for attack obfuscation and to avoid connecting through a company’s edge network. I don’t think companies pay enough attention to passive physical monitoring and intrusion threats like this, especially given the insecurity of wireless encryption standards. What do you think?
Ledger is a powerful yet simple double-entry accounting system with a command line interface, making it perfect for those of us who prefer our text editor and flat files over any confusing and inflexible accounting program.
I’ve been using Ledger for about a year now, including for balancing last year’s budget. In the process, I’ve needed both to import CSV files of financial data from various sources and to label that data with the most appropriate account. To do this, I’ve written a Ruby gem called Reckon that can usually guess bank data CSV headings, and can also use Bayesian learning to automatically categorize each entry. I think of this as Mint for the command line, but where you don’t have to trust a 3rd party with your bank account passwords.
Getting started with Ledger is pretty easy. I recommend skimming the official documentation (pdf).
I usually start out the year by making a new year.dat file and entering my business bank account’s starting balance:
2010/01/01 * Checking Assets:Bank:Checking $5.000.00 Equity:Opening Balances
Next, I run Reckon on a CSV dump file from my bank:reckon -f bank.csv -p
If the output looks reasonable, I convert to ledger format and label everything:
Now, my output.dat file looks something like:$ reckon -f bank.csv -o output.dat What is the account name of this bank account in Ledger? |Assets:Bank:Checking| (Here I accept the default because I want to have all money flowing in and out of my bank account.) +------------+--------+--------------------------+ | 2010/03/13 | $100.00 | GOOGLE ADSENSE REVENUE | +------------+--------+--------------------------+ Which account provided this income? ([account]/[q]uit/[s]kip) Income:Adsense (I decided to call this Income:Adsense.) +------------+---------+-----------------------------+ | 2010/03/14 | -$10.00 | FEE: INCOMING DOMESTIC WIRE | +------------+---------+-----------------------------+ To which account did this money go? ([account]/[q]uit/[s]kip) |Income:Adsense| Expenses:Bank Fees +------------+-----------+-----------------------+ | 2010/03/14 | $1000.00 | WIRE TRANSFER DEPOSIT | +------------+-----------+-----------------------+ Which account provided this income? ([account]/[q]uit/[s]kip) |Expenses:Bank Fees| Income:Various Sales (Reckon guessedExpenses:Bank Fees, but I decided to call thisIncome:Blogging.) —————————————————————————+ | 2010/03/28 | $300.00 | GOOGLE ADSENSE REVENUE | +——————+—————+————————————-+ Which account provided this income? ([account]/[q]uit/[s]kip) |Income:Adsense| (Notice how this time it guessedIncome:Adsensecorrectly.) …
And if I run Ledger on it, I can get a breakdown:2010/01/01 * Checking Assets:Bank:Checking $5.000.00 Equity:Opening Balances 2010/03/13 GOOGLE ADSENSE REVENUE Assets:Bank:Checking $100.00 Income:Adsense -$100.00 2010/03/14 FEE: INCOMING DOMESTIC WIRE Expenses:Bank Fees $10.00 Assets:Bank:Checking -$10.00 2010/03/14 WIRE TRANSFER DEPOSIT Assets:Bank:Checking $1000.00 Income:Blogging -$1000.00 2010/03/28 GOOGLE ADSENSE REVENUE Assets:Bank:Checking $300.00 Income:Adsense -$300.00
$ ledger -f output.dat balance $6390.00 Assets $-5000.00 Equity $10.00 Expenses $-1400.00 Income $ ledger -f output.dat equity 2010/11/06 Opening Balances Assets:Bank:Checking $6390.00 Equity:Opening Balances $-5000.00 Expenses:Bank Fees $10.00 Income:Adsense $-400.00 Income:Blogging $-1000.00 0
Notice that the income is negative because the money flowed from the income source (Google and Blogging) to the destination (my bank account). This is double entry accounting, so the final sum is always zero, as seen in the last row.
Finally, later in the year when there is new financial data, I want Reckon to learn from my existing .dat file, so I do:
reckon -f bank.csv -l 2010.dat -o output.dat
To install Ledger and Reckon, see their Github pages:
https://github.com/iterationlabs/reckon
https://github.com/jwiegley/ledger
Today I experimented with running a large Rails RSpec test suite on a RAM disk. My hope was that by hosting either the MySQL server or the Rails project directory on the RAM disk, the test execution would be significantly increased. If this were the case, I would feel (more) compelled to buy a certain new device with a solid-state disk drive. Unfortunately, while I now have some slick scripts to bring up a RAM disk with either my Rails project or MySQL running on it, the improvements were on the order of 10 seconds over a 10 minute test run (the load time of Rails). Thus, it is clear that these tests are CPU bound, not disk IO bound, and a SSD wouldn’t help.
If you have an SSD, can you corroborate this?
(Tests were performed on a brand new Quad-Core Intel Core i7 iMac.)
Sometime in the late ’80s I convinced my parents to get an external hard drive for our Mac Plus to augment our extravagant two floppy disk drives. We got a 70MB drive for about $400, which is about $500 in today’s dollars. Now you can get 2TB for $100, or 10TB for $500. This is an increase of about 14 million percent in about 20 years! Talk about technological change! I have no doubt that this growth - that storage is now basically free - can enable incredible new technologies. What can we do with this?
This snippet demonstrates how to get the title from any webpage using a simple YQL query and jQuery. The title is fetched from url and is placed in #page_title.
If you’re running Chrome on Ubuntu (likely elsewhere too), you can run multiple copies of Chrome with fully different profiles by launching it with the --user-data-dir option. For example, I run two copies of Chrome like so:
/opt/google/chrome/google-chrome --user-data-dir=~/.config/google-chrome-work & /opt/google/chrome/google-chrome --user-data-dir=~/.config/google-chrome-personal &
Recently, I was building a project list application in Rails and I needed to be sure that sub-projects showed up in the list somewhere below their parents.
A topological sort does just what I needed, and I was pleased to discover that Ruby ships with a TSort module. Here is how I extended Array to allow sorting of Projects:
(Aside: I later post-processed the list to indent sub-projects and position them just below their parents. This post-processing was made easier by the fact that all sub-projects were already somewhere below their parents in the list.)This is an old post from my last blog.
Firefox and Safari support an onload event for SCRIPT elements. That is, you can dynamically add a new script to a page, set its onload event to fire a callback, and know when the script has been successfully loaded. You would want to do this because when you include a bunch of new SCRIPT tags in a page, there are no guarantees in what order the browser will decide to evaluate them, thus making dependencies among the scripts difficult to resolve. Using onload to chain the script additions is one solution to this, however, Internet Explorer doesn’t seem to support onload in SCRIPT tags.
Update: Owen in the comments says: Thanks for your post, but I have since found a more efficient way to do this and thought I might share with you. As you said you can use an onload event in Firefox, but in IE you can use the onreadystatechange event. Works from at least IE6. Haven’t tested earlier.
My solution:
function importJS(src, look_for, onload) {
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('src', src);
if (onload) wait_for_script_load(look_for, onload);
var head = document.getElementsByTagName('head')[0];
if (head) {
head.appendChild(s);
} else {
document.body.appendChild(s);
}
}
function importCSS(href, look_for, onload) {
var s = document.createElement('link');
s.setAttribute('rel', 'stylesheet');
s.setAttribute('type', 'text/css');
s.setAttribute('media', 'screen');
s.setAttribute('href', href);
if (onload) wait_for_script_load(look_for, onload);
var head = document.getElementsByTagName('head')[0];
if (head) {
head.appendChild(s);
} else {
document.body.appendChild(s);
}
}
function wait_for_script_load(look_for, callback) {
var interval = setInterval(function() {
if (eval("typeof " + look_for) != 'undefined') {
clearInterval(interval);
callback();
}
}, 50);
}
(function(){
importCSS('some_stylesheet.css');
importJS('jquery-1.2.6.js', 'jQuery', function() {
importJS('some_script_that_uses_jquery.js');
importJS('another_one.js', 'SomeClassOrVariableSetByTheScript',
function() {
importJS('a_script_that_uses_that_class_or_variable.js');
});
});
})();