Showing posts with label technology. Show all posts
Showing posts with label technology. Show all posts

Thursday, March 12, 2015

How to install Googlebar for Firefox 35 and beyond

Update: At least for now, anyway, it looks like googlebar doesn't work for Firefox anymore. I tried to install googlebar for Firefox 36, by clicking on the link, and by manually installing the add-on, but keep getting this message:

googlebar could not be installed because it is not compatible with Firefox 36.0.1

It looks like we die-hard users of googlebar are now forced to use Googlebar Lite, but what I miss most about googlebar is typing whatever you want to search on, and performing your favorite google searches in just one click, whereas with Googlebar Lite, at least in the cursory examination I have given it, your favorite google searches are two clicks away.

Thanks to a suggestion from my friend David McIntyre in his comment below, rather than editing an XML file, I recommend installing Nightly Tester Tools, which helps to make googlebar compatible with the latest Firefox upgrades, almost without a hitch. However, what I found is that occasionally, Nightly Tester Tools, when upgrading googlebar to the latest version of Firefox, works for a little bit, but for whatever reason your browser crashes, resulting in googlebar disappearing, so I had to use the instructions below.

Those of us who use the Firefox add-on Googlebar know it is one of the best interfaces on Firefox to Google, "with an emphasis on easy access to many types of specialized searches". The problem is, the maintainers, John Woods, Andy Boughton, and Francis Turner, don't seem to stay on top of the version changes; while the add-on is a very useful tool, the maintainers don't seem to be very useful when it comes to applying an incredibly simple fix, so that Googlebar can be installed on the latest version of Firefox. We will now correct their oversight:

  1. Right-click on the following link and "Save Link As..." to download Googlebar 0.9.20.05 locally to your computer:
    https://addons.mozilla.org/firefox/downloads/latest/33/addon-33-latest.xpi?src=addondetail
    If you simply click on the link, your browser will try to install it, and the attempt may fail.
  2. What you downloaded has a file extension of xpi, Cross Platform Install, which is basically a package of files that has been compressed. What we want to do now is decompress the xpi, in order to access a file inside named install.rdf. Since xpi is a compressed file, you can easily decompress it, using your operating system's default decompressor, by changing the file extension from .xpi to .zip. Then you click on the renamed file to display its contents, and open install.rdf with a text editor.
  3. Scroll down the file, and look for the section for Firefox:
    <!-- Firefox -->
    <em:targetApplication>
     <Description>
      <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
      <em:minVersion>2.0</em:minVersion>
      <em:maxVersion>5.*</em:maxVersion>
     </Description>
    </em:targetApplication>
    In the line that says maxVersion:
    <em:maxVersion>5.*</em:maxVersion>
    replace 5.* with the latest version of Firefox, which, as of today, is 34.*
  4. Save the install.rdf file, and add it back to the zip file.
  5. Rename the file extension, from zip, back to xpi.
  6. In your browser, click Firefox, Add-ons, Gear button, "Install Add-on From File..." and install the xpi file that you just modified.

Thursday, November 7, 2013

Be Very Careful When Selling Your Digital Goods on eBay

Back in December 2011, I detailed a harrowing journey which started with my offering digital goods for sale on eBay, and resulted in my losing both my digital goods and the money that was paid to me for said goods. Now that my losses are a matter of public record, I can come out and say I lost 486.4 bitcoin, and have nothing to show for it other than a grim, and ultimately fruitless for me, journey with eBay through the courts. My long ordeal with eBay finally came to a less than positive conclusion yesterday morning, when the commissioner presiding over my small claims trial, Lisa Steingart, ruled against me while court was still in session, saying that based on what she had heard from me and from the defendant eBay (represented by a paralegal who introduced herself to me as Stephanie), the defendant eBay did not owe me, as the plaintiff who had brought suit against eBay, anything, because the eBay user agreement that I allegedly agreed to when I created my account in 1999 states sellers cannot sell "intangible currency".

My main argument in court was that eBay is talking out of both sides of their mouth, because the user agreement may state that sales of digital goods are prohibited, but eBay continues to reap massive financial reward by allowing sales to continue, even encouraging sales of so-called prohibited items, and collecting commissions on successful sales of cellphone ringtones, music, movies, domain names, software, electronic books, electronic currency, financial and cash services, video game accessories and characters, electronic gift certificates and coupon codes, and much more. To this day a thriving market for digital goods exists (I contend to rival Amazon, Netflix and Apple), and eBay does nothing about it other than to say that eBay will take down individual listings when people report violations of the User Agreement.

Note that even though eBay says their User Agreement states that sales of intangible currency are prohibited, they have a category for sales of "Virtual Currency", which gives lie to the idea that eBay prohibits such sales:
http://www.ebay.com/sch/Coins-Paper-Money-/11116/i.html?clk_rvr_id=390780746032&_nkw=bitcoin

eBay bitcoin sales virtual currencyThe crux of my argument is that I had created four separate listings to sell my digital goods, and during that entire time, eBay never once warned me, or anyone else who lists digital goods for sale, that doing so could result in the eBay seller being doubly damaged, meaning, the eBay seller could lose both the item being offered for sale, and the money paid for said items. I told the commissioner that eBay benefits from sales of prohibited items (and upon further analysis, even encourages sales of prohibited items), and eBay does not provide adequate safeguards to protect eBay users who are vendors and sellers.

How eBay deals with eBay users who sue eBay:

  1. eBay has a paralegal attempt to contact you to dismiss the case in your county, and refile in Santa Clara County, where eBay headquarters is, and where eBay hopes to have home field advantage. In Santa Clara County, the commissioners or pro-tem judges who you appear before will likely be unfamiliar to you as plaintiff, but more likely to be familiar to the eBay legal team. eBay then sends legal documents to your home county, arguing the motion for change of forum from your home county to Santa Clara County, and in my case, the commissioner decided in eBay's favor.
  2. eBay points to their User Agreement which states that in matters of contention, you agree to file in Santa Clara County, and that you also agree that sales of digital goods are prohibited.

Someone will have to successfully hold eBay accountable, and that someone has to be other than me. I feel my strongest arguments for why eBay owes me monetary damages for the loss I suffered are:

  1. eBay is saying that they have proof an unauthorized third party accessed the eBay buyer's account (please keep in mind that the eBay buyer is claiming his eBay, Paypal, AND personal email accounts were all compromised by this unauthorized third party) and bid on my items without the account holder's permission, but eBay won't tell me what this evidence is, let alone, let me examine this evidence. I am simply supposed to take eBay at their word.
  2. even if what ebay is saying about the compromised accounts is true, there was a time window of 24 hours between when the item in question was first purchased by the buyer, and when eBay notified me that the buyer account was accessed by an unauthorized third party. Why didn't eBay let me know sooner, if they had evidence that the buyer's eBay, Paypal and email accounts had been compromised?
  3. when I was creating the listings, why didn't eBay warn me that my digital goods, and what I paid for them, and could sell them for, could potentially all be lost, and unrecoverable, and that digital goods auction listings were not covered by eBay or Paypal?
  4. Paypal says that if you receive payment for an item, you are covered by Paypal seller protection; you only need to provide proof of shipping, and that you sent the item to an address that is verified by Paypal. However, this protection does not cover digital goods, even though I have the evidence to show I sent the items and the buyer received them.
  5. when it comes to high value transactions, eBay can set up an escrow system, just like it does for eBay Motors, where a disinterested third party, perhaps an eBay employee, can make sure that the buyer is who he or she says s/he is, and that the seller actually has said goods and they are the value claimed by the seller, before payment is released and goods are delivered, as overseen by the third party.
To pour salt in the wound, after I lose my bitcoin and the money paid for them, my Paypal account is limited until I send in a notarized document agreeing not to buy or sell bitcoin using Paypal. When I tried to resolve this by contacting an eBay seller advocate, I was told that in the future, if I want to sell digital goods, to list said goods using eBay Classified Ads, for which you pay a flat fee of $9.95:

http://pages.ebay.com/help/sell/adformatfees.html

Here again, I feel eBay is being a bit disingenuous, because while eBay may not necessarily get more money in each and every auction sale, 11% (eBay and Paypal fees combined) of a large number of digital goods auctions or Buy It Now transactions, even if many of those transactions are where the buyer claims their account was hacked, is much better than a fixed fee of $9.95 per Classified Ad transaction. That is my theory for why eBay doesn't force, or even automatically notify, sellers listing digital goods to go to eBay classifieds. The seller may lose out on money and goods, and eBay may have to refund the fees, but eBay suffers no additional loss, other than the small percentage of people who successfully sue eBay and collect.

Ultimately, I feel that the fact that eBay continues to allow and encourage digital goods auctions to take place, to allow people to see what said goods can sell for, presents a sort of attractive nuisance, much like a clean, well-lit pool on private property with an invisible fence around it, in an area with lots of families with children and young people.

Wednesday, October 31, 2012

how to find out who's been watching you and how to start watching them

Countersurveillance: the attempt to avoid being watched. Last month, I briefly addressed how to avoid being detected when browsing online. This month, we will delve into spying on those who are spying on you. How do we ascertain when someone is investigating you and maybe doing research on you on the internet, and how do we turn the tables and start doing same to them?

