Parameters main. What you need to know about .htaccess


This article grew out of an idea for advanced training for our employees technical support working with mod_rewrite. Practice has shown that after studying the large number of textbooks in Russian, support staff are good at solving template problems, but independent compilation of rules occurs by trial and error. large quantity errors. The problem is that for good understanding mod_rewrite requires studying the original English documentation, followed by either additional explanations or hours of experimentation with RewriteLog.

The article describes how mod_rewrite works. Understanding the principles of its operation allows you to clearly understand the effect of each directive and clearly imagine what is happening at one time or another inside mod_rewrite when processing directives.

I assume that the reader is already familiar with what mod_rewrite is, and I will not describe its basics, which are easy to find on the Internet. It should also be noted that the article covers the work of mod_rewrite when using its directives in the .htaccess file. Differences when working in context set out in .

So, you've studied mod_rewrite, compiled several RewriteRules and managed to encounter endless redirections, the case when a rule for some reason does not catch your request, as well as the unpredictable operation of a group of rules when a subsequent rule unexpectedly changes a request that was painstakingly prepared by the previous rules.

What does RewriteRule work with?

The first RewriteRule is passed the path from where .htaccess is located to the requested file. This line never starts with "/". Subsequent RewriteRules transmit the result of previous transformations.

To thoroughly understand how RewriteRule works, you must first define what it works with. Let's look at how Apache receives the string that is initially passed to the RewriteRule in .htaccess for processing.

When you first start working with mod_rewrite, you logically assume that it works with links. However, this is not the case when using mod_rewrite in .htaccess. In fact, it is not a link that is sent to RewriteRule, but the path to the requested file.

Due to Apache's internal architecture, the moment .htaccess comes into play, mod_rewrite can only operate on the path to the file that needs to be processed. This is due to the fact that before being sent to mod_rewrite, the request could have already been modified by other modules (for example, mod_alias), and the final path to the file on the site may no longer coincide with the original link. If mod_rewrite worked on the original reference, it would break the action of modules that modified the request before it.

Therefore, mod_rewrite is passed the absolute path to the file that should be processed. Mod_rewrite also knows the path to .htaccess, where the RewriteRule rules are located. To make the path to the file something similar to the link that the site developer plans to work with, mod_rewrite cuts off the part to the .htaccess file from the absolute path.

So, it is this path, from which the path to .htaccess is cut off, that is passed to the first RewriteRule. For example:

Request: http://example.com/templates/silver/images/logo.gif DocumentRoot: /var/www/example.com Path to file: /var/www/example.com/templates/silver/images/logo. gif .htaccess is located in: /var/www/example.com/templates/.htaccess

The first RewriteRule will receive: silver/images/logo.gif Please note: “templates/” was also cut off. how RewriteRule works The path to .htaccess is cut off along with the slash. There is a consequence from this: the line that is initially passed to RewriteRule processing never begins with "/".

It's important to remember what RewriteRule doesn't do. It does not process the site name, the arguments that are passed to the script, and it does not process the entire link if the .htaccess is not located in the root of the site. All this is done by RewriteCond, which we will briefly touch on a little later. So:

# will not work - the rule starts with / RewriteRule ^/index.php$ /my-index.php # will not work - the site name is not analyzed RewriteRule RewriteRule ^example.com/.* http://www.example.com # will not work - the link arguments do not fall into the RewriteRule RewriteRule index.php\?newspage=(+) news.php?page=$1 # Will only work if .htaccess is located in the same place as the templates folder, # for example, in the root of the site . That is, if .htaccess is in templates/.htaccess , the # rule WILL NOT work, because mod_rewrite will cut off the path to .htaccess and the line will end up at the RewriteRule # input without "templates/" RewriteRule ^templates/common/yandex-money. gif$ templates/shared/yad.gif

We figured out what RewriteRule works with. Now let's see how it works.

How RewriteRule works

RewriteRule simply transforms the string according to regular expressions and that's it. RewriteRule operates on a string, not a link or path to a file.

As we found out above, the RewriteRule input includes the path from .htaccess to the requested file. It is most convenient now to abstract from paths and links and consider what RewriteRule works with as an ordinary string. This string is passed from RewriteRule to RewriteRule, modified if any of the RewriteRules worked.

