Archive

Archive for the ‘PHP’ Category

How to Make a Link Automatically Start to Download a File Using Content-Disposition Header

July 21st, 2010 admin No comments

Sometimes we want to have a link to a file that rather than open the audio file/image/pdf and display in the browser, to have it automatically download the file to the user’s machine without requiring them to right click and “save as.” Some call this a “force download” link. The way this is done is to modify the headers of the page.

You might be looking for something to put into the <a > tag, but unfortunately it’s a little more complicated than that. Instead of pointing the link directly to the file, point it to a php file with an argument for the file to download. Something like this:

<a href='download.php?file=test_file.pdf'>Download</a>

In the download.php file, a couple headers need to be defined in order to ensure the browser handles it correctly (and doesn’t take matters into its own Preferences). You do this in PHP like this:

<?php

header("content-type: application/pdf");    // Tell browser what kind of stuff you're sending; here, render a PDF

header("content-disposition: attachment; filename=name_to_be_saved_as.pdf"); // Tell browser how to treat it; here, directly download

?>

For different types of files, you should define the content-type appropriately.  Here’s a good reference for the content-type string needed for the kind of file you’re sending  http://www.w3schools.com/media/media_mimeref.asp. You can set the filename with the ‘filename’ attribute after Content-Disposition. Note the use of the  ’=’ instead of the ‘:’ in assigning the filename.

Then you need to send the content itself:

<?php  echo file_get_contents("test_file.pdf");  ?>

Be careful not to echo anything other than the content of the file you want to force-download. That can throw errors.

Categories: PHP

Text Image Creator

May 16th, 2008 admin No comments

This is a simple image creator to make images out of text. It uses functions in the GD library for PHP. The image is updated automatically when the specifications form inputs are changed (except for the text) with some simple Javascript. The image created is in .png format and if you click the download link, the file is saved as text_image.png.

Requests for additional features/image attributes can be submitted through the comments section.

And since this is a nice example of using the GD Library, here’s the code:

