0

I have a webpage for that is for internal use only. It is going to be hosted on a server that is primarily running other processes that generate log files in the /opt/appname/logs/ dir. I have been tasked with making a web interface that will allow these log files to be downloaded to any computer on our network. I am using Apache on Debian. This is what I have so far:

<details>
   <summary><b>Download Log Files</b></summary>
   <?php
   foreach (glob("/opt/appname/logs/*.log") as $filename) {
      $file_info = explode("/logs/", $filename);
      ?>
      <a href="<?php echo $filename ?>" download><?php echo $file_info[1] ?></a>
      <br>
   <?php } ?>
</details>

When I try and download a log file the download looks like it starts but then gives me the message "Failed No file". I have found many posts on line that say you can or can't do this but none of them provide adequate examples. I realize that there are issues with accessing anything outside of the web folders but there has to be some way to do this. I am really at a loss here so any suggestions would be great. Lastly I am self taught so if you see any errors or things that I am not doing best practice please let me know. I am always trying to improve.

mando222
  • 543
  • 3
  • 6
  • 16
  • http://stackoverflow.com/questions/40943/how-to-automatically-start-a-download-in-php – low_rents May 11 '16 at 13:55
  • Little clarification here. I am unsure as to how that link helps me. I have the download ready to go when the link is clicked it is a matter of security folder permissions and/or paths. Isn't it better to use built in html5 functionality as opposed to recreating this with php? – mando222 May 11 '16 at 14:02

2 Answers2

1

It's a security related thing, that only files which are in certain paths on the server can be accessed by a browser, so there should not be a 'simple' solution to this.

What you can do:

  1. Define an alias to the path or file in your web server configuration

or

  1. Write a small program which is called instead and which reads the file from the desired location and send it as output.

In the latter case, you should remember that giving the path via parameters is like an open door for all those who like to read all files on your server!

JSchirrmacher
  • 3,243
  • 2
  • 19
  • 27
  • about the latter case (2.): what do you mean by "given the path via parameters"? – low_rents May 11 '16 at 13:58
  • 1
    In your case, you only use the file name, not the path. That might be ok, so that only files in a certain folder are available. If you would instead use the complete path as parameter, it would be a problem. Just wanted to warn you ;-) – JSchirrmacher May 11 '16 at 13:59
  • FYI: i am not the one who wrote the opening post. – low_rents May 11 '16 at 14:03
  • @Jachim Schirrmacher That is basically what I changed. I am only passing the file name from the main page and in download.php I have the path hard coded. I realize there are still ways to get around this but it is a world safer then before. I will be adding more in the future. +1 for the useful info. – mando222 May 11 '16 at 14:33
0

You could create a file download.php. This file can look something like:

Download.php

$fn = $_GET["filename"];

if (is_readable($fn)) {
    header('Content-Description: File Transfer');
    header('Content-Type: text/plain');
    header('Content-Disposition: attachment; filename="'.$fn.'"');        
    readfile($fn);
} else {
   //return a 404 error perhaps.
}

You could then modify your original listing code to:

<details>
   <summary><b>Download Log Files</b></summary>
   <?php
   foreach (glob("/opt/appname/logs/*.log") as $filename) {
      $file_info = explode("/logs/", $filename);
      ?>
      <a href="download.php?filename=<?php echo $filename ?>" download><?php echo $file_info[1] ?></a>
      <br>
   <?php } ?>
</details>

I personally like this method because you can also add extra checks and exceptions in the "download manager".

apokryfos
  • 38,771
  • 9
  • 70
  • 114
  • This is what I meant by telling about security holes... You could easily call `download.php?filename=/etc/passwd` or similar to allow reading any file on your server. – JSchirrmacher May 11 '16 at 14:06
  • @JoachimSchirrmacher It's just an example. There's obviously lots of security checks that need to be added on something that people will actually be using in the real world. – apokryfos May 11 '16 at 14:19
  • While I understand the security issues with this given the current situation this fits perfectly. I would never deploy this into a web facing page but this what I have here is for a small internal staff that has access to the server anyway if they really wanted it. I now am getting the file to download but it is empty when I open it. Any ideas? – mando222 May 11 '16 at 14:20
  • Got it. I changed to readfile($file_name); instead of the fopen and fpassthru and that did the trick. Thanks a ton for your help guys. I will be working a bit to fix the security issues with this. – mando222 May 11 '16 at 14:23