Overall, barring the complexities of using flags (some of which we'll look at below) and the complexities of writing regular expressions (which we won't touch on much in this article), RewriteRule works VERY simply. We took the line. Compare with the regular expression in the first argument. If there is a match, replace the entire string with the value of the second argument. Passed the string to the next RewriteRule. That's basically all. To clearly illustrate that RewriteRule works specifically with a string, consider the following fantastic example:

# Request: http://mysite.com/info.html # The first RewriteRule will contain "info.html" # Convert the request to an arbitrary string. RewriteRule ^info.html$ "I saw a turtle in the hole. And it was dancing rock-n-roll. And it was smiling. All in all, it was a very funny doll." # "info.html" -> "I saw a turtle..." # Replace this line with external link. RewriteRule turtle https://example.com/information/index.html # "I saw a turtle..." -> "https://example.com/information/index.html" # Replace the site name! RewriteRule ^(.*)example.com(.*)$ $1example.org$2 # "https://example.com/information/index.html" -> "https://example.org/information/index. html" # Replace the protocol! RewriteRule ^https:(.*)$ ftp:$1 # "https://example.org/information/index.html" -> "ftp://example.org/information/index.html" # Replace the final link. RewriteRule ^(.*)/index.html$ $1/main.php # "ftp://example.org/information/index.html" -> "ftp://example.org/information/main.php"

As you can see, RewriteRule doesn't care what it works with - it simply transforms the string according to the arguments given to it. If you want, you can store any data arrays in a line; if you wish, persistence and have good knowledge of regular expressions, you can even write tic-tac-toe on RewriteRule.

A note needs to be made here: although RewriteRule works with a pure string, it is still focused on working with links. Therefore, it will react in a special way to lines starting with

https://

or analogues (it will remember that we wanted to make an external redirect) and to the "?" (considers the following characters as arguments that will need to be substituted for the request). However, we're not interested in that for now - it's important to understand that there's no magic in RewriteRule - it just takes a string and changes it the way you tell it to. We will look at external redirects and arguments later in the article; there is something to talk about there too.

After all transformations have been completed and the last RewriteRule has been executed, RewriteBase takes effect.

What is RewriteBase used for?

If the resulting query is relative and different from the original query, RewriteBase will add itself to the left of it. It is necessary to specify RewriteBase in .htaccess. Its value is the path from the site root to .htaccess. RewriteBase is executed only after all RewriteRules, not between them.

We have already said above that mod_rewrite, which works in .htaccess, contains the absolute path to the requested file. To pass it to the RewriteRule, mod_rewrite cuts off the path to .htaccess. Then the RewriteRules sequentially change the request one by one. And now, after the request is modified, Apache must restore the absolute path to the file that it must ultimately process. RewriteBase is actually a hack that helps restore the original path of a file.

RewriteBase is executed after all transformations. This means that it will not change the request between RewriteRules, but will only take effect when all RewriteRules have completed.

After all the transformations, RewriteBase looks at whether the resulting path is relative or absolute. In the context of Apache, this means a relative or absolute path, starting from the root of the site: images/logo.gif - relative. /images/logo.gif - absolute (slash at the beginning). http://example.com/images/logo.gif - the most absolute of all. If the path is absolute, RewriteBase does nothing. And if it is relative, RewriteBase appends itself to the left. This works for both internal and external redirects:

# .htaccess is located in /images/ # RewriteBase is specified /images/ RewriteBase /images/ # Request http://example.com/images/logo.gif # The RewriteRule input is "logo.gif" RewriteRule ^logo.gif$ logo -orange.gif # After RewriteRule: "logo.gif" -> "logo-orange.gif" # After RewriteBase: "logo-orange.gif" -> "/images/logo-orange.gif" # Request http:/ /example.com/images/header.png # The RewriteRule input is "header.png" RewriteRule ^header.png$ /templates/rebranding/header.png # After the RewriteRule: "header.png" -> "/templates/rebranding /header.png" # After RewriteBase: nothing changes, so the final result of the transformation begins with "/". # Request http://example.com/images/director.tiff # The RewriteRule input is "director.tiff" # We use an external relative redirect RewriteRule ^director.tiff$ staff/manager/director.tiff # After the RewriteRule: "director. tiff" -> "staff/manager/director.tiff" # + mod_rewrite remembered that there will be an external redirect # After RewriteBase: "staff/manager/director.tiff" -> "/images/staff/manager/director.tiff" # mod_rewrite remembered about the external redirect: # "/images/staff/manager/director.tiff" -> http://example.com/images/staff/manager/director.tiff

