Why is the string length showing up in the URL? - php

I am trying to pass an array through a url. I have tried encoding the URL, serializing the URL, serializing and encoding the URL, and no matter what I do, the length of the strings is coming up in the url.
For example, if I pass the array through a URL this way:
<a href='http://splitsum.com/samples/your_store/checkout_form2.php?arr=<?PHP echo serialize($order); ?>'>Next Page</a>
The resulting URL looks like this (with the string count printed out):
.....s:15:%22shipping_method%22;s:20:%22Flat%20Rate%20(Best%20Way)%22;.....
Does anyone know why this is happening? I can var_dump the entire array (and see the string counts on the page) but I cant seem to print individual values in the array. Could it have something to do with a problem in the URL and the printing of the string length?
Thanks!

Because you're using serialize(). You should be using urlencode() instead.
serialize is intended to take internal arbitrary data structures, and encode them into a portable format for re-use in a PHP system somewhere else. It does NOT produce code that is guaranteed valid in a URL context. Basically you're using a hammer to pound in a screw. Use a screwdriver instead.
Note that urlencode will not accept an array. Perhaps http_build_query() would be more appropriate

The length is appearing because you're using serialize. That how it outputs. It's used to store a PHP variable, so that it can be loaded back into PHP again. It's output format contains the length of arrays/strings.
This is the wrong tool for this job. You want to use http_build_query here instead.
<a href='http://splitsum.com/samples/your_store/checkout_form2.php?<?PHP echo http_build_query(array('arr' => $order)); ?>'>Next Page</a>
Then $_GET['arr'] in checkout_form2.php will be your $order array.

Related

Is it a JSON string? Get array in PHP

I import data from WordPress. It is a WebDirectory 2.0 that saves the data as a "strange" string in a database.
Example:
s:95:"a:2:{s:3:"url";s:39:"http://www.google.com/";s:4:"text";s:13:"Website";}";
I have tried json_decode() and unserialize(). Both do not work. They return the string as it is. I can see, this is an array with two values, but how this can be parsed in PHP? In what format this string can be?
If you have this:
echo serialize(serialize(['url'=>'http://www.google.com/','text'=>'Website']));
The output will be
s:71:"a:2:{s:3:"url";s:22:"http://www.google.com/";s:4:"text";s:7:"Website";}";
But what you have is
s:95:"a:2:{s:3:"url";s:39:"http://www.google.com/";s:4:"text";s:13:"Website";}";
Which is different. See, s:95 != s:71, among other elements.
Or this is not a real data or by some reason it's generating extra chars, and causing the problem. I would check how the encoding from both PHP and database to see if all matches.

Why does Symfony escape & characters when using url_for()?

