URL/URI encoding is very complicated matter.
For example
'http://example.org:port/path1/path2/data?key1=value1&argument#fragment' (1), or
'scheme://user:[email protected]:port/path1/path2/data?key1=value1&key2=value2#fragment' (2)
e.g. this (2) should be encoded:
'scheme://'.rawurlencode('user').':'.rawurlencode('password').'@example.com:port/'
.rawurlencode('path1').'/'.rawurlencode('path2').'/'.rawurlencode('data')
.'?'.htmlentities(urlencode('key1').'='.urlencode('value1').'&'.urlencode('key2').'='.urlencode('value2'))
.'#'.urlencode('fragment') etc.
For easy encoding, I've written 'toURI' function, see https://gist.github.com/msegu/bf7160257037ec3e301e7e9c8b05b00a
URIs as: [scheme:][//authority][path][?query][#fragment]
means [scheme:][//[user[:password]@]host[:port]][/path][?query][#fragment]
or: scheme:[user@host][?query] (mailto: etc.)
toURI() short review:
fragment ==> urlencode (e.g. space to '+')
query, as 'key1=value1&key2' ==> each key and value: urlencode (or rawurlencode when $type<0)
then whole query ==> htmlentities
path, as dir/dir/file ==> each dir and file: rawurlencode (e.g. space to %20)
user:password ==> user and password separately: rawurlencode
(see Anonymous note from 2002-09-13 !)
toURI() using examples:
<?php
//Simple use, without special characters in query arguments/values
echo toURI('key1=value1&key2=value 2&argument1 argument2#fragment');
//'key1=value1&key2=value+2&argument1+argument2#fragment' - OK
echo toURI('?key1=value 1&argu+ments#frag');
//'?key1=value+1&argu%2Bments#frag' - OK
echo toURI('../path 1/path 2/file name');
//'../path%201/path%202/file%20name' - OK
echo toURI('example.com/path1/path2/data?key1=value1&key2=value2#fragment', 1);
//'example.com/path1/path2/data?key1=value1&key2=value2#fragment' - OK; better 1 than autodetection
echo toURI('http://user:_pass [email protected]:123/path 1/data?key1=value 1&key2=value2#fragment'); // with username, password or unknown query arguments, use $spec_replace - see below
echo toURI('path 1/path 2/da ta?key1=value 1&argu+ments#frag', 5);
//'path 1/path%202/da%20ta?key1=value+1&argu%2Bments#frag' - wrong, should be 4:
echo toURI('path 1/path 2/da ta?key1=value 1&argu+ments#frag', 4);
//'path%201/path%202/da%20ta?key1=value+1&argu%2Bments#frag' - OK
echo toURI('example.com:port/path1/path2/data?key=value&path=dir 1/dir 2/file#fragment', 5);
//'example.com:port/path1/path2/data?key=value&path=dir+1/dir+2/file#fragment' - OK
echo toURI('path1/path2/data?key1=valueWith~!@?/#$%^&*()inside&arg#frag', 2);
//'path1/path2/data?key1=valueWith%7E%21@?/%23%24%25%5E&%2A%28%29inside&arg#frag' - wrong (first &), use $spec_replace - see fuller examples on my github https://gist.github.com/msegu/bf7160257037ec3e301e7e9c8b05b00a
?>