Help with htaccess

Hello,

I am building my new site. My old homepage was accessible under mydomain.com/web/index.php
I used to use a simple meta-refresh (shame) in mydomain.com/index.php, but for my new site I want .htaccess file.
However, I do (ab)use my site also for other webpages. So I have some photoalbums under mydomain.com/newyork and mydomain.com/montreal etc.

My new homepage is under mydomain.com/new/index.php
I changed basically everything so I don’t need a link specific redirect.
But I do want:

  1. What should my .htaccess look like?

Would this do the trick?

redirect 301 /index.php http://www.mydomain.com/new/index.php
redirect 301 /web/ http://www.mydomain.com/new/index.php

  1. And if I put the .htaccess in the root (mydomain.com) do I also need to put a index.php file in the root?
    (If so, what should it contain?)

Hello,

I am building my new site based on Wordpress. My old homepage was accessible under mydomain.com/web/index.php
I used to use a simple meta-refresh (shame) in mydomain.com/index.php, but for my new site I want to use .htaccess file.
However, I do (ab)use my site also for other webpages. So I have some photoalbums under mydomain.com/newyork and mydomain.com/montreal etc. I use this to quickly share holiday photo’s with friends and collegues and remove them after a month or so. Still building a permanent photo-site.

My new wordpress homepage is under mydomain.com/new/index.php. I don’t mind visitors seeing the /new/ sublevels. I changed basically everything so I don’t need a link specific redirect from my old site.
But I do want:

  1. Should I better use Wordpress handle the redirect/rewrite with htaccess or use a simple redirect?

  2. Suppose I make my own redirect, what should my .htaccess look like?

Would this do the trick?

redirect 301 /index.php http://www.mydomain.com/new/index.php
redirect 301 /web/ http://www.mydomain.com/new/index.php

  1. And if I put my own .htaccess in the root (mydomain.com) do I also need to put an index.php file in the root?
    (If so, what should it contain?)

Help is appreciated, need to get my site live this weekend and I don’t want it to be offline because I screw up htaccess files.

Karaat,

First, WELCOME to SitePoint!

Second, your first “want” id mutually exclusive with the third “want” so you’ll never get to newyork.

Third, you’ve actually broken the code for doing the impossible (from your specification)! With /index.php being redirected to /new/index.php (you don’t need to have this ABSOLUTE redirection be external), you’ve resolved the index.php part of your spec (not the EVERYTHING). The second Redirect handles the second part of your specification and the third (no redirection) handles itself!

Now, back to the EVERYTHING part of redirecting to new/index.php. You will need mod_rewrite for that to check whether the other requests (newyork and montreal, etc) exist before redirecting. For that, check the {REQUEST_FILENAME} NOT being -f and -d before redirecting .? to new%{REQUEST_URI}.

If you don’t understand that, please have a look at some of the coding examples in my signature’s tutorial before creating your code and testing then come back with questions (in other words, I don’t like spoonfeeding because you won’t learn anything if I merely provide you with the code - be assured that I will be sure you get to the solution, though).

Regards,

DK

Hi DK,

Well I did some study and understand it somewhat more.

Second, your first “want” id mutually exclusive with the third “want” so you’ll never get to newyork.

What I meant is anyone typing mydomain.com (with www, which I omit because sitepoint tunrs it into a url format) in his browser gets to mydomain.com/new/ (with www).

Third, you’ve actually broken the code for doing the impossible (from your specification)! With /index.php being redirected to /new/index.php (you don’t need to have this ABSOLUTE redirection be external), you’ve resolved the index.php part of your spec (not the EVERYTHING). The second Redirect handles the second part of your specification and the third (no redirection) handles itself!

Eerrr, how should I interpret this? Are the exclamation marks ironical or meant as a compliment?

Anyway, let’s see what I think I should do.
As far as I now understand, the following code seems to fulfil requirements one and three:

  • not redirect if the request is already made to mydomain.com/new,
  • AND to redirect everything to mydomain.com/new if it is a request to a non-existing file or folder.
  • R=301 means permanent redirection.

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule ^/new/index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /new/index.php [R=301,L]
</IfModule>