Typically, after some familiarity with mod_rewrite, the following habit develops:

    add “RewriteBase /” to each .htaccess

    All redirections begin with a slash: “RewriteRule news.php /index.php?act=news”. This helps to get rid of artifacts from RewriteBase, but it is wrong to do this. Now that we know what RewriteBase does, we can formulate the following correct rules:

RewriteBase must match the path from the site root to .htaccess. You only need to start redirections with "/" when you need to specify the absolute path from the site root to the file.

What happens if you don't specify RewriteBase? By default Apache makes it equal absolute path on file system to.htaccess (for example /var/www/example.com/templates/). The incorrectness of this Apache assumption is manifested in external relative redirects:

# Request http://example.com/index.php # DocumentRoot: /var/www/example.com/ # .htaccess is at the root of the site and does NOT have a RewriteBase specified. # Therefore, by default, RewriteBase is equal to the absolute path to.htaccess: /var/www/example.com/ # The input RewriteRule is "index.php" RewriteRule ^index.php main.php [R] # The output is "index.php" " -> "main.php" # mod_rewrite remembered that an external redirect is needed # RewriteRule ran out # mod_rewrite still executes RewriteBase, since it has a default value. # It turns out: "main.php" -> "/var/www/example.com/main.php" # Here mod_rewrite remembers that there was an external redirect: # "/var/www/example.com/main.php" - > http://example.com/var/www/example.com/main.php # It turned out not at all what they had in mind.

So, the request went through all the RewriteRules, after which, if necessary, a RewriteBase was added to it. Should Apache now serve the file that the resulting path points to? No. Now the resulting request will be processed again.

How mod_rewrite works. Flag [L]

mod_rewrite starts processing the request over and over until it stops changing. And the flag [L] can't stop it.

When creating more or less complex mod_rewrite configurations, it is important to understand that query modification does not end at last RewriteRule. After the last RewriteRule has fired and a RewriteBase has been added, mod_rewrite looks to see if the request has changed or not. If the request has changed, its processing starts again from the beginning.htaccess.

Apache does this because in the process of changing the request, it may have been redirected to another directory. It may have its own .htaccess that was not involved in the previous request processing. This new .htaccess may contain rules that affect the processing of the request - both mod_rewrite rules and rules of other modules. To handle this situation correctly, Apache must restart the entire processing loop.

Wait, but there is a flag [L], which stops processing the mod_rewrite request!

Not certainly in that way. Flag [L] stops the current iteration of request processing. However, if the request was modified by those RewriteRules that still managed to process, Apache will start the request processing cycle again from the first RewriteRule.

# Request: http://example.com/a.html RewriteBase / RewriteRule ^a.html$ b.html [L] RewriteRule ^b.html$ a.html [L]

The example above will result in an infinite loop of redirects and " Internal Server Error" in the end. In this example, the infinite loop is obvious, but in more complex configurations you may need to dig into the rules to determine which requests are looping between each other.

To avoid such situations, it is recommended to use the [L] flag only when necessary. The need can be of two types: When an external redirect is used - or . In the case of an external redirect, further processing of the request is undesirable (see below about the flag [R]), and it's better to stop it. When there is a loop in .htaccess that cannot be eliminated, and processing of the request by mod_rewrite must be forcibly stopped. In this case, a special construction is used - see tips on this topic at the end of the article.

But the example below will not loop. Try to determine why and which file will be given to Apache in the end.

# Request: http://example.com/a.html # Start.htaccess RewriteBase / RewriteRule ^a.html$ b.html RewriteRule ^b.html$ a.html # End.htaccess

Solution: As a result of executing all RewriteRules, the request changes in such a way that final result equal to the original one. Apache sees this and does not re-process the request. The a.html file will be returned.

How mod_rewrite works. Flag [R]

    Flag [R] does not stop request processing, returning an external redirect immediately. Instead, it remembers the need for an external redirect, and processing the request continues with the following RewriteRule. It is recommended to always use with the flag [L].

    Flag [R] tells Apache that it needs to perform an external redirect rather than an internal one. What is the difference between an external redirect and an internal one? An internal redirect simply changes the path to the file that will be given to the user, while the user believes that he is receiving the file that he originally requested. With an external redirect, Apache returns the response status 301 or 302 to the user instead of the contents of the file and informs the user of the link that the browser should use to get the file.

