Saturday, August 22, 2009

StumbleUpon Doesn't Honor Permanent Redirects

The folks at StumbleUpon just gave me the worst website advice that I have ever heard.

When you change your domain name, StumbleUpon refuses to follow the permanent redirect to your new site. They recommend leaving the old website up with a "please click here" message instead!

Wait, really?

StumbleUpon provides a browser toolbar with a "Stumble!" button. When you click the button, it sends you to a random web page, and lets you rate it. If lots of people like your page, StumbleUpon will send more people there.

I've been running an online game from my personal website for about eight years. It eventually got pretty popular, averaging ~2 million pageviews a month. The load became too much for my home DSL connection, so about a month ago, I decided to move the game to Google AppEngine, on a separate domain. I diligently set up a permanent (301) redirect from the old website to the new website, and notified Google of my address change using Google Webmaster Tools.

For a while, everything was fine, but then, all of a sudden, I noticed my traffic had dropped by 50%. Puzzled, I checked my logs.

It turns out that about 50% of my traffic came from StumbleUpon; they were sending me hundreds of new visitors a day, some of whom would play the game for hours at a time. The game is a lot of fun, so it got hundreds of positive reviews. Eventually, StumbleUpon grew to represent a huge fraction of my inbound traffic. Now, all of it is gone.

StumbleUpon now says, "We are showing this site as unavailable. Should we check again?"

I emailed StumbleUpon about this, and they gave me this advice:

Hello Dan,

Thanks for your feedback,

Unfortunately, once you've redirected a site, you
are losing all reviews and traffic from the
original URL. There is nothing we can do about
this, as each unique URL in our community has it's
own unique review page.

If we allowed transfer of reviews and traffic
counts, we would facilitate gaming of our system.
You may however do a different type of redirect:
keep the homepage of the old URL alive and insert
a link that users must click to reach the new URL.
That way, the review page for the old URL will
still be accessible and the site will still regain
it's viral momentum and get stumbled around. While
doing this, you can slowly build reviews and
traffic for the new URL.

I hope this helped.

Regards,
Monica
xxxx@stumbleupon.com

This is horrible advice; nobody should ever do this.

If you follow Monica's advice, search engines like Google and Bing will continue to send searchers to the old website instead of the new website. Both Google and Bing rank websites by how many people link to them. Since the old website has more links, it will rank higher in the search results than the new website. Eventually, hopefully, you'll have two websites in Google and Bing, each performing only half as well as they should.

This is bad for my users and bad for searchers. Nobody wants to see duplicate content in their search results.

Gaming the system?

Monica says that if StumbleUpon honored redirects, it could be used to "game" their system. After all, what if I one day replaced my website with a redirect to a spam website? Then StumbleUpon might send users to some spam site.

But that's silly. Anyone who could redirect my website to spam could just as easily put spam right on my website! Redirecting doesn't help me game their system at all.

On the contrary, instead they're asking me to turn my old site into a pointless "doorway" page, forcing their users to click on an extra link just to get to the fun stuff. How is that good for their users?

If you don't believe me, then maybe you'll believe Google. StumbleUpon may claim to be worried about spam, but Google eats far more spam than StumbleUpon. People try to spam Google all the time, often by setting up useful sites and then replacing them with spam sites. If redirects made it easier to "game the system", then Google would stop honoring them.

Instead, Google gives clear and explicit directions explaining how to change your domain name. They recommend setting up a permanent 301 redirect, and notifying Google of the change of ownership using Google Webmaster Tools.

StumbleUpon should learn a lesson from Google and honor permanent redirects. It's the right thing to do for my users, Google's users, and their users.

Sunday, April 26, 2009

Tipjoy is Insecure; Don't Use It

Tipjoy is a cool new site that lets you exchange micropayments over the Internet. Unfortunately, on their "createAccount" page, they prompt you to give them your password without encryption!

http://tipjoy.com/createAccount/

That URL should be HTTPS-only, not HTTP. If you enter your password on that page, any "man in the middle" can read it and use it to impersonate you on Tipjoy.

By capturing your password, the attacker can spend money that belongs to you, transfer money stored in your Tipjoy account into the attacker's account, etc.

