Configuring Salesforce Chatter with an account in an org that doesn't have Chatter enabled results in an unusable app. Upon start-up, it authenticates against the org, shows an error, "Chatter is not enabled for this organization", then exits.
To restore Chatter to a state where it prompts for the org type, Default or Sandbox, I had to remove the Encrypted Local Store used by AIR apps.
$ rm -rf ~/.appdata/Adobe/AIR/ELS/sfdc-desktop.*
tech » salesforce | Permanent Link
Today, I was trying to find email messages that I had sent which haven't had any responses. My MUA is mutt and my mail is stored in Maildir folders. This could be done with a fairly simple shell script using find and grep, but with about 40,000 messages in the one folder I wanted to search, I was looking for at least a slightly more elegant solution.
The idea is to find messages I had sent (to a specific recipient in this case) and extract the Message-Id; then for each Message-Id, search for messages with that Message-Id in their In-Reply-To or References header. If no messages are found for this second search, we conclude that no response has been received.
I ended up writing a simple shell script that makes use of mairix, which indexes each of the three fields I need to search. Unfortunately, mairix doesn't allow searching the In-Reply-To or References headers directly, but does provide a way to return all of the messages within the same thread as messages returned as a search result. This allows us to restrict the number of messages searched in the second pass to a single thread instead of the entire mailbox.
See the script below:
tech » mail | Permanent Link
I added rel="nofollow" support to the Blosxom writeback plugin. I use Doug Alcorn's version that supports a blacklist and emails me when a new comment/trackback is posted.
Only one small change was required. I simply modified the writeback plugin to
prepend all href attributes with rel="nofollow".
--- writeback.orig 2005-01-20 10:59:23.000000000 -0800
+++ writeback 2005-01-20 11:31:00.000000000 -0800
@@ -233,6 +233,7 @@
$writeback =~ s/\$writeback::(\w+)/$param{$1}/ge;
$writeback =~ s!mailto:([^\s<]+)!<a href="mailto:$1">$1</a>!g;
+ $writeback =~ s!\bhref\b!rel="nofollow" href!ig;
$writebacks .= $writeback;
$count++;
}
Updated: changed regex to match word boundaries around href.
To cover my state and federal taxes for last year and my estimated payments for this year, as well as my IRA contribution, I scheduled a transfer from my ING Direct account to my regular checking account for Monday. I actually had enough in there to cover the taxes, but not the IRA contribution, so I wrote a check for the contribution and mailed it on Monday so I could be pretty confident that the ING transfer would be complete before the check was presented for settlement. Despite the fact that the government was going to be sucking a bunch of money out of my account, I was relieved to have my taxes done and all the payments worked out.
One small problem: I accidentally scheduled the transfer from my checking account to ING instead of the other way around, so on Monday my checking account was emptied resulting in the rejection of three of the tax withdrawals as well as a scheduled credit card payment, generating four NSF fees, and my taxes not being paid on time.
I called ING to schedule the transfer of the mistaken withdrawal as well as the original deposit I meant to make, and my other bank to ask that they honor payments presented in the mean time. I hope that my IRA contribution check clears or I may have to file an ammended tax return without the contribution and pay more taxes plus penalties. What a disaster.
My post about the first night on my Novafoam mattress still gets the most traffic on this blog (although a homework assignment about the French health care system has been remarkably popular the past month or so). Every couple of months, I get an email asking about the mattress. Dale emailed me this morning to ask how we like the mattress after sleeping on it for over three years:
Hi,
In searching the web, I found your blog ("first night on..." on pinkhamster) on
shopping for a Novafoam mattress - now that your blog is more than three years
old, I'd like to hear an update if you could take a moment to let me know (or
add a posting and point me to it) as my wife and I are in need of a new
mattress and no better source than a longer-term customer...
Thanks,
Dale
I'm happy to report that we are still satisfied with our Novafoam mattress. It hasn't lost its support, and it still very comfortable. One thing that I didn't mention in the original post is that motion isn't transmitted laterally much when your sleeping companion moves. It's much better than the bouncing that happens on when sleeping on a cheaper spring mattress or an air mattress. Having spent two nights on an air mattress a couple weeks ago reminded me how much I like our mattress. I think we'll probably buy a King Novafoam mattress when we move to a larger home.
p.s. This season of Penn & Teller's Bullshit! has an episode on mattresses and sleep aids.
Saleforce uses 15-character IDs as primary keys for every record. When retrieving an ID over the API, 18-character case-insensitive IDs are returned. Generally, this doesn't cause any problems because the 18-character version can be used anywhere the 15-character one is. One problem arises though when you are storing IDs in a text field. In this case, you may need to convert a 15-character ID into its 18-character version. Salesforce provides a description of how to perform this conversion.
Here is a PHP implementation of the algorithm.
function sf15to18($short) {
$chunks = str_split($short, 5);
$extra = '';
foreach ($chunks as $chunk) {
$chars = str_split($chunk, 1);
$bits = '';
foreach ($chars as $char) {
$bits .= (!is_numeric($char) && $char == strtoupper($char)) ? '1' : '0';
}
$map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345';
$extra .= substr($map, base_convert(strrev($bits), 2, 10), 1);
}
return $short . $extra;
}
tech » salesforce | Permanent Link
If you are trying to track multiple domains within the same Google Analytics or Urchin profile, make sure you are using the same tracking library on all sites. I was attempting to track a visitor from one site using urchin.js to another using ga.js, and I spent a few hours trying to figure out why it wasn't working.
It turns out that the cookie data is encoded differently in query string appended to the url of the site to which you are passing it. With urchin.js and __utmLinker(), the __utmz cookie is url-encoded, but not with ga.js and ._link(). Compare the two URLs below.
http://example.com/?__utma=1.1181041260.1202679736.1202679736.1202679736.1&__utmb=1&__utmc=1.0&__utmx=-&__utmz=1.1202680382.1.3.utmcsr%3DFake%2BSource%7Cutmccn%3Dbogus%7Cutmcmd%3Dclicky%2Bclicky&__utmv=-&__utmk=129628685 http://example.com/?__utma=1.1181041260.1202679736.1202679736.1202679736.1&__utmb=1.0&__utmc=1.0&__utmx=-&__utmz=1.1202680287.1.2.utmcsr=Fake%2BSource|utmccn=bogus|utmcmd=clicky%2Bclicky&__utmv=-&__utmk=54196648
The ga.js _initData() won't properly parse the __utmz data from the query string in the first example. I hope this saves someone else some time.
I've created a new site at http://bookne.ws that searches blogs and Google News for references to books in an Amazon Wishlist.
It uses Amazon's E-Commerce Web Service to find a wishlist by name or email address, and to retrieve the list of books on a wishlist. Then it uses Yahoo Pipes to search for news for each of the book titles and sort the results by date. Finally, it takes the results and replaces the book titles and authors with links to pages that will return results for an individual book or author. It also uses Freebase, a sort of structured Wikipedia, to retrieve a short description of on author pages where they exist. Every page also provides an RSS feed of the results that are returned.
For example, if you use my wishlist of mostly economics books (which also happens to be the default list used at the bookne.ws homepage), you might see an except and link to an article about Nassim Taleb's Fooled by Randomness, one of the books on my list.
Amazon has a new service called Unspun that makes it easy to create "best-of" lists. People can vote on Amazon's site, and lists can be embedded in other web pages so votes can be solicited elsewhere.
I've created two lists: Best Living Economists and Best Economics Books. For the economists list, I basically just put down the economists whose blogs I read, and who I thought were especially good at Mises University. I haven't finished my list of top econ books; it's harder than I expected.
If you work with people, you have probably received meeting requests from MS Outlook/Exchange users. I used to add these to KOrganizer using korganizerIn, but I stopped using KOrganizer a long time ago, and I've been pretty happy using Google Calendar for a while. My goal was to add meeting requests to my Google Calendar. The OpenSync library provides the means for moving events between different calendar formats, and multisync-tools provide a command-line interface to the OpenSync library.
Install and configure multisync-tools.
# apt-get install multisync-tools opensync-plugin-google-calendar opensync-plugin-file $ mkdir ~/calendar $ echo "text/calendar;~/bin/addCalendarItem %s; needsterminal;" >> ~/.mailcap $ msynctool --addgroup file-google $ msynctool --addmember file-google file-sync $ msynctool --addmember file-google google-calendar $ msynctool --configure file-google 1
Change the contents of the <path> tag.<config><path>/home/dir/calendar</path><recursive>FALSE</recursive></config>$ msynctool --configure file-google 2
Replace USER@gmail.com with your Google username and PASSWORD with your password.
Create ~/bin/addCalendarItem:
#!/bin/sh echo loading $1; cp $1 `tempfile -d ~/calendar` msynctool --sync file-google 2> /dev/null
Now when you get a meeting request in mutt, you can view-attachments, then view-attach (<Return>) on the meeting.ics attachment, and the meeting will be added to your Google calendar. It's not perfect. No acceptance notifications are sent. If you view a meeting request multiple times, it will be added to the calendar multiple times. Sometimes the synchronization hangs, and when you try it again, it detects conflicts between what's in your calendar directory and your Google calendar, and you have to tell it which to keep.
If I ever get the motivation, I might write a script to just add events using the Google Calendar API since I don't really need two-way synchronization.
Thanks to Trond for getting me started.

The state is that great fiction by which everyone tries to live at the expense of everyone else. - Frederic Bastiat