PHP privacy over folders

Hello, i have a problem
In my webpage is a username, password login page
when a user logged in, this user is associate to a code
each code is associate with a folder name
each user has his unique code/folder
on server i have a folder named "files"
in the folder files all the users folders
i want when a user is logged in, to have access ONLY on the files from his folder and download ONLY files from his folder
thanks
fradolcinoAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Richard QuadlingSenior Software DeveloperCommented:
Many ways to deal with this.

But, I think the simplest is to use something like this ...

When user logs in the code is placed in a session for that user.

When the user requests files from any folder, instead of asking directly for the file, the request is made to a PHP script which looks at the session and confirms that the code in the session relates to the code for the file/folder.

If so, the script will the supply the file as requested.

If not, the user is logged out, the session cleared and the user told to not access files he does not have permissions to.

If you can supply some code that you have already, I can talk you through amending it.

fradolcinoAuthor Commented:
ok, on the login page if user provide good username and password
$_SESSION["code"]=$code;
Header('Location:account.php');die;

on account.php page
if (isset($_SESSION["code"])){
   $code=$_SESSION["code"];
   $mydir=dir('files/'.$code);
   while(($file = $mydir->read()) !== false) {
            if (($file!='.')&&($file!='..')){
                         $file_name='files/'.$code.'/'.$file;
                        echo '<a href="'.$file_name.'">'.$file.'</a>';
                }
   }
}

That's what i manage, but if the user know the code and the name of the file of another user he can type in address bar and download the file of another user
Thanks
Richard QuadlingSenior Software DeveloperCommented:
How is the "code" determined?

Say the code is the username and valid ones are rquadling and fradolcino. I know the rquadling password. I don't know the fradolcino one.

So.

In the login script, once you have determined that the username and password are correct ...

<?php
...
session_start();
$_SESSION['code'] = $_POST['supplied_and_validate_username'];
?>

In the script that shows the files ...

<?php
session_start();
/** @file directoryfilterdots.inc
 * @ingroup Examples
 * @brief class DirectoryFilterDots
 * @author  Marcus Boerger
 * @date    2003 - 2006
 *
 * SPL - Standard PHP Library
 */

/** @ingroup Examples
 * @brief   A filtered DirectoryIterator
 * @author  Marcus Boerger
 * @version 1.1
 *
 * This Iteraotr takes a pathname from which it creates a DirectoryIterator
 * and makes it recursive. Further more it filters the entries '.' and '..'.
 */
class DirectoryFilterDots extends RecursiveFilterIterator
{
      /** Construct from a path.
       * @param $path directory to iterate
       */
      function __construct($path)
      {
            parent::__construct(new DirectoryIterator($path));
      }

      /** @return whether the current entry is neither '.' nor '..'
       */      
      function accept()
      {
            return !$this->getInnerIterator()->isDot();
      }

      /** @return the current entries path name
       */
      function key()
      {
            return $this->getInnerIterator()->getPathname();
      }
}

foreach(new DirectoryFilterDots('files/' . $_SESSION['code']) as $file)
 {
 echo '<a href="get.php?file=' . urlencode($file) . '&lock=' . md5('MYLOCK' . $_SESSION['code'] . $file) . '">' . $file . '</a><br />';
 }
?>

Then create a new script called get.php