Some time in the recent past, I got into a conflict with a party that spilled into the arena of the law. I've since settled the case out of court, and on the day of the settlement, I signed a confidentiality agreement, so I cannot reveal specifics about the case. What I can say is that a couple of months after my attorney agreed to represent me and to file suit against the other party, I was reviewing my Google Analytics (henceforth GA) report for my blog, which I do on a nightly basis, when I see the following:GA screenshot for my October 2012 blog post Someone, whose identity was unknown to me, had typed my name into a search engine, clicked on one of the search result links, loaded my blog on their computer, and had proceeded to go through the stuff I had written. In the interest of full disclosure, finding out who is watching you is much easier when your name is unique; I know of no one else on the internet who has the same first AND last name as I do. If your name is not unique, you cannot be certain that the person who typed the words into the search engine is looking for you; the search engine user may have happened upon your website while looking for someone else, and got interested in you or what you had to say. But once my mind came to grips with the fact that somebody had conducted an online search of me, I formed a theory that the person doing research on me was either the party I was suing, or connected with the lawsuit, or associated with the attorney for the party I was suing. A few days later, I happened to be at a local courthouse, at the registrar of voters, trying to find out how to get a mail-in ballot sent to me. Afterwards, it occurred to me that if I was curious to see the latest developments in a court case involving me and another party, and I wanted to search the database of lawsuits that had been filed in the very county that I happened to be in, to see how my lawsuit was progressing, the place that I'd want to be is at a courthouse in the county where the lawsuit was filed. I asked around, inquired at the information desk, and was directed to the courthouse Records department. There, I saw a few computers that members of the general public can sit in front of and type in keywords to look up court records. After I conducted my own search on the name of the party I was suing, I confirmed that on the day my name was used as a search term by an unknown person or persons, the party I was suing, i.e., the defendant, had gotten served with the papers containing the text of the lawsuit in which I was plaintiff. While I cannot be 100% certain, I think there's a high probability that said party, after having been served with court papers, had gone online to find out more about me. The next week, I was at my attorney's office and I confirmed that my attorney's process server had traveled to the city where the GA report had indicated the online search may have originated, and served the defendant. In the next few weeks, the GA report indicated that my name was used twice more as a search term, but in both cases, the searches originated from a city that court records told me the defendant's attorney had his office. This could all just be a coincidence, of course, but I also think there's a high probability that the lawyer for the defendant may have conducted an online search of me, wanting to look through what I had written, perhaps in an attempt to find out anything that could be used to hurt my legal case against the attorney's client.

