Computers Windows Internet

What is the difference between HTTP_HOST and SERVER_NAME in PHP? PHP $ _SERVER Global Array Retrieving Environment Variable HTTP_X_FORWARDED_FOR

$ _SERVER is one of the most important predefined arrays in PHP. It contains the variables received from the server by the PHP interpreter. Everyone used these variables, or will definitely use them, since without them it is rather difficult to organize full support for web applications.

In my article, I propose a table with the main variables of the $ _SERVER superglobal array. The table is similar to the one made for PHP string functions.

To view all the elements of the $ _SERVER array, you need to: a) either call the print_r () function, which will print the array; b) either call the phpinfo () function, which will display information about the PHP interpreter.

Briefly about $ HTTP_SERVER_VARS

The $ _SERVER superglobal array replaces the $ HTTP_SERVER_VARS array in PHP 4.1.0. $ HTTP_SERVER_VARS not used now, but it's worth knowing about it. First of all, the old version was not autoglobal. The second difference is that some elements of the $ _SERVER array do not exist in $ HTTP_SERVER_VARS, although in most cases their variables are the same.

Element

Short description

Example

$ _SERVER ["DOCUMENT_ROOT"]

Contains the path to the root directory of the server.

$ _SERVER ["HTTP_HOST"]

$ _SERVER ["SERVER_NAME"]

$ _SERVER ["SCRIPT_FILENAME"]

Contains the name of the script, starting from the root directory of the virtual host.

C: \ folder \ index.php

/www/folder/index.php

$ _SERVER ["PHP_SELF"]

$ _SERVER ["SCRIPT_NAME"]

Contains the name of the script.

$ _SERVER ["REQUEST_URI"]

Contains the name of the script, starting from the root directory of the firm's host, as well as the parameters passed to it by the GET method.

/www/folder/index.php?page=2&num=5

$ _SERVER ["QUERY_STRING"]

Contains parameters passed to the script by the GET method.

For address

http://site.com/index.php?page=2&num=5

will be output

$ _SERVER ["REQUEST_METHOD"]

Contains the request method that is used to invoke the script.

GET or POST

$ _SERVER ["HTTP_REFERER"]

Contains the address of the page from which the visitor came.

http://yandex.ru/yandsearch

$ _SERVER ["HTTP_USER_AGENT"]

Contains the type and version of the visitor's browser and operating system. It can also detect search robots and the brand of a cell phone. Below is a comparison of the phone brand and its cipher in a string.

Nokia - NOKIA; Sony Ericsson - ERICSSON or SONYERICSSON; Samsung - SAMSUNG or SEC-; Motorola - MOT; LG - LG or LG-; Alcatel - ALCATEL; Panasonic - PANASONIC; Sagem - SAGEM; Pantech - PANTECH; Siemens - SIE; BenQ - BENQ; NEC - NEC; Sharp - SHARP.

Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1) ( IE 6andWindows XP)

Mozilla / 4.0 (compatible; MSIE 7.0; Windows NT 5.0) Opera 9.50 ( Opera 9.5andWindows 2000)

$ _SERVER ["REMOTE_ADDR"]

Contains the client's IP address.

$ _SERVER ["SERVER_ADDR"]

Contains the IP address of the server.

$ _SERVER ["HTTP_ACCEPT"]

Describes the client's preference for document type. The content of this element is retrieved from the Accept HTTP header passed to the server by the client.

Output format: MIME type [[; q], another MIME type [; q] ...]

There can be several preferred MIME types, then they are separated by commas. * is used to set a template, grouping. q - preference coefficient, by default 1, ranges from 0 to 1.

image / jpeg, image / x-xbitmap, application / x-shockwave-flash

image / *; q = 0.5, image / jpeg (prefers zhpeg to all other formats)

$ _SERVER ["HTTP_ACCEPT_LANGUAGE"]

Similar to the previous element, but related to language preferences. Can be used to determine the nationality of visitors. But the estimate will be approximate, since some people like to use English versions of browsers

ru, en; q = 0.9 (preference for Russian, but if it is not there - and English will do)

$ _SERVER ["HTTP_ACCEPT_CHARSET"]

Similar to the previous ones. Contains the Accept-Charset header

$ _SERVER ["HTTP_ACCEPT_ENCODING"]

Similar to the previous ones. Contains the Accept-Encoding header

$ _SERVER ["SERVER_PORT"]

Contains the server listening port.

$ _SERVER ["SERVER_SOFTWARE"]

Contains information about the web server.

Apache / 2.2.4 (Win32)

$ _SERVER ["SERVER_PROTOCOL"]

Contains the version of the HTTP protocol.

$ _SERVER ["GATEWAY_INTERFACE"]

Contains the version of the CGI used by the web server.

$ _SERVER ["REQUEST_TIME"]

The start time of the web page request in UNIX format. Available since PHP 5.1.0

Full address of the page with parameters:

echo "http: //" .SERVER_NAME. $ _ SERVER ["REQUEST_URI"];
?>

The table with all functions can be downloaded from the link in * .doc format.

Pay special attention to the $ _SERVER ["REQUEST_URI"] variable and don't forget to check it! The fact is that its use may not be particularly safe. For example, on your site, some urls are generated using this parameter. Then you can write the link http://site.com/index.php in the browser line? ”>... This will bring up a window showing the contents of the cookie file. This example is harmless, but it is a hole through which a hacker can exploit the breach, for example, to steal data from another user. Therefore - check the variable for invalid characters, especially> and<.

For today, perhaps, everything. Until next time and happy weekend!

JavaScript is blocked in your browser. Please enable JavaScript for the site to work!

Superglobal array $ _SERVER

Into an array $ _SERVER The PHP interpreter puts in the variables received from the server. Without these variables, it is difficult to provide full support for Web applications. The following is a description of the most important elements of the superglobal array $ _SERVER.

Comment

  • View the complete list of $ _SERVER array elements
  • you can either use the print_r () function, which prints a dump of the array, or using the phpinfo () function, which displays information about the PHP interpreter.

    Array (=> on => 200 => on => htmlweb.ru => https => 443 => close => Mozilla / 5.0 (compatible; Googlebot / 2.1; + http: //www.google.com/bot. html) => * / * => beget = begetok; => gzip, deflate => / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin = > => Apache / 2.4.25 (Debian) mpm-itk / 2.4.7-04 OpenSSL / 1.0.2l => htmlweb.ru => 185.12.92.137 => 80 => 144.76.78.4 => / var / www / htmlweb / data / www / htmlweb.ru => http => => /var/www/htmlweb/data/www/htmlweb.ru => [email protected]=>. php => 35242 => /php/function/$_server.php => CGI / 1.1 => HTTP / 1.0 => GET => => /php/function/%24_server.php => /index.php => /index.php => 1560059525.711 => 1560059525) 1

    $ _SERVER [" DOCUMENT_ROOT"]

    The $ _SERVER ["DOCUMENT_ROOT"] element contains the path to the root directory of the server, if the script is executed in a virtual host, this element contains the path to the root directory of the virtual host. Those. in the httpd.conf configuration file the virtual host has the DocumentRoot directive, which is assigned the value "D: / main", the $ _SERVER ["DOCUMENT_ROOT"] element will contain the value "D: main".

    $ _SERVER [" REMOTE_ADDR"]

    The $ _SERVER ["REMOTE_ADDR"] element contains the client's IP address. When testing on a local machine, this address will be 127.0.0.1. However, when testing on the network, the variable will return the IP address of the client or the last proxy server through which the client got to the server. If the client uses a proxy server, you can find out its IP address using the HTTP_X_FORWARDED_FOR environment variable, the value of which can be obtained using the getenv () function.

    Comment

    Proxy servers are special intermediate servers that provide a special type of service: traffic compression, data encryption, adaptation for mobile devices, etc. Among the many proxy servers, so-called anonymous proxy servers are distinguished, which allow you to hide the true IP address of the client; such servers do not return the HTTP_X_FORWARDED_FOR environment variable.

    Extracting an environment variable HTTP_X_FORWARDED_FOR

    echo @getenv (HTTP_X_FORWARDED_FOR);

    $ _SERVER [" SCRIPT_FILENAME"]

    The $ _SERVER ["SCRIPT_FILENAME"] element contains the absolute path to the file from the root of the disk. So, if the server is running under the Windows operating system, then this path may look like this "d: main estindex.php", i.e. the path is specified from the disk, in a UNIX-like operating system, the path is specified from the root directory /, for example, "/var/share/www/test/index.php".

    /var/www/htmlweb/data/www/site/index.php

    $ _SERVER [" SERVER_NAME"]

    The $ _SERVER ["SERVER_NAME"] element contains the server name, as a rule, the same as the domain name of the site located on it. For example,

    The content of the $ _SERVER ["SERVER_NAME"] element is often the same as the content of the $ _SERVER ["HTTP_HOST"] element. In addition to the server name, the $ _SERVER superglobal array allows you to find out a number of server parameters, for example, the server's IP address, listening port, which Web server is installed, and the version of the HTTP protocol. This information is placed in $ _SERVER ["SERVER_ADDR"], $ _SERVER ["SERVER_PORT"], $ _SERVER ["SERVER_SOFTWARE"], and $ _SERVER ["SERVER_PROTOCOL"], respectively. Below is an example using these items.

    Using the elements of the $ _SERVER array

    echo "Server name is". $ _ SERVER ["SERVER_NAME"]. "
    "; echo" Server IP is ". $ _ SERVER [" SERVER_ADDR "]."
    "; echo" Server port is ". $ _ SERVER [" SERVER_PORT "]."
    "; echo" Web server - ". $ _ SERVER [" SERVER_SOFTWARE "]."
    "; echo" HTTP protocol version - ". $ _ SERVER [" SERVER_PROTOCOL "]."
    ";

    Server name - site
    Server IP - 185.12.92.137
    Server port - 80
    Web server - Apache / 2.4.25 (Debian) mpm-itk / 2.4.7-04 OpenSSL / 1.0.2l
    HTTP protocol version - HTTP / 1.0

    $ _SERVER [" REQUEST_METHOD"]

    The $ _SERVER ["REQUEST_METHOD"] element contains the request method that is used to call the script: GET or POST.

    Echo $ _SERVER ["REQUEST_METHOD"];

    $ _SERVER [" QUERY_STRING"]

    The $ _SERVER ["QUERY_STRING"] element contains the parameters passed to the script if the query string is an address

    For example, when referring to:
    the $ _SERVER ["QUERY_STRING"] element will contain all the text after the "?" sign:

    Echo $ _SERVER ["QUERY_STRING"];

    id = 1 & test = wet & id_theme = 512

    $ _SERVER [" PHP_SELF"]

    The $ _SERVER ["PHP_SELF"] element contains the name of the script, starting from the root directory of the virtual host, i.e. if the query string is an address http://www.mysite.ru/test/index.php?id=1&test=wet&id_theme=512 then the $ _SERVER ["PHP_SELF"] element will contain a snippet "/test/index.php"... Typically, the same fragment is placed in the $ _SERVER ["SCRIPT_NAME"] element.

    $ _SERVER [" REQUEST_URI"]

    The element $ _SERVER ["REQUEST_URI"] contains the name of the script, starting from the root directory of the virtual host and parameters, ie if the query string is an address: http://www.mysite.ru/test/index.php?id=1&test=wet&id_theme=512 then the $ _SERVER ["REQUEST_URI"] element will contain a snippet "/test/index.php?id=1&test=wet&id_theme=512"... In order to restore the full address in the script, which is placed in the query line, it is enough to use the combination of elements of the $ _SERVER array, presented below

    Full address to the script

    echo "http: //". $ _ SERVER ["SERVER_NAME"]. $ _ SERVER ["REQUEST_URI"];
    • Translation
    • Tutorial

    One of the coolest new features in php 5.4 is the built-in server built specifically for development and testing. Now you can write and test your code without having a full web server - just start the embedded server, test your code, and shut it down when you're done.
    The server also provides an opportunity for creative use. For example, you can distribute a portable web application on CD or USB, or even as a desktop application built in PHP without using GTK or other graphics libraries.

    The PHP manual emphasizes that the built-in server is intended for development and it is recommended not to use it on a production server. There are no INI directives responsible for the server (except for the colorization of the output in the console), and it seems that the main idea of ​​the documentation is: "We now also have a Web server, leave us alone."
    Regardless, I believe that embedded server can be a valuable development and testing tool. For example, on my machine I am using pre-installed Apache with a custom configuration that suits me, but sometimes I want to try some new Web applications. With the embedded web server, I can test the application directly from the downloads folder or temp folder and move it to my normal environment only when needed.
    But for starters, it's not that easy, as many applications written use .htaccess and mod_rewrite. But I'm sure someone (maybe one of you, why not?) Will write an adapter for this, and I would like to be the first to test it.
    In this article, I will explain some basic examples of using the embedded server and show you how to make it useful for development and testing.

    We use the built-in server

    So, to use the server, we need php 5.4 or higher. To check your PHP version, run:
    php -v
    You can also determine if the server is available in your assembly by running:
    php -h
    and look there for a description of the "-S" and "-t" options, which are only used for the server.
    To check the server, you can create an index.php file in the current directory, which will contain a call to the phpinfo () function and then start the server:
    $ php -S 127.0.0.1:8080 PHP 5.4.0RC7 Development Server started at Fri Feb 26 18:49:29 2012 Listening on 127.0.0.1:8080 Document root is / home / ec2-user Press Ctrl-C to quit.
    And now you can see the content served by the embedded web server:

    Each client request will be written to the console:
    80.180.55.37:36318 : / 80.180.55.37:36584 : /
    Coming back, let's take a look at the "-S" command line parameter, which is used to specify the address from which the server will be accessible. Possible values:
    localhost- the server will be accessible only from the local machine,
    0.0.0.0 - on any interface of the machine,
    Any external or gray IP- only on the specified IP
    The -t option sets the specified directory root. For example:
    $ php -S : 8090 -t / home / ec2-user / public
    Besides,. you can specify the name of a specific router file. For example:
    $ php -S> localhost or your public IP>: 8080 -t / home / ec2-user / public public / index.php
    The output of this router will be parsed and executed by the server. Simple example:
    Welcome to PHP

    ";
    If the script returns FALSE, then the requested URI will be processed by the server, which will issue the requested resource, or will return a 404 error. If the script returns anything else, the script's output will be passed to the client.
    While this approach gives us more control, there are a few things you should know. First, the PHP server only sends a minimal set of HTTP headers:
    Connection: closed Content-Type: text / html Host: aws-dev-01.vtardia.com X-Powered-By: PHP / 5.4.0RC7 D
    Compare this to the headers returned by the Apache server:
    Accept-Ranges: bytes Connection: Keep-Alive Content-Length: 631 Content-Type: text / html Date: Sat, 04 Feb 2012 18:24:42 GMT Etag: "bbb99-277-4ace8c5470a40" Keep-Alive: timeout = 15, max = 100 Last-Modified: Wed, 14 Sep 2011 15:54:09 GMT Server: Apache / 2.2.21 (Unix) DAV / 2
    If your application uses headers, then it must account for the difference in development and production environments.
    Secondly, the embedded server has a different SAPI (Server API). Thus, by performing routing in index, php, you can define a call to the script on the test or production server. php_sapi_name () will return "cli-server" on the embedded server:
    There is one special INI directive called "cli_server.color". This directive returns colored output to the console. Create an empty file named cli-server.ini and insert this line:
    cli_server.color = on
    You can create a unique environment configuration for your server by specifying the necessary directives in your INI file. Undeclared directives will accept their default values. Now we have declared only one directive - cli_server.color.
    Start the server with the "-c" parameter specifying the INI file:
    $ php -S localhost -c cli-server.ini
    If your terminal supports colors, then you should be able to see the "colored" output in the console. 200 status will be highlighted in green, 404 in orange, and script errors will be highlighted in red.

    We create a personal server

    Now that you know everything there is to know about an embedded server, let's do something cool. Let's create our own portable server!
    I'll start with the following structure for our application:

    The library folder contains the application code, public is the root directory, contains index.php and some static files. This tutorial will focus on the "server" folder, so our application will consist of a simple "Hello Word!" and a few pictures and css.
    Our goal is to be able to start the server from the application directory with one command, and our server will take care of routing, HTTP headers and errors.
    $ ./start.sh
    Let's take a look at the startup script:
    #! / bin / bash INIFILE = "$ (pwd) /server/server.ini" DOCROOT = "$ (pwd) / public" ROUTER = "$ (pwd) /server/router.php" HOST = 0.0.0.0 PORT = 8080 PHP = $ (which php) if [$? ! = 0]; then echo "Unable to find PHP" exit 1 fi $ PHP -S $ HOST: $ PORT -c $ INIFILE -t $ DOCROOT $ ROUTER
    I am assuming that the script is run from the application directory, so INIFILE, DOCROOT, ROUTER are defined using pwd. The path to php is determined using the which command. If php was not found in the user's $ PATH, then the script will fail with an error.
    This works well enough, but let's give the user the ability to change any of the given parameters from the command line, for example:
    if [! -z $ INIFILE]; then INIFILE = "$ (pwd) /server/server.ini" fi
    Continuing, the "errors" folder contains files for HTTP error messages. Here's an example about a 403 error: although I used only HTML, the script will be included, I use include so you can use any php code:
    403

    403: Forbidden

    Sorry, the requested resource is not accessible.



    Now let's take a look at router.php. The task of this file is to receive and manage all requests and transfer them to the server only if this file exists. All error pages are displayed by connecting the template.
    In the first lines, I define some global parameters such as DIRECTORY_INDEX, the directory with error templates. The date_default_timezone_set () parameter must match the OS settings, otherwise there will be inconsistencies between the entries in the log and on the server. I also added a list of allowed IP addresses to improve security.
    The logAccess () function is necessary because when the routing script accepts a request, the server log is ignored by default. The function only accepts a status code, and the output format is fully consistent with the server format.
    Our first task is to check security. If the client's IP is not in the array of allowed IPs, display an error message and exit the script. We need to give a status code other than 200 and the header () function will not work here, so we use a new function - http_response_code.
    If the client's IP is in the array of allowed IPs, then our next step is to get the requested path and file extension. If the extension is empty, we assume that the user is requesting a folder and build the path using the DIRECTORY_INDEX defined first.
    Finally, if the requested file exists, return FALSE and let the server access the file. If not, then a 404 error message is displayed.

    Summary

    It's all. As you can see, the php server is easy to use. Our personal server is very simple. The code can be optimized and incorporated into more complex and functional classes. Happy coding!

    p.s. I will gladly accept criticism and comments to the translation in a personal.

    And that is what the client actually used as the "target host" of the request. SERVER_NAME is defined in the server configuration. Which one depends on what you need it for. You should now understand that this is a client controlled value, which thus cannot be reliable for use in business logic, and the other is a server controlled value that is more reliable. However, you need to make sure that the web server has the correct SERVER_NAME configuration. Taking Apache HTTPD as an example, here's an excerpt from its documentation:

    If ServerName is not specified, then the server tries to infer the hostname by doing a reverse lookup on the IP address. If no port is specified in ServerName, then the server will use the port from the incoming request. For optimal reliability and predictability, you must specify an explicit hostname and port using the ServerName directive.

    Refresh: after checking Pekka's answer to your question which contains a link to bobince's answer that PHP will always return the HTTP_HOST value for SERVER_NAME, which is contrary to my own PHP 4.x + Apache HTTPD 1.2.x experience from a couple of years ago, I blew the dust off of my current XAMPP on Windows XP (Apache HTTPD 2.2.1 with PHP 5.2.8), ran it, created a PHP page that prints both values, created a Java test application using URLConnection to change the Host header, and the tests taught me that this is indeed (false) the case.

    After first suspecting PHP and digging into some PHP error reporting on the subject, I found out that the root of the problem is on the web server in use, that it did not correctly return the HTTP Host header when SERVER_NAME was requested. So I dug into Apache HTTPD error reporting using various keywords regarding the subject, and I finally found a related error. This behavior has been introduced since around Apache HTTPD 1.3. You need to set the UseCanonicalName directive on in the entry ServerName in httpd.conf (also check the warning at the bottom of the doc!).

    ServerName example.com UseCanonicalName on

    This worked for me.

    Generalized, SERVER_NAME is more reliable, but you dependent in the server configuration!

    HTTP_HOST is the target host sent by the client. The user is free to manipulate the user. It is not necessary to send a request to your site with an HTTP_HOST request for the value of www.stackoverflow.com.

    SERVER_NAME comes from the definition of the VirtualHost server and is therefore considered more reliable. It can also be manipulated externally under certain conditions related to setting up your web server. See This This SO question which deals with the safety aspects of both options.

    You don't have to rely on to be safe. However, which one to use really depends on what you want to do. If you want to determine which domain your script is running on, you can safely use HTTP_HOST as long as invalid values ​​coming from an attacker cannot break anything.

    Note that if you want to use IPv6, you probably want to use HTTP_HOST and not SERVER_NAME. If you enter http: // [:: 1] /, the environment variables are as follows:

    HTTP_HOST = [:: 1] SERVER_NAME = :: 1

    This means that if you do mod_rewrite, for example, you might get a nasty result. SSL redirect example:

    # SERVER_NAME will NOT work - Redirection to https: // :: 1 / RewriteRule. * Https: //% (SERVER_NAME) / # HTTP_HOST will work - Redirection to https: // [:: 1] / RewriteRule. * Https: //% (HTTP_HOST) /

    This ONLY applies if you are accessing the server without a hostname.

    if you want to check through server.php or what you want to call with the following:

    Then access all valid urls for your site and check the difference.

    It took me a while to figure out what people mean by "SERVER_NAME more reliable". I am using a shared server and have no access to the virtual host directives. So, I am using mod_rewrite in .htaccess to map different HTTP_HOSTs in different directories. In this case, this HTTP_HOST value makes sense.

    The situation is similar if you are using name-based virtual hosts: the ServerName directive inside a virtual host simply says which hostname will be mapped to that virtual host. The bottom line is that in both cases, the hostname provided by the client during the request (HTTP_HOST) must match the name on the server, which itself maps to the directory. Whether the mapping is done with virtual host directives or with htaccess mod_rewrite rules is secondary here. In these cases, HTTP_HOST will be the same as SERVER_NAME. I'm glad Apache is configured this way.

    However, the situation is different from IP based virtual hosts. In this case, and only in this case, SERVER_NAME and HTTP_HOST can be different, because now the client selects the server by IP, not by name. Indeed, there may be special configurations where this is important.

    So from now on I'll be using SERVER_NAME in case my code gets pushed into these special configurations.

    Assuming you have a simple setup (CentOS 7, Apache 2.4.x and PHP 5.6.20) and only one website (no shared hosting) ...

    In the PHP sense, $ _SERVER ["SERVER_NAME"] is a PHP element registered in the $ _SERVER superclass based on your Apache configuration (** ServerName ** directive with UseCanonicalName On) in httpd.conf (whether from an enabled virtual host configuration file, whatever, etc.). HTTP_HOST is deduced from the HTTP host header. Treat it like user input. Filter and check before use.

    Here's an example where I am using $ _SERVER ["SERVER_NAME"] as the basis for my comparison. The next method is for a specific child class, which I named ServerValidator (a child of Validator). ServerValidator validates six or seven items in $ _SERVER before using them.

    When determining if an HTTP request is a POST, I use this method.

    Public function isPOST () (return (($ this-> requestMethod === "POST") && // Ignore $ this-> hasTokenTimeLeft () && // Ignore $ this-> hasSameGETandPOSTIdentities () && // Ingore ($ this -> httpHost === filter_input (INPUT_SERVER, "SERVER_NAME")));)

    By the time this method is called, all filtering and validation of the corresponding $ _SERVER elements (and their corresponding property sets) will be done.

    ($ this-> httpHost === filter_input (INPUT_SERVER, "SERVER_NAME")

    Checks that the value of $ _SERVER ["HTTP_HOST"] (ultimately derived from the requested HTTP host header) matches $ _SERVER ["SERVER_NAME"].

    Now I'm using superglobal conversation to explain my example, but that's because some people aren't familiar with INPUT_GET, INPUT_POST, and INPUT_SERVER in relation to filter_input_array ().

    The bottom line is that I don't process POST requests on my server unless all four conditions are met. Hence, in terms of POST requests, refusing to provide HTTP host header (presence checked for earlier) doom spells for strict browsers HTTP 1.0... In addition, the requested host must match the value ServerName in httpd.conf, and by extension - the value of $ _SERVER ("SERVER_NAME") in the $ _SERVER supermacle. Again, I would use INPUT_SERVER with PHP filter functions, but you were breaking my drift.

    As pointed out by balusC, SERVER_NAME is not reliable and can be changed in apache config, server config and firewall that may be between you and the server.

    The following function always returns the real host (user typed host) without a port, and it is almost reliable:

    Function getRealHost () (list ($ realHost,) = explode (":", $ _ SERVER ["HTTP_HOST"]); return $ realHost;)

    to share

    To begin with, we will improve the registration page by adding the ability to upload an avatar. The original image must be in jpg, gif or png format. Also, it should be no more than 2 MB. Don't worry, after compressing it with a script, the avatar will be about 3 kb in size and in jpg format. Open the page reg.php and add in the tag < form> line enctype = "multipart / form-data" as in the example:


    registration










    Now we save reg.php

    2.Then you need to create another field in the table users... Go to phpmyadmin, select the required base and table.


    We set all the values, as in the picture:

    The path to the avatar will be written in this field, and it will be saved in a separate folder, let's call it "avatars". The folder will be located in the same directory as the rest of the script files.

    3.Go to the file save_ user. php and add the following code after removing the spaces from the login and password:

    // remove extra spaces
    $ login = trim ($ login);

    // add a new one *******************************************

    // add a check for the length of the login and password
    if (strlen ($ login)< 3 or strlen($login) > 15) {
    exit ("Login must be at least 3 characters and no more than 15.");
    }
    if (strlen ($ password)< 3 or strlen($password) > 15) {
    exit ("The password must be at least 3 characters and no more than 15.");
    }

    if (! empty ($ _ POST ["fupload"])) // check if the user has posted an image
    {
    $ fupload = $ _ POST ["fupload"]; $ fupload = trim ($ fupload);
    if ($ fupload == "" or empty ($ fupload)) (
    unset ($ fupload); // if the $ fupload variable is empty, then remove it
    }
    }
    if (! isset ($ fupload) or empty ($ fupload) or $ fupload == "")
    {
    // if the variable does not exist (the user did not send the image), then assign it a pre-prepared image with the inscription "no avatar"
    $ avatar = "avatars / net-avatara.jpg"; // you can draw net-avatara.jpg or take in source
    }
    else
    {
    // otherwise - load the user image
    $ path_to_90_directory = "avatars /"; // folder where the initial image and its compressed copy will be loaded

    If (preg_match ("/ [.] (JPG) | (jpg) | (gif) | (GIF) | (png) | (PNG) $ /", $ _ FILES ["fupload"] ["name"])) // check the format of the original image
    {
    $ filename = $ _FILES ["fupload"] ["name"];
    $ source = $ _FILES ["fupload"] ["tmp_name"];
    $ target = $ path_to_90_directory. $ filename;
    move_uploaded_file ($ source, $ target); // upload the original to the $ path_to_90_directory folder
    if (preg_match ("/ [.] (GIF) | (gif) $ /", $ filename)) (
    $ im = imagecreatefromgif ($ path_to_90_directory. $ filename); // if the original was in gif format, then create an image in the same format. Required for subsequent compression
    }
    if (preg_match ("/ [.] (PNG) | (png) $ /", $ filename)) (
    $ im = imagecreatefrompng ($ path_to_90_directory. $ filename); // if the original was in png format, then create an image in the same format. Required for subsequent compression
    }

    If (preg_match ("/ [.] (JPG) | (jpg) | (jpeg) | (JPEG) $ /", $ filename)) (
    $ im = imagecreatefromjpeg ($ path_to_90_directory. $ filename); // if the original was in jpg format, then create an image in the same format. Required for subsequent compression
    }
    // CREATION OF A SQUARE IMAGE AND ITS FOLLOWING COMPRESSION TAKEN FROM THE SITE www.codenet.ru
    // Create a 90x90 square
    // dest - the resulting image
    // w - image width
    // ratio - aspect ratio
    $ w = 90; // square 90x90. Other sizes can be supplied.
    // create the original image based on
    // source file and determine its size
    $ w_src = imagesx ($ im); // calculate the width
    $ h_src = imagesy ($ im); // calculate the height of the image
    // create an empty square image
    // it is truecolor! that is important !, otherwise we will have an 8-bit result
    $ dest = imagecreatetruecolor ($ w, $ w);
    // cut out the square center at x if the photo is horizontal
    if ($ w_src> $ h_src)
    imagecopyresampled ($ dest, $ im, 0, 0,
    round ((max ($ w_src, $ h_src) -min ($ w_src, $ h_src)) / 2),
    0, $ w, $ w, min ($ w_src, $ h_src), min ($ w_src, $ h_src));
    // cut out the square top at y,
    // if the photo is vertical (although the middle is also possible)
    if ($ w_src<$h_src)
    imagecopyresampled ($ dest, $ im, 0, 0, 0, 0, $ w, $ w,
    min ($ w_src, $ h_src), min ($ w_src, $ h_src));
    // the square picture is scaled without clippings
    if ($ w_src == $ h_src)
    imagecopyresampled ($ dest, $ im, 0, 0, 0, 0, $ w, $ w, $ w_src, $ w_src);
    $ date = time (); // calculate the time at the moment.
    imagejpeg ($ dest, $ path_to_90_directory. $ date. ". jpg"); // save the jpg image to the desired folder, the name will be the current time. Made so that avatars do not have the same name.
    // why jpg? It takes up very little space + the animation of the gif image, which distracts the user, is destroyed. It is not very pleasant to read his commentary when you notice some movement out of the corner of your eye.
    $ avatar = $ path_to_90_directory. $ date. ". jpg"; // enter the path to the avatar into the variable.
    $ delfull = $ path_to_90_directory. $ filename;
    unlink ($ delfull); // delete the original uploaded image, we no longer need it. The task was to get a miniature.
    }
    else
    {
    // in case of format mismatch, issue an appropriate message
    exit ("The avatar must be in the format JPG, GIF or PNG");
    }
    // the end of the loading process and assigning the $ avatar variable to the address of the loaded avatar
    }



    // added a new one *******************************************
    // Then everything from the first part of the article follows, but it is necessary to add the change to the request to the database.
    // connect to the database
    // check for the existence of a user with the same login
    $ result = mysql_query ("SELECT id FROM users WHERE login =" $ login "", $ db);
    if (! empty ($ myrow ["id"])) (
    exit ("Sorry, the username you entered is already registered. Please enter another username.");
    }
    // if not, then save the data
    $ result2 = mysql_query ("INSERT INTO users (login, password, avatar) VALUES (" $ login "," $ password "," $ avatar ")");
    // Check if there are any errors
    if ($ result2 == "TRUE")
    {
    echo "You have successfully registered! You can now visit the site. Home page";
    }
    else (
    echo "Error! You are not registered.";
    }
    ?>

    4. It is necessary to add one table to the same database. It will store the ip-addresses that made mistakes when entering. Thus, we will be able to restrict access to those who have made a mistake more than three times in a row for 15 minutes. I think the programs that guess passwords will have to mess around for a long time.
    Go to phpmyadmin and create a new table with 3 fields:


    ip - ip-address.
    date - the date of unsuccessful login for the last 15 minutes for the user with the given ip. col - the number of errors for the last 15 minutes for the user with the given ip.
    Fine! Done, now let's change the login and password verification file, because now our password is encrypted. Open testreg.php and delete everything further than removing spaces from the login and password. Next, add the following code:

    // remove extra spaces
    $ login = trim ($ login);
    $ password = trim ($ password);

    // replace with a new *******************************************
    // connect to the database
    include ("bd.php"); // bd.php file must be in the same folder as everyone else, if it is not, then just change the path
    // mini-check for password guessing
    $ ip = getenv ("HTTP_X_FORWARDED_FOR");
    if (empty ($ ip) || $ ip == "unknown") ($ ip = getenv ("REMOTE_ADDR");) // retrieve ip
    mysql_query ("DELETE FROM oshibka WHERE UNIX_TIMESTAMP () - UNIX_TIMESTAMP (date)> 900"); // delete the ip-addresses of the users who logged in error after 15 minutes.
    $ result = mysql_query ("SELECT col FROM oshibka WHERE ip =" $ ip "", $ db); // retrieve from the database the number of unsuccessful login attempts for the last 15 user with the given ip
    $ myrow = mysql_fetch_array ($ result);
    if ($ myrow ["col"]> 2) (
    // if there are more than two errors, i.e. three, then issue a message.
    exit ("You typed your login or password incorrectly 3 times. Wait 15 minutes before the next attempt.");
    }
    $ password = md5 ($ password); // encrypt the password
    $ password = strrev ($ password); // add a reverse for safety
    $ password = $ password. "b3p6f";
    // you can add several of your characters to your liking, for example, by typing "b3p6f". If this password is cracked by the brute-force method on their own server with the same md5, then obviously nothing good will come of it. But I advise you to put other characters, you can at the beginning of a line or in the middle.
    // In this case, it is necessary to increase the length of the password field in the database. The encrypted password can be much larger.

    $ result = mysql_query ("SELECT * FROM users WHERE login =" $ login "AND password =" $ password "", $ db); // retrieve from the database all data about the user with the entered username and password
    $ myrow = mysql_fetch_array ($ result);
    if (empty ($ myrow ["id"]))
    {
    // if the user with the entered username and password does not exist
    // Make a note that the given ip could not enter.
    $ select = mysql_query ("SELECT ip FROM oshibka WHERE ip =" $ ip "");
    $ tmp = mysql_fetch_row ($ select);
    if ($ ip == $ tmp) (// check if the user is in the "oshibka" table
    $ result52 = mysql_query ("SELECT col FROM oshibka WHERE ip =" $ ip "", $ db);
    $ myrow52 = mysql_fetch_array ($ result52);
    $ col = $ myrow52 + 1; // add another failed login attempt
    mysql_query ("UPDATE oshibka SET col = $ col, date = NOW () WHERE ip =" $ ip "");
    }
    else (
    mysql_query ("INSERT INTO oshibka (ip, date, col) VALUES (" $ ip ", NOW ()," 1 ")");
    // if there were no errors in the last 15 minutes, then insert a new record into the "oshibka" table
    }

    exit ("Sorry, the username or password you entered is incorrect.");
    }
    else (
    nbsp; // if the passwords match, then we start a session for the user! You can congratulate him, he entered!
    $ _SESSION ["password"] = $ myrow ["password"];
    $ _SESSION ["login"] = $ myrow ["login"];
    $ _SESSION ["id"] = $ myrow ["id"]; // this data is very often used, so the logged in user will "carry with him"

    // Next, we remember the data in cookies, for subsequent login.
    //ATTENTION!!! DO IT AT YOUR DISCEPT AS THE DATA IS STORED IN COOKIES WITHOUT ENCRYPTION
    if ($ _POST ["save"] == 1) (
    // If the user wants his data to be saved for the next login, then we save it in the cookies of his browser
    setcookie ("login", $ _POST ["login"], time () + 9999999);
    setcookie ("password", $ _POST ["password"], time () + 9999999);
    }}
    echo " "; // redirect the user to the main page, there he will be informed about a successful login
    ?>

    5. Completely change the main page. It is necessary to display the user's avatar on it, display a link to log out of the account and add a checkbox to remember the password when logging in.
    Index.php

    // the whole procedure works on sessions. It is in it that the user's data is stored while he is on the site. It is very important to run them at the very beginning of the page !!!
    session_start ();
    include ("bd.php"); // bd.php file must be in the same folder as everyone else, if it is not, then just change the path
    if (! empty ($ _ SESSION ["login"]) and! empty ($ _ SESSION ["password"]))
    {
    // if there is a login and password in sessions, then we check them and retrieve the avatar
    $ login = $ _SESSION ["login"];
    $ password = $ _SESSION ["password"];
    $ result = mysql_query ("SELECT id, avatar FROM users WHERE login =" $ login "AND password =" $ password "", $ db);
    $ myrow = mysql_fetch_array ($ result);
    // retrieve the required user data
    }
    ?>


    Home page


    Home page

    if (! isset ($ myrow ["avatar"]) or $ myrow ["avatar"] == "") (
    // check if the user data has been retrieved from the database. If not, then he did not enter, or the password in the session is incorrect. We display the login window. But we will not display it for those who have entered, they no longer need it.
    print<<


    HERE;

    If (isset ($ _ COOKIE ["login"])) // is there a variable with login in COOKIE. Should be if the user at the previous login clicked on the "Remember me" checkbox
    {
    // if yes, then insert its value into the form. In this case, the user is shown that his login has already been entered in the required column
    echo "value =" ". $ _ COOKIE [" login "]." ">";
    }

    print<<




    HERE;

    If (isset ($ _ COOKIE ["password"])) // is there a variable with a password in the COOKIE. Should be if the user at the previous login clicked on the "Remember me" checkbox
    {
    // if yes, then insert its value into the form. In this case, the user is shown that his password has already been entered in the required column
    echo "value =" ". $ _ COOKIE [" password "]." ">";
    }

    Print<<



    Remember me.






    Register now



    You are logged in as a guest

    HERE;
    }
    else
    {
    // upon successful login, the user is given everything below between the asterisks.

    print<<
    You are logged into the site as $ _SESSION (logout)


    This link is only available to registered users

    Your avatar:




    HERE;

    //************************************************************************************
    // on successful login, the user is given everything ABOVE between the asterisks.
    }
    ?>



    6. It is necessary to make it possible to log out of the account for users who are logged in. There was already an exit link on the main page. But this file does not exist yet. So let's create a new file exit.php with code:

    session_start ();
    if (empty ($ _ SESSION ["login"]) or empty ($ _ SESSION ["password"]))
    {
    // if there is no session with username and password, then an unlocked user got to this file. He doesn't belong here. We issue an error message, stop the script
    exit ("Access to this page is allowed only to registered users. If you are registered, then enter the site using your username and password
    Home page ");
    }

    unset ($ _ SESSION ["password"]);
    unset ($ _ SESSION ["login"]);
    unset ($ _ SESSION ["id"]); // destroy variables in sessions
    exit (" ");
    // send the user to the main page.
    ?>

    So that is all! Use it to your health! Good luck!