<?php
session_start();
if (isset($_GET['file']) && file_exists('file/' . $_SESSION['code'] . '/' . $_GET['file']) && isset($_GET['lock']) && ($_GET['lock'] === md5('MYLOCK' . $_SESSION['code'] . $_GET['file']))
 {
 fpassthru('file/' . $_SESSION['code'] . '/' . $_GET['file']);
 }
else
 {
 echo 'Nope! No cheating.';
 }
?>

NOTE: This is untested, and uses the PHP5 SPL. You can replace the class with your original dir() mechanism, but thought you may like to see the SPL in action.


Here is an example for the SPL without any fluff.

<?php

/** @file directoryfilterdots.inc
 * @ingroup Examples
 * @brief class DirectoryFilterDots
 * @author  Marcus Boerger
 * @date    2003 - 2006
 *
 * SPL - Standard PHP Library
 */

/** @ingroup Examples
 * @brief   A filtered DirectoryIterator
 * @author  Marcus Boerger
 * @version 1.1
 *
 * This Iteraotr takes a pathname from which it creates a DirectoryIterator
 * and makes it recursive. Further more it filters the entries '.' and '..'.
 */
class DirectoryFilterDots extends FilterIterator
{
      /** Construct from a path.
       * @param $path directory to iterate
       */
      function __construct($path)
      {
            parent::__construct(new DirectoryIterator($path));
      }

      /** @return whether the current entry is neither '.' nor '..'
       */      
      function accept()
      {
            return !$this->getInnerIterator()->isDot();
      }

      /** @return the current entries path name
       */
      function key()
      {
            return $this->getInnerIterator()->getPathname();
      }
}

foreach(new DirectoryFilterDots('.') as $file)
      {
      echo $file . "<br />\n";
      }
?>

Lists all the files in the current directory. The class would be loaded either as a require_once or an __autoload() (depending upon how you want to set it all up).

So, to get all the files from the current directory really is as simple as 1 line of code.

The $file variable is actually an SPL_FILE_OBJECT.

Try this instead ...

foreach(new DirectoryFilterDots('.') as $file)
      {
      echo $file . ' Size = ' . $file->getSize() . "\n";
      }

For full dox on the SPL see http://www.php.net/~helly/php/ext/spl/
CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

fradolcinoAuthor Commented:
Hello again
It gives me an error at this line:
  return !$this->getInnerIterator()->isDot();
Parse error: parse error, unexpected T_OBJECT_OPERATOR in d:\www\vali\fisier-old.php on line 33
Thanks
Richard QuadlingSenior Software DeveloperCommented:
Can you show the lines above.

<?php

/** @file directoryfilterdots.inc
 * @ingroup Examples
 * @brief class DirectoryFilterDots
 * @author  Marcus Boerger
 * @date    2003 - 2006
 *
 * SPL - Standard PHP Library
 */

/** @ingroup Examples
 * @brief   A filtered DirectoryIterator
 * @author  Marcus Boerger
 * @version 1.1
 *
 * This Iteraotr takes a pathname from which it creates a DirectoryIterator
 * and makes it recursive. Further more it filters the entries '.' and '..'.
 */
class DirectoryFilterDots extends FilterIterator
{
      /** Construct from a path.
       * @param $path directory to iterate
       */
      function __construct($path)
      {
            parent::__construct(new DirectoryIterator($path));
      }

      /** @return whether the current entry is neither '.' nor '..'
       */      
      function accept()
      {
            return !$this->getInnerIterator()->isDot();
      }

      /** @return the current entries path name
       */
      function key()
      {
            return $this->getInnerIterator()->getPathname();
      }
}

foreach(new DirectoryFilterDots('C:/BATCH') as $file)
      {
      echo $file . ' Size = ' . $file->getSize() . "\n";
      }
?>

results in ...

25.BAT Size = 28
50.BAT Size = 30
ABG.BAT Size = 135
CLEAN.BAT Size = 9839
Convert Triple C Data.bat Size = 2359
EmptyDirs.BAT Size = 1352
Live Triple C.BAT Size = 781
Live Triple C.lnk Size = 1538
LiveTripleC.bmp Size = 6966
NCCC.BAT Size = 601
OVER.BAT Size = 22
phpchm.bat Size = 273
Q Size = 96
qt.bat Size = 126
RARIT.BAT Size = 114
RARUP.BAT Size = 754
RBG.BAT Size = 133
soff.bat Size = 25
son.bat Size = 26
soup.bat Size = 55
SOV.BAT Size = 10916
SOV2.BAT Size = 16685
TOP20.BAT Size = 56
Triple C V730.BAT Size = 775
Triple C.BAT Size = 775
Triple C.lnk Size = 739
TripleC.bmp Size = 6966
unert.bat Size = 212
UP.BAT Size = 19
upxit.bat Size = 39
VALID.BAT Size = 1265
ZIP.BAT Size = 65
ZIPOK.BAT Size = 773
ZIPU.BAT Size = 152
ZIPUP.BAT Size = 750

Which is as expected.

What version of PHP are you running?

Go to a cmd prompt and type

php -v

You may need to change directory to your PHP directory if you have not put the PHP directory in the PATH (Well worth doing!)

PHP 5.1.3-dev (cli) (built: Feb 20 2006 00:29:25)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
    with Zend Extension Manager v1.0.10, Copyright (c) 2003-2006, by Zend Technologies
    with Zend Optimizer v3.0.0-Beta2, Copyright (c) 1998-2006, by Zend Technologies

fradolcinoAuthor Commented:
until now i successfully install php 5.1.2
the code above gives me no error but nothing on screen, just an blank webpage
Richard QuadlingSenior Software DeveloperCommented:
V5.1.2 is fine for the code.

My test was for a folder called C:\BATCH

Make sure you put something sensible there for testing.

You could use '.' to look in the current folder.

fradolcinoAuthor Commented:
now i manage to list all the files from a specified directory on my hard drive, also to view the file from 12345, or depends
but i have little problems with download the files
if i click nothing happend and if i save target as , get.php appear to download
thanks for your time again
Richard QuadlingSenior Software DeveloperCommented:
Yes. I'm not surprised. Sorry.

Try this as a test for the get.php first.

<?php
session_start();
if (isset($_GET['file']) && file_exists('file/' . $_SESSION['code'] . '/' . $_GET['file']) && isset($_GET['lock']) && ($_GET['lock'] === md5('MYLOCK' . $_SESSION['code'] . $_GET['file']))
 {
 //fpassthru('file/' . $_SESSION['code'] . '/' . $_GET['file']);
 echo 'Yes. You may download <a href="file/{$_SESSION['code']}/{$_GET['file']}">{$_GET['file']}</a><br />";
 }
else
 {
 echo 'Nope! No cheating.';
 }
?>

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.