Bizarrely, tipjoy.com does support HTTPS... they just choose not to use it on most of their webpages, including the /createAccount page and the /settings/account/ page where you go to change your password. (The /login page is HTTPS by default.)

You can even opt-in to transmit your password securely, by modifying the URL to use SSL: https://tipjoy.com/createAccount/. That may be an acceptable workaround until tipjoy fixes their site.

But, even knowing that workaround, you STILL shouldn't use Tipjoy to put a button on your site until they fix this issue. If you put a Tipjoy button on your site, your users (the people who like you and generously want to give you a small tip) will probably NOT notice the problem; they will just create an account using the default /createAccount link, exposing their passwords to a man-in-the-middle attack.

Hopefully Tipjoy will get the message and fix this soon. Frankly, as a payment exchange system, their ENTIRE SITE should be behind HTTPS, not just key login pages. This is how paypal.com works; it's also how most bank websites work. When money is on the line, you really can't accept anything less.

Saturday, November 01, 2008

SPOILER: Unlock Blue Frog "Cheat" Mode and Battle Mode in Quest For Glory 2 (QFG2) VGA Remake

What is Blue Frog Mode?

The original Sierra "Quest for Glory 2: Trial by Fire" EGA game had a "cheat" mode. If you typed "suck blue frog," you could use secret key codes to give you unlimited money, raise your stats, create any item, teleport to any room in the game, etc. Officially it's a debug mode, used by developers to test the game without playing through the entire game. Unofficially, most people use it to cheat.

The AGDI have released a VGA remake for Quest for Glory 2; it has a similar "debug" / "cheat" mode called "Blue Frog Mode." Finding it is hard, but unlocking it is easy.

Blue Frog Mode Menu

Unlocking the easy way

Just download this file (Qfg2vga.025) put it in your "Quest for Glory II" installation directory, which is probably in "C:\Program Files\AGD Interactive\Quest for Glory II." You'll need to replace the Qfg2vga.025 file that already exists in that directory.

Then just start the game from the beginning (or import a character from the previous game, "Quest for Glory I" aka Qfg1 aka "Hero's Quest"). Press F10 to activate Blue Frog Mode.

Unlocking the normal way

It's a little more work to unlock Blue Frog Mode yourself without "cheating." You have to find and capture the blue frog, and beat the game with maximum puzzle points.

First, you'll need the bellows from Issur, the weaponsmaster. Go to the Dervish; there's a lilypad in Dervish's oasis. Repeatedly exit/enter the oasis. Every time you enter the oasis there's a small chance that a tiny blue frog will be sitting on the lilypad. Use the bellows on the frog; you'll take the frog and keep it in your inventory.

Dervish Oasis with Blue Frog

Note that the bellows must be empty to find and capture the blue frog. Later in the game you have to use the bellows to capture the Air Elemental; once you've captured the Air Elemental, you can't get the blue frog.

