I got this freely available php-script to track download statistics. Simple really, it just count downloads and pass it on to a log file and another script uses that log file to display a top 10 list. So it's exactly what I need so I would really like to make this script work. But it doesn't. Of course. I have limited knowledge in php (but have learned a lot since encountering this script!). According to the author, it has been tested on Apache- and php-versions similar to mine, without problems. So I have been hesitant to actually change any code. I have tried to chmod logfile and/or whole subdirectory to 666 and 777 with no success.
My own poor detective work leads nowhere and I have really tried. So I resort to the one thing I usually never do, to ask for help.
The link should have the form:
<a href=http://www.yoursite.com/downloader/download.php?number=1&file=filename.zip>
download.php follows below:
$number = $_GET['number'];
$file = $_GET['file'];
$logfile = "ROOT DIRECTORY PATH/logfile.txt";
$array[dir_1] = "URL PATH/DOWNLOADFILESFOLDER";
$download = "dir"."_"."$number";
if ($array[$download]) {
$fp = fopen($logfile,'r');
while (!feof($fp))
{
$data[] = chop(fgets($fp,4096));
}
fclose($fp);
$fp = fopen($logfile,"w");
if (flock($fp,LOCK_EX)) {
// list and split each filename and number of downloads
foreach ($data as $lines){
list($downloads,$filename,$realname) = split("\|",$lines);
// check if file already exists and add one more download if it does
if ($filename == $file){
$downloads++;
}
if ($filename <> ""){
fputs($fp,"$downloads|$filename|$realname\r\n");
}
}
flock($fp,LOCK_UN);
}
fclose($fp);
header("Location: $array[$download]/$file");
}
However one part of the script doesn't make sense to me; where does it obtain the filename and the realname so it can be put into the logfile if the file never has been downloaded before? The list() function and the array of the directory boggles my mind a bit. Though it seems logical.
If someone catches some fundamental error or have some tips on how I can continue, it would be highly appreciated.
PS. I am trying to track pdf-files if that helps.
UPDATE! By kind suggestion I ran error reporting and got an error. The faulty scripts had an error in it that I removed. I ran error checking again and only got "Notices" about undefined variables. I changed the error reporting to
error_reporting(E_ALL ^ E_NOTICE);
After that, no errors at all.
You have to change these:
$logfile = "ROOT DIRECTORY PATH/logfile.txt";
$array[dir_1] = "URL PATH/DOWNLOADFILESFOLDER";
To your actual paths.
Next time, turn on error reporting so you can know when stuff throw errors. One way to do this is adding the following line to the top of your script:
error_reporting(-1) // will show all errors
See: http://php.net/manual/en/function.error-reporting.php
Related
Hello I am relatively new to PHP and I was trying to replace a row in a csv file, i didnt find an optimal solution so I concocted script (a work around) which suits my needs for the time being till I grasp a better understanding of PHP
I tested it on my localhost using XAMPP and everything was working fine , it was replacing the row as intended but when i uploaded the files to my cpanel it stopped replacing and instead it just goes the normal route and write the row on new line.
this is my code :
$fileName = 'Usecase.csv'; //This is the CSV file
$tempName = 'temp.csv';
$inFile = fopen($fileName, 'r');
$outFile = fopen($tempName,'w');
while (($line = fgetcsv($inFile)) !== FALSE)
{
if(($line[0] == "$fin") ) //Here I am checking the value of the variable to see if same value exists in the array then i am replacing the array which will be later written into the csv file
{
$line = explode (",", "$tempstr10");
$asd=$asd+1; //this is the variable that i defined and assigned value 0 in the top most section, this is used later in the code
}
fputcsv($outFile, $line );
}
fclose($inFile);
fclose($outFile);
unlink($fileName);
rename($tempName, $fileName);
if( $asd==0 && filesize("Usecase.csv")>0) // here its checking if the value is 0 , if value is 0 then that means the above code didnt execute which means the value wasnt present in the file , this is to avoid writing the same string again into the file
{ file_put_contents("Usecase.csv", "$tempstr10\r\n",FILE_APPEND | LOCK_EX); }
if( $asd==0 && filesize("Usecase.csv")==0)
{ file_put_contents("Usecase.csv", "$tempstr10\r\n",FILE_APPEND | LOCK_EX); }
and as I mentioned above , its working on the localhost but not on the cpanel , can someone point out if something is wrong with the code ? or if its something else ?
thank you
The most likely problem is that your local version of PHP or your local configuration of PHP is different from what is on the server.
For example, fopen is a feature that can be disabled on some shared servers.
You can check this by creating a php file with the following conents:
<?php phpinfo();
Then visit that PHP file in your browser. Do this for both your local dev environment and your cPanel server to compare the configuration to identify the differences that may be contributing to the differing behavior.
You should also check the error logs. They can be found in multiple different places depending on how your hosting provider has things configured. If you can't find them, you'll need to ask your hosting provider to know for sure where the error logs are.
Typical locations are:
The "Errors" icon in cPanel
A file named "error_log" in one of the folders of your site. Via ssh or the Terminal icon in cPanel you can use this command to find those files: find $PWD -name error_log
If your server is configured to use PHP-FPM, the php error log is located at ~/logs/yourdomain_tld.php.error.log
You should also consider turning on error reporting for the script by putting this at the very top. Please note that this should only be used temporarily while you are actively debugging the application. Leaving this kind of debugging output on could expose details about your application that may invite additional security risks.
<?php
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
... Your code here ...
I found some PHP online (it's a 1 page file manager with no permissions) that I find is really awesome, it suits my current needs. However, I'm having some issues changing the working (default) directory.
I got the script from a GitHub project that is no longer maintained. The PHP itself is a 1 page PHP file manager with no permissions, no databases etc. I already have a user accounts system and would like to change the working directory based on an existing database variable, however I can't seem to find a way around changing the directory.
Currently, the script is uploaded to /home/advenacm/public_html/my/ (as the file is /home/advenacm/public_html/my/files.php. By what I can tell, the PHP uses a cookie to determine the working directory, but it can't find a way around setting a custom directory. I want to use '/home/advenacm/public_html/my/'.$userdomain;, which will as a result become something like /home/advenacm/public_html/my/userdomain.com/.
What I would like to do is set the default (or "home") directory so that the file manager cannot access the root directory, only a specified subfolder.
Something like directory = "/home/advenaio/public_html/directory/" is the best way to explain it. I've tried a number of methods to try and achieve this but nothing seems to work.
I've taken the liberty of uploading my code to pastebin with the PHP syntax highlighting. Here is the snippet of PHP that I believe is choosing the working directory (line 19-29):
$tmp = realpath($_REQUEST['file']);
if($tmp === false)
err(404,'File or Directory Not Found');
if(substr($tmp, 0,strlen(__DIR__)) !== __DIR__)
err(403,"Forbidden");
if(!$_COOKIE['_sfm_xsrf'])
setcookie('_sfm_xsrf',bin2hex(openssl_random_pseudo_bytes(16)));
if($_POST) {
if($_COOKIE['_sfm_xsrf'] !== $_POST['xsrf'] || !$_POST['xsrf'])
err(403,"XSRF Failure");
}
I appreciate any help anyone can offer me and would like to thank anyone in advance for even taking the time to look at my question.
Have you tried chdir() function ?
later edit
Updating my answer based on your edited question.
The main problem is line 30
$file = $_REQUEST['file'] ?: '.';
That needs to be a full real path to the file and has to be compared with your user's 'home'.
And you should use the same path for the checks at line 19.
So you can replace 19-30 with:
$user_home = __DIR__ . "/{$userdomain}";
$file = $_REQUEST['file'] ?: $user_home; //you might have to prepend $userdomain to $_REQUEST['file'], can't see from html the format.
$file = realpath($_REQUEST['file']);
if($file === false) {
err(404,'File or Directory Not Found');
}
if(strpos($file, $user_home) !== 0) {
err(403,"Forbidden");
}
if(!$_COOKIE['_sfm_xsrf']) {
setcookie('_sfm_xsrf',bin2hex(openssl_random_pseudo_bytes(16)));
}
if($_POST) {
if($_COOKIE['_sfm_xsrf'] !== $_POST['xsrf'] || !$_POST['xsrf'])
err(403,"XSRF Failure");
}
Although this might solve your question I think the entire script is a poorly written solution.
My environment is: Windows, MsSQL and PHP 5.4.
My scenario:
I'm doing a small shell script that creates a full backup from my wanted database to a temp folder and then moves it to a new location.
The backup goes fine and the file is created to my temp folder. Then I rename it to the 2nd folder and sometimes it goes ok, sometimes it cannot find the source file.
Of course at this point I know that I could skip the temporary location alltogether, but the actual problem with not finding the file bothers me. Why is it so random and might it also affect other file functions I've written before this one... Also i need to be able to control how and when the files move to the destination.
The base code is simple as it should be (although this is a simplified version of my actual code, since I doubt anyone would be interested in my error handling/logging conditions):
$query = "use test; backup database test to disk '//server01/temp/backups/file.bak', COMPRESSION;";
if($SQLClass->query($query)) {
$source="////server01//temp//backups//file.bak";
$destination="////server02//storage//backups//file.bak";
if(!rename($source , $destination)) {
//handleError is just a class function of mine that logs and outputs errors.
$this->handleError("Moving {$source} to {$destination} failed.");
}
}
else {
die('backup failed');
}
What I have tried is:
I added a file_exists before it and it can't find the source file either, when rename can't.
As the file can't be found, copy() and unlink() will not work either
Tried clearstatcache()
Tried sleep(10) after the sql backup completes
None of these didn't help at all. I and google seem to be out of ideas on what to do or try next. Of course I could some shell_execing, but that wouldn't remove my worries about my earlier products.
I only noticed this problem when I tried to run the command multiple times in a row. Is there some sort of cache for filenames that clearstatcache() won't touch ? It seems to be related to some sort of ghost file phenomena, where php is late to refresh the file system contents or such.
I would appreciate any ideas on what to try next and if you read this far thank you :).
You may try calling system's copy command.
I had once problem like yours (on Linux box) when i had to copy files between two NFS shares. It just failed from time to time with no visible reasons. After i switched to cp (analog of Windows copy) problem has gone.
Surely it is not perfect, but it worked for me.
It might be cache-related, or the mysql process has not yet released the file.
mysql will dump the file into another temp file, first and finally moves it to your temp folder.
While the file is beeing moved, it might be inaccessible by other processes.
First I would try to glob() all the files inside temp dir, when the error appears. Maybe you notice, its still not finished.
Also have you tried to implemente something like 10 retry iterations, with some delay?
$notMoved = 0;
while($notMoved < 10){
$source="////server01//temp//backups//file.bak";
$destination="////server02//storage//backups//file.bak";
if(!rename($source , $destination)) {
//handleError is just a class function of mine that logs and outputs errors.
if ($notMoved++ < 10){
sleep(20);
} else {
$this->handleError("Moving {$source} to {$destination} failed.");
break;
}
}else{
break;
}
}
To bypass the issue:
Don't dump and move
Move then dump :-)
(ofc. your backup store would be one behind then)
$source="////server01//temp//backups//file.bak";
$destination="////server02//storage//backups//file.bak";
if(!rename($source , $destination)) {
//handleError is just a class function of mine that logs and outputs errors.
$this->handleError("Moving {$source} to {$destination} failed.");
}
$query = "use test; backup database test to disk '//server01/temp/backups/file.bak', COMPRESSION;";
if($SQLClass->query($query)) {
//done :-)
}
else {
die('backup failed');
}
Try
$source = "\\server01\temp\backups\file.bak";
$destination = "\\server02\storage\backups\file.bak";
$content = file_get_content($source);
file_put_contents($destination, $content);
I am extremely knew to working with databases and servers and just downloaded MAMP. I have a website I made in html and css and want to inject a php script to it. I have saved the file in .php and when I navigate to it from the localhost port on my browser, none of the html is displayed. It only shows a blank white page. There is probably a really obvious answer but I've been searching google for an hour and haven't found a solution.
This is the php script. It is wrapped in a tag everything else in the document is html.
<?PHP
$filelocation = "Text.txt";
if (!file_exists($filelocation)) {
echo "Couldn't find datafile, please contact the administrator.";
}
else {
$newfile = fopen($filelocation,"r");
$content = fread($newfile, filesize($filelocation));
fclose($newfile);
}
$content = stripslashes($content):
$content = htmlentities($content):
$content = nl2br($content);
echo $content;
?>
Most likely there's an error in your PHP code and it can't be parsed. Check the server logs to see what the error message is.
That seems to be valid PHP at a glance.
You could read the file more easily by doing...
$content = file_get_contents($filelocation);
but that's incidental.
Turn on Error reporting in your php.ini file and then restart your webserver. This should give more detailed error information. You should also check your server error logs as there's usually something in there too.
Are you getting an HTTP 500 response code with the blank page? Also, are you sure the file in question actually has any contents?
You have two syntax errors in your code:
$content = stripslashes($content):
$content = htmlentities($content):
They must end with semicolon
$content = stripslashes($content);
$content = htmlentities($content);
Besides that, your errors are likely catched and written to logs as said by others.
Most probably you have a php / php syntax error.
On the first line of your .php file write the following:
<?php error_reporting(E_ALL); ?>
this should make the interpreter to show you the errors you have.
Also, more details about your problem won't hurt.
The script is in myusername/public_html/item/index.php
code to save file:
$filename = $_SERVER['DOCUMENT_ROOT'].'/../data/guestbook.txt';
$filehandle = fopen($filename, 'ab+') or die("<p>Unable to create the file!</p>\n".$filename);
flock($filehandle, LOCK_EX) or die("<p>Unable to lock the file!</p>\n");
fwrite($filehandle, $new_entry) or die("<p>Unable to write to the file!</p>\n");
fclose($filehandle);
For some reason it fails on the fopen and the filename is actually ends up being literally with the /../ instead of navigating to the proper path.
What to do, what to do?
you can code like this if the php script is in the item folder and item and data are at the same level in the directory hierarchy
$savedir = '../data/';
$filename = $savedir.'guestbook.txt';
make sure apache user has the write access to the directory by "chown -R apache:apache" and "chmod 755".
Probably the " /../ " in your code is giving the error. Try removing the first forward slash.
For some reason it fails on the fopen
There is no "some reasons" in programming. There are always a certain reason.
And you have to know it.
filename is actually ends up being literally with the /../
That's exactly what you wrote, nothing to complain of.
How can I save a file in PHP to a directory higher than current?
Technically you are setting it correct.
But there can be another reason, other than wrong way of the path creation.
Yes, there always can be many reasons for the program to fail!
What to do, what to do?
Run this code and see what it says.
ini_set('display_errors',1);
error_reporting(E_ALL);
$filename = $_SERVER['DOCUMENT_ROOT'].'/../data/guestbook.txt';
file_put_contents($filename,$new_entry);
it will tell you the reason why it fails.