It would seem that when processing the flag [R] Apache should immediately stop processing the RewriteRule and return the external redirect to the user. However, let's remember the fantastic example from the How RewriteRule Works section. In it we first indicated the flag [R], indicating the need for an external redirect, after which they continued to change the link with the following RewriteRule.

This is exactly how Apache works when specifying an external redirect. It simply “notes” to itself that after executing all the rules it is necessary to return status 302 (default), but at the same time continues executing all RewriteRules further down the list. We can continue to change the request as we need, the only thing that won’t work is making the redirect back internal.

However, it is unlikely that you want to change it in any way after sending an external redirect. Therefore, it is recommended when using the flag [R] indicate it together with [L]:

# BlackJack has moved to the beautiful name RewriteRule ^bj/(.*) blackjack/$1 # You can just use the external link RewriteRule ^bj/(.*) http://blackjack.example.com/$1 [L]

Instead of using a flag [R] You can simply provide an external link. In this case, Apache itself will guess that it is necessary to make an external redirect. Here, as in the case of explicitly specifying the flag [R], it is recommended to use the flag [L]. If an external redirect leads to the same site, it is better to use the flag [R] without indication full link(in other words, use a relative external redirect). This will make the rule independent of the site name. If an external redirect leads to another site, this cannot be done otherwise than by specifying a full external link.

How mod_rewrite works. Specifying request parameters and flag

Changing the query parameters in a RewriteRule does not change the row that the next RewriteRule operates on. However, changing the parameters changes the %(QUERY_STRING) variable that RewriteCond can work with.

Terminology used: “parameters” - request parameters, “arguments” - RewriteRule arguments.

Using RewriteRule, you can change not only the path to the file that will be processed, but also the parameters GET request which will be transmitted to him. This is often used to transfer NC processing to a generic handler script, eg: RewriteBase /

# Request: http://example.com/news/2010/07/12/grand-opening.html # Input: "news/2010/07/12/grand-opening.html" RewriteRule ^news/(.* )$ index.php?act=news&what=$1 # After RewriteRule: "news/2010/07/12/grand-opening.html" -> "index.php" # %(QUERY_STRING): "" -> "act= news&what=2010/07/12/grand-opening.html"

The moment the RewriteRule encounters a question mark in its second argument, it knows that the parameters in the request are being modified. What happens as a result is that RewriteRule replaces the string it is working with with part of the second argument before question mark. Please note that the new request parameters do not end up in the string that subsequent RewriteRules will work on. The part of the second argument after the question mark ends up in the %(QUERY_STRING) variable. If a flag was specified , the query parameters will be added to the beginning of %(QUERY_STRING). If the flag was not specified, %(QUERY_STRING) will be completely replaced by the query parameters from the RewriteRule. A couple more examples:

RewriteBase / # Request: http://example.com/news/2010/?page=2 # Input RewriteRule: "news/2010/" RewriteRule ^news/(.*)$ index.php?act=news&what=$1 # After conversion: "news/2010/" -> "index.php" # Value %(QUERY_STRING): "page=2" -> "act=news&what=2010/" Most likely, the rule above does not work correctly, as it is lost argument page. Let's fix this: RewriteBase / # Request: http://example.com/news/2010/?page=2 # Input RewriteRule: "news/2010/" RewriteRule ^news/(.*)$ index.php?act= news&what=$1 # After conversion: "news/2010/" -> "index.php" # Value %(QUERY_STRING): "page=2" -> "act=news&what=2010/&page=2"

It is important to understand that changing the query parameters changes the %(QUERY_STRING) which can be used later in RewriteCond. This must be taken into account when writing subsequent rules that check arguments.

Of course, it changes, because the request is sent for re-processing by Apache!

No, %(QUERY_STRING) changes immediately. I won’t give a proof - more has already been written about parameters than is interesting to read :)

What can you do to check in RewriteCond exactly those request parameters that were passed by the user, and not those modified by RewriteRules? See the tips at the end of the article.

RewriteCond and performance

First, the match of the request with the RewriteRule is checked, and only then - additional conditions RewriteCond.

A few words should be said about the order in which mod_rewrite executes directives. Since .htaccess comes with RewriteCond first and then RewriteRule, it seems that mod_rewrite checks all the conditions first and then starts executing the RewriteRule.

