Jump to content

Recommended Posts

I've got a problem hopefully someone can assist with when unlinking files it has to do with file names that have spaces in them.

 

If the file name contains no spaces the name is displayed correctly and the URL is complete. However if the file name contains spaces, the filename is displayed correctly but the URL is truncated at the space and the delete routine doesn't work, I must be missing something obvious here????

 

Any ideas on how to fix?

<?php
//initialize the session
if (!isset($_SESSION)) {
  session_start();
}

$claim_folder= $_SESSION['port_recordID']; //variable comes from detail page only used to carry claimnumber

$path = "../docs/" . $doc_folder . "/";
if(isset($_GET['delete']) && $_GET['delete']=='true') {
        $fname = $_GET['deletefile'];
        $fID = $_GET['recordid'];
        $path = '../claims/' . $fID . '/';
        print_r($path.$fname);
        //exit();
        unlink($path.$fname);
        //header('location: file_list.php');
        die();
}
?>
<?php
$dir = dir($path);
while($file = $dir->read()) {
     if($file != '.' && $file != '..') {
    echo "<form method='post' action="?><?php echo $_SERVER['PHP_SELF'].'?delete=true&recordid='.$doc_folder.'&deletefile='.$file;?>
    <?php echo" ><a href= /pages/download.php?file=$file> $file </a>   <input type='submit' value='delete'></form>";
    }
}
?>

AJM,

Link to comment
https://forums.phpfreaks.com/topic/295624-problem-unlinking-files-using-while/
Share on other sites

I think I need to lean more towards urlencode()? As long as the filename doesn't contain a "space" then the routine works as designed..

 

I' m trying to figure out what's happening first so that I can make a better assesment of how to fix it, thanks for the suggestion.

 

AJM,

(sigh)

 

You should always put quotes around attributes in HTML. If you don't do that then spaces will mess it up and you'll lose stuff.

Also, PHP_SELF is not safe to use unless you wrap it in a function like htmlspecialchars().

echo "<form method='post' action='"?><?php echo htmlspecialchars($_SERVER['PHP_SELF']).'?delete=true&recordid='.$doc_folder.'&deletefile='.$file;?>
<?php echo"' ><a href='/pages/download.php?file=$file'> $file </a>   <input type='submit' value='delete'></form>";
And what's with your opening and closing tags? You've gone crazy with them.

Nah, I sighed because this question comes up a lot but it's not the easiest thing to Google for. Problem is the symptoms vary, like broken links or losing form data. And just given those symptoms it's not necessarily obvious what's wrong, and the first place you'd check (the PHP code) isn't actually where the true problem is. Just one of those things where you know the answer from experience, not from raw PHP knowledge.

Many thanks for the help, that resolved the problem.

 

Also, PHP_SELF is not safe to use unless you wrap it in a function like htmlspecialchars().

 

 

Can you elaborate on the security issue and how the htmlspecialchars() functions aleviates the problem?

 

AJM,

On 4/17/2015 at 6:00 PM, A JM said:

Can you elaborate on the security issue and how the htmlspecialchars() functions aleviates the problem?

PHP_SELF contains a portion of the URL that is pretty much exactly as the user entered it in their browser. Most of the time someone can enter in something you didn't expect and still execute your script. For example, "script.php" may be triggered with "script/foo/bar": the web server sees "script", realizes there's a matching file "script.php", and then executes it.

Edited by requinix
removed xss demo because it actually managed to attack this forum XD

requinex,

 

Having a similar issue after I encapsulated the HTML attributes with quotes... seems like it should be working, thoughts? I'm still seeing the file name get truncated at spaces..

<?php
//initialize the session
if (!isset($_SESSION)) {
  session_start();
}
$doc_folder= $_SESSION['port_recordID']; //variable comes from detail page only used to carry claimnumber
$path = "../claims/" . $doc_folder . "/";

