A few days ago, I did the database work to ignore case when browsing to a cat/port. Tonight, I did the website side.
database access
First, I altered the database function (in classes/element_record.php) to use the new stored procedure:
- function FetchByName($Name) {
+ function FetchByName($Name, $caseSensitive = true) {
+ $Debug = 0;
+
+ if ($Debug) echo "looking for '$Name' and caseSensitive is '$caseSensitive'<br>";
if (IsSet($Name)) {
$this->element_pathname = $Name;
$this->id = '';
}
- $sql = "select * from elementGet('" . pg_escape_string($Name) . "')";
- $result = pg_exec($this->dbh, $sql);
+ if ($caseSensitive) {
+ $sql = "select * from elementGet('" . pg_escape_string($Name) . "')";
+ if ($Debug) echo "invoking $sql<br>";
+ $result = pg_exec($this->dbh, $sql);
+ } else {
+ $result = pg_query_params($this->dbh, 'select * from elementGetCaseInsensitive($1)', array($Name));
+ }
+
if ($result) {
+ if ($Debug) echo "we got a result<br>";
+
$numrows = pg_numrows($result);
+ if ($Debug) echo "we have '$numrows' rows<br>";
if ($numrows == 1) {
$myrow = pg_fetch_array ($result, 0);
$this->PopulateValues($myrow);
On line one, I modify the function to pass in an optional parameter which preserves the original behavior.
Line 10 is the original code.
Lines 13-20 invokes the elementGetCaseInsensitive() stored procedure to work on a case insensitive solution.
Redirecting when finding a different match
When getting a result, we check to see if the path differs. If we get a result, we know it matches, but we need to know if it’s a different case. Here is that code (from rewrite/functions.php):
- if ($ElementRecord->FetchByName('/ports/head/' . $pathname)) {
+ if ($ElementRecord->FetchByName(FRESHPORTS_PORTS_TREE_PREFIX . PATH_NAME, 0)) {
$IsElement = true;
if ($Debug) echo 'we found an element for that<br>';
+ if ($Debug) echo "we have: '$ElementRecord->element_pathname'<br>";
+ if ($Debug) echo " we had: '" . FRESHPORTS_PORTS_TREE_PREFIX . PATH_NAME . "'<br>";
+ if (PathnameDiffers($ElementRecord->element_pathname . '/', FRESHPORTS_PORTS_TREE_PREFIX . PATH_NAME)) {
+ # in a case insensitive search, we want to redirect if the case was wrong
+ if ($Debug) echo "we are redirecting to '" . $ElementRecord->element_pathname . "/'<br>";
+ if ($Debug) echo 'which normalizes to ' . str_replace(FRESHPORTS_PORTS_TREE_PREFIX, '/', $ElementRecord->element_pathname . '/<br>');
+ $https = ((!empty($_SERVER['HTTPS'])) && ($_SERVER['HTTPS'] != 'off'));
+ if ($https) {
+ $protocol = "https";
+ } else {
+ $protocol = "http";
+ }
+
+ header("HTTP/1.1 301 Moved Permanently");
+ header('Location: ' . $protocol . '://' . $_SERVER['HTTP_HOST'] . str_replace(FRESHPORTS_PORTS_TREE_PREFIX, '/', $ElementRecord->element_pathname . '/'));
+ exit;
+ }
+ }
+
Line 7 invokes PathDiffers to do a comparison between the two strings. This is not a simple A != B operation. sysutils/bacula9-server is not the same as sysutils/bacula9-server/ despite them showing the same content on the website. The paths, or URIs, must first be ‘normalized’ (that’s my chosen terminology, not anything official).
If the user has included a trailing slash (/) on their URL, the code will strip that before looking for a matching entry in the element table.
The debugging information shows some of this:
the URI is
'/sysutils/bacula9-SERVER/'
the url parts are
array(1) {
["path"]=>
string(25) "/sysutils/bacula9-SERVER/"
}
The pathname is '/sysutils/bacula9-SERVER/'
we found an element for that
we have: '/ports/head/sysutils/bacula9-server'
we had: '/ports/head/sysutils/bacula9-SERVER'
we are redirecting to '/ports/head/sysutils/bacula9-server/'
which normalizes to /sysutils/bacula9-server/
The function in question looks like this:
function PathnameDiffers($Path1, $Path2) {
# if the two paths are different, we might want to redirect
# if one path ends in a / and the other does not, adjust them
if (substr($Path1, -1) == '/') {
if (substr($Path2, -1) != '/') {
$Path2 .= '/';
}
} else {
if (substr($Path2, -1) == '/') {
$Path1 .= '/';
}
}
return $Path1 != $Path2;
}
That redirect happens early enough in the code to handle all elements, not just ports (e.g. cat/ports/Makefile or distinfo or pkg-descr).