Sometimes I find the last rule written as RewriteRule ^$ /new/ [R=301,L]
Is it better to use . or ^$ (question)?

Now I need to redirect requests to my old sites.
So I need to add RewriteRule ^/web/$ /new/index.php [R=301,L]
I just put it below the first rule.

So the full one will read:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule ^/new/index.php$ - [L]
RewriteRule ^/web/$ /new/index.php [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /new/index.php [R=301,L]
</IfModule>

How about this?

Question:
My new site is actually a Wordpress site. So under new there is htaccess as well. They use
RewriteBase /new/
I fail to understand what that does exactly. I read an explanation that base is used to be added as a prefix to every rewrite rule. http://randomtype.ca/blog/the-wordpress-htaccess-file-explained/ But that didn’t seem logical, because the Rewrite rule is still RewriteRule . /new/index.php [L] If the Base would be added the rewrite would read new/new/index.php
.

Oke, I have caught up a little more and it seems I can remove the IfModule rule (read your rant about it, haha).
And the first ReWriteRule seems superfluous, because the first RewriteCond handles this. (Wonder why Wordpress guys include it. It is supposed to prevent looping, but I don’t know)

So would this code do?


RewriteEngine On

 RewriteRule ^/web/$ /new/index.php [R=301,L]
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule . /new/index.php [R=301,L]

Hi Karaat,

First, to remove the automatic creation of links, look under the message textarea and uncheck the “Automatically parse links in text” box. That will take care of your www problem!

So, if your visitor types www.example.com/, you want it sent to www.example.com/new/, correct? IMHO, UNLESS you want to use your DocumentRoot for something else, simply change the DocumentRoot of your domain (redirect within cPanel). Okay, that’s not your question so I’ll go on.

The first exclamation point was a “gudonya,” a compliment as you’d performed a miracle … until we both realized that you are not redirecting everything as you’d intended. The second was a “whew” moment as you didn’t need to do anything to satisfy your “do nothing” requirement.

PLEASE wrap your code in [noparse]

...

[/noparse] tags as that preserves the code when quoting for a reply.

Your specification is:

[indent]As far as I now understand, the following code seems to fulfil requirements one and three:

  • not redirect if the request is already made to mydomain.com/new,
  • AND to redirect everything to mydomain.com/new if it is a request to a non-existing file or folder.
  • R=301 means permanent redirection.[/indent]

Then your code is:

[COLOR="#FF0000"]<IfModule mod_rewrite.c>[/COLOR]
# Yes, I read your next post but couldn't let that stand :lol:
RewriteEngine On

RewriteRule ^/new/index.php$ - [L]
# passthrough - ditto the comment above, though

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /new/index.php [R=301,L]
# What about the domain request, i.e., no characters?
# Simply change the . to .? (optional anything)
# Then the leading / in the redirection is an absolute redirection
# which is not necessary from the DocumentRoot
[COLOR="#FF0000"]</IfModule>[/COLOR]

Sometimes I find the last rule written as RewriteRule ^$ /new/ [R=301,L]
Is it better to use . or ^$ (question)?

Really? :nono: Too dumb for me! I prefer (as above) to use .? as there is no need to match anything.

Now I need to redirect requests to my old sites.

OMG, your old site was in the web directory? :eek2:

Question:
My new site is actually a Wordpress site. So under new there is htaccess as well. They use
RewriteBase /new/
I fail to understand what that does exactly. I read an explanation that base is used to be added as a prefix to every rewrite rule. http://randomtype.ca/blog/the-wordpress-htaccess-file-explained/ But that didn’t seem logical, because the Rewrite rule is still RewriteRule . /new/index.php [L] If the Base would be added the rewrite would read new/new/index.php
.

Well, I have to admit that I can’t get my head around any valid reason to use RewriteBase. The RewriteBase directive was created to UNDO a mod_alias Redirect so that mod_rewrite could work on it. WP alters that philosophy and uses it to force the directory in which it resides. RewriteBase simply tells Apache to redirect everything to the directory specified but, if you understand mod_rewrite, you’re already doing that with your code.

That works for me (as modified)! IT would redirect everything requested from web/ to new/index.php then check that a the requested file doesn’t exist as a file or as a directory then redirects to new/index.php. That seems to be what you’re asking for so you’re done (and have learned something while you were at it). Congratulations, you’re a mod_rewrite guru … well, practitioner with a good grasp of what you’re doing!

:award:

Regards,

DK

Thanks for the help!

Ah, the $ is an “anchor”. What’s that? I read a bad tutorial that $ would tell where [this] ends and [that] starts: Rewrite [this]$ (to) [that]. As I understand it now, it will only match now if www.doamin.com/web/ is requested, which is not good. So Oke, I change it to:


RewriteEngine On

RewriteRule ^/web /new/index.php [R=301,L]
# Redirect from the web directory to new/index.php.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? /new/index.php [R=301,L]

Thanks to your help I do understand it much better. I could have cheated my way out partly, by letting workpress do the redirection to new. But I don’t like them to fiddle with my root .htaccess without me understanding . If they provide an upgrade of their software this may get screwed up. Or if I want to have another site running under my root, I wouldn’t know how to make them coexist. And it wouldn’t have redirected the requests to the old website, which may be bookmarked by our previous visitors.So being in control feels much better. Thanks for that.

So, if your visitor types www.example.com/, you want it sent to www.example.com/new/, correct? IMHO, UNLESS you want to use your DocumentRoot for something else, simply change the DocumentRoot of your domain (redirect within cPanel). Okay, that’s not your question so I’ll go on.

Well my site is hosted at one.com. So I don’t know where cPanel would reside, if I can control it at all.

Further, my current htaccess in the root contains


# -FrontPage-

IndexIgnore .htaccess */.??* *~ *# */HEADER* */README* */_vti*

<Limit GET POST>
order deny,allow
deny from all
allow from all
</Limit>
<Limit PUT DELETE>
order deny,allow
deny from all
</Limit>

I have never worked with Frontpage, used Dreamweaver for my old site, so I almost assume this is some kind of default from one.com. But what should I do with it? The first rule seems daunting…

Finally, with the new htaccess in place, do I need to have a index.php or .html in my root? I guess not, but just to be sure.

(I will make the switch to my new website later this weekend I hope. So I won’t put the htaccess up until the new wordpress site is ready. Will let you know whether some unexpected behaviour occurs.)

Regards,

Menno

Karaat,

The $ is the end anchor, a no-length character denoting the end of a string. If your {REQUEST_URI} is index.php, it’s located after the .php. The ^ character is the start anchor which, in this case, is located immediately before the i in index. Think of it as ^index.php$.

The format for the RewriteRule directive is RewriteRule {regex} {redirection} [{flags}]. All this is covered in my signature’s tutorial. You might benefit from reading the mod_rewrite tutorial linked in my signature as it contains explanations and sample code. It’s helped may members and should help you, too.

:tup: Kudos to you for wanting to understand the code WP added to your DocumentRoot’s .htaccess! Too many members allow themselves to be treated like “script kiddies” by using code they do not understand.

Good to plan ahead, too!

If you have another website “running under (your) root,” if it’s an add-on domain, any request to the add-on domain will bypass the main domain’s DocumentRoot so that will not be a problem. However, if you’re using other “canned scripts” within your main domain, WP’s code (also as we’ve modified it) will most certainly hijack any request which is not made directly for an existing file (remember the !-f and !-d?). I’d had a website where a client wanted to run both WP and another “canned program” so I created a Home Page which allowed visitors to select their destination and treated each of the two directories as if they were the DocumentRoot for their apps.

The code you showed was typical “boilerplate” which you can ignore. The first bit is fine and the second is better placed in the server’s configuration file (which it probably is). It does NOT make you use FrontPage which, IMHO, is a good thing (you avoid M$'s propensity for generating proprietary code which can only be viewed by IE).

You do NOT need any file (other than your .htaccess) in your DocumentRoot (so long as mod_rewrite is enabled). The choice of a filename is yours as you can list your preference with the DirectoryIndex index.php index.html default.page yadda-yadda statement (the first file listed which is found by Apache will be the one served to the visitor).

Regards,

DK

Hi DK,

I read your tutorial which was very informative. But let me understand this clearly. You said the RewriteRuke ^/web/$ would only match requests which are for www.domain/com/web/ and not for instance for www.domain.com/web/whateverfile.php. Is that because of the closing ‘$’ (question)? Of because of the ‘/’. It’s not fully clear to me when you use a $ in the RewriteRul or not, because it is not necessary to include it at the end.

I found another cool application for the htaccess


# secure wordpress contact forms via referrer check
 RewriteCond %{HTTP_REFERER} !^http://www.mydomain.com/.*$ [NC]
 RewriteCond %{REQUEST_POST} new/contact/$
#forbid access
 RewriteRule .* - [F]
#or reroute them to my homepage
RewriteRule .* www.mydomain.com/index.php [L]

Is this code still used a lot?
I have simple numerical captcha at my contact site to prevent spam. If I would make them complicated, people might not contact us. And second, captchas can be solved anyway by smart spambots, so this seems a nice trick.

Best regards

Menno

Hi Karaat,

Actually, your RewriteRule ^/web/$ would only web/ if your server was Apache 1.x because the leading / is assumed in Apache 2.x (which will NOT match if you’ve required a leading /). You can use ^/? if you’re not sure and both versions of Apache will accept that code.

As for the end anchor, your regex will only match if the domain and web/ directory request is made. The $ end anchor requires that it be at the end of the string it’s trying to match. Omit the $ if you don’t care whether a file is requested in the web directory; omit the / if you don’t have any web.* files or other directories in your DocumentRoot. In other words, both /'s in your regex were problems, one because of the version of Apache you’re using and the second because your visitors may be lazy and only request web to gain access to your web directory.

Again, the ^ denotes the start of the string you’re trying to match and $ denotes the end of the string; nothing more and nothing less.

Sorry, the code you posted will not keep anyone from your contact forms (they can be accessed from your website via any file). Further, I’ve never seen {REQUEST_POST} before so I searched and found:

To me, that says that someone’s blowing smoke up your … and trying to cause you to bring your own site down with a 500 (server) error (which it will do with unrecognized code like this). Therefore, I’d say that it’s not used a lot (probably never).

There are a large number of CAPTCHA scripts at phpclasses.org (a very nice site for PHP programmers) so I’d suggest that you find one you like there and simply use that IN ADDITION TO KEEPING YOUR WP UP TO DATE (that’s the most critical thing)! Next, CHECK THE RESPONSES you receive from your form against what you expect, i.e., get rid of < and > and http:// and href and mailto and defintely all apostrophes (') before using mysqli_real_escape_string to safe the data before getting near your database. Do NOT use a script to assign values based on key/value pairs; go through the keys you put in the form and assign those values yourself. In other words, practice safe coding rather than rely on “cutsie” code that you don’t understand (and doesn’t work for the purpose you intend - it’s only conceivable purpose is to bring your website down which it will do if uploaded [and the RewriteRule’s regex is matched - the rule’s regex is actually matched before the conditions]).

Regards,

DK

Hi DK,

Thanks for that. I got the code from http://perishablepress.com/stupid-htaccess-tricks/ which seemed to be a knowledgable resource. I do like the idea of checking whether my contacts form was found by clicking on a link from my page instead of filed from a remote site. But I can live without it for the time being. Let’s see how much spam we get.

Captchas are oke to block the most simple spam mechanims, but smart spammers use a mechanical turk to crack captchas

Regards,

Menno

Karaat,

Use {HTTP_REFERER} to test that the request to your action script came from your form’s script - I have no problem with that at all.

CAPTCHAs of various types can be too difficult for any automated technique. When thinking about security, please remember that security is a trade-off with both cost and complexity (for you as a coder as well as for the visitor). If you’re protecting a bank vault, then it’s worth a LOT of cost but, if you’re protecting a database of jokes (sorry, Kevin), then it’s not worth much effort at all.

Regards,

DK