Once you have the blue frog, you must finish the game with maximum puzzle points to unlock Blue Frog Mode. For non-Paladins, you need 500 puzzle points out of a maximum of 500; for Paladins, you need 550 puzzle points out of a maximum of 550. (If you're short a few Paladin points at the end of the game, you can choose to "decline" becoming a Paladin to lower the maximum to 500 points.)

Note that on the AGDI forums, some people have suggested that you also need to max out all of your character statistics (strength, agility, etc. need to be 200) to unlock Blue Frog Mode. You definitely do not need max stats. I was able to unlock Blue Frog Mode as a Thief imported from Qfg1 with Communications of 185 and Honor of 107. Admittedly, all of my other stats were at or above 200, so there may be some requirement around stats, but I doubt it.

Instructions on how to get the bellows and find the Dervish are available in CyricZ's excellent GameFAQs walkthrough for the VGA remake; no doubt it will be updated soon to include information on how to unlock Blue Frog Mode. If you're having trouble finishing the game with maximum puzzle points, CyricZ also includes a "Point List" in section 10C, which lists all of the possible ways to earn points. In some cases, you may need to restore your game or even start your game over from scratch to get maximum points.

Item/Room List

Here's a list of item numbers for Blue Frog Mode; here's a list of room numbers for Blue Frog Mode. Note that most room numbers just cause the game to crash with an error message.

Battle Mode

There is a second "debug" mode available called "Battle Mode." Battle Mode and Blue Frog Mode must be unlocked separately.

Battle Mode has five features:

  • Combat Tests: Battle any specific monster in "test" mode. In test mode, you won't die if you lose, but you also won't gain stats during the fight. (Not that you care because you've also got Blue Frog Mode, right?)
  • Damage Meter: See the exact amount of damage dealt in combat.
  • Summon Monsters: In the desert, cause a specific monster to appear.
  • Enable/Disable Random Encounters in the desert.
  • Set Battle Speed: Press Ctrl-Z during combat to slow down or speed up the fight.
  • Enable/Disable Auto-Critical Mode: All of your attacks become critical hits.

The easy way to unlock Battle Mode is to install this file (Qfg2vga.026) in your Qfg2 installation directory. Start a new game and press F4 to access the Battle Mode menu.

The hard way to unlock Battle Mode is to find, defeat and capture the secret Pizza Elemental, then beat the game with maximum puzzle points.

To capture the Pizza Elemental, you'll need an empty pizza box. You can find one outside the entrance to the Eternal Order of Fighters. In the simplified street system it's at the end of Saif Darb; in the classic street system it's at the end of Askari Darb, which branches off of Saif Darb.


Simplified

Classic

You can't find the Pizza Elemental until after you've defeated the Fire Elemental, on Day 5 or later. When you're ready, go four (4) screens South of Shapier, then about forty (40) screens West. Eventually you'll find the Pizza Elemental.

Defeating the Pizza Elemental is a lot of work, even at the easiest combat difficulty setting. I recommend unlocking Blue Frog Mode first, and using it to raise your Luck, Dodge and Weapon Use skill to 250 before challenging him. (You can raise your other stats to 250 as well, but if you start the fight with more than 200 HP or 200 SP, you'll be reduced to 200 HP/SP at the start of the fight.)

CyricZ's walkthrough includes some tips on how to defeat the Pizza Elemental. There's also a YouTube clip demonstrating how to beat him.

Basically, you have to step back and duck a lot (avoid jumping, it wastes stamina). Be sure to attack the elemental when he eats you or tries to eat a pizza. Eventually you'll run out of stamina; just patiently dodge the falling pizzas to recover stamina until you're ready to fight again. It requires quick reflexes and a lot of patience.

Once you've beaten the Pizza Elemental, use your pizza box to capture him. Then beat the game with maximum puzzle points (again, maximum stats are not required) to unlock Battle Mode.

Despite what you may have read elsewhere, you do not have to defeat Sweeping Sir James to unlock Battle Mode, or complete the Warrior's Diary. (See CyricZ's walkthrough for details on these optional missions.)

Monday, March 10, 2008

Java annotation parameters can't default to null

I don't update here often enough, but here's a tidbit I wish I'd found on Google earlier.

Suppose you want to write a Java annotation that has a parameter value, but you want its default value to be null. Well, too bad. It is illegal to write this annotation:

public @interface Optional {
   public String value() default null;
}

It's a compile time error. javac says "attribute value must be constant;" Eclipse says "The value for annotation attribute Optional.value must be a constant expression." In fact, it's not that surprising, because even if you didn't set a default value, writing this would also be illegal (same error):

@Optional(null)

What the error is saying is that you can't set a Java annotation parameter to null.

Why is this? The specifications are opaque. JSR-175, which defined annotations for Java 5, just says "If member type is a primitive type or String, the ConditionalExpression must be a constant expression (JLS 15.28)." JLS 15.28, in turn, says that constant expressions can be, for example, any of these:

true
(short)(1*2*3*4*5*6)
Integer.MAX_VALUE / 2
2.0 * Math.PI
"The integer " + Long.MAX_VALUE + " is mighty big."

Notice anything missing? That's right, null. You can never pass null as a Java annotation parameter value, because, uh, null isn't a ConstantExpression.

Why? We may never know. The only thing you can do is workaround it, like this:

public @interface Optional {
   public String value() default NULL;
   public static final NULL = "THIS IS A SPECIAL NULL VALUE - DO NOT USE";
}

... and then make your code carefully treat Optional.NULL as if it were really null.

LAME!

Friday, January 11, 2008

BART Tracker

BART Tracker reports on arriving San Francisco area BART trains in real time, using a system tray icon.

It uses BART's new "Estimated Arrivals" or "BART System Status" feature, that reports on the current up-to-the-minute status of arriving trains at every BART station.

Thursday, October 18, 2007

Hudsuckr: Advanced Windows proxy configuration from the command line

Windows stores proxy configuration settings in the registry, in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings. However, the settings there like "ProxyServer" "ProxyEnable" can be somewhat misleading, and certain advanced settings (like the setting to "Automatically detect settings" using WPAD) aren't available as separate registry keys.

In IE4, proxy settings were stored in the "Internet Settings" key as simple strings (REG_SZ) and ints (REG_DWORD), but since IE5 it has been possible to set proxy configurations separately for each Internet connection. For example, you could set up your computer to use a proxy when you're using a VPN, use WPAD when you're on dial-up, and to go directly to the Internet when you're corrected directly using the LAN. These "per connections" settings are stored in the "Internet Settings\Connections" key; unfortunately, they're stored there in REG_BINARY blobs that are not meant to be edited directly. (When you use the "Internet Options" Control Panel, it automatically updates both the REG_BINARY blobs and the regular registry settings in "Internet Settings" automatically.)

That makes it difficult to configure "per connection" settings (like WPAD) using command line tools, including proxycfg.exe and others. We needed to be able to automatically enable/disable WPAD in Selenium RC, so I've coded up a simple command-line executable called "hudsuckr" that lets you do it. (It's named after the classic 1994 Coen brothers movie The Hudsucker Proxy. "Hudsuckr" contains no "e" because that makes it easier to Google and because it makes it more Web 2.0. ;-)

Here's the usage documentation that you get when you run "hudsuckr --help" from the command line:

    Hudsuckr Windows Proxy Configuration Tool: "You know, for kids!"
    
    Windows manages Internet proxy connection information in the registry;
    each Internet "connection" can have its own separate proxy
    configuration.  These settings correspond to settings in the "Internet
    Options" Control Panel, under the "Connections" tab.
    
    Run "hudsuckr" without arguments to print out the current proxy
    configuration details.  We print out the name of the current active
    connection, the four connection flags (DIRECT, PROXY, AUTO_PROXY_URL,
    AUTO_DETECT), and three strings: PROXY_SERVER, PROXY_BYPASS, and
    AUTOCONFIG_URL. The seven settings are described in MS documentation
    available here: http://msdn2.microsoft.com/en-us/library/aa385145.aspx
    
    Run "hudsuckr" with exactly eight arguments to set the proxy
    configuration, like this:
      hudsuckr (null) true true true true "localhost:4444" "" "file://c:/proxy.pac"
    
    Specify the name of the connection first (or use the LAN settings by
    specifying "(null)"), then set the four flags using "true" and
    "false", then the proxy server (with a colon to specify the port), the
    list of servers to bypass delimited by semi-colons (with "" as
    a special string that bypasses local addresses), and finally the URL
    to a proxy PAC autoconfiguration file.  Use "" or "(null)" to leave
    string settings blank/empty.
    
    If you're still confused about the flags, look at the proxy settings
    in the "Internet Options" Control Panel. See how you can check those
    checkboxes independently of one another? The flags correspond to those
    checkboxes.  If AUTO_DETECT is true, IE will try to use WPAD; if
    successful, WPAD will override the specified AUTOCONFIG_URL. If an
    AUTOCONFIG_URL is detected (by AUTO_DETECT) or specified directly
    (AUTO_PROXY_URL is enabled), IE will use the autoconfig script as a
    proxy PAC file.  If no AUTOCONFIG_URL was specified or detected, IE
    will attempt to use the server specified in PROXY_SERVER if the PROXY
    flag is enabled; it will bypass the proxy for the list of servers
    specified in PROXY_BYPASS. Finally, if PROXY, AUTO_DETECT and
    AUTO_PROXY_URL are all set to false, IE will attempt to contact the
    web server directly.  Note that the DIRECT flag always appears to be
    true, even if the PROXY flag is true; we recommend you leave it that
    way, too.

Here's what you might see if you run hudsuckr without command line arguments:

    > hudsuckr.exe
    ACTIVE_CONNECTION=(null)
    PROXY_TYPE_DIRECT=true
    PROXY_TYPE_PROXY=false
    PROXY_TYPE_AUTO_PROXY_URL=false
    PROXY_TYPE_AUTO_DETECT=false
    INTERNET_PER_CONN_PROXY_SERVER=(null)
    INTERNET_PER_CONN_PROXY_BYPASS=(null)
    INTERNET_PER_CONN_AUTOCONFIG_URL=(null)

Or, after you've configured lots of proxy settings:

    > hudsuckr.exe (null) true true true true "localhost:4444" "" "file://c:/proxy.pac"
    ACTIVE_CONNECTION=(null)
    PROXY_TYPE_DIRECT=true
    PROXY_TYPE_PROXY=true
    PROXY_TYPE_AUTO_PROXY_URL=true
    PROXY_TYPE_AUTO_DETECT=true
    INTERNET_PER_CONN_PROXY_SERVER=localhost:4444
    INTERNET_PER_CONN_PROXY_BYPASS=
    INTERNET_PER_CONN_AUTOCONFIG_URL=file://c:/proxy.pac

To turn off all proxies for the LAN connection, you might run a command like this:

    > hudsuckr (null) true false false false (null) (null) (null)
    ACTIVE_CONNECTION=(null)
    PROXY_TYPE_DIRECT=true
    PROXY_TYPE_PROXY=false
    PROXY_TYPE_AUTO_PROXY_URL=false
    PROXY_TYPE_AUTO_DETECT=false
    INTERNET_PER_CONN_PROXY_SERVER=(null)
    INTERNET_PER_CONN_PROXY_BYPASS=(null)
    INTERNET_PER_CONN_AUTOCONFIG_URL=(null)

Download hudsuckr.exe
Hudsuckr source code

Friday, September 07, 2007

Windows, killableprocess, and the Case of the Suicidal Parent (or: How to kill a process and all of its subprocesses reliably on Windows)

The two major browsers available on the market today (Firefox and IE) are sometimes "suicidal parents" when launched from the command line. That is, they occasionally have to re-launch themselves, by spawning a new copy of their executable (firefox.exe or iexplore.exe) and killing the currently running process. In these cases, the orphaned child process lives on to become the GUI that you actually see on the screen.

Firefox commits suicide when it sees that it needs to make significant adjustments to its user profile directory, e.g. when it has detected new versions of your extensions/add-ons. IE commits suicide on Vista when running in Vista's new "Protected" mode. When you launch iexplore.exe from the command line on Vista in Protected mode, your iexplore.exe process spawns a copy of "ieuser.exe" (if one isn't running already) and allows THAT process to launch a new copy of iexplore.exe.

