• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Yet another routing or .htaccess question...

#1
[eluser]mrh[/eluser]
Hi, I'll try to make this short... I searched and I've been experimenting and I've read the user guide but I'm kind of not getting how to do this.

We have our company side in Code Igniter at our domain:

www.ourdomain.com

With our default route this takes us into the main controller and all is well.

My boss is a very active forum participant and he has a folder on the site full of images that he uses for emoticons, examples, etc. Because he is a lousy typist and he comes from a Windows base host (now on linux) he has not been watching the case of his references to these images. So in some of his posts he does:

http://www.ourdomain.com/ttt/SlapsHead.jpg

In another post he'll do:

http://www.ourdomain.com/ttt/SLAPSHEAD.JPG

Now on a Windows host this was fine. But on our new linux host it doesn't work of course. What I'm hoping to do is to use CodeIgniter to fix this problem for him. Since all of his images reside in a folder called "ttt" I was thinking about writing a controller called "ttt" and the code within that controller would have an array of the files in the directory and be able to fix the case. So the goal would be if one of his posts is:

http://www.ourdomain.com/ttt/SLAPSHEAD.JPG

but the file in the folder is really "slapshead.jpg" that I could in effect intercept this call and return the correct file from say an echo statement.

My issue is getting the routing to the controller to work. In my limited Code Igniter experience to get to the ttt controller I need to call:

http://www.ourdomain.com/index.php/ttt

I need a route or an .htaccess entry that will take his calls like:

http://www.ourdomain.com/ttt/SlapsHead.jpg

and map them to my controller of choice like:

http://www.ourdomain.com/index.php/ttt/SlapsHead.jpg

In my controller I'd look at the argument which would be "SlapsHead.jpg", scan the array and figure out that the disk filename is: "slapshead.jpg" and I'd basically echo out that image file.

It seems like this should be doable but in my few attempts to achieve the correct routing I cannot get it to work. I was planning to rename his image directory to something like _ttt and then when his request came in for

http://www.ourdomain.com/ttt/SlapsHead.jpg

my controller would load and hopefully cache the list of files in the _ttt folder and use that as a look up table to return the correct thing. I was sort of thinking of trying to redirect to the correct image file.

Any thoughts? If I can get this to work then we can stay on our linux host. Other wise he will take us back to the wonderful world of Windows which will make my job more difficult I think to support the site.

Any help would be much appreciated.


#2
[eluser]mrh[/eluser]
Ok I didn't get any replies on this, probably because it turned out not to be too hard. But for anyone else looking into how to do this I'll give a run down here.

The problem:

Someone uses their website as a host for images, files, etc. and that someone doesn't understand or didn't know that filenames on linux hosts are case sensitive. So when the website including their "special" files are moved from a Windows host to a linux host many of their links to their special files no longer work.

The solution:

Three things are needed:

First a rule in the .htaccess which will take a URL of the form the user uses for their special files and rewrite it into a controller call in CI.

Second the ABC directory must be renamed to something else or the rewrite rule will retrigger on the redirect. So name it like XYZ or something.

Third a small controller or function within a controller that figures out the filename case problem.

In my specific case my boss had a number of image and other types of files in a directory on the server. Lets call this directory "ABC". So he was used to referencing these images in his forum posts as follows:

http://www.domain.com/ABC/image.jpg

Now as long as he supplied the correct case on everything this would work even under linux. But my boss is a lousy typest and his site was previously hosted on Windows which allowed him (and other posters using his images) to get away with mixed case filenames and things would still work.

In looking on this forum I saw things like the following:

http://www.domain.com/ABC/image1.jpg
http://www.domain.com/abc/Image1.jpg
http://www.domain.com/Abc/IMAGE1.jpg

All of these on the Windows host resolved to the same actual file: ABC/image1.jpg. But when the site was moved to linux these links broke. Unfortunately my boss was extremely active in this one forum and had over 13,000 posts. He was not willing to try and hunt down the broken links and fix them.

So enter the solution above. The first step was to create a rewrite rule. Mine looked like this:

RewriteRule ^[aA][bB][cC]/(.*)$ http:/www.domain.com/index.php/main/getfile/$1 [L]

I'm still new to .htaccess files but this rule worked. The regular expression at the beginning matches any case version of ABC. So ABC, Abc,ABc,aBC, etc all work. The next portion grabs whatever follows the /.

This is then redirected to my main controller into a function getfile. The filename obtained by the regular expression group: (.*) is passed as an argument to this "getfile" controller function.

The "getfile" controller function looks like this:

Code:
public function getfile( $file="" )
{
  if( $file!="" )
  {
   $file = strtoupper( $file );
  
   $XYZDir = scandir( './XYZ' );
  
   foreach( $XYZDir as &$value )
   {
    if( strtoupper($value)==$file )
    {
     redirect( base_url( 'XYZ' ) . "/" . $value );
    }
   }
  }
}

This function is pretty simple. If there is a filename passed in then it scans the directory "XYZ". From the returned array of filenames we loop and compare our passed in uppercase filename until we find a match. If we find a match we issue a redirect to the correct case significant path to the file.

So a request for:

http://www.domain.com/ABC/image1.jpg

is translated to:

http://www.domain.com/XYZ/image1.jpg

Regardless of the case used for ABC or the filename "image1.jpg".

Now I'm sure those of you with tons more experience would find an even easier way to do this and I'm open to any and all suggestions but this works well and it seems fast enough for his needs.

I can think of a number of optimizations. In this case my boss has about 150 files in his directory. The linear search works well but I can see if the directory had 5000 files you might be better off with a binary search since scandir returns the list in alphabetical order it would be pretty easy to convert this to a much faster binary search.

In my tests of this code on the real website the time to traverse the entire list for a file say at the end was not noticeable to the webuser. Obviously there are other ways to enhance this. Perhaps the file list could be cached.

Anyway it solved my bosses problem. It also allows him and his fellow posters to mangle the names all they want and still get to the images so it works for me.

This does have a limitation that it is limited to just the specified folder. IE this works for references like:

http://www.domain.com/ABC/image1.jpg

It does not however work for:

http://www/domain.com/ABC/SubFolder/image2.jpg

I'm sure this could be expanded to work in this second case but I didn't go there since my boss has everything in just one folder.

I hope this helps someone else facing a similar problem. Please feel free to offer up corrections and enhancements. I'm still learning.


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.