With this Symfony page, I am passing $_GET parameters in the URI like this:
http://www.mysite.com/article?page=4&sort=1
Once in my layout, there are certain links in the page that need to have the same query string in them.
Anyways, using Symfony's url_for() command I'm making URLs like so:
$url = url_for('article/index?.http_build_query($_GET));
That way it makes a new url using the $_GET variables. For some of the links I'm changing the $_GET values ahead of time, like $_GET['sort']=0; before generating the url. That's why I'm using this method.
Anyways, when I look at the generated URL, it now looks like this:
http://www.mysite.com/article?page=4&amp%3Bsort=1
The &amp%3B is the encoded form of & which is just an & character.
So the problem is that when I check for my $_GET parameters in my controller now, there is no longer a sort parameter that is passed. It's now called &amp%3Bsort... It's causing all sorts of issues.
Two questions:
How do I avoid this problem? Can I decode the $_GET parameter key values in my controller or something?
Why is symfony encoding a & character in the first place? It's a perfectly acceptable URI character. Heck, even the encoded value, &amp%3B contains a & !!!
I believe, it is because of output escaping is ON in your application. As a result, $_GET array is wrapped inside sfOutputEscaperArrayDecorator class. You can get a raw value using this: $_GET->getRawValue().
$url = url_for('article/index?.http_build_query($_GET->getRawValue()))
Or you can decode the result query using sfOutputEscaper::unescape
$url = url_for('article/index?.sfOutputEscaper::unescape(http_build_query($_GET)));
Hope this will be useful.
Best if you use Symfony's own method for getting the request parameters. For example, in templates, use:
$sf_request->getParameter('some_param');
If you must use $_GET, maybe try:
((( $sf_data->getRaw('_GET') )))
... to get past the output escaping. Not totally sure if that'll work as is.

Safely pass variables from one php file to another php file in the URL

This might be a basic question and I've been searching for a safe and clean way to do this. Im passing a normal string which CAN include special characters (like $ ^ % etc). How can I do this in the url? For example I have a variable called $text which In addto.php from $_GET. How do I then transfer this to more.php?
'more.php?varname='.urlencode($_GET['text']);
urlencode sounds like what you want.
(from the docs)
This function is convenient when encoding a string to be used in a query part of a URL, as a convenient way to pass variables to the next page.
You can pass data through an URL, it should be in the form of key/value pairs, but you shouldn't use it to pass too much data because an URL has a limit. You also should not pass sensitive information.
A key/value pair is something like this:
key=value
If you have more then one pair, you need to separate them using the & char. Here is an example:
myScript.php?color1=blue&color2=red
The string after ? is called the Query String. With PHP you can easily access those key/value pairs using the super-global $_GET. So, in myScript.php you do:
$a = $_GET['color1'];
$b = $_GET['color2'];
Now, if you are going to create a dynamic query string, you should use urlencode() at least, so any special characters will be translated to maintain a proper URL format.
Please read the following:
http://php.net/urlencode
http://php.net/manual/en/function.http-build-query.php

exported json as string (not array)

Some have see that code :
<?php
echo stripslashes(json_encode(glob("photos-".$_GET["folder"].'/*.jpg')));
?>
it echo a really nice perfect string like that :
["photos-animaux/ani-01.jpg","photos-animaux/ani-02.jpg","photos-animaux/ani-02b.jpg","photos-animaux/ani-03.jpg","photos-animaux/ani-04.jpg","photos-animaux/ani-05.jpg","photos-animaux/ani-06.jpg","photos-animaux/ani-07.jpg","photos-animaux/ani-08.jpg","photos-animaux/ani-09.jpg","photos-animaux/ani-10.jpg","photos-animaux/ani-11.jpg","photos-animaux/ani-12.jpg","photos-animaux/ani-13.jpg","photos-animaux/ani-14.jpg"]
With json encode it shoul send a array so variable[0] should = to photos-animaux/ani-01.jpg
NOW it is only the fisrt caracter of the string..
how a array get converted to string, and how in javascipt to convert string to array to be able to get value [0] [1] etc..
the question is WHEN or WHY the perfect array get converted to string anyway ?
Using JSON.parse(), from the library available here, is preferable to using eval() since this only reads JSON strings and hence avoids the inherant security risks associated with eval().
In order to parse a JSON-encoded string into actual javascript objects, you need to eval() the data returned in order for javascript to execute against the data:
var data = eval(json_string)
Keep in mind that you should only ever run eval on a string when you trust the source and are sure that there is no possibility of a script injection attack, since javascript will run everything present in the string.
Use one of the JSON libraries listed at the bottom of http://json.org/
WHEN or WHY
If I understood correctly, the answer to both is json_encode(): check out the documentation. Converting a variable to a string (often called serialization or flattening) is a quite common operation.

Multiple Variables into 1 in a URL

I am looking to have a list of arguments passed across in an a URL.
$url['key1']=1;
$url['key2']=2;
$url['key3']=3;
$url['key4']=4;
$url['key5']=5;
$url['key6']=6;
$url['key7']=7;
Please Note I am trying to pass this in the URL in 1 GET variable. I know this would be better done by ?key1=1&key2=2&key3=3...etc but for reasons that are too complicated to try and explain they can't be in this format.
Any suggestions how I can convert this array into something that can be passed as 1 get var in a URL string?
Thanks in advance.
You can use json_encode() or serialize()
$myUrl = 'http://www.example.com/?myKey=' . urlencode(json_encode($url));
or
$myUrl = 'http://www.example.com/?myKey=' . urlencode(serialize($url));
Using json_encode will usually give you a shorter string, but very old PHP version might not have the json_decode function available to decode it again.
The final way would be to create your own custom encoding... it could be as simple a pipe-separated values: key1|1|key2|2|key3|3
This would give you the best option for a short URL, but is the most work.
Try http_build_query:
$url['key1']=1;
$url['key2']=2;
$url['key3']=3;
$url['key4']=4;
$url['key5']=5;
$url['key6']=6;
$url['key7']=7;
echo http_build_query($url);
//echos key1=1&key2=2&key3=3&key...
What it does is converting an array into a query string using the keys and automatically takes care of url-encoding.
EDIT:
Just read your additional requirement that it should be just one variable. So nevermind this answer.
If your problem was the proper encoding though you might want to give this another try.
Hope that helps.
The recommendation to use serialize() is fine. If space is an issue, then use a combination of bzcompress() and serialize().
However, there's a security considering that hasn't been brought up, and that's that the end user (who can see and edit this url) could manipulate the data within it. You may think it's difficult, but most of the PHP-attacking worms in the wild do this to some degree or another.
If letting the user directly manipulate any of the keys or values (or replacing it with an integer, or an object, or anything else), then you should protect your script (and your users) from this attack.
A simple solution is to simply use a shared secret. It can be anything; just so long as it's unique and truly secret (perhaps you should randomly generate it at install-time). Let's say you have in your config file something like this:
define('SECRET', 'unoqetbioqtnioqrntbioqt');
Then, you can digitally sign the serialized data created with: $s=serialize($m) using $k=sha1($s.SECRET) and make the url value $k.$s
Then, before you unserialize() do this:
$v=substr($input,0,40);
$s=substr($input,40);
if ($v != sha1($s.SECRET)) { die("invalid input"); }
$m=unserialize($s);
This way, you know that $m is the same as the original value that you serialized.
If you like, you can use the following drop-in replacements:
define('SECRET','buh9tnb1094tib014'); // make sure you pick something else
function secureserialize($o) {
$s=serialize($o);
return sha1($s.SECRET).$s;
}
function secureunserialize($i) {
$v=substr($i,0,40);$s=substr($i,40);
if ($v!=sha1($s.SECRET)){die("invalid input");}
return unserialize($s);
}
You could serialize them as key-value pairs when constructing the URL, putting the resultant serialized value in a single $_GET variable (e.g. data=sfsdfasdf98sdfasdf), then unserialize the $_GET["data"] variable. You'll need to use urlencode to make sure the resultant serialized values are URL-safe. Make sure you watch out for maximum URL lengths - 2083 characters in IE.
However, unless you really can't use key-value pairs in URLs (per your question), key1=foo&key2=bar... is definitely the way to go.
If you don't mind dropping the key names, you can use
http://example.com?url[]=1&url[]=2&url[]=3
EDIT Keeping the key names:
http://example.com?values[]=1&values[]=2&values[]=3&keys[]=1&keys[]=2&keys[]=3
Then in your PHP script:
$url = array_combine($_GET['keys'], $_GET['values']);
Could you solve your problem by saving the data as a HTML cookie? That way you don't have to modify the URL at all.
If you know the values in advance, you can set them from the server side when you send the user the page with your target link on it.
If you won't know the values until the user fills out a form it can still be done using JavascriptL When the user clicks the form submit you can set multiple cookies by making multiple javascript calls like:
document.cookie = 'key1=test; expires=Mon, 7 Sept 2009 23:47:11 UTC; path=/'
The security model might give you some trouble if you are trying to pass this data from one domain to another though.

Categories