While a trip downtown to the courthouse may be fun, if you have an interest in the proceedings of a legal case, you can just as easily get updates from the comfort of your own home. You simply locate the website for the county courthouse that your lawsuit was filed in, and as long as you have the case number, or you know the date the case was filed, you can use the courthouse website to see how your (or anyone else's) legal case is progressing. However, perhaps because of privacy concerns, you cannot go online and perform a keyword search through county court records; you still need to physically be present in front of a county courthouse computer in order to search by a party's name.

On November 1, 2011, Google put into place a new feature of their evolving privacy policy; if a person typing keywords into Google's search engine is using a browser that is already logged into a Google account, Google no longer discloses the keyword search terms on your GA report. Therefore, if you now perform a search for my name on Google while logged into your Google account, and say you visit my blog, if I were to use GA to generate my blog's traffic analysis report, my name as a keyword would no longer be visible to me. What I'd see, instead of my name, is Keyword (not provided):GA cut selection for my October 2012 blog post None of us like being watched, but knowing we are being watched by other people keeps us honest (if not a little paranoid). Because of Google's new privacy policy implementation, you have less information in your GA reports than before, and therefore you are far less certain than before that someone is actually investigating you. However, you can still use GA to develop profiles of online users who may be watching you:

  1. If your blog, like mine, is about many different topics, and the online user's keyword is (not provided) and the first page the user alights upon is your blog's landing page, instead of a specific blog post, that may be an indication that the user typed in your unique first and last name as the keyword, while using a browser that is logged into a Google account.
  2. If your blog URL is not easy to remember, such as tpc247.blogspot.com, but using the URL is how the user accesses your blog's landing page, then the source of traffic to your blog's landing page is direct; this is an indication that the user typed your blog URL (or at least the first few letters of the URL) into the browser's address bar and pressed 'Enter', or the user has your blog in his or her browser bookmarks. Another possibility is that the user may have searched for your unique name, copied and pasted the blog's URL from the search results into the browser address field, then pressed 'Enter', possibly in order to evade detection by GA.
The aforementioned profiles are, of course, just guidelines, and do not necessarily match someone who may be investigating you. The user may have entered one or more keywords that are not your name, and ended up on the landing page of your blog. The user who perhaps copied and pasted your blog's URL from the search results into his or her browser address bar may not have been motivated by evading detection, but may have performed this extra work out of habit, or maybe as a lark, i.e., he or she may have just felt like doing it at that time. However, the information from these profiles, in combination with all the other data that GA provides you, such as geography and technology information, can be used in totality to track your website visitors, and any possible return visitors, in order to help you paint a better picture of who may be watching you.

Out of all the visits that GA tracks, there are still many where a keyword is provided, and occasionally that keyword may be your unique name. Even if you are a celebrity, you may still want to know who is googling your name and landing on your website or blog. In GA, I have created a filter with the following condition: where a user's keyword contains my first name, or my last name, or the keyword exactly matches my first and last name, then I can isolate that segment of user, and find out more about his or her visit. I'd like GA, at some point in the future, to be able to let me create an email alert (GA calls them Intelligence Events), so that I am notified by email when certain conditions in a filter in my own GA instance are met, such as the aforementioned profile. However, as we go to press, it looks like the only email alerts that you can create in GA are for when your website traffic has significant statistical variation, i.e., website traffic goes up or down by a certain percentage.

Gentle reader, all of this is to say that, so yes, I've been watching you, and now I know that you know that I know that you've been watching me.

Sunday, September 30, 2012

How To Execute Javascript in Firefox 6 and Beyond

For anyone who maintains a website, blog, application or mobile app, one of the best tools for getting a sense of who your audience is, and how many people are visiting, consuming and using your work of art, is Google Analytics. When you first start using this free service, you soon may realize that one of the most frequent users of your creation is you. There are at least two main ways to prevent Google Analytics (henceforth GA) from tracking your own visits; one is IP-based, and the other is browser-based. The IP address-based way involves creating a GA filter, and works well if you happen to possess a static IP, or most of the IP address or addresses for your office, company or home is predictable and doesn't change often, i.e., you possess a range of IPs that you lease from your internet service provider and dole out to your employees or home computers. However, this scheme quickly falls apart if your ISP allocates dynamic IP addresses, or you visit your site from a cafe, school or library.

With the browser-based approach, since it is browser-specific, you have to remember to always use the same browser. A major downside is that, sometimes unpredictably, when your browser environment changes, such as during a major upgrade, or if something goes wrong when you are using your web browser to do something unrelated to GA or your website, such as during installation of a browser add-on, or if you were to erase all your cookies in an attempt to get past the LA Times paywall or in an attempt to reset your browser (this happened to me recently when I was using Amazon to purchase some music, and I inadvertently clicked on the option to download the music file using Amazon's downloading app, when I just wanted to download the mp3 file, so I had to delete my cookies to reset my browser so that I could be presented with the user interface to choose the correct option), or your operating system or browser crashes and reverts back to an earlier state, you may need to reapply or reinstall your browser-based solution again.

From what I gather, there are many ways to implement a browser-based approach. I have read that one way is to use the NoScript add-on and to not authorize GA to run scripts. Another way is to install the Google Analytics Opt-out Browser Add-on. The one I am most familiar with involves creating a GA filter, and then manually setting a cookie to exclude yourself from GA tracking. I used Brian Yang's instructions, but as an update, note that under his "Create the Cookie", Step 2:

Remove everything from the address bar and paste in the following and hit enter.
This may not apply to other browsers, but if you use Firefox, the information provided by Mr. Yang is no longer applicable, and Step 2 is obsolete. In the latest versions of Firefox (as we go to press, we are at Firefox 15.0.1), if you try to run the Javascript snippet in the address bar, nothing will happen, and you may see
pagetracker is not defined
According to Mozilla, the makers of Firefox, after Firefox 6, "javascript in the url-bar runs with a null security principal for security reasons". The workaround is to visit your website or application that already has the GA tracking code, then in your browser, click on Firefox / Web Developer / Web Console, and in the command line, execute or run your Javascript there. After Firefox 6, you can no longer run Javascript from the address bar.

If you don't have a creation or work that has the GA tracking code enabled, and you're here to find out how to avoid being tracked altogether, may I suggest that, instead of trying to avoid GA, you can retain some of your privacy, but still give us, the people who labor in the kitchen to make the food that you eat, a consolation prize, which is a bit of information about your visit; in a previous blog post, we show how you can use Tor to browse the web; once you close the Tor browser, you erase any evidence of previous visits and avoid being tracked between browsing sessions. Gentle reader, thank you for your continued patronage.

Saturday, June 30, 2012

How to Retain, Save, or Migrate Your Bookmarks When Upgrading Tor on Windows

As of Tor Browser version 4.02, I was able to upgrade to version 4.03 today (January 16, 2015) through an in-browser clickable notice, which also allowed me to restart Tor. Afterwards, all my bookmarks were automatically imported. However, below are the instructions in case you wanted to import bookmarks the way you did before.

So now that you can use Tor to bypass paywalls on websites that have metered content (though I encourage you to pay your fair share to media organizations like the LA Times that are doing a great deal of social good), we will discuss how, on Windows, you can retain, save, or migrate your bookmarks, when upgrading Tor on Windows. You can use Tor to browse the web anonymously, maintaining your privacy and keeping your online activity hidden from despotic governments and intrusive corporations. "I'm not doing anything wrong, so I have nothing to hide." True, although most of us would not welcome indoor cameras in our homes, because as your home is your castle, your own home computer should be your castle.

From participating in and reading online discussion, I've gathered that the method we're about to detail below cannot be applied to Tor installations on Mac and Linux operating systems. For now, the following process should work on Windows only.
  1. Soon as you see "HOWEVER, this browser is out of date" (or in previous versions, "there is a security update available for the Tor Browser Bundle"), download the new package. Henceforth, the Tor installation that you plan to replace will be the old, and the Tor installation that contains the latest fixes and security updates will be the new.
  2. In your old Tor folder, there is a folder containing your valuable bookmarks information. On Windows 7, if you're upgrading Tor version 3.6.6 to Tor version 4.0, the old Tor's places.sqlite file will be in:
    Tor Browser\Data\Browser\profile.default
    If you're upgrading Tor version 2.3.x (and earlier) to Tor version 3.5.x, the old Tor's places.sqlite will be in
    Tor Browser\FirefoxPortable\Data\profile
    Inside this folder, identify the file named places.sqlite and place it on your desktop by copying the file and pasting it onto your desktop.
  3. Navigate to the location containing your old Tor folder, and move the entire folder containing your old Tor into a temporary location, such as your recycle bin. Do not permanently erase the old folder just yet, until you've confirmed that the new Tor works. You may want to keep the old Tor around in case the new Tor doesn't work correctly on your computer (more on this later).
  4. Once you've moved the old Tor to a new location, download and uncompress the new Tor folder, and place it on your desktop
  5. Inside the new Tor folder, click to run Start Tor Browser.exe
  6. Once the new Vidalia is open, running, and has notified you that you are connected to Tor, wait for the new Tor browser to open up automatically. Once it has done so, immediately close and exit the browser and Tor.
  7. In step 6, what we did was run for the first time a brand new instance of new Tor. New Tor created a new default bookmarks file. By exiting new Tor, we are now able to replace the new Tor's newly created default bookmarks file with your old Tor's bookmarks file. Navigate to the location where your new Tor's default bookmarks file is stored. New Tor's places.sqlite file will be in:
    Tor Browser\Browser\TorBrowser\Data\Browser\profile.default
    Once you are in your new Tor's "profile.default" folder (in Tor 2.3.x and earlier, you will be in the "profile" folder), confirm that there is a file called places.sqlite. You are going to replace the new Tor's places.sqlite with the old Tor's places.sqlite.
  8. Locate the places.sqlite file that you had copied and previously set aside from your old Tor, which should be on your desktop. Copy the places.sqlite file from the old Tor into the "profile.default" folder. Confirm that you want to replace the new Tor file with the old Tor file.
  9. Navigate away from the "profile.default" folder window, to the "Tor Browser" window, and click to run Start Tor Browser.exe. Wait for the new Tor browser to open up, and you should now see your old bookmarks.
As an aside, I have been confronted with how buggy Tor on Windows can be. To this day, I still haven't been able to figure out the root of a problem I encountered when upgrading Tor, but I have devised a workaround.

I'm currently running tor-browser-2.2.35-13, I attempted to upgrade to tor-browser-2.2.37, and was met with the following:

Tor Browser_Vidalia  was unable to start the configured web browser
Vidalia was unable to start the configured web browser
Vidalia is the graphical controller and view of Tor's connections and settings. Startled and confused by this weird message, I get the sense that, for some unknown reason, tor-browser-2.2.37 just doesn't work for me. I decide to download and install the next level up, tor-browser-2.3.12-alpha-2. Everything seemed to be going ok, up to Vidalia starting and telling me I was connected to Tor. The next step was for the Tor browser to automatically pop open on my screen, but it never did. All that would happen was that Vidalia would run, but the Tor browser never appeared or opened up. I assumed this was because there was a bug with the alpha release, so I attempt to revert and go back to my last known working version of Tor Browser Bundle, 2.2.35-13. This time, when the Tor browser opens up, instead of the familiar message "Congratulations. Your browser is configured to use Tor.", I now have a new problem:

Tor Browser_proxy server is refusing connections
The proxy server is refusing connections

Firefox is configured to use a proxy server that is refusing connections.

Check the proxy settings to make sure that they are correct.
Contact your network administrator to make sure the proxy server is working.
Whiskey. Tango. Foxtrot. Maybe I should go into Windows Registry and remove all traces of Tor. In regedit, I deleted all registry keys I could find after searching for
Tor Browser, tor-browser, tbb, tor, vidalia
Presumably, I had wiped the slate clean, and could reinstall Tor like I was installing Tor for the first time. I again tried the last known working version of Tor. Darn, no go! I got the exact same "proxy server is refusing connections" messages as before. I then decided to abandon Tor Browser Bundle, and try to install Tor on Firefox. In an act of desperation, I tried installing TorButton for Firefox, even though this is no longer in active development. This was to no avail, because I got the same messages; in fact, what I ultimately did with Firefox was erase my Firefox tabs and wipe out all the cookies I had accumulated. I then tried to install Tor on Google Chrome, and again got the same "proxy server is refusing connections" messages. To my utter shock, I had run out of ideas and had no working Tor browser on my computer, and had no clue even what the problem could be or where to go next. At a definite low point, frustrated, preoccupied, I kept fiddling around, until I hit on a bit of luck. Recall that I had three different "Tor Browser" folders from the installation packages for 2.2.35-13, 2.2.37-1, and 2.3.12-alpha-2. Keeping them all straight was a hassle, so I simply relabeled my last known working version as "Tor Browser, last known working, now broken". This was 2.2.35-13. Out of habit, I clicked on Start Tor Browser.exe, and lo and behold, Tor was working again! As an experiment, I went to the "Tor Browser" folder for 2.2.37-1, and simply changed the name of that folder, from "Tor Browser", to "Tor Browser_a". That worked too!

In conclusion, your inability to connect to Tor, signified by the "proxy server is refusing connections" messages, can be overcome if you simply rename your "Tor Browser" folder to another name other than "Tor Browser". For me, I renamed it simply "Tor Browser 2.2.37-1" and now I've got working Tor with all the latest security updates.

So what is the root of the problem? Given that I had gone into my Windows registry, and tried to remove all traces of Tor, I am at a loss. Frankly, I don't have the patience or the motivation to delve into and figure out the problem. My best guess is that something happened with Tor, Windows, or the interplay between the two, that has Windows associating the folder C:\Program Files (x86)\Tor Browser\ with a defective version of the Tor protocol. Even going into Windows registry and trying to remove all traces of Tor seems to be of no effect.

Once I got Tor working again, and figured out the workaround, was the moment where the Pope gets off the airplane and bends down to kiss the ground.

Update: Since filing an official bug report, I have been in contact with a Tor developer, who told me that the problem of seeing the message "Vidalia was unable to start the configured web browser" can be avoided if you make it part of your routine to store your Tor folder on your desktop, instead of in C:\Program Files (x86):
Only installed applications go in C:\Program Files (x86). The Tor Browser Bundle is self-contained and does not actually install itself onto your computer, it just runs whenever you click the Start Tor Browser.exe icon. If you run Tor from the Desktop, then you should not have any problems with Vidalia not being able to start the browser - now or when you upgrade.

Saturday, April 28, 2012

Why Writing Tests is Fundamental to Computer Programming

A typical day in the life of a student of life involves trying to gather information about whether what a person says about himself, and our own ideas about that person, are accurate. One simplistic example involves getting a sense of a person's experience and background in the hard sciences by presenting the following word to him or her, without alerting the person that they are being put on the spot:
unionized
Most people might see the word union-ized, but a high school or college student who has spent some time with the periodic table, or someone in a laboratory, working with protons and electrons, would know about the tendency for some atomic elements to gain or lose electrons to other atomic elements, according to an atom's orbital shell; they might see the word as un-ion-ized. A person who works with her hands, or perhaps a labor law paralegal, who has experience in workplace discrimination or worker injury cases, or who served as a mediator in employment contract negotiation, may see union-ized. If a person says he is a chemist, and, in an unguarded moment, immediately sees and pronounces the word as union-ized, then you may be dealing with somebody who may be less than what he says. If a person says he is a community organizer, and pronounces the word as un-ion-ized, you may be dealing with someone who may be more than what he says.

Students of life that we are, you should already know much about studying for and taking tests and quizzes against a clock deadline, with observers making sure you have no unfair advantage, and the numerous assignments, problem sets, term papers, group projects, oral reports and other homework required of you at educational institutions, for which you then receive a score, grade or mark for your efforts. The American education system administers standardized PSAT and SAT or ACT tests in reading, writing, and math for students on the college track, which give you an idea of how well you performed answering verbal and quantitative questions in a controlled setting, in comparison with your peers. The people who paid for the test systems to be created and administered get an idea of what you know and whether you know how to use what you know to solve problems.

Whether you like it or not, you need to make space in your life for tests, either testing other people or being tested yourself, so that you're always subjecting your assumptions to scrutiny, making sure that the model of the world you have in your head corresponds to reality. In this way, you help decrease the probability of encountering unpleasant surprises in your daily work that could affect your life in a profoundly negative way. In 2002, Kent Beck introduced his book Test Driven Development, suggesting that the proper way to write computer programs was to begin not by writing code, but by writing a test for what you expect the code to do. Let's say you wanted to write a computer program that helped you pick lottery numbers, let's say for a large Mega Millions jackpot. Here are some expectations you demand must be met, or your code is no good:
  • There should be a total of six numbers
  • The first five numbers should include or be between 1 to 75 (formerly 1 to 56)
  • The sixth number should include or be between 1 to 15 (formerly 1 to 46)
  • Out of the group of five numbers, none of the numbers should be the same as another in the group
If your computer program code has failed any of the tests, then the code must be changed until it can pass the test. If all the requirements are met, then your code is passing all the tests, and you can move on to writing the next test, which might involve figuring out which sets of numbers are winners, or picking numbers for a different lottery game, perhaps the Fantasy 5, or Daily 3, and so forth.

In essence, writing a test involves first setting a minimum standard for your code that must be met, then writing your code and seeing it pass or fail. Writing the test first may seem silly (it certainly did to me for the longest time, and frankly, it sometimes still does), but the idea is that if you begin by writing code, you can spend hours and days optimizing and improving some piece that is not important; you should really be getting into the discipline of ensuring basic functionality is up and running (you can always make your code more terse, elegant and abstract when necessity demands). You want to prevent yourself from getting distracted from the main goal, which is to publish a basic, working prototype. Initially we wanted a way to generate numbers for a specific lottery game, but then we wanted numbers for different lottery games, and to figure out which number sets were wins. As your desires expand and grow, what was a simple computer program becomes more of an involved project, and quickly the program can become an application that is the foundation for a business or enterprise that might involve other programmers who want to look at and change your code. As your codebase grows, it becomes more complex and much harder to maintain, simply because what was once a simple computer program is now doing much more, and depends on more technology, written by other people, that is out of your control, and you may need to have people look over and touch your code. Writing tests first is based on the assumption that, in the long run, untested code requires much more time spent poring over and fixing puzzling bugs, than if you had done the hard work upfront. If your code is not supported by tests, you may have a greater probability of encountering a showstopper, i.e., some hard to find, unexpected problem in your system that prevents you from moving forward and releasing improved versions of your software in a timely manner.

One caveat: writing tests first is hard, perhaps more difficult than writing code first. There is the argument that if you start by writing tests, setting an expectation for what you want to see your code do, you can improve the design, and readily determine what are the essential pieces, and how you want to organize your code so that you can get a better idea when something goes wrong.

In closing, a recent PBS NEWSHOUR story really brought home to me the message of how important it is to create a system that is easy to maintain. A woman who has worked in Africa understands the problem of women dying in childbirth due to lack of light in maternity wards. Her husband, in response, designs a solar lighting apparatus that is portable:
Developing countries are a graveyard of well-intentioned technologies from the First World.

SPENCER MICHELS: Environmental engineer Ashok Gadgil has been consulting with WE CARE Solar. He developed the Darfur Stove that has revolutionized cooking in the developing world. And he's a senior scientist at the Lawrence Berkeley National Laboratory.

He says he's impressed with what he's seen so far, but he says if Stachel and Aronson are to succeed, they must address how the system will be maintained over the long term.

ASHOK GADGIL: No single technology, no single piece of machinery has infinite life. When one wants to introduce a technology into society, it needs social placement. The technology needs links and threads that connect it to a Web of experts or spare parts dealers or maintenance people or diagnostic technicians which will keep it going.

SPENCER MICHELS: How do you know that, after a year, this thing isn't going to get rusted or break or whatever?

Watch 'Solar Suitcase' Sheds Light on Darkened Delivery Rooms on PBS.
See more from PBS NewsHour.

Monday, January 30, 2012

Occupy a Tea Party From the Cloud

Imagine you are going to a genteel scone and crumpets breakfast party in the English countryside. In another time and place, to be invited to such a gathering would have meant you had arrived, as they say, into the society pages. "Anything less would be uncivilized," you might utter, with your pinky finger sticking way out in the air, as you and your gentle friends titter over tea and biscuits and contemplate a jaunt to the opera. You are uninvited, but you still want to go, so you invite yourself to the gathering, knowing there are others like you in support of a planned assembly, a rally of sorts, even a demonstration of your numbers, and your attendance is part of a larger uprising and community movement. Before, during and after the event, you post and look at pictures and video, text, tweet, maybe facebook or google search, chat, email, all this in support of your common goal, to non-violently disrupt business-as-usual, and pleasure-as-usual, in the layers of society that seem to you unbearably hardened, even calcified. In preparation for the protest, you and your ever growing society hang out and chat in-person, then use your laptop and notebook computers, tablets, cellular phones, smart phones and PDAs, to form your own network of friends, to create a buzz and attract more people, and on the day of the event, you print out maps and directions, see what other people are doing and tag along, and before you know it, you've used the Internet and mobile phone network (collectively called the cloud) to plan, collaborate, share, publicize, attend, rally, demonstrate, and afterwards, document what happened, learn from others, and possibly prepare to organize and make the announcement to occupy another location.

About a year and a half ago, the author Clay Shirky gave a talk on cognitive surplus, "the shared, online work we do with our spare brain cycles. While we're busy editing Wikipedia, and making LOLcats," he argues, "we're building a better, more cooperative world." Clay states that people want to consume, but also we like to create, and sometimes we want to share. He relates the story of a woman in Kenya who found, in the midst of a disputed presidential election, that there was an outbreak of ethnic violence. In her blog, she solicited from her commenters more information about the dangers inherent in any succession of power in human society, and what areas to be mindful of, depending on who you were. She collated and posted the information flowing in, but there was so much data coming in, it became way more than one woman could manage. She asked if there was a way to automate the process. Two programmers saw her plea for help and, in 72 hours, launched ushahidi, which means witness or testimony in Swahili. This application very simply takes reports from the field, i.e., from the web, or mobile phones and sms, aggregates those reports, puts it on a map and makes it public. The app spawned a social push which became known as crisis mapping. Enough people found ushahidi valuable that the programmers decided to make it open source and turn it into a platform. The number of deployments of ushahidi went from a single idea and implementation in Kenya, to global reach, in less than 3 years. Cognitive surplus, then, can be the ability of the world population to volunteer, contribute, and collaborate on large, sometimes worldwide, projects.

In his talk (below), Clay Shirky states that civic value is when something is created by the participants, but enjoyed by society as a whole; when something is enjoyed just by the participants, that would have only communal value. When the Occupy Wall Street movement was getting started in New York, one of the first things the group did was put, at the top of their website, a link to the software platform that the participants used to consume, create and share. The idea was, should the movement catch fire (and how!), Occupy groups in other cities could download, install, deploy and begin their own geographic base of online operations. Github is where the occupy movement and ushahidi store their repositories, which contain the master copy of the project. Anyone in the world, on their own initiative, can download and install the software built from the master code, On a computer with a connection to the internet, you can soon host your own city chapter. You can contribute to the technological platform you downloaded by helping people get connected and stay more involved towards a common goal. For those who have spent enough time thinking about and using a tool, suggestions for improvement or features come to mind, such as adding the ability to show live video, or to display content in a specific language, or to give some users more or less responsibilities and privileges. If you make a change to your local copy, such as fixing a mistake, those improvements can be merged into the master code, and the communal becomes civic.

But that is all really big picture, so let's bring it back to the day to day life each one of us leads. How does this all apply to me? As we start in on 2012, what gets me out of bed in the morning is getting more users. I am here, and at your service. Last year, I had a goal of creating 2 blog posts for every month, which worked out well; now my new year's resolution is to make an app and host it on github, and to show you how to do it.

With the Tea Party, Occupy, the Arab Spring, and the demonstrations led by a Russian blogger Alexei Navalny against Vladimir Putin in Russia, it seems protest is in season.

Here's the link to the page with the video:
http://www.ted.com/talks/clay_shirky_how_cognitive_surplus_will_change_the_world.html

Hat tip to JJ Behrens for sharing the video.

Thursday, December 29, 2011

The Danger in Selling Digital Goods on Ebay & Accepting Paypal as Payment

Many of you casual gamers on Facebook may know how popular digital goods are in the online marketplace, where people pay lots of real money to buy items used in video games and online transactions. Digital goods can range from cell phone ringtones, music, movies and shows, electronic books (ebooks), rights to domain names, online accessories and characters (avatars) in video games, electronic gift certificates and coupon codes, online electronic currencies like Linden dollars and bitcoins (btc), financial & cash services like ukash, moneypak, pecunix and more, secure, encrypted web browsing and software packages, sometimes written to a flash drive that you can use to boot from, and I'm sure there is much that I missed and am not aware of. I'm not going to identify what I sold, because it's embarrassing that I not only got scammed, but that I spend so much time online acquiring digital goods. Maybe it's because my fear is I am socially inept in crowds and I would rather be indoors playing video games than out mingling and meeting people. Suffice it to say that, yesterday, around this time, I felt richer. 24 hours later, I feel poorer. Here's the story:

I poured quite a bit of time and effort into acquiring an online digital good. At the same time, I decided to take advantage of a temporary promotion on ebay where you can list items for free for the next 3 days. Among the many items that I listed, I decided to take a chance and list that particular digital good, my asking price for it about 25% higher than what I paid for it, after ebay and paypal fees. I had done my due diligence, looked at competitors, saw many people buying and selling the same item on ebay, and thought, with my account in good standing and lots of positive feedback, why not see if it might sell? Well, imagine my pleasant surprise when I got out of bed in the morning, checked my email, and saw that my item had sold through Buy It Now for a couple of thousand dollars, hand to God. The buyer also seemed good, with 76 feedback and a rating of 95.4%, and he paid me with paypal, in the amount of $2736 after ebay and paypal fees. The buyer used ebay messages to specify the online address where I could deliver the item, and after confirming the money was in my paypal account, I promptly sent the item to him.

I was feeling high for about most of the day, happy that all the money, time and effort I had spent in my online community was beginning to pay off. The ebay buyer had told me the item had been received, and had even given me positive feedback. Imagine my surprise and horror when, around 10 pm yesternight, about 11 hours after I delivered the digital good, I received 2 messages, one from ebay, one from paypal, with the Subjects: "MC143 eBay Listing Removed", and "Notification of Cancelled Withdrawal", respectively. The first message said:
We recently learned that someone was using an account to bid on items without the account owner's permission. For this reason, we have canceled all bids on the following listing...All associated fees have been credited to your account. Please note that we're working with the account owner to prevent any additional unauthorized activity.

If you have any concerns or questions, click "Customer Support" at the top of most eBay pages.

We're sorry for any inconvenience, and we thank you for your patience and cooperation.

Sincerely,

eBay Customer Support
The second message, from Paypal, came about because I was trying to transfer the money sent by the buyer for my digital good into my bank account, and it read:
Recently, your account balance became negative. To cover your negative balance, we have reversed "Pending" electronic funds transactions that you had initiated from your PayPal account. This is to confirm that the following transaction(s) have been cancelled...Thanks,

PayPal Finance Department
Long story short, I called ebay, told them the buyer was making a false claim, because I had been in touch with the buyer by the hotmail email address associated with the buyer's Paypal account, and also by ebay messages, and I had an email from the buyer saying the digital good had been received, and the buyer had even given me positive feedback. My protests had no effect. In the eyes of the ebay customer service agent, Dustin, the account that bid on and won my item was accessed by a third party, without the account holder's permission, and for security reasons, Dustin could not tell me what the criteria or proof was that ebay possessed showing them the account had been accessed by a third party. When I told Dustin that the problem was I had lost the item I sent to the buyer, Dustin put me on hold, then said he was going to advise me to contact law enforcement about this. When I told Dustin that the buyer was in a different country, Dustin said "that's the only way we can resolve it." When I asked for the payment back, Dustin said they could not do that, because the items were purchased by a third party. At this point Dustin must have heard me typing, because he asked me if I was recording this call, and when I said yes, Dustin said at this point he is forced to disconnect this call. Click. And that, ladies and gentlemen, is the embarrassing story of how I got scammed out of the digital good I had, and the money I paid for it.

November 7, 2013: Latest update on this case is here.

Thursday, October 27, 2011

How to Use Google Prediction API to Estimate a Sale Price for Your Home

This blog post is based on Martin Omander's workshop at Silicon Valley Code Camp, which I attended on Saturday, October 8:
Store your data, predict the future

Speaker: Martin Omander
Level: Intermediate | Room: 3525 | 9:45 AM Saturday
  • Make your smart applications smarter with Google's Prediction API. Take advantage of Google's machine learning algorithms to make recommendations, analyze Twitter, detect spam, classify documents, identify languages and more.
  • Store your applications' data securely and efficiently in Google's data centers with the Storage API.
The real estate home price data file mentioned below was compiled by Martin from Redfin data for the Rex Manor neighborhood of Mountain View, California.


If you've ever wanted to buy a house or sell your home, and would like a reasonable estimate for what the ultimate sale price will be in this market, you can get a real estate agent's take, or you can use Google Prediction API (henceforth Prediction) to give you another estimated price, given available market data. The idea is, you grab a number of sale price records for the ZIP code you want to buy or sell in, feed the data into Prediction, and Prediction will spit out a number based on the data you fed it. Besides spitting out scalar values, Prediction also does classification. To get your feet wet, here is a beginner tutorial that figures out, in an automated way, whether some text you pass in is English, French or Spanish:

http://code.google.com/apis/predict/docs/hello_world.html

Assuming you were able to successfully use Google's Prediction API, in conjunction with Google Storage and Google's APIs Explorer Tool, to classify samples of text that you pass in, the next step is to predict a sale price for your home.
  1. Download Martin's houses.csv data here
  2. Using the same steps in the tutorial above, upload the houses.csv data into Google Storage, and then use the data to train Prediction
  3. After training is complete, we want to get a predicted price. To do this, we want to pass in the values for a house that we want to buy or sell. Let's say we're trying to sell a 3 bedroom, 3 bathroom, 1800 square foot, built in 1960, single family residence. I found that when I tried to pass in the following as a value for the csvInstance key, I got an error:
    3 3 1800 1960 house
    I then tried the same thing with commas, but that didn't work either. What I found finally worked is, in the APIs Explorer tool, when specifying the value of the csvInstance, you need to count how many field values you are putting in, let's call it n (in this case, n equals 5), then provision that same number by clicking on "Add" n times, and manually insert the values in order, like so:
     {
    "input": {
    "csvInstance": [
    "3",
    "3",
    "1800",
    "1960",
    "house"
    ]
    }
    }
Caveat for those who want to read in or import additional data sets: if you want Prediction to spit out a number, i.e., a scalar value, one thing to remember is that the column associated with the scalar value that you want a prediction on (in this case, home sale price) should be the first column inside the data file you feed into Prediction. Martin said that when he was putting together the home sale price data, he had to manually copy and paste from Redfin into his spreadsheet program, then move the column for the home sale price to be the first column, and then exported the spreadsheet as a csv, i.e., comma separated values, file.

Saturday, August 27, 2011

Canon is awesome

I want to let you all know about some pleasantly surprising, then, rather amazing, customer service I received, from the consumer and business technology company Canon. Back in October 10, 2003, I purchased a Canon Powershot S400 digital camera with $300 my parents had given me for my birthday. I really liked the camera, and got to use it a lot, but then last year, I started noticing some problems. The problem I was having was, whenever I tried to take a picture, I saw something like this (thanks, Deepak Prakash, for the photo):

The image on the LCD monitor on the camera, and in subsequent photographs I took, was smeared, blurred, washed-out, and tinted pinkish-red. Other times, I noted a warped, noisy, false-color image, then the LCD monitor would go dark on me.

I was ready to toss the camera and buy a new one, but in a last bid attempt to save money and salvage what I had, on Friday, August 20, 2010, I called Canon, and from a conversation I had with Canon representative Mike, in Chesapeake, Virginia, he told me the following (and I paraphrase):
This particular camera has a service notice, for an issue with an image sensor, a CCD, charge-coupled device. That sensor can fail. What I need to do is send the camera to Canon, and they will repair it for free. I need to give Mike my information, and get a case created for me. Before I send the camera in, remove the battery, memory card, and strap from the device. Wrap camera in bubble wrap, and put in a cardboard box. Mike will send 2 emails to you, the first has instructions on what to do and where to send it to, along with an evaluation form that I print out and put inside the box, and the 2nd email will come from UPS, with a free shipping label, prepaid and insured. Once the camera is received, it will take 2 to 3 days for the Canon technicians to check in the camera and evaluate it; they will send me an email with a repair order and status, and then 5 to 7 days to repair and return to you. Return shipping is via Fedex, and I will need to sign for it. The advisory for this service notice went out in 2007, but you weren't registered, so you didn't receive the notice
Lo and behold, on Thursday, September 9, 2010, I received a repaired Canon S400 camera, which has been working for me just fine since then. I thought it was worth mentioning that, other than the inconvenience of my not having the camera during the time it was in transit, being repaired, and shipped back to me, the whole repair process cost me nothing, and even the shipping was completely paid for by Canon. I've come to find that the problem I encountered was common to many digital cameras from many brands that contained a particular Sony-made part:

http://www.imaging-resource.com/badccds.html

I've also come to find out that Canon is slowly phasing out the cameras they will repair, according to a timeline. So if you have a Canon Powershot S400, it looks like you may be out of luck:

http://camerarepair.blogspot.com/2007/11/canon-digital-cameras-showing-black.html

Monday, July 25, 2011

How to Add Google +1 to Your Blogger/Blogspot Presence

The Google Plus social network has been fun to play with so far, and I understand that even though Google+ has been growing really fast, it still has a ways to go before it catches up with Facebook and Twitter. Unlike the latter two, one thing that takes getting used to in Google+ is the lack of a system to send a direct or private message to who you're connected with. There is a work-around, where you can publish to your intended recipient's stream: you click on "Share what's new...", type something, but then when it comes time to 'Share', instead of specifying a circle, you type out the name of the person who you're connected to. Your message then gets published to that person's plus.google.com stream. The problem with this method of approximating direct messaging is, as Google+ warns:
Your content may be shared beyond the bounds which you originally intended if your post is reshared or if someone is mentioned on your post. For instance, if someone is mentioned in a comment, they'll be able to see the entire post even if the post wasn't originally shared with them.
So if you mention someone else in the content of the post, and happen to prepend that third person's name with a '+' or '@', then that person can now read your message, which defeats the purpose of a private, direct message.

That said, Google+ is still pretty cool, and one can argue that because there is this limitation of no direct messaging, Google+ is cleaner and leaner, akin to Twitter's self-imposed 140 character limit (which I, and Farhad Manjoo, think has outlived its usefulness, especially for Twitter conversations).

Before Google Plus came out, Google introduced +1, which is their version of the Facebook 'Like' button. In addition to Google's how to add +1 to your blog, for those on blogger/blogspot, here's what I did:

As stated in the Google document above, you need to copy and paste one of the following 3 possible pairs of XML elements into your blog template:
  • <script> and <g:plusone> elements
  • <script> and <div> elements
  • Two <script> elements, the latter of which makes a call to the render function, as explained in the section Javascript API
They all accomplish the same thing, but if you don't know which one to use, I'd go with the first, or the second, one, either of which are easy to copy, as Google provides the boilerplate for you, without the need for any additional changes from you. Our next steps are for where to paste what we copied:
  1. In Blogger's tabs console, click on 'Design'
  2. Click on 'Edit HTML', and in the section 'Edit Template', click on 'Expand Widget Templates'
  3. Paste anywhere inside. I recommend that you provision a section inside the template so you can keep track of all the changes you've made to the default.

Friday, June 17, 2011

one of the best computer deals out there right now

This past Memorial day, I got a brand new computer. It took Dell about a week to assemble and ship to me, and about a week for me and machine to get friendly. Coming up for air, here's one thing I really love about mi computador nuevo: the place where you rest your hands on your wrists, as you are about to type, feels really good. It's never too cool, which is what you might expect from a smooth metal surface, and it's also never too hot, which is what you'd expect from metal sitting just millimeters above powerful circuitry. The wrist rests on my new machine have a high-quality brushed metal finish, that feels almost silky, and the fact that you can rest your palms before typing, and not have the coolness transfer from the metal to your body, is a nice touch, and feels just right. It's kind of like you were shipped a computer with the luxury upgrade of hand-and-wrist-rest warmers, and evokes in me a great deal of confidence in my recent purchase. Those Dell engineers, artists and designers thought of everything, and presumably come from the same school of thought as the geniuses who gave you the ability to keep your cooked rice hot, your favorite massage chair heated, your toilet seat warm, your movie theater seats toasty, your car's front seats comfy in that morning chill, heck, yes, even your steering wheel warm:

Sure, it's a minor detail, as can be said about any luxury, and I'm not quite sure how they did it, but it speaks to the finesse of a homegrown company that has been at it for years, and has finally come into its own. My new laptop is also energy star 5.0 compliant, unlike your tv set-top box or DVR, meaning when it comes to your utility bill, this laptop uses less electricity when idle, and very little power when you've got it asleep, or hibernating.

My previous computer, an Acer Aspire 9410-2028, was purchased back in August of 2007, and did not have any hand/wrist warmers. It was a good computer for its time, at a good price, but fast forward to the present, about 3.5 years later, and now getting anything done on the same computer is a real slog. First, the hinges broke about a year and a half ago, which meant I had to find a way to prop up my screen or else it wouldn't stay up by itself. Then, for the past year, if I ran my operating system for a while without rebooting, I noticed extreme latency, lots of disk spinning, very slow response time, and often my screen would suddenly go dark for a minute or more because of my graphics driver crashing (this occurred sometimes multiple times an hour). If I tried to switch between web browser tabs or web browser windows, I dreaded having to endure 6 second to several minute waits while the computer finished what it was doing and caught up to me. Trying to switch between a browser window to my desktop, or playing a movie, were bitterly negative experiences, evoking in me a range of responses from impatience, to taking the Lord's name in vain, to prolonged bouts of swearing and exasperation, sometimes leading to existential cries that made me doubt my commitment to sparkle motion:
If you're in the market, looking to buy, or have been shopping for a new computer, you could do a lot worse than what I got for $1239.61 ($1,123.99 + $6 environmental disposal fee + $109.62 tax):
Dell XPS 17 (L702X), Windows® 7 Home Premium, 64-Bit
PROCESSOR 2nd generation Intel® Core i7-2720QM processor 2.20 GHz with Turbo Boost 2.0 up to 3.30 GHz
OPERATING SYSTEM Genuine Windows® Home Premium, 64-Bit, English
SERVICE PLAN 1 Year Limited Hardware Warranty (Mail-in repair in 10-14 business days - Shipping not included)
HD DISPLAY 17.3" FHD (1080p) with 2.0MP HD Webcam
MEMORY 8GB Shared Dual Channel DDR3 Memory
VIDEO CARD NVIDIA® GeForce® GT 550M 1GB graphics with Optimus
BATTERY OPTIONS 90 WHr 9-cell Lithium Ion Primary Battery
HARD DRIVE 1.0TB 500GB 7.2k HDD x 2
OFFICE SOFTWARE Microsoft® Office Starter: reduced-functionality Word & Excel w/ ads. No PowerPoint or Outlook
SECURITY SOFTWARE McAfee Security Center with VirusScan, Firewall, Spyware Removal, 30-Day Trial
INTERNAL OPTICAL DRIVE Tray Load Blu-ray Disc BD-Combo (Reads BD and Writes to DVD/CD)
WIRELESS + BLUETOOTH Intel® Centrino® Wireless-N 1000
SOUND OPTIONS JBL 2.1 Speakers with Waves Maxx Audio 3

Dell XPS 17 for:
Order Subtotal: $1,123.99
Shipping and Handling: $9.00
Shipping Discount: -$9.00
Environmental Disposal Fee: $6.00
Tax Total: $109.62
Total Amount: $1,239.61
What was important for me was the 64-bit quad-core CoreTM i7 2720qm CPU, only 1 or 2 steps below the state-of-the-art, most advanced chip currently out on the market. Also, I needed my next computer to have 8 gigabytes of RAM, 1 terabyte of hard drive space, a 17-inch high-resolution 1920 x 1080 screen (yes, high definition), and the ability to play Blu-ray DVDs. To get this computer at such a great price, I had to make two sacrifices and apply two coupon codes:
  1. opt for the limited hardware warranty (essentially, I am betting Dell won't send me a lemon) of "Mail-in repair in 10-14 business days - Shipping not included" instead of the standard 1 Year Home Express Service of "Mail-in repair in 1-2 business days - Shipping included"

  2. decide against the 3D capable screen and the 3D glasses

  3. These codes subtract an additional $500 off. Both codes expire June 30, 2011, but you can always search for dell coupon codes to find the combination that gives you the most money off:
    • 8GHR80Q1PLLCF7
    • 7WR1C2?HTTQQ11
Perhaps the economy has people spooked about spending $1200 on a computer, but I was surprised I wasn't able to find this deal advertised anywhere else. I found this deal on my own, meaning I took the time to pick out which computer I wanted, and, through trial and error research, which applicable coupon codes were stackable, as many of the codes have restrictions. At first I looked on techbargains.com, then on Costco's website and in their stores, and I was contemplating buying an HP Pavilion dv7t Quad Edition customizable Notebook PC for $1484.14 ($1,344.99 + $8 recycling fee + $131.14 tax), but that tax rate of almost 10% seemed exorbitant to me. In a defiant act of tax avoidance (remember, Jesus votes Republican), I decided to do some research on computers being offered for sale on ebay, where sometimes you can buy items tax-free. At one point I was willing to pay $1600 for the right configuration of parts, but not being able to find what I wanted from ebay, I decided to go on Dell's site directly. There, I found I still had to pay tax, but Dell's grand total price was almost $300 less than the HP I was first expecting to buy, for an upgrade on the CPU, hard drive spin from 5400 rpm to 7200 rpm, 17.3 inch screen with resolution increase from 1600 x 900 to 1920 x 1080, and I was able to throw in a 50% upgrade in battery life, from 6 to 9 battery cells.

Until the end of the year, Dell is taking an additional $20 off, and throwing in free shipping. You can actually get this computer for $20 less than what I paid! Here's the link to what it looks like:

http://www.dell.com/content/products/productdetails.aspx/xps-17?c=us&cs=19&l=en&s=corp&~lt=popup

Friday, March 25, 2011

How to use Perl, PHP, Python, R, and Ruby to find Euclidean distance between two points

According to Wikipedia:
In the Euclidean plane, if p = (p1, p2) and q = (q1, q2) then the distance is given by:

Assuming you are using the Cartesian coordinate system, your two coordinates must both be of length n, where n can be any non-zero positive integer. So if the two points in question, p and q, each had 3 values:

p = (p1, p2, p3), q = (q1, q2, q3)

Then n would equal 3, and the distance formula would be:



The hardest part for me, when putting this all together, was figuring out, for each scripting language, how to iterate over, i.e., step through, the respective elements of both coordinates, simultaneously:

Perl 5 (5.12.2):
use List::Util qw(sum);
use List::MoreUtils qw{ any pairwise };

sub get_distance_between
{
if (scalar(@_) != 2)
{
die "You must supply 2, and only 2, coordinates, no more, no less. Stopped";
}

my $a_ref = shift;
my $b_ref = shift;

if (@$a_ref != @$b_ref)
{
die "Coordinates do not have the same number of elements, stopped";
}
else
{
@x = pairwise { ($a - $b)**2 } @a, @b;
return sqrt(sum(@x));
}
}

# Usage:
@a = (1008, 2243, 976), @b = (1005, 2249, 974);
$ad = get_distance_between(\@a, \@b);
print "\$ad == $ad";

PHP 5.3.6:
function subtract_and_square($n, $m)
{
return(pow($n - $m, 2));
}

function find_distance_between($p, $q)
{
$numargs = func_num_args();
if ($numargs != 2)
{
die("You must supply 2, and only 2, coordinates, no more, no less.\n");
}
else if (sizeof($p) != sizeof($q))
{
die("Coordinates do not have the same number of elements.\n");
}
else
{
$c = array_map("subtract_and_square", $p, $q);
return pow(array_sum($c), .5);
}
}

Python 2 (2.5.4):
def get_distance_between(p, q):
if len(p) != len(q):
raise Exception
else:
sum = 0
for pval, qval in zip(p, q):
sum += (pval - qval)**2
return sum**(.5)

R (2.12.1):
get_distance_between = function(p, q)
{
if (length(p) != length(q))
{
stop("\nCoordinates do not have the same number of elements.")
}
else
{
element_products = mapply(function(a,b) (a - b)**2, p, q)
sqrt(sum(element_products))
}
}

Ruby 1.9.2:
require 'generator'

def get_distance_between(p, q)
if p.length != q.length
raise Exception
else
sum = 0
syen = SyncEnumerator.new(p, q)
for pval, qval in syen
sum += (pval - qval)**2
end
end
return Math.sqrt(sum)
end

In the Perl example, thanks to Miller Hall and Jon Bjornstad for their review and suggestions on how to improve my Perl code to make it more readable.
In the R example, thanks to Spencer Graves and Nicholas Lewin-Koh for pointing me to mapply and plyr (which I did not have time to research and use).

Update: On October 31, 2011, my friend Nikita Borisov, assistant professor in Computer Science, offered the following suggestion on facebook re the R and Python code:
This person clearly hasn't used these languages very much. In R, you can say sqrt(sum((p-q)**2)). Similarly, in Python you can write sqrt(sum([(x-y)**2 for (x,y) in zip(p,q)]))
Thanks, Nikita!

Monday, March 21, 2011

The 3 Most Important Things a Programmer Must Know

Write code, run code, fix code is essentially what a programmer does, said the speaker at an intriguing talk I recently attended, hosted by the Perl Mongers group. Zed Shaw is the author of Learning Python the Hard Way and in review, I have to agree with this user-generated comment:
Very knowledgeable not just with Python, but he has a deep understanding of programming. He inspired me to be a better thinker and programmer.
I was interested in this talk because Zed Shaw made a name for himself by coding the Mongrel web server, as well as Mongrel2, both of which were and are integral parts of Ruby on Rails. I looked forward to the rather unique confluence of a core Ruby on Rails programmer giving a talk about Python at a Perl meetup. I had a prior discussion with a female attendee at a Ruby on Rails Workshop for Women on why religious wars in technology were so prevalent; some people get worked-up over a particular choice of scripting language (Perl vs Python vs Ruby) or text editor, and soon flame wars ensue on the internet about which technology is best. Rodney King asked us after the Los Angeles riots, and Zed is living proof that we can all get along, at least when it comes to scripting languages.

Zed took a year off to learn jazz guitar. He realized, when learning music, you have the concept of a trainer, who tells you to play individual chords multiple times until you get better at it. Then the trainer tells you to play another chord, and then play a song in both chords, in a progression, until you have some experience under your belt. Whenever you want to learn something difficult, it's hard to explain the ideas unless you have some experience under your belt. Using this same principle, Zed decided to introduce the beginner to simple coding exercises, until you get better at writing computer programs, and then he slowly introduces the concepts to you.

The fact that Zed was able to use an analogy from music learning in explaining hard-to-grasp concepts in computer programming makes his experience valuable and his book a must-read for me. Zed strikes me as hard-working, dedicated to his craft, and he knows something about how to get beginner programmers engaged in a new, complex, but rewarding venture. One last thing he said that really hit home for me: Zed recommends learning parsing and lexing, the two most important things, other than algorithms, that a programmer must know. Right now, Zed is doing C and Lua, and he mentioned software called Corona that enables the Lua programmer to write iPhone games.

Monday, November 1, 2010

Rails3: Migrating from MySQL to PostgreSQL

I encountered an error even though I had successfully run:
gem install pg
I googled:
install postgresql rails windows "no such file to load -- pg"
and Peter Mac helped me out. In your Rails 3 Gemfile, make the following change:
#  gem 'mysql'
gem 'pg', :require => 'pg'

Wednesday, September 23, 2009

how to import data into R and SAS

What is bio-statistics and how does it relate to me ? I am often asked this question, and now I think I may have an answer. With the advent of the Internet, we are now in the Age of Information, and when it comes to "statistical data analysis", a rather imposing mouthful, to quote a recent article in the New York Times (and I paraphrase):
In field after field, computing and the Web are creating new realms of data to explore - sensor signals, surveillance tapes, social network chatter, public records and more. We're rapidly entering a world where everything can be monitored and measured, but the big problem is going to be the ability of humans to use, analyze and make sense of the data. Strong correlations of data do not necessarily prove a cause-and-effect link. For example, in the late 1940s, before there was a polio vaccine, public health experts in America noted that polio cases increased in step with the consumption of ice cream and soft drinks. Eliminating such treats was even recommended as part of an anti-polio diet. It turned out that polio outbreaks were most common in the hot months of summer, when people naturally ate more ice cream, showing only an association. Computers do what they are good at, which is trawling these massive data sets for something that is mathematically odd, and humans do what they are good at and explain these anomalies.
To analyze statistical data, we use computer programs as tools to work with such information as biological data. Yet another recent article in the New York Times compares and contrasts two of these computer programs, R and SAS (and again I paraphrase):
SAS Institute (the privately held business software company that specializes in data analysis)'s namesake SAS has been the preferred tool of scholars and corporate managers. But the R Project has also quickly found a following because statisticians, engineers and scientists without computer programming skills find it easy to use.
Reference:
http://www.nytimes.com/2009/08/06/technology/06stats.html
http://www.nytimes.com/2009/01/07/technology/business-computing/07program.html?pagewanted=all

So "Statistical Data Analysis" in the abstract sense is a formidable journey of a thousand miles, but the bite-size journey's first step involves importing a set of data into the tool (I'm assuming you already obtained, installed, and are running the software). For purposes of demonstration, I've created a data set using the actual previous year's receipts I had gathered and saved from each and every time I filled my car's tank with gasoline:
    18AUG2009  6 12.815 37.66
14JUL2009 12 4.340 11.8
28MAY2009 6 9.532 24.39
22APR2009 4 7.348 16.01
25MAR2009 2 5.509 11.12
15MAR2009 7 4.230 8.62
04MAR2009 3 11.989 25.16
21FEB2009 7 13.298 27.91
29JAN2009 15 13.989 27.68
03JAN2009 6 12.620 22.70
29NOV2008 16 11.239 20.78
25SEP2008 8 13.929 51.80
Note that on the tail end of the second line, in the last figure, 11.8, I omitted a zero ('0') when I was typing the data in. We'll come back to that later. I decided to record the following four fields for each time I filled the gas tank (all took place at Costco in San Leandro):
  1. date of purchase
  2. pump number
  3. quantity of gas obtained, in gallons
  4. cost of the transaction
In both tools, R and SAS, we will then divide cost by quantity and generate a fifth field, price per gallon.

To import a dataset into your software, you can either read from a file, or copy and paste it in (although for R, you will copy the data set, but you won't actually paste anything). The following scripts have been tested on R versions 2.8.1, 2.9.2 and SAS version 9.1.3 Service Pack 4.
  • To read data from a file within R and SAS:
    1. identify the path to the file containing your data set. Let's say the path is:
      G:\tpc247\petrol.txt
      if you're on Windows, the convention is to delimit or separate folders with a backslash, but this poses a problem for software that is trained to recognize tabs and carriage returns and newlines as '\t', '\r' and '\n' respectively. For reasons of cross-platform compatibility, if there are backslashes in your Windows path, add another one right next to it:
      G:\\tpc247\\petrol.txt
      or replace the backslash with a forward slash:
      G:/tpc247/petrol.txt
    2. at the command prompt, input and run the following incantations:
      • R:
        petrol_01 = read.table("G:/tpc247/petrol.txt", header=FALSE, col.names=c('date', 'pump', 'quantity', 'cost'))
        petrol_01$per_gallon <- petrol_01$cost / petrol_01$quantity
        petrol_01
      • SAS:
        data petrol_01;
        infile "G:/tpc247/petrol.txt";
        input date_of_sale$ 5-13 pump_number$ 16-17 quantity 20-25 cost 28-32;
        per_gallon = cost / quantity;
        proc print data=petrol_01;
        title 'Unleaded gasoline purchase history for 1 year, San Leandro, California Costco';
        run;
  • To read data from computer memory in R and SAS:
    • R:
      1. copy and paste this into R, but don't actually run the incantation yet:
        petrol_01 = read.table("clipboard", col.names=c('date', 'pump', 'quantity', 'cost'))
      2. copy your data set, then run the previous incantation

      3. run the rest as you normally would:
        petrol_01$price_per_gallon <- petrol_01$cost / petrol_01$quantity
        petrol_01
    • SAS:
      data petrol_01;
      input date_of_sale$ 5-13 pump_number$ 15-16 quantity 18-23 cost 25-29;
      per_gallon = cost / quantity;
      datalines;
      18AUG2009 6 12.815 37.66
      14JUL2009 12 4.340 11.8
      28MAY2009 6 9.532 24.39
      22APR2009 4 7.348 16.01
      25MAR2009 2 5.509 11.12
      15MAR2009 7 4.230 8.62
      04MAR2009 3 11.989 25.16
      21FEB2009 7 13.298 27.91
      29JAN2009 15 13.989 27.68
      03JAN2009 6 12.620 22.70
      29NOV2008 16 11.239 20.78
      25SEP2008 8 13.929 51.80
      proc print data=petrol_01;
      title 'Unleaded gasoline purchase history for 1 year, Costco in San Leandro, California';
      run;
Coming back to the omitted zero ('0') on the second line in our last figure, 11.8, you might find it amusing how finicky R and SAS are about what they eat. Putting this tutorial together gave me the opportunity to learn some valuable things about the two tools. Just like a toddler can be very picky about the food she feels like taking in her, feeding data to R and SAS and ensuring they digest the data correctly may require some forethought and planning. When importing the dataset into both tools from a file, I noticed that in:
  • R, if I didn't include in my incantation:
    header = FALSE
    I would find the first record in my dataset on file would be missing from my dataset in R
  • SAS, omitting the zero ('0') when I typed the following into my dataset, for July 14, 2009:
    14JUL2009 12  4.340 11.8
    did not pose a problem, as long as I ran a previous incarnation of my SAS script:
    data petrol_01;
    infile "G:/tpc247/petrol.txt";
    input date_of_sale$ pump_number$ quantity cost;
    per_gallon = cost / quantity;
    proc print data=petrol_01;
    run;
    However, I didn't like the resulting output in SAS. I have developed a preference for a specific way of representing dates that is 9 characters long and in a format that, to my eyes, is more easy to read. However, when I ran the aforementioned script on my data set, my dates were truncated:
    SAS fill gas tank dataset
    It seemed that SAS preferred data in columns to be 8 characters or less, or else it would truncate any value greater than 8 characters. So even though running my SAS script resulted in SAS correctly reading in my data, and there was no problem with my omitting the zero ('0'), I decided to modify the incantations in my script and specify the columns so that the dates in my desired format would not be cut off. When I did this, I noticed that data in SAS was different from the data on file:
    SAS fill gas tank dataset
    As you can see, the information from the fill_the_gas_tank event for 28MAY2009 has disappeared, and the line in my dataset on file:
    14JUL2009 12  4.340 11.8
    has been replaced in SAS with
    14JUL2009 12  4.340 2.00 0.46083
    I imagine SAS would read 11.8 and then be confused because there were no more numbers and I had told it to expect one more, but I can't explain how SAS computed a cost of 2.00. However, I can explain that the price_per_gallon of around 46 cents is simply derived from dividing 2.00 dollars by 4.34 gallons. The fact that the record for May 28, 2009 is missing leads me to conclude that when reading data from file, and your SAS statement specifies columns, SAS seems to expect values for the entire range of columns you specify. I've confirmed this phenomenon, of a missing record when you specify in your SAS statement the columns where values can be found, manifests itself in SAS only when reading data from file, and not from the copy and paste of data.
Other separators and delimiters

If you have commas separating your data:
    18AUG2009,  6, 12.815, 37.66
14JUL2009, 12, 4.340, 11.8
28MAY2009, 6, 9.532, 24.39
22APR2009, 4, 7.348, 16.01
25MAR2009, 2, 5.509, 11.12
15MAR2009, 7, 4.230, 8.62
04MAR2009, 3, 11.989, 25.16
21FEB2009, 7, 13.298, 27.91
29JAN2009, 15, 13.989, 27.68
03JAN2009, 6, 12.620, 22.70
29NOV2008, 16, 11.239, 20.78
25SEP2008, 8, 13.929, 51.80
In:When importing data into R or SAS, you need to look at your dataset, and tell R or SAS exactly what to expect, or your statistical data analysis software may complain.

Reference: http://www.stat.psu.edu/online/program/stat481/01importingI/02importingI_styles.html

Monday, August 24, 2009

how to use Google's mail server to send email

Just a little over 2 years ago I enrolled in a 3 month course from Wesley Chun in Intermediate Python, held in Los Altos Hills on the main campus of Foothill College. I found Wesley's lesson plan to be very challenging, but in my journey as a computer programmer since, one of the nuggets of wisdom I come back to is his lesson on writing internet clients. One small task he prompted us with was a valuable exercise on how to write clients that use the servers run by free email providers (yahoo, aol, hotmail, gmail). First, a little history on the instruction leading up to the in-class assignment... Why, I remember like it was yesterday (swirling, squiggly lines as harp strings are plucked & played by unseen angels should now be occupying your visual and aural landscape):

Internet Client programming
All internet clients are built on top of TCP

We talked about four internet clients: ftp, nntp, pop3, smtp
After covering ftp and nntp, Wesley began with an overview of email, how electronic mail as a system is complex and to operate it requires lots of working pieces:
  • Message Transport Agent
    • responsible for moving email, routing, queueing, sending of email.
    • sendmail, postfix, qmail, exim (unix)
    • exchange (windows)
  • Message Transport System
    • protocol used by MTAs to transfer email host-to-host
    • Simple Mail Transfer Protocol
  • Message User Agent
    • protocol used to get email from servers client-to-host
    • post office protocols
    • internet message access protocols
At one time, every desk with a workstation had an email server, but this framework was not scalable. Wesley talked about Python's poplib, and about the SMTP interface in smtplib:
  1. connect
  2. login
  3. send email
  4. quit
then he challenged us to write our own POP and SMTP clients.

As we go to press, the code below, tailored specifically to work with Google's SMTP server, was tested to work on Windows 2000 & Vista, and Debian Linux 5.0 (Lenny):
def use_gmail_smtp(te, tffn, ttfs, subject, msg_body):
from smtplib import SMTP
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart
SMTP_server = 'smtp.gmail.com'
username = 'your gmail handle'
passwd = 'your gmail password'
msg = MIMEMultipart()
msg['From'] = tffn
msg['To'] = ttfs
msg['Subject'] = subject
msg.attach(MIMEText(msg_body))
server = SMTP(SMTP_server, 587)
server.ehlo() # see note below for Python 2.5 and 2.6 users
ssl_connection_errors = server.starttls()
ehlo_connection_errors = server.ehlo()
server.login(username, passwd)
server.sendmail('tpc247', (te, ), msg.as_string())
server.close()
A primer for the acronyms in the use_gmail_smtp() argument list:
  1. te is the target_email, the email address where you want the message to arrive
  2. tffn is the_from_field_name, what you want the user to see in the From: field's name portion. To tffn, Gmail will append <your_gmail_handle@gmail.com>
  3. ttfs is the_to_field_string, what you want the user to see in the To: field, usually in the format:
    "Your Name <yourname@company.com>"
A previous incarnation of the code behaved correctly on Python 2.5, but strangely enough, not on Python 2.6, because it called:
...
server.helo()
ssl_connection_errors = server.starttls()
...
resulting in the error:
Traceback (most recent call last):
...
File "", line 11, in use_gmail_smtp
ssl_connection_errors = send_server.starttls()
File "C:\Python26\lib\smtplib.py", line 611, in starttls
...
SMTPException: STARTTLS extension not supported by server.
It's a mystery to me why this error is only on the aforementioned version of Python, but switching the call out was the answer.

I tested my script on 3 different operating systems, each running at least two different versions of Python:
  • Windows
    • 2000: Python 2.6.1, 2.6.2
    • Vista: Python 2.5.4, 2.6.1, 2.6.2
  • Debian Linux 5.0 Lenny: Python 2.5.2, 2.6.1, 2.6.2
Other notes: when installing Python 2.6.1 on Windows Vista, for the first time ever I saw:
Please wait while the installer finishes
determining your disk space requirements
and then the installation would stall and never complete. The workaround is to open a command prompt, and type:
msiexec.exe -package <mypackage.msi> –qr
Reference: http://bloggingabout.net/blogs/jpsmit/archive/2009/08/28/please-wait-while-the-installer-finishes-determining-your-disk-space-requirements-message-drives-me-nuts.aspx

For you who would like to use gmail to send emails that look like they come from your workplace, you can now do so without the "on behalf of" that make you look less than authentic.

Reference: http://gadgetwise.blogs.nytimes.com/2009/07/31/gmail-drops-the-dreaded-on-behalf-of-lingo/