-1

I have a file (.zip, .msi etc) on our server that we try and protect as much as possible. I know sessions can be spoofed, as well as referrer. We either require you to come from our download page (where session starts) or from one specific partner. I have all of this working. I wanted to insert Google Analytics but Ive read inserting js/html will corrupt the download. I would like to just create then write to a txt file and capture the date of each download and create a running count of total downloads. Here is my code to force the download - this is in a file that is directly called and doesn't take user off the partner website:

<?php
    session_start();
    $ref = $_SERVER['HTTP_REFERER'];
    $refData = parse_url($ref);
    if(time() - $_SESSION['time'] < 2000 || ($refData['host'] == 'partnersite.com'))  {
        $path = '/var/www/vhosts/example.org/dir/dir/dir/App.Install.de-de.msi';
        $mm_type="Content-type: application/x-ole-storage";
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header("Content-Description: File Transfer");
        header("Content-Type: " . $mm_type);
        header("Content-Length: " .(string)(filesize($path)) );
        header('Content-Disposition: attachment; filename="'.basename($path).'"');
        header("Content-Transfer-Encoding: binary\n");
        readfile($path);

        //try and write to file and count downloads
        $current_count = file_get_contents('count');
        $f = fopen('count', 'w+');
        fwrite($f, $current_count + 1);
        fclose($f);

        exit();
    } else { ?>
        <?php header("Location: https://example.org/404.php");
        die(); ?>
    <?php }
?>

Again, this works exactly like I want it to in forcing and 'softly' protecting the download from hotlinking. Somewhere in there I need to create "count.php" write to it w/o over writing and then close it.

halfer
  • 19,824
  • 17
  • 99
  • 186
Dirty Bird Design
  • 5,333
  • 13
  • 64
  • 121
  • 2
    What’s stopping you from keeping count before you call ‘readfile ‘? I don’t understand what’s the issue here. – yivi Feb 15 '19 at 16:36
  • 1
    Note you can push hits to Google Analytics from PHP on the server side. See [this question](https://stackoverflow.com/questions/9503329/is-there-any-way-to-post-events-to-google-analytics-via-server-side-api). – Alex Howansky Feb 15 '19 at 16:37
  • Maybe `file_put_contents('somefile.txt', $count, lock_constant_look.up.real.syntax.for.this);`? – user3783243 Feb 15 '19 at 16:38
  • @AlexHowansky - that looks very promising. I built a string in the "Hit Builder" tool, but not sure how to implement. Any example? – Dirty Bird Design Feb 15 '19 at 16:45
  • Are you asking _where_ and _how_ to write to a log file? – waterloomatt Feb 15 '19 at 16:45
  • Yes, I know there are several examples, and I can get them to work on their own. I just can't figure out how to combine it with the working part I have already. – Dirty Bird Design Feb 15 '19 at 16:46
  • OK - To start, put it directly inside your `if` statement. Edit your question with what you have, even if it is not fully working. With that, we can assist further. – waterloomatt Feb 15 '19 at 16:47
  • https://stackoverflow.com/questions/23329531/php-making-a-download-counter-without-leaving-the-current-page – yivi Feb 15 '19 at 16:52
  • https://stackoverflow.com/questions/7213940/php-count-downloads – yivi Feb 15 '19 at 16:52
  • @yivi - I looked at those links. However both seem to depend on a 'wrapper' file or link modification - passing file name through URL and output HTML. I don't want people to leave the 'parnter site' – Dirty Bird Design Feb 15 '19 at 16:56
  • @waterloomatt Added attempt (I know its wrong) at writing to a file and incrementally counting downlaods – Dirty Bird Design Feb 15 '19 at 17:01
  • Doesn’t matter. What you are missing is not that but the “write to file “ part. – yivi Feb 15 '19 at 17:01
  • OK, moved it above readfile – Dirty Bird Design Feb 15 '19 at 17:05
  • This is racy. You should [lock the file](http://php.net/manual/en/function.flock.php) during the update operation. – Peter Feb 15 '19 at 17:45
  • Rolled back the edit of your question since the edited version made the answers irrelevant and hard to understand. – yivi Feb 15 '19 at 20:08
  • If you find your own answer, please do not edit it into the question - and especially not the start of the question, where it is confusing to start with a solution. Always add your solution material as an answer below. – halfer Feb 22 '19 at 22:47

3 Answers3

1

Once you call readfile() you are surrendering control.

Do your logging before calling it, and it will work.

You can either keep a counter or write a log file. Since you already know how to write to a file, the details are up to you.

yivi
  • 42,438
  • 18
  • 116
  • 138
0

You don't have to keep track of count because you can simply count the lines of the file to see how many downloads there have been. https://stackoverflow.com/a/2162528/296555

if(time() - $_SESSION['time'] < 2000 || ($refData['host'] == 'partnersite.com'))  { 
    // Sudo code - see real example here - https://stackoverflow.com/a/19898993/296555
    // Write to log file before initiating the download.
    $log = current date time
    file_put_contents('./log_file.log', $log, FILE_APPEND);

    // Now, do the download part
    ...
E_net4
  • 27,810
  • 13
  • 101
  • 139
waterloomatt
  • 3,662
  • 1
  • 19
  • 25
  • 1
    Thank you. Ill figure out how to create the file and update download total. As both you and @Yivi pointed out, I need to do this before the download and readfile(). – Dirty Bird Design Feb 15 '19 at 17:17
0

(Posted on behalf of the question author).

Writing to a log is easy and can be done with the links provided in answers. I ended up needing a more robust solution, and one that worked with our existing Google Analytics set up. So I used Google's Measurement Protocol and their Hit Builder to test. Here is a good source of info from SO on it.

halfer
  • 19,824
  • 17
  • 99
  • 186