This suicidal behavior is invisible to normal end users, but it can be very difficult for people who want to automatically launch and kill browsers for automated testing, like I do. For example, if you spawn a suicidal parent in Java and then try to .destroy it, you'll run straight into Java bug 4770092 (Process.destroy does not kill multiple child processes).

Benjamin Smedberg posted an interesting blog entry about a way to use Python to handle child processes: killableprocess.py. On Windows, killableprocess.py handles child processes by launching them inside of a Windows "Job" object. Processes within a Job may be assigned special security privileges or restrictions, and, by default, whenever any process in a Job creates a subprocess, the subprocess becomes a member of the same Job. (Job objects were introduced in Windows 2000.) It's easy and convenient to terminate an entire Job at once, killing all processes within it, even if the processes are orphans of suicidal parents.

Using Jobs to manage a process tree is a great idea, but not everybody in the world has the Python runtime installed, so I decided to code up something like it in C++.

The compiled executable (killableprocess.exe) can be used to launch any other process you like, assigning that process to a new unnamed Job. killableprocess.exe will automatically terminate if every process in the Job has died. It's also designed to handle shutdown signals (Ctrl-C and Ctrl-Break), to terminate the Job as killableprocess.exe is being shutdown. As a fallback, it additionally registers a "job limit" with the operating system to automatically kill the Job if killableprocess.exe is forcibly terminated. (Beware... the job limit doesn't work if you use Process Explorer.)

You can use killableprocess.exe as a wrapper around other processes that you expect to be suicidal parents.

Download killableprocess.exe
Source code for killableprocess.exe