Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
1df3cfff
Commit
1df3cfff
authored
Jan 29, 2010
by
Dries
Browse files
- Patch
#284899
by c960657, voxpelli, mattconnolly: fixed Drupal url problem with clean urls.
parent
139f4375
Changes
14
Hide whitespace changes
Inline
Side-by-side
.htaccess
View file @
1df3cfff
...
...
@@ -88,11 +88,12 @@ DirectoryIndex index.php index.html index.htm
# uncomment the following line:
# RewriteBase /
# Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
# Pass all requests not referring directly to files in the filesystem to
# index.php. Clean URLs are handled in drupal_environment_initialize().
RewriteCond
%{REQUEST_FILENAME} !-f
RewriteCond
%{REQUEST_FILENAME} !-d
RewriteCond
%{REQUEST_URI} !=/favicon.ico
RewriteRule
^
(.*)$
index.php
?q=$1 [L,QSA
]
RewriteRule
^ index.php
[L
]
</
IfModule
>
# $Id$
includes/bootstrap.inc
View file @
1df3cfff
...
...
@@ -492,6 +492,13 @@ function drupal_environment_initialize() {
$_SERVER
[
'HTTP_HOST'
]
=
''
;
}
// When clean URLs are enabled, emulate ?q=foo/bar using REQUEST_URI. It is
// not possible to append the query string using mod_rewrite without the B
// flag (this was added in Apache 2.2.8), because mod_rewrite unescapes the
// path before passing it on to PHP. This is a problem when the path contains
// e.g. "&" or "%" that have special meanings in URLs and must be encoded.
$_GET
[
'q'
]
=
request_path
();
// Enforce E_ALL, but allow users to set levels not part of E_ALL.
error_reporting
(
E_ALL
|
error_reporting
());
...
...
@@ -559,8 +566,8 @@ function drupal_settings_initialize() {
// $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not
// be modified by a visitor.
if
(
$dir
=
trim
(
dirname
(
$_SERVER
[
'SCRIPT_NAME'
]),
'\
,
/'
))
{
$base_path
=
"/
$dir
"
;
if
(
$dir
=
r
trim
(
dirname
(
$_SERVER
[
'SCRIPT_NAME'
]),
'\/'
))
{
$base_path
=
$dir
;
$base_url
.
=
$base_path
;
$base_path
.
=
'/'
;
}
...
...
@@ -1858,6 +1865,50 @@ function language_default($property = NULL) {
return
$property
?
$language
->
$property
:
$language
;
}
/**
* Returns the requested URL path of the page being viewed.
*
* Examples:
* - http://example.com/node/306 returns "node/306".
* - http://example.com/drupalfolder/node/306 returns "node/306" while
* base_path() returns "/drupalfolder/".
* - http://example.com/path/alias (which is a path alias for node/306) returns
* "path/alias" as opposed to the internal path.
*
* @return
* The requested Drupal URL path.
*
* @see current_path()
*/
function
request_path
()
{
static
$path
;
if
(
isset
(
$path
))
{
return
$path
;
}
if
(
isset
(
$_GET
[
'q'
]))
{
// This is a request with a ?q=foo/bar query string. $_GET['q'] is
// overwritten in drupal_path_initialize(), but request_path() is called
// very early in the bootstrap process, so the original value is saved in
// $path and returned in later calls.
$path
=
$_GET
[
'q'
];
}
elseif
(
isset
(
$_SERVER
[
'REQUEST_URI'
]))
{
// This is a request using a clean URL. Extract the path from REQUEST_URI.
$request_path
=
strtok
(
$_SERVER
[
'REQUEST_URI'
],
'?'
);
$base_path_len
=
strlen
(
rtrim
(
dirname
(
$_SERVER
[
'SCRIPT_NAME'
]),
'\/'
));
// Unescape and strip $base_path prefix, leaving q without a leading slash.
$path
=
substr
(
urldecode
(
$request_path
),
$base_path_len
+
1
);
}
else
{
// This is the front page.
$path
=
''
;
}
return
$path
;
}
/**
* If Drupal is behind a reverse proxy, we use the X-Forwarded-For header
* instead of $_SERVER['REMOTE_ADDR'], which would be the IP address of
...
...
includes/common.inc
View file @
1df3cfff
...
...
@@ -501,7 +501,6 @@ function drupal_http_build_query(array $query, $parent = '') {
}
else
{
// For better readability of paths in query strings, we decode slashes.
// @see drupal_encode_path()
$params
[]
=
$key
.
'='
.
str_replace
(
'%2F'
,
'/'
,
rawurlencode
(
$value
));
}
}
...
...
@@ -623,38 +622,18 @@ function drupal_parse_url($url) {
}
/**
* Encode a path for us
ag
e in a URL.
* Encode
s
a
Drupal
path for use in a URL.
*
* Wrapper around rawurlencode() which avoids Apache quirks. Should be used when
* placing arbitrary data into the path component of an URL.
* For aesthetic reasons slashes are not escaped.
*
* Do not use this function to pass a path to url(). url() properly handles
* and encodes paths internally.
* This function should only be used on paths, not on query string arguments.
* Otherwise, unwanted double encoding will occur.
*
* Notes:
* - For aesthetic reasons, we do not escape slashes. This also avoids a 'feature'
* in Apache where it 404s on any path containing '%2F'.
* - mod_rewrite unescapes %-encoded ampersands, hashes, and slashes when clean
* URLs are used, which are interpreted as delimiters by PHP. These
* characters are double escaped so PHP will still see the encoded version.
* - With clean URLs, Apache changes '//' to '/', so every second slash is
* double escaped.
* Note that url() takes care of calling this function, so a path passed to that
* function should not be encoded in advance.
*
* @param $path
* The
URL path component
to encode.
* The
Drupal path
to encode.
*/
function
drupal_encode_path
(
$path
)
{
if
(
!
empty
(
$GLOBALS
[
'conf'
][
'clean_url'
]))
{
return
str_replace
(
array
(
'%2F'
,
'%26'
,
'%23'
,
'//'
),
array
(
'/'
,
'%2526'
,
'%2523'
,
'/%252F'
),
rawurlencode
(
$path
)
);
}
else
{
return
str_replace
(
'%2F'
,
'/'
,
rawurlencode
(
$path
));
}
return
str_replace
(
'%2F'
,
'/'
,
rawurlencode
(
$path
));
}
/**
...
...
includes/file.inc
View file @
1df3cfff
...
...
@@ -901,6 +901,10 @@ function file_unmunge_filename($filename) {
* of $basename.
*/
function
file_create_filename
(
$basename
,
$directory
)
{
// Strip control characters (ASCII value < 32). Though these are allowed in
// some filesystems, not many applications handle them well.
$basename
=
preg_replace
(
'/[\x00-\x1F]/u'
,
'_'
,
$basename
);
// A URI or path may already have a trailing slash or look like "public://".
if
(
substr
(
$directory
,
-
1
)
==
'/'
)
{
$separator
=
''
;
...
...
includes/path.inc
View file @
1df3cfff
...
...
@@ -384,6 +384,8 @@ function drupal_match_path($path, $patterns) {
*
* @return
* The current Drupal URL path.
*
* @see request_path()
*/
function
current_path
()
{
return
$_GET
[
'q'
];
...
...
includes/stream_wrappers.inc
View file @
1df3cfff
...
...
@@ -639,7 +639,7 @@ public function getDirectoryPath() {
*/
function
getExternalUrl
()
{
$path
=
str_replace
(
'\\'
,
'/'
,
file_uri_target
(
$this
->
uri
));
return
$GLOBALS
[
'base_url'
]
.
'/'
.
self
::
getDirectoryPath
()
.
'/'
.
$path
;
return
$GLOBALS
[
'base_url'
]
.
'/'
.
self
::
getDirectoryPath
()
.
'/'
.
drupal_encode_path
(
$path
)
;
}
}
...
...
misc/autocomplete.js
View file @
1df3cfff
...
...
@@ -276,7 +276,7 @@ Drupal.ACDB.prototype.search = function (searchString) {
// Ajax GET request for autocompletion.
$
.
ajax
({
type
:
'
GET
'
,
url
:
db
.
uri
+
'
/
'
+
Drupal
.
encodePath
(
searchString
),
url
:
db
.
uri
+
'
/
'
+
encodeURIComponent
(
searchString
),
dataType
:
'
json
'
,
success
:
function
(
matches
)
{
if
(
typeof
matches
.
status
==
'
undefined
'
||
matches
.
status
!=
0
)
{
...
...
misc/drupal.js
View file @
1df3cfff
...
...
@@ -282,14 +282,13 @@ Drupal.unfreezeHeight = function () {
};
/**
*
Wrapper around encodeURIComponent() which avoids Apache quirks (equivalent of
*
drupal_encode_path() in PHP). This function should only be used on paths, not
*
on query string arguments
.
*
Encodes a Drupal path for use in a URL.
*
*
For aesthetic reasons slashes are not escaped
.
*/
Drupal
.
encodePath
=
function
(
item
,
uri
)
{
uri
=
uri
||
location
.
href
;
item
=
encodeURIComponent
(
item
).
replace
(
/%2F/g
,
'
/
'
);
return
(
uri
.
indexOf
(
'
?q=
'
)
!=
-
1
)
?
item
:
item
.
replace
(
/%26/g
,
'
%2526
'
).
replace
(
/%23/g
,
'
%2523
'
).
replace
(
/
\/\/
/g
,
'
/%252F
'
);
return
encodeURIComponent
(
item
).
replace
(
/%2F/g
,
'
/
'
);
};
/**
...
...
modules/path/path.test
View file @
1df3cfff
...
...
@@ -66,11 +66,13 @@ class PathTestCase extends DrupalWebTestCase {
$this
->
assertText
(
$node1
->
title
,
'Alias works.'
);
$this
->
assertResponse
(
200
);
// Change alias.
// Change alias
to one containing "exotic" characters
.
$pid
=
$this
->
getPID
(
$edit
[
'alias'
]);
$previous
=
$edit
[
'alias'
];
$edit
[
'alias'
]
=
$this
->
randomName
(
8
);
$edit
[
'alias'
]
=
"- ._~!$'
\"
()*@[]?&+%#,;=:"
.
// "Special" ASCII characters.
"%23%25%26%2B%2F%3F"
.
// Characters that look like a percent-escaped string.
"éøïвβ中國書۞"
;
// Characters from various non-ASCII alphabets.
$this
->
drupalPost
(
'admin/config/search/path/edit/'
.
$pid
,
$edit
,
t
(
'Save'
));
// Confirm that the alias works.
...
...
@@ -122,9 +124,11 @@ class PathTestCase extends DrupalWebTestCase {
$this
->
assertText
(
$node1
->
title
,
'Alias works.'
);
$this
->
assertResponse
(
200
);
// Change alias.
// Change alias
to one containing "exotic" characters
.
$previous
=
$edit
[
'path[alias]'
];
$edit
[
'path[alias]'
]
=
$this
->
randomName
(
8
);
$edit
[
'path[alias]'
]
=
"- ._~!$'
\"
()*@[]?&+%#,;=:"
.
// "Special" ASCII characters.
"%23%25%26%2B%2F%3F"
.
// Characters that look like a percent-escaped string.
"éøïвβ中國書۞"
;
// Characters from various non-ASCII alphabets.
$this
->
drupalPost
(
'node/'
.
$node1
->
nid
.
'/edit'
,
$edit
,
t
(
'Save'
));
// Confirm that the alias works.
...
...
modules/simpletest/tests/file.test
View file @
1df3cfff
...
...
@@ -1888,6 +1888,8 @@ class FileDownloadTest extends FileTestCase {
function
setUp
()
{
parent
::
setUp
(
'file_test'
);
// Clear out any hook calls.
file_test_reset
();
}
/**
...
...
@@ -1937,6 +1939,70 @@ class FileDownloadTest extends FileTestCase {
$this
->
drupalHead
(
$url
);
$this
->
assertResponse
(
404
,
t
(
'Correctly returned 404 response for a non-existent file.'
));
}
/**
* Test file_create_url().
*/
function
testFileCreateUrl
()
{
global
$base_url
;
$basename
=
" -._~!$'
\"
()*@[]?&+%#,;=:
\n\x00
"
.
// "Special" ASCII characters.
"%23%25%26%2B%2F%3F"
.
// Characters that look like a percent-escaped string.
"éøïвβ中國書۞"
;
// Characters from various non-ASCII alphabets.
$basename_encoded
=
'%20-._%7E%21%24%27%22%28%29%2A%40%5B%5D%3F%26%2B%25%23%2C%3B%3D%3A__'
.
'%2523%2525%2526%252B%252F%253F'
.
'%C3%A9%C3%B8%C3%AF%D0%B2%CE%B2%E4%B8%AD%E5%9C%8B%E6%9B%B8%DB%9E'
;
$this
->
checkUrl
(
'public'
,
''
,
$basename
,
$base_url
.
'/'
.
file_directory_path
()
.
'/'
.
$basename_encoded
);
$this
->
checkUrl
(
'private'
,
''
,
$basename
,
$base_url
.
'/system/files/'
.
$basename_encoded
);
$this
->
checkUrl
(
'private'
,
''
,
$basename
,
$base_url
.
'/?q=system/files/'
.
$basename_encoded
,
'0'
);
}
/**
* Download a file from the URL generated by file_create_url().
*
* Create a file with the specified scheme, directory and filename; check that
* the URL generated by file_create_url() for the specified file equals the
* specified URL; fetch the URL and then compare the contents to the file.
*
* @param $scheme
* A scheme, e.g. "public"
* @param $directory
* A directory, possibly ""
* @param $filename
* A filename
* @param $expected_url
* The expected URL
* @param $clean_url
* The value of the clean_url setting
*/
private
function
checkUrl
(
$scheme
,
$directory
,
$filename
,
$expected_url
,
$clean_url
=
'1'
)
{
variable_set
(
'clean_url'
,
$clean_url
);
// Convert $filename to a valid filename, i.e. strip characters not
// supported by the filesystem, and create the file in the specified
// directory.
$filepath
=
file_create_filename
(
$filename
,
$directory
);
$directory_uri
=
$scheme
.
'://'
.
dirname
(
$filepath
);
file_prepare_directory
(
$directory_uri
,
FILE_CREATE_DIRECTORY
);
$file
=
$this
->
createFile
(
$filepath
,
NULL
,
$scheme
);
$url
=
file_create_url
(
$file
->
uri
);
$this
->
assertEqual
(
$url
,
$expected_url
,
t
(
'Generated URL matches expected URL.'
));
if
(
$scheme
==
'private'
)
{
// Tell the implementation of hook_file_download() in file_test.module
// that this file may be downloaded.
file_test_set_return
(
'download'
,
array
(
'x-foo'
=>
'Bar'
));
}
$this
->
drupalGet
(
$url
);
if
(
$this
->
assertResponse
(
200
)
==
'pass'
)
{
$this
->
assertRaw
(
file_get_contents
(
$file
->
uri
),
t
(
'Contents of the file are correct.'
));
}
file_delete
(
$file
);
}
}
/**
...
...
modules/simpletest/tests/menu.test
View file @
1df3cfff
...
...
@@ -51,6 +51,17 @@ class MenuRouterTestCase extends DrupalWebTestCase {
$this
->
assertRaw
(
'seven/style.css'
,
t
(
"The administrative theme's CSS appears on the page."
));
}
/**
* Test path containing "exotic" characters.
*/
function
testExoticPath
()
{
$path
=
"menu-test/ -._~!$'
\"
()*@[]?&+%#,;=:"
.
// "Special" ASCII characters.
"%23%25%26%2B%2F%3F"
.
// Characters that look like a percent-escaped string.
"éøïвβ中國書۞"
;
// Characters from various non-ASCII alphabets.
$this
->
drupalGet
(
$path
);
$this
->
assertRaw
(
'This is menu_test_callback().'
);
}
/**
* Test the theme callback when the site is in maintenance mode.
*/
...
...
modules/simpletest/tests/menu_test.module
View file @
1df3cfff
...
...
@@ -58,6 +58,15 @@ function menu_test_menu() {
'page arguments'
=>
array
(
TRUE
),
'access arguments'
=>
array
(
'access content'
),
);
// Path containing "exotic" characters.
$path
=
"menu-test/ -._~!$'
\"
()*@[]?&+%#,;=:"
.
// "Special" ASCII characters.
"%23%25%26%2B%2F%3F"
.
// Characters that look like a percent-escaped string.
"éøïвβ中國書۞"
;
// Characters from various non-ASCII alphabets.
$items
[
$path
]
=
array
(
'title'
=>
'"Exotic" path'
,
'page callback'
=>
'menu_test_callback'
,
'access arguments'
=>
array
(
'access content'
),
);
// Hidden tests; base parents.
// Same structure as in Menu and Block modules. Since those structures can
...
...
@@ -174,7 +183,7 @@ function menu_test_menu() {
* A random string.
*/
function
menu_test_callback
()
{
return
$t
his
->
randomName
()
;
return
'T
his
is menu_test_callback().'
;
}
/**
...
...
modules/simpletest/tests/path.test
View file @
1df3cfff
...
...
@@ -200,6 +200,15 @@ class UrlAlterFunctionalTest extends DrupalWebTestCase {
$this
->
assertUrlOutboundAlter
(
"taxonomy/term/
$tid
"
,
"taxonomy/term/
$tid
"
);
}
/**
* Test current_path() and request_path().
*/
function
testCurrentUrlRequestedPath
()
{
$this
->
drupalGet
(
'url-alter-test/bar'
);
$this
->
assertRaw
(
'request_path=url-alter-test/bar'
,
t
(
'request_path() returns the requested path.'
));
$this
->
assertRaw
(
'current_path=url-alter-test/foo'
,
t
(
'current_path() returns the internal path.'
));
}
/**
* Assert that an outbound path is altered to an expected value.
*
...
...
modules/simpletest/tests/url_alter_test.module
View file @
1df3cfff
...
...
@@ -6,6 +6,27 @@
* Module to help test hook_url_inbound_alter() and hook_url_outbound_alter().
*/
/**
* Implements hook_menu().
*/
function
url_alter_test_menu
()
{
$items
[
'url-alter-test/foo'
]
=
array
(
'title'
=>
'Foo'
,
'page callback'
=>
'url_alter_test_foo'
,
'access arguments'
=>
array
(
'access content'
),
'type'
=>
MENU_CALLBACK
,
);
return
$items
;
}
/**
* Menu callback.
*/
function
url_alter_test_foo
()
{
print
'current_path='
.
current_path
()
.
' request_path='
.
request_path
();
exit
;
}
/**
* Implements hook_url_inbound_alter().
*/
...
...
@@ -22,6 +43,10 @@ function url_alter_test_url_inbound_alter(&$path, $original_path, $path_language
if
(
$path
==
'community'
||
strpos
(
$path
,
'community/'
)
===
0
)
{
$path
=
'forum'
.
substr
(
$path
,
9
);
}
if
(
$path
==
'url-alter-test/bar'
)
{
$path
=
'url-alter-test/foo'
;
}
}
/**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment