1. Trang chủ
  2. » Công Nghệ Thông Tin

php solutions dynamic web design made easy phần 5 pdf

48 295 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 48
Dung lượng 762,5 KB

Nội dung

// convert the maximum size to KB $max = number_format(MAX_FILE_SIZE/1024, 1).'KB'; // create an array of permitted MIME types $permitted = array('image/gif', 'image/jpeg', 'image/pjpeg', ➥ 'image/png'); foreach ($_FILES['image']['name'] as $number => $file) { // replace any spaces in the filename with underscores $file = str_replace(' ', '_', $file); // begin by assuming the file is unacceptable $sizeOK = false; $typeOK = false; // check that file is within the permitted size if ($_FILES['image']['size'][$number] > 0 || ➥ $_FILES['image']['size'][$number] <= MAX_FILE_SIZE) { $sizeOK = true; } // check that file is of a permitted MIME type foreach ($permitted as $type) { if ($type == $_FILES['image']['type'][$number]) { $typeOK = true; break; } } if ($sizeOK && $typeOK) { switch($_FILES['image']['error'][$number]) { case 0: // check if a file of the same name has been uploaded if (!file_exists(UPLOAD_DIR.$file)) { // move the file to the upload folder and rename it $success = move_uploaded_file($_FILES['image'] ➥ ['tmp_name'][$number], UPLOAD_DIR.$file); } else { // get the date and time ini_set('date.timezone', 'Europe/London'); $now = date('Y-m-d-His'); $success = move_uploaded_file($_FILES['image'] ➥ ['tmp_name'][$number], UPLOAD_DIR.$now.$file); } if ($success) { $result[] = "$file uploaded successfully"; } else { $result[] = "Error uploading $file. Please try again."; } break; UPLOADING FILES 175 6 7311ch06.qxd 10/10/06 10:38 PM Page 175 case 3: $result[] = "Error uploading $file. Please try again."; default: $result[] = "System error uploading $file. Contact ➥ webmaster."; } } elseif ($_FILES['image']['error'][$number] == 4) { $result[] = 'No file selected'; } else { $result[] = "$file cannot be uploaded. Maximum size: $max. ➥ Acceptable file types: gif, jpg, png."; } } } ?> The key line in this code is line 13, which looks like this: foreach ($_FILES['image']['name'] as $number => $file) { When two files are uploaded simultaneously, the name part of the array looks like this: $_FILES['image']['name'][0] = basin.jpg; $_FILES['image']['name'][1] = monk.jpg; By looping through $_FILES['image']['name'], on the first iteration $number is 0 and $file is basin.jpg. The next time the loop runs, $number is 1 and $file is monk.jpg. This does the same as the following line in the original script: $file = $_FILES['image']['name']; The added bonus is that $number gives you access to the other parts of the $_FILES array. When $number is 0, $_FILES['image']['size'][$number] gives you the size of basin.jpg, and on the second pass through the loop, the size of monk.jpg. Consequently, you need to add [$number] at the end of each reference to the $_FILES array to access the details of the current file. The only other changes are that the code to remove spaces from filenames is now inside the loop and square brackets have been added to $result to turn it into an array. 2. Since $result is an array, you need to loop through it in the main body of the page to let users know the outcome of each upload. The revised code looks like this: if (isset($result)) { echo '<ol>'; foreach ($result as $item) { echo "<strong><li>$item</li></strong>"; } echo '</ol>'; } PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 176 7311ch06.qxd 10/10/06 10:38 PM Page 176 This produces a numbered list of results as shown in the screenshot to the right. Thanks to the use of a foreach loop, this script can handle as many files as you like. However, you need a separate file input field for each file. You should also beware of exceeding any limits imposed by the server configuration as listed in Table 6-1. Points to watch with file uploads Uploading files from a web form is easy with PHP. The main causes of failure are not set- ting the correct permissions on the upload directory or folder, and forgetting to move the uploaded file to its target destination before the end of the script. Letting other peo- ple upload files to your server, however, exposes you to risk. In effect, you’re allowing vis- itors the freedom to write to your server’s hard disk. It’s not something you would allow strangers to do on your own computer, so you should guard access to your upload direc- tory with the same degree of vigilance. Ideally, uploads should be restricted to registered and trusted users, so the upload form should be in a password-protected part of your site. Also, the upload folder does not need to be inside your site root, so locate it in a private directory whenever possible unless you want uploaded material to be displayed immediately in your web pages. Remember, though, there is no way PHP can check that material is legal or decent, so immediate pub- lic display entails risks that go beyond the merely technical. You should also bear the fol- lowing security points in mind: Set a maximum size for uploads both in the web form and on the server side. Make sure you’re dealing with a genuine uploaded file by using move_uploaded_file() instead of copy(). Otherwise, sensitive files, such as your server’s password file, might be copied to a public folder. PHP has a function called is_uploaded_file(), which can be used to verify a gen- uine upload, but move_uploaded_file() is sufficient on its own because it checks the status of a file before moving it. Restrict the types of uploaded files by inspecting the MIME type in the $_FILES array. Adopt a naming policy, such as adding a timestamp to filenames or using the consecutive series solution in the next chapter, to prevent existing files being overwritten. Replace spaces in filenames with underscores or hyphens. Follow these guidelines, and your upload scripts should remain secure. One final thought: don’t forget to inspect your upload folder on a regular basis. Make sure there’s nothing in there that shouldn’t be, and do some housekeeping from time to time. Even if you limit file upload sizes, you may run out of your allocated space without realizing it. UPLOADING FILES 177 6 7311ch06.qxd 10/10/06 10:38 PM Page 177 7311ch07.qxd 10/10/06 11:09 PM Page 178 7 USING PHP TO MANAGE FILES 7311ch07.qxd 10/10/06 11:09 PM Page 179 What this chapter covers: Reading and writing files Listing the contents of a folder Automatically naming the next file in a series Opening remote data sources Creating a download link PHP has a huge range of functions designed to work with the server’s file system, but find- ing the right one for the job isn’t always easy. This chapter cuts through the tangle to show you some practical uses of these functions, such as reading and writing text files to store small amounts of information without a database. I’ll also show you how to create a drop- down menu that lists all images in a folder, automatically name the next file in a series, and prompt a visitor to download an image or PDF file rather than open it in the browser. As with file uploads in the previous chapter, setting the correct permissions is crucial to success in using many of the file management functions. Unfortunately, hosting companies often impose limits on their use. So, I’ll begin with a quick overview of some of the restric- tions you need to be aware of. Checking that PHP has permission to open a file As you saw in Chapter 4, a PHP script has the ability to open another file and include the content as its own. In a default PHP configuration, the file doesn’t even need to be on the same server; as long as PHP can find the file and open it, the contents of both files are merged. This is an extremely powerful concept, which—sadly—is open to misuse. As a result, you must have the right permissions to open a file. This affects not only the file sys- tem functions that are the main focus of this chapter, but also any function that opens another file, among them include(), require(), and simplexml_load_file(). As I explained in the previous chapter, PHP runs on most Linux servers as nobody or apache. Consequently, a folder must have minimum access permissions of 755 for scripts to open a file. If you also want your scripts to create or alter files, you normally need to set global access permissions of 777, the least secure setting. If PHP is configured to run in your own name, you can be more restrictive, because your scripts can create and write to files in any folder for which you have read, write, and execute permissions. On a Windows server, you need write permission to create or update a file. Configuration settings that affect file access Hosting companies can impose further restrictions on file access through php.ini. To find out what restrictions have been imposed, run <?php phpinfo(); ?> on your website, and check the settings in PHP Core. Table 7-1 lists the settings you need to check and notes changes planned in PHP 6. PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 180 7311ch07.qxd 10/10/06 11:09 PM Page 180 Table 7-1. PHP configuration settings that affect file access Directive Default value Description allow_url_fopen On Allows PHP scripts to open public files anywhere on the Internet. Prior to PHP 6, if allow_url_fopen is enabled, remote files can also be used as include files. allow_url_include Off New in PHP 6. Controls the ability to include remote files. Disabled by default. open_basedir no value Restricts accessible files to the specified directory tree. Even if no value is set, restrictions may be set directly in the server configuration. safe_mode Off Mainly restricts the ability to use certain functions (for details, see www.php.net/ manual/en/features.safe-mode. functions.php). Removed from PHP 6. safe_mode_include_dir no value If safe_mode is enabled, user and group ID checks are skipped when files are included from the specified directory tree. Arguably the most important of these settings is allow_url_fopen. If it’s disabled, you are prevented from accessing useful external data sources, such as news feeds and public XML documents. Fortunately, you can get around this problem by creating a socket connection, as shown in PHP Solution 7-5. Hopefully, the decision to create a separate allow_url_include directive in PHP 6 will encourage hosting companies to reverse any restrictions on the use of allow_url_fopen. If the Local Value column displays a setting for open_basedir or safe_mode_include_dir, the meaning depends on whether the value ends with a trailing slash, like this: /home/includes/ If it does, it means you are restricted to opening or including files from the specified direc- tory or any of its subdirectories. If the value doesn’t have a trailing slash, it acts as a prefix. For example, /home/inc gives you access to /home/inc, /home/includes, /home/incredible, and so on—assuming, of course, that they exist or you have the right to create them. Creating a file storage folder for local testing It should be obvious that storing data inside your site root is highly insecure, particularly if you need to set global access permissions on the folder. If you have access to a private folder outside the site root, create your data store as a subfolder and give it the necessary permissions. USING PHP TO MANAGE FILES 181 7 7311ch07.qxd 10/10/06 11:09 PM Page 181 For the purposes of this chapter, I suggest that Windows users create a folder called private on their C drive. Mac users should create a private folder inside their home folder, and then set Read & Write permissions in Get Info as shown in Figure 6-3 in the pre- vious chapter. Reading and writing files The restrictions described in the previous section reduce considerably the attraction of reading and writing files with PHP. Using a database is more convenient and offers greater security. However, that assumes you have access to a database and the necessary knowl- edge to administer it. So, for relatively small-scale data storage and retrieval, working directly with text files is worth considering. It’s also useful to know how PHP interacts with external files, because you can use the same techniques to inspect the contents of a folder or prompt a user to download a file. Reading files in a single operation Since PHP 4.3.0, the simplest way to read the entire contents of a text file is to use the file_get_contents() function. 1. Create a text file in your private folder, type some text into it, and save it as filetest01.txt (or use the version in the download files). 2. Create a new folder called filesystem in your phpsolutions site root, and create a PHP file called file_get_contents.php in the new folder. Insert the following code inside a PHP block (the download file file_get_contents01.php shows the code embedded in a web page, but you can use just the PHP for testing purposes): echo file_get_contents('C:/private/filetest01.txt'); If you’re on a Mac, amend the pathname like this, using your own Mac username: echo file_get_contents('/Users/username/private/filetest01.txt'); If you’re testing on a remote server, amend the pathname accordingly. 3. Save file_get_contents.php and view it in a browser. Depending on what you wrote in filetest01.txt, you should see some- thing like the screenshot to the left. For brevity, the remaining code examples in this chapter show only the Windows pathname. PHP Solution 7-1: Reading a text file into a string PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 182 7311ch07.qxd 10/10/06 11:09 PM Page 182 When testing on your local system, you shouldn’t see any error messages, unless you typed the code incorrectly or you did not set the correct permissions on a Mac. However, on a remote system, you may see error messages similar to this: The error messages in the preceding screenshot were created on a local system to demonstrate what happens when open_basedir has been set either in php.ini or on the server. It means that you are trying to access a file outside your permitted file structure. The first error message should indicate the allowed paths. On a Windows server, each path is separated by a semicolon. On Linux, the separator is a colon. Another possible cause of errors on a remote server is the use of spaces or illegal characters in the names of files or folders. Never use spaces in filenames on the Web. 4. At this stage, using file_get_contents() looks no different from using an include command. However, file_get_contents() treats the external file as a string, which means that you can store the contents in a variable and manipulate it in a way that’s impossible with an include file. Change file_get_contents.php like this (or use file_get_contents02.php) and load the page into a browser: $contents = file_get_contents('C:/private/filetest01.txt'); // convert contents to uppercase and display echo strtoupper($contents); The result should look like the screenshot to the right: Admittedly, this is a trivial example, but it means that you can use any of PHP’s string functions to format the contents of an external file or to search for specific information with regular expressions and pat- tern matching functions. 5. A danger with an external file is that you may not be able to open it: the file might be missing, its name misspelled, or the network connection down. Change the code like this (it’s in file_get_contents03.php): $contents = file_get_contents('C:/private/filetest01.txt'); if ($contents === false) { echo 'Sorry, there was a problem reading the file.'; } else { // convert contents to uppercase and display echo strtoupper($contents); } USING PHP TO MANAGE FILES 183 7 7311ch07.qxd 10/10/06 11:09 PM Page 183 If the file_get_contents() function can’t open the file, it returns false. Often, you can test for false by using the negative operator like this: if (!$contents) { The reason I haven’t used that shortcut here is because the external file might be empty, or you might want it to store a number. As explained in “The truth accord- ing to PHP” in Chapter 3, an empty string and 0 also equate to false. So, in this case, I’ve used the identical operator (three equal signs), which ensures that both the value and the data type are the same. 6. Test the page in a browser, and it should work as before. Change the first line like this so that it loads filetest02.txt: $contents = file_get_contents('C:/private/filetest02.txt'); The new text file contains the number 0, which should display correctly when you test file_get_contents.php. Delete the number in filetest02.txt, and reload file_get_contents.php. You should get a blank screen, but no error message. This indicates that the file was loaded successfully, but doesn’t contain anything. 7. Change the first line in file_get_contents.php so that it attempts to load a non- existent file, such as filetest0.txt. When you load the page, you should see an ugly error message reporting that file_get_contents() “failed to open stream”— in other words, it couldn’t open the file. 8. This is an ideal place to use the error control operator (see Chapter 4). Insert an @ mark immediately in front of the call to file_get_contents() like this: $contents = @ file_get_contents('C:/private/filetest0.txt'); 9. Test file_get_contents.php in a browser. You should now see only the following custom error message: Text files can be used as a flat-file database—where each record is stored on a separate line, with a tab, comma, or other delimiter between each field (see http://en.wikipedia.org/ wiki/Flat_file_database). When handling this sort of file, it’s more convenient to store each line individually in an array ready for processing with a loop. The PHP file() function builds the array automatically. Always add the error control operator only after testing the rest of a script. When devel- oping, error messages are your friends. You need to see them to understand why some- thing isn’t working the way you expect. PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 184 7311ch07.qxd 10/10/06 11:09 PM Page 184 [...]... 7-1 PHP makes light work of creating a drop-down menu of images in a specific folder PHP Solution 7-3: Using the buildFileList() function 1 Create a PHP page called imagelist .php in the filesystem folder If you just want to study the code, use either imagelist _php5 .php or imagelist _php4 .php from the download files, depending on the version of PHP running on your server 2 Copy buildFileList5 .php (for PHP. .. the download files, depending on the version of PHP running on your server 2 Copy buildFileList5 .php (for PHP 5) or buildFileList4 .php (for PHP 4) to your includes folder 197 7311ch07.qxd 10/10/06 11:10 PM Page 198 PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 3 Create a form inside imagelist .php, and insert a element with just one like this: . need to check and notes changes planned in PHP 6. PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 180 7311ch07.qxd 10/10/06 11:09 PM Page 180 Table 7-1. PHP configuration settings that affect file. examples in this chapter show only the Windows pathname. PHP Solution 7-1: Reading a text file into a string PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 182 7311ch07.qxd 10/10/06 11:09 PM Page 182 When. $tmp[0], 'password' => rtrim($tmp[1])); PHP SOLUTIONS: DYNAMIC WEB DESIGN MADE EASY 186 7311ch07.qxd 10/10/06 11:10 PM Page 186 5. As always, you need to check that the file is accessible

Ngày đăng: 14/08/2014, 11:21