views:

42

answers:

2

I have a SWF that can be hosted in several different places on the web (including facebook.com). How can I determine which page is hosting my SWF from within Actionscript?

A: 

The only way to get the URL of the page hosting the swf is via an ExternalInterface call, which can execute JavaScript to get things like window.location. There is a couple of SO questions about it where you can find the details.

But since you mention facebook, you may not be able to use that method there, because facebook doesn't allow swf files to execute JavaScript in their pages (the allowscriptaccess parameter is set to "never"), I believe. But I'm not 100% sure about that, so you may want to check that out your self.

Lars
A: 

There isn't an bulletproof method for what you want.

The most usual and simpler approachs are:

1) Use ExternalInterface.call to call javascript an return the localtion.

Something like:

var location:String = ExternalInterface.call('window.location.href');

2) Pass a flashvar to your swf in the HTML embed code.

Pros:

Both are quite easy to implement

Cons:

Not always possible / available.

When your swf is embedded as a third party widget, it's quite likely that it will not be granted access to javascript. In fact, by default, your swf will not have access to JS, unless the embedding code explicitly sets allowscriptaccess to "*" (everyone).

In the flashvars case, that data has to be passed by the embed code, obviously. But you typically don't control this code, so it might work in some cases but not others.

There's a third way (there could be others) that is rather hackish and more involved, but I actually used it once and worked fine. The basic idea is this. Instead of serving your swf directly, have the embed code load a page that you can control server side. Let's call this yoursite.com/loader.php. This script grabs the http referrer and passes it to your swf (caveat: yes, http referrer is not mandatory and could be absent in the request or be spoofed; in a normal scenario, this is not an actual problem as most browsers do send this data).

Now, this is the tricky part. You have to somehow write that data into your swf. There are options to compile swf on the fly, server-side. You could also try and parse the swf format (it's fairly documented). But this seemed ovekill for I was trying to do (I mean, overkill for the server).

So I decided to have a simple loader.swf that loaded the actual swf. This loader.swf had a string variable (let's call it referrer) with some placeholder data that was 1) easy to find, 2) very unikely to happen randomly in the binary, and 3) large enough to hold a url (I mean a big string like "$BEGIN_PLACEHOLDER$0123456789$END_PLACEHOLDER$", where "0123456789" is just a filler that is repeated to make the placeholder big enough; I had a 1000 bytes string or something like that, just to be safe; this has to be one literal string in your actionscript code or it will be compiled to more than one constant and you will not be able to find it in the swf binary).

The php script simply opened the loader with fopen, looked for the begin and end tokens and replaced the whole string with the referrer (if I recall correctly I added some character to pad this string). The script then returned the read swf with the referrer injected. At runtime, the effect of this is that in your loader swf, the referrer is just a normal compile-time variable. This loader swf then loaded the actual swf and passed the value of referrer through the querystring, so the app end up being called like this: yourdomain.com/app.swf?referrer=the_referrer_value. Then, in the app, the referrer was just a normal flashvar.

Now, for this to work, the loader was exported as an "uncompressed" swf. If it's compressed, you have to decompress first, etc, etc. Also, this is way I used a loader swf instead of doing this in the real app; the loader itself was tiny, so it dind't matter it was not compressed, but the real app could not be uncompressed.

It's a bit involved and not the most elegant, but it wasn't that hard to get the whole thing working and wasn't too demanding on the server.

Juan Pablo Califano