In fact, everything happens the other way around. First, mod_rewrite checks whether the current request value matches the regular expression RewriteRule, and only then it will check all the conditions listed in RewriteCond.

So if you have a two-page regular expression in your RewriteRule and, thinking about performance, you decide to limit the execution of this rule to additional RewriteConds, you should know that nothing will work. In this case, it is better to use the RewriteRule [C] or [S] flags to skip more complicated rule, if more simple checks didn't work.

RewriteCond variables and flags, other RewriteRule flags, etc.

Read the documentation.

We got acquainted with the principles of operation of RewriteRule, RewriteBase, flags [L], [R] And , and also analyzed the request processing mechanism inside mod_rewrite. The following remained unaffected: other RewriteRule flags, RewriteCond and RewriteMap directives.

Fortunately, these directives and flags are not fraught with any mystery and work exactly as described in most tutorials. To understand them, just read the official documentation. First of all, I recommend studying the list of variables that can be checked in RewriteCond - %(QUERY_STING), %(THE_REQUEST), %(REMOTE_ADDR), %(HTTP_HOST), %(HTTP:header), etc.)

Difference in how mod_rewrite works in the .htaccess context and in the VirtualHost context

In the context mod_rewrite works exactly the opposite.

As I said at the beginning of the article, everything described above concerns the use of mod_rewrite in the .htaccess context. If mod_rewrite is used in , it will work differently: In the RewriteRule includes the entire request path, starting from the first slash and ending with the beginning GET parameters: "http://example.com/some/news/category/post.html?comments_page=3" → "/news/category/post.html". This line always starts with /. The second argument of RewriteRule must also start with /, otherwise it will be "Bad Request". RewriteBase doesn't make sense. Passing the rules occurs only once. Flag [L] actually finishes processing all the rules described in , without any further iterations.

Writing Regular Expressions

Try to compose regular expressions so that they most narrowly define exactly those queries that you want to modify - so that the RewriteRule rules do not accidentally work for another query. For example:

# Start all regular expressions with "^" (the beginning of a line) # and end with "$" (the end of a line): RewriteRule ^news.php$ index.php # Even if this is not necessary - for versatility and better understanding of the configuration: RewriteRule ^news/(.*)$ index.php # If only numbers should be included in the mask, specify this explicitly. # If some numbers are constant, specify them explicitly. # If slashes cannot be present in the rest of the request, limit their presence. # Don't forget to escape "." (dots). # The following rule targets requests like http://example.com/news/2009/07/28/b-effect.html RewriteRule ^news/20(2)/(2)/(2)/[^/]+ \.html index.php

However, there is a whole section on regular expressions on one well-known website.

Changing external redirects

Despite the fact that mod_rewrite allows you to change even external redirects using RewriteRule, right down to the protocol, I strongly do not recommend doing this. In the article, the example of changing external redirects is used only to get rid of such concepts as “links” and “files” and more clearly show that RewriteRule works with a simple string.

I don’t think the mod_rewrite developers intended that anyone would do this, so all sorts of artifacts are possible. Don't do this please.

How to stop an infinite loop

Sometimes the logic of redirects on a site is such that without special actions, mod_rewrite perceives them as an endless loop of redirects. Let's take the following example.

The site had a page /info.html. The SEO specialist decided that search engines will index this page better if it is called /information.html and asked for an external redirect from info.html to information.html. However, for some reason, the site developer cannot simply rename info.html to information.html and make a redirect - he needs the data to be sent directly from the info.html file. He writes the following rule: # make an external redirect RewriteRule ^info.html information.html # but upon request /information.html still give info.html RewriteRule ^information.html info.html

... and encounters an infinite loop. Every /information.html request gets an external redirect back to /information.html.

This problem can be solved in at least two ways. One of them has already been described on Habré - you need to set an environment variable and stop redirections based on its value. The code will look like this:

RewriteCond %(ENV:REDIRECT_FINISH) !^$ RewriteRule ^ - [L] RewriteRule ^info.html$ information.html RewriteRule ^information.html$ info.html

Note that mod_rewrite appends "REDIRECT_" to the variable name.

The second way is to check in THE_REQUEST what exactly was requested by the user:

# External redirect only happens if the user requested info.html. # If info.html is the result of an internal redirect, the rule will not fire. RewriteCond %(THE_REQUEST) "^(GET|POST|HEAD) /info.html HTTP/+$" RewriteRule ^info.html$ information.html RewriteRule ^information.html$ info.html