$dir = dir($path);
while($file = $dir->read()) {
     if($file != '.' && $file != '..') {
    echo "<a href='/pages/download.php?file=$file&recordid=$doc_folder'> $file </a>";
    }
}
?>

So digging further... ugh.

 

I can accomodate for files with a single quote by using the following:

$file = htmlspecialchars($value, ENT_QUOTES);

However when the user clicks on the link to download the file the file name now has an "_" underscore in the name, from the GET() function?

 

2003 Baja 20_' Outlaw.pdf

<?php
$ID=stripslashes($_GET['recordid']);
$file = $_GET['file'];
// the absolute path to your directory storing your files.
$path = '../claims/' . $ID . '/';
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Description: File Transfer");
header('Accept-Ranges: bytes');
header('Content-Length: ' . filesize($file));
readfile($path.$file);
?>
Edited by A JM

$_GET won't do that. Which is an array, by the way, not a function.

 

You need two functions: rawurlencode and htmlspecialchars(). Applied to $file in that order. And htmlspecialchars() alone for the second $file.

echo " ", htmlspecialchars($file, ENT_QUOTES), " ";
That's because the filename is going into a URL, and you're putting that URL within HTML. When the browser figures out what to do when you click the link, it will HTML-decode the URL first (because it's in HTML) and then verify it is an acceptable URL (and if not, URL-encode it automatically because it's nice like that).

 

In download.php you only look in $_GET: there will be no HTML encoding and the URL decoding happened earlier (since, being in a URL, PHP knew it must necessarily happen at some point anyways).

Edited by requinix

I didn't think to use them together..rawurlencode() or htmspecialcharacters()... duh!

 

I'm still experiencing issues with it though (see attached)

 

The 2nd file, seems to pass correctly to the download but then appears the "_".

 

AJM,

 

EDIT

 

I've tried to break it up like this:

 

$dir = dir($path);
while($value = $dir->read()) {
     if($value != '.' && $value != '..') {
        $file = htmlspecialchars(rawurlencode($value), ENT_QUOTES);
        echo "<form method='post' action='"?><?php echo"' ><a href='/pages/download.php?file=$file&recordid=$claim_doc_folder'> $value </a></form>";
    }
}
 

post-79107-0-21750200-1429668790_thumb.jpg

post-79107-0-19126100-1429668794_thumb.jpg

Edited by A JM

It seems to be tied to the down load somehow since the file name looks correct in the URL that is passed. In this cas I tried a simple .jpg that wen clicked is assumed to be a .wav file??

<?php
$ID=stripslashes($_GET['recordid']);
$file = $_GET['file'];
// the absolute path to your directory storing your files.
$path = '../claims/' . $ID . '/';
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Description: File Transfer");
header('Accept-Ranges: bytes');
header('Content-Length: ' . filesize($file));
readfile($path.$file);
?>

post-79107-0-67122900-1429754978_thumb.jpg

post-79107-0-70467100-1429755062_thumb.jpg

Your taught your computer that application/force-download type is a "Wave Sound".

 

The thing that triggers the download is the Content-Disposition header, so leave the Content-Type with the right value. Unfortunately that varies by file, and you probably aren't recording it anywhere accessible.

You should install something like fileinfo in order to get the type based on the file contents (your only recourse), but if that's not an option,

header("Content-Type: application/octet-stream");
the application/octet-stream type is your best option because it has an official meaning, unlike application/force-download (which someone simply made up).

Is there a better way to address file downloads? Maybe a jquery addin or something similar and sort of remove the php coding for the download by passing it the variables of the file, location, etc.?

 

Just trying to remedy the problem with an alternate solution.

 

Thanks for the insight.

 

AJM,

The best way to address the name issue is to deal with it when the file is UPLOADED. Replace spaces with underscores, remove apostrophes, etc. from the uploaded filename. Then you won't have this issue of having to encode/decode, etc.

 

Personally I'd just use preg_replace and replace anything in the filename that isn't alphanumeric, a period, an underscore or a dash.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.