views:

86

answers:

2

I know that I should encodeURI any url passed to anything else, because I read this: http://www.digitalbart.com/jquery-and-urlencode/

I want to share the current time of the current track I am listening to. So I installed the excellent yoururls shortener. And I have a bit of code that puts all the bits together, and makes the following: track=2&time=967

As I don't want everyone seeing my private key, I have a little php file which takes the input, and appends the following, so it looks like this: http://myshorten.example/yourls-api.php?signature=x&action=shorturl&format=simple&url=http://urltoshorten?track=2&time=967

So in the main page, I call the jquery of $("div.shorturl").load(loadall);

It then does a little bit of CURL and then shortener returns a nice short URL.

Like this:

$myurl='http://myshorten.example/yourls-api.php?signature=x&action=shorturl&format=simple&url=' . $theurl;
$ch = curl_init($myurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
  echo 'cURL failed';
  exit;
}
echo $data;

All perfect.

Except... the URL which is shortened is always in the form of http://urltoshorten?track=2 - anything after the ampersand is shortened.

I have tried wrapping the whole URL in php's URLencode, I've wrapped the track=2&time=967 in both encodeURI and encodeURIComponent, I've evem tried wrapping the whole thing in one or both. And still, the & breaks it, even though I can see the submitted url looks like track=1%26time%3D5 at the end.

If I paste this or even the "plain" version with the unencoded url either into the yoururls interface, or submit it to the yoururls via the api as a normal URL pasted into the location bar of the browser, again it works perfectly.

So it's not yoururls at fault, it seems like the url is being encoded properly, the only thing I can think of is CURL possibly?

Now at this point you might be thinking "why not replace the & with a * and then convert it back again?". OK, so when the url is expanded, I get the values from

var track = $.getUrlVar('track');
var time = $.getUrlVar('time');

so I COULD lose the time var, then do a bit of finding on where the * is in track and then assume the rest of anything after * is the time, but it's a bit ugly, and more to the point, it's not really the correct way to do things.

If anyone could help me, it would be appreciated.

+2  A: 

I have tried wrapping the whole URL in php's URLencode

That is indeed what you have to do (assuming by ‘URL’ you mean inner URL being passed as a component of the outer URL). Any time you put a value in a URL component, you need to URL-encode, whether the value you're setting is a URL or not.

$myurl='http://...?...&url='.rawurlencode($theurl);

(urlencode() is OK for query parameters like this, but rawurlencode() is also OK for path parts, so unless you really need spaces to look slightly prettier [+ vs %20], I'd go for rawurlencode() by default.)

This will give you a final URL like:

http://myshorten.example/yourls-api.php?signature=x&action=shorturl&format=simple&url=http%3A%2F%2Furltoshorten%3Ftrack%3D2%26time%3D967

Which you should be able to verify works. If it doesn't, there is something wrong with yourls-api.php.

bobince
You absolute star! Works perfectly - I didn't even know about rawurlencode as opposed to urlencode - that was indeed the one. Genius - I'm a happy man, many thanks.
talkingnews
+1  A: 

I have tried wrapping the whole URL in php's URLencode, I've wrapped the track=2&time=967 in both encodeURI and encodeURIComponent, I've evem tried wrapping the whole thing in one or both. And still, the & breaks it, even though I can see the submitted url looks like track=1%26time%3D5 at the end.

Maybe an explanation of how HTTP variables work will help you out.

If I'm getting a page with the following variables and values:

var1 = Bruce Oxford
var2 = Brandy&Wine
var3 = ➋➌➔            (unicode chars)

We uri-encode the var name and the value of the var, ie:

var1 = Bruce+Oxford
var2 = Brandy%26Wine
var3 = %E2%9E%8B%E2%9E%8C%E2%9E%94

What we are not doing is encoding the delimiting charecters, so what the request data will look like for the above is:

?var1=Bruce+Oxford&var2=Brandy%26Wine&var3=%E2%9E%8B%E2%9E%8C%E2%9E%94

Rather than:

%3Fvar1%3DBruce+Oxford%26var2%3DBrandy%26Wine%26var3%3D%E2%9E%8B%E2%9E%8C%E2%9E%94

Which is of course just gibberish.