Analyzing the original user request - combating Apache link disclosure

When processing a request, Apache expands the URL-encoded characters from the original request. In some cases, this may not be desirable - the developer wants to check exactly the original, unmodified user request. This can be done by checking the %(THE_REQUEST) variable in RewriteCond:

RewriteCond %(THE_REQUEST) ^GET[\ ]+/tag/([^/]+)/[\ ]+HTTP.*$ RewriteRule ^(.*)$ index.php?tag=%1 [L]

Htaccess is optional configuration file Apache, which allows you to configure the web server for each individual directory without affecting global ones Apache settings. Local analogy httpd.conf. Typically he is responsible for redirects and directory access control.

The name begins with a dot. We can say that this is an untitled file with the htaccess extension.

The .htaccess settings affect the directory in which it is located and all child directories. Create a file and place it in the directory you need. For example, to the root of the project.

Now you need to fill it. Let's see what .htaccess can do, but first, let's study an example of a simple redirect.

mod_rewrite and redirects

Make sure that in the configuration Apache filehttpd.conf activated mod_rewrite. That is, the corresponding line is uncommented:

LoadModule rewrite_module modules/mod_rewrite.so

Or, if you don't want to open in text editor file, you can use the command in the terminal:

Sudo a2enmod rewrite

mod_rewrite is an Apache module designed to rewrite URLs. Let's look at an example of how it works. Let's say the user enters the following address:

Using mod_rewrite you can send content from a different URL, like this:

Http://www.example.com/public/src/view/page.html

Why do we need this? It’s easy to guess that writing the full path to a page is long and simply inconvenient. Site visitors do not need to think about the internal structure of the site - what is important for them is to get to the page they are looking for as quickly as possible.

IN address bar the user will still see what he entered:

http://www.example.com/page.html

This is an example of the simplest redirect.

Straight to practice

Let's analyze the configuration file used in one of our projects. This way we will understand which line to edit if problems arise.

Php_value short_open_tag 1 php_value upload_max_filesize 10M php_value post_max_size 10M RewriteEngine On RewriteBase / RewriteRule ^(application|modules|system) - RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php/$0

  • php_value setting string and numerical values
  • php_flag sets boolean values ​​(yes/no)

General directive syntax

Php_value/php_flag directive_name php flag/value

Directive short_open_tag allows the use of a short syntax for formatting PHP code:

Php_value short_open_tag 1

upload_max_filesize defines maximum size downloaded file.

Php_value upload_max_filesize 10M

A post_max_size sets the maximum allowed size of data sent POST method.

Php_value post_max_size 10M

RewriteEngine

Turns the mechanism on/off mod_rewrite.

RewriteEngine On

RewriteRule

RewriteRule simply transforms the string according to regular expressions.

Syntax: RewriteRule regular_expression

# Input RewriteRule "index.php" RewriteRule ^index.php main.php [R] # Output: "index.php" -> "main.php"

We converted index.php to main.php and performed the redirect.

Important: RewriteRule usually takes two arguments: What needs to be replaced and for what need to replace. If we don’t need to perform the replacement, we can write it in the form:

The "-" symbol means "do not convert"

RewriteBase

After all RewriteRules, RewriteBase comes into force. If the resulting query after transformations is relative and different from the original one, RewriteBase will restore it, making it absolute. RewriteBase will simply append itself to the request on the left. Because the RewriteBase value is the path from the site root to .htaccess. In our case, .htaccess is located right in the root, so:

Syntax: RewriteBase URL-path-from-.htaccess-file-to-site-root

For example:

# .htaccess is located in /dir/ # Path from the site root to .htaccess /dir/ RewriteBase /dir/ # Request http://example.com/dir/logo.gif # The RewriteRule input is "logo.gif" RewriteRule ^ logo.gif$ logo-orange.gif # After RewriteRule: "logo.gif" -> "logo-orange.gif" # After RewriteBase: "logo-orange.gif" -> "/dir/logo-orange.gif"

Regular expressions

Regular Expressions, which you may encounter in .htaccess.