class text_image_creator { function text_image_creator($text, $font="AmericanaItalicBT.ttf", $font_size = 20, $text_color = "#000000", $background_color = "#FFFFFF", $download = false) { $font = getcwd()."/fonts/".$font; $textbox = imagettfbbox($font_size, 0, $font, $text); /*RETURN VALUES FOR IMAGETTFBBOX 0 lower left corner, X position 1 lower left corner, Y position 2 lower right corner, X position 3 lower right corner, Y position 4 upper right corner, X position 5 upper right corner, Y position 6 upper left corner, X position (0,0) 7 upper left corner, Y position */ // BUILD IMAGE WITH A PADDING OF 1X THE FONT SIZE $height = $textbox[1] + 2*$font_size; //compensate for large tff files $width = $textbox[2] + $font_size; $image = @imagecreate($width, $height) or die('Cannot Initialize new GD image stream'); $bc_array = get_rgb_values($background_color); $background_color = imagecolorallocatealpha($image, $bc_array['r'], $bc_array['g'], $bc_array['b'], 0); $tc_array = get_rgb_values($text_color); $text_color = imagecolorallocate($image, $tc_array['r'], $tc_array['g'], $tc_array['b']); // COMPUTE POSITION COORDINATES $pos_x = ($width - $textbox[4])/2; $pos_y = ($height - $textbox[3])/2 + ($font_size/2); imagettftext($image, $font_size, 0, $pos_x, $pos_y, $text_color, $font , $text); header('Content-Type: image/png'); if($download) header('Content-Disposition: attachment; filename=text_image.png'); imagepng($image); imagedestroy($image); } } function get_rgb_values($color) { $color = str_replace("#", "", $color); $a['r'] = hexdec(substr($color, 0, 2)); $a['g'] = hexdec(substr($color, 2, 2)); $a['b'] = hexdec(substr($color, 4, 2)); return $a; } if(isset($_GET['text']) AND $_GET['text'] != '') $text = urldecode($_GET['text']); else $text = "Sample"; if(isset($_GET['font']) AND $_GET['font'] != '') $font = urldecode($_GET['font']); else $font="AmericanaItalicBT.ttf"; if(isset($_GET['font_size']) AND $_GET['font_size'] != '') $font_size = urldecode($_GET['font_size']); else $font_size = 20; if(isset($_GET['text_color']) AND $_GET['text_color'] != '') $text_color = urldecode($_GET['text_color']); else $text_color = "#000000"; if(isset($_GET['background_color']) AND $_GET['background_color'] != '') $background_color = urldecode($_GET['background_color']); else $background_color = "#FFFFFF"; new text_image_creator($text, $font, $font_size, $text_color, $background_color, $_GET['download']);
Categories: Intermediate, PHP, Toys, Tutorials

Login / Logout Mechanism Using Cookies

March 8th, 2008 admin 1 comment

Introduction

The two most common methods for storing a user’s logged-in or logged-out state are sessions and cookies. Sessions are a construct that stores a set of variables on the server and gives the user’s browser an id as a key to those variables. Cookies are variables stored on the user’s machine that can be set and set and accessed by the server. Though very different in construction, they accomplish the same goal: they allow users to uniquely identify themselves. I prefer using cookies, mostly because I understand them better. An argument can be made that cookies are less secure than sessions since cookies’ values can be read and set by the user, but there are measures that can be taken to make malicious activity very difficult (using encryption).

The basic idea then is to store the logged in / out status of the user in the cookie. If you have many users with their own accounts, you can also store an id or something by which to identify the user in the cookie (be sure to read the ‘Security Concerns’ section below).

Setting / Accessing Cookies

Reading cookies is really easy. Cookies are held in the global $_COOKIE array, and can be accessed by $_COOKIE[’cookie_name’].

Setting cookies requires the use of the PHP function setcookie(). You should read through the PHP documentation for a more complete explanation of all the options available, but I’ll explain the essentials. The setcookie() function should have at least two arguments: $cookie_name and $cookie_value. One big advantage of cookies is that they can be set to persist for however long you want – years if desired. By specifying the third argument (as in the example below) we can set the time the cookie should expire (in seconds from midnight Jan. 1, 1970).

The Decision Tree

The decision tree for logging someone in and out isn’t that complicated, but can be tedious. The following code describes the decision tree for logging a user in / out. This code needs to be on every page that users need to be logged in to view. The functions cookie_is_valid(), make_cookie_value(), and login_is_valid() are where you do the fun stuff individual to your site like encrypt and decrypt your cookies and verify login info.


$cookie_name = "logged_in_status";

if(!cookie_is_valid($_COOKIE[$cookie_name])) {   //  USER IS NOT LOGGED IN

    $valid = login_is_valid($_POST['un'], $_POST['pw']);

    if($valid) {
        $cookie_value = make_cookie_value($_POST['un'], $_POST['pw']);
        setcookie($cookie_name, $cookie_value, time() + 60*60);
        header("location: ".$_SERVER['PHP_SELF']); // reload or wherever you want them to go after they log in
    } else if(isset($valid)){
        echo "<font color='red'>INVALID LOGIN</font><br>";
    } else {
        echo "You must be logged in to view this page<br>";
    }

    ?>
     <form action='<?= $_SERVER["PHP_SELF"] ?>' method='POST'>
         Username: <input type='text' name='un' value=''> - it's "correct_username"
         <br>Password: <input type='password' name='pw' value=''> - it's "correct_password"
         <br><input type='submit' value='Login'>
     </form>

    <?

} else if($_GET['logOut']){
    setcookie($cookie_name, false, time() - 24*60*60);
    header("location: ".$_SERVER['PHP_SELF']);    // reload or wherever you want them to go after they log out
} else {
    setcookie($cookie_name, $_COOKIE[$cookie_name], time() + 60*60);
    echo "You are logged in. <a href='?logOut=true'>Log Out</a>";
}

Verifying Login Information

If you have users logging in and creating accounts etc., you probably want to query your database here to determine the validity of the username / password combination. If you’re just protecting an administrator page or something, you can do what I did here and just have the username and password hardcoded into the script. Returning a value of null vs. false is important to the functioning of the decision tree. Basically, if the arguments are null, (the user hasn’t filled out the form yet), we don’t display a “INVALID LOGIN” message as we would if the user did fill out the form and the entries were invalid.

function login_is_valid($un = null, $pw = null) {
    if(isset($un) AND isset($pw)) {
        if($un == 'correct_username' AND $pw == 'correct_password') return true;
        else return false;
    } else return null;
}

Security Concerns

Addressing the security concerns mentioned earlier, these functions should be something cool and unique to your site. This is really only a concern if you have multiple users with accounts.

Again, the cookie value should hold the user’s logged in / out status and identify the user that’s logged in. Remember that users can view and set cookies manually (I’ve done it with FireFox – anyone want an article on that?), so we can’t just have cookies called $logged_in_status = true and $user_id = 123 because then anyone could set their cookies manually and effectively log in as whoever they wanted.

The solution is to encrypt the cookie value. Encryption a guilty pleasure of mine, but for this exercise, I’ll just use a simple algorithm that’s been around since Ancient Greece – a simple substitution cipher.

//	http://www.thescripts.com/forum/thread5669.html

function doEncDecTranslation($text, $decrypt = false) {
    define(A, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&');
    define(B, 'qFpkt79uxTlRWNngCye1isvODmVzJK82I3GLUYSQrjHdoa&f4XEMZ6A05BbhPcw');
    //str_shuffle(A);

    return $decrypt ? strtr($text, B, A) : strtr($text, A, B);
}

function encrypt($str) {
    return doEncDecTranslation($str);
}

function decrypt($str) {
    return doEncDecTranslation($str, true);
}

The method goes like this: First each user gets a randomly generated string (variable length between 20 and 30 characters long) when they register, call it $user_key, that is stored in the database along with their username and password. The cookie value is then set to an encrypted concatenation (combination of the strings) of the $user_id and $user_key separated by a delimiter like ‘&’. This gives us the functions:

function make_cookie_value ($un, $pw) {
    $sql = "SELECT user_id, user_key FROM tblUserInfo WHERE username='$un' AND password='$pw' LIMIT 1";
    list($id, $key) = mysql_fetch_row(mysql_query($sql));
    return encrypt($id."&".$key);
}

function cookie_is_valid($cookie_value) {
    list($id, $key) = explode("&", decrypt($cookie_value));
    if(!alpha_numeric($id) OR !alpha_numeric($key)) return false;  //  TO PREVENT SQL INJECTION
    $sql = "SELECT TRUE FROM tblUserInfo WHERE user_id = '$id' AND user_key='$key' LIMIT 1";
    list($valid) = mysql_fetch_row(mysql_query($sql));
    return $valid;
}

 //  http://www.roscripts.com/snippets/show/41
function alpha_numeric($str) {
    return (strspn($str, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") == strlen($str));
}

The alpha_numeric test is to guard against SQL injection, but that is for another article.

Even though this uses pretty simple tools, this method is pretty hard to crack. I’d welcome any feedback, though, from anyone who disagrees.

Categories: Beginner, PHP, Tutorials