Symbol Meaning Example
. Any one symbol c.t is cat, cot, cut, etc.
+ One or more identical characters a+ is a, aa, aaa, etc.
* Zero or several identical characters a* works the same as a+ but in the case of a* the empty string will satisfy the condition
? Match optional colou?r will suit both color and colour.
^ The symbol from which begins line ^a matches a string that starts with a
$ The symbol that ends line a$ matches a string that ends with a .
() Finds and remembers matches groups characters.

Can also be used for Back-Reference(see example)

(ab)+ will satisfy ababab

Back-Reference example:

RewriteRule ^/ (+) /(.*) $ /home?page= $1 &id= $2

/album/123 → /home?page= album&id= 123

One of possible characters ct is suitable cut , cot or cat.

More regular expressions

Flags

Syntax: RewriteRule regular_expression [flag1,flag2,flag3]

Flag Description
[F] Forbidden- returns error 403 Forbidden.
[L] Last- stop the transformation process at this point and do not apply any more transformation rules.
Query String Append- this flag indicates to the conversion mechanism to add, not replace,query strings from URL to existing,in the substitution string.
PassThrough- stops the conversion process and transmits the received new link further down the chain.
[R] Redirect- stops the conversion process and returns the result to the client browser as a redirect to a new page.
[S] Skip- skips the next rule if the current rule is triggered. You can specify the number of subsequent rules to ignore.

When creating a console application in the C++ programming language, a line very similar to this is automatically created:

Int main(int argc, char* argv) // main() function parameters

This line is the header main function main() , the parameters argс and argv are declared in parentheses. So, if you run a program via the command line, then it is possible to transfer some information to this program, for this there are parameters argc and argv. The argc parameter is of type data int, and contains the number of parameters passed to the main function. Moreover, argc is always at least 1, even when we do not pass any information, since the first parameter is the name of the function. The argv parameter is an array of pointers to strings. Only string data can be passed through the command line. Pointers and strings are two big themes for which separate sections. So it is through the argv parameter that any information is transmitted. Let's develop a program that we will launch through the command line Windows string, and give her some information.

// argc_argv.cpp: Defines the entry point for the console application. #include "stdafx.h" #include using namespace std; int main(int argc, char* argv) ( if (argc ><< argv<

// code Code::Blocks

// Dev-C++ code

// argc_argv.cpp: Defines the entry point for the console application. #include using namespace std; int main(int argc, char* argv) ( if (argc > 1) // if we pass arguments, then argc will be greater than 1 (depending on the number of arguments) ( cout<< argv<

After we have debugged the program, open the Windows command line and drag the executable file of our program into the command line window. The full path to the program will be displayed in the command line (but you can enter the path to the program manually), after which you can click ENTER and the program will start (see Figure 1).

Figure 1 - Main function parameters

Since we simply ran the program and did not pass any arguments to it, the Not arguments message appeared. Figure 2 shows the launch of the same program via the command line, but passing it the Open argument.

Figure 2 - Main function parameters

The argument is the word Open, as can be seen from the figure, this word appeared on the screen. You can pass several parameters at once, separating them with a comma. If you need to pass a parameter consisting of several words, then they must be enclosed in double quotes, and then these words will be considered as one parameter. For example, the figure shows the launch of a program, passing it an argument consisting of two words - It work.

Figure 3 - Main function parameters

And if you remove the quotes. Then we will see only the word It. If you do not plan to pass any information when running the program, you can remove the arguments in the main() function, and you can also change the names of these arguments. Sometimes modifications to the argc and argv parameters are encountered, but this all depends on the type of application being created or on the development environment.

Borland C++ supports three arguments to main(). The first two are the traditional argc and argv. These are the only arguments to main() defined by the ANSI C standard. They allow command line arguments to be passed to the program. Command line arguments are the information that follows the program name on the operating system command line. For example, when a program is compiled using the Borland line compiler, it is typically typed bcc program_name

Where program_name is a program that needs to be compiled. The program name is passed to the compiler as an argument.

The argc parameter contains the number of command line arguments and is an integer. It is always equal to at least 1, since the program name qualifies as the first argument. The argv parameter is a pointer to an array of character pointers. Each element of this array points to a command line argument. All command line arguments are strings. All numbers are converted by the program into internal format. The following program prints "Hello" followed by the username when typed directly after the program name:

#include

{
if(argc!=2)
{
printf("You forgot to type your name\n");
return 1;
}
printf("Hello %s", argv);
return 0;
}

If you call this program name, and the user name is Sergey, then to start the program you should type:
name Sergey.
As a result of the program the following will appear:
"Hello Sergey."

Command line arguments must be separated by spaces or tabs. Commas, semicolons, and similar characters are not considered delimiters. For example:

Consists of three lines, while

Herb,Rick,Fred

This is one line - commas are not delimiters.

If you need to pass a string containing spaces or tabs as a single argument, you must enclose it in double quotes. For example, this is one argument:

"this is a test"

It is important to declare argv correctly. The most typical method is:

Empty parentheses indicate that the array does not have a fixed length. You can access individual elements using argv indexing. For example, argv points to the first line, which always contains the program name. argv points to the next line and so on.

Below is a small example of using command line arguments. It counts down from the value specified on the command line and emits a signal when it reaches zero. Note that the first argument contains a number converted to an integer using the standard atoi() function. If the string "display" is present as the second argument, then the counter itself will be displayed on the screen.

/* counting program */

#include
#include
#include
int main(int argc, char *argv)
{
int disp, count;
if(argc<2)
{
printf("You must enter the length of the count\n");
printf("on the command line. Try again.\n");
return 1;
}
if (argc==3 && !strcmp(argv,"display")) disp = 1;
else disp = 0;
for(count=atoi(argv); count; -count)
if (disp) printf("%d ", count);
printf("%c", "\a"); /* on most computers this is a call */
return 0;
}

Please note that if no arguments are specified, an error message appears. This is most typical for programs that use command line arguments to issue instructions if an attempt was made to run the program without the correct information.

To access individual command line characters, add a second index to argv. For example, the following program prints out all the arguments it was called with, one character at a time:

#include
int main(int argc, char *argv)
{
int t, i;
for(t=0; t {
i = 0;
while(argv[t][i])
{
printf("%c", argv[t][i]);
}
printf(" ");
}
return 0;
}

We must remember that the first index is for accessing a string, and the second is for accessing a character in a string.

Typically argc and argv are used to obtain source commands. It is theoretically possible to have up to 32767 arguments, but most operating systems don't even allow you to get close to that. Typically these arguments are used to specify a file name or options. Using command line arguments gives the program a professional look and allows the program to be used in batch files.

If you include the WILDARGS.OBJ file supplied with Borland C++, you can use templates in *.EXE type arguments. (Borland C++ automatically handles wildcards and increments argc accordingly.) For example, if you connect WILDARGS.OBJ to the following program, it will tell you how many files match the filename specified on the command line:

/* Link this program with WILDARGS.OBJ */

#include
int main(int argc, char *argv)
{
register int i;
printf("%d files match specified name\n", argc-1);
printf("They are: ");
for(i=1; i printf("%s ", argv[i]);
return 0;
}

If we call this program WA, then run it as follows, we will get the number of files with the EXE extension and a list of the names of these files:

In addition to argc and argv, Borland C++ also provides a third command line argument -env. The env parameter allows a program to access information about the operating system environment. The env parameter must follow argc and argv and is declared as follows:

As you can see, env is declared in the same way as argv. Just like argv, it is a pointer to an array of strings. Each line is an environment string defined by the operating system. The env parameter has no equivalent argc parameter that tells how many environment rows there are. Instead, the last line of the environment is null. The following program prints all the environment strings currently defined in the operating system:

/* this program displays all the environment lines */

#include
int main(int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]/ t++)
printf("%s\n", env[t]);
return 0;
}

Please note that although argc and argv are not used by the program, they must be present in the parameter list. C doesn't know the parameter names. Instead, their use is determined by the order in which the parameters are declared. In fact, you can call the parameter whatever you like. Since argc, argv, and env are traditional names, it is best to continue to use them so that anyone reading the program can instantly understand that these are arguments to the main() function.

A typical task for programs is to look up a value defined in an environment string. For example, the contents of the PATH line allow programs to use search paths. The following program demonstrates how to find strings that declare standard search paths. It uses the standard library function strstr(), which has the following prototype:

Char *strstr(const char *str1, const char *str2);

The strstr() function searches for the string pointed to by str1 in the string pointed to by str2. If such a string is found, a pointer to the first position is returned. If no matches are found, the function returns NULL.

/* the program searches among the environment strings for a line containing PATH */

#include
#include
int main (int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]; t++)
{
if(strstr(env[t], "PATH"))
printf("%s\n", env[t]);
}
return 0;
}







2024 gtavrl.ru.