How to pass file names from a batch file to CLI PHP - php

I wanted to pass a file name, generated by a batch file, to a commandline php script as an argument. Of course, to access local files in Windows, you have to double the backslashes (c:\\blah\\yeah.txt). It's challenging because the back slash is an escape character.
$fName = $_GET["fileName"]; // yields c:\blah\yeah.txt
$fName = ___TRANSFORM THE SLASHES HERE___; //needs to be c:\\blah\\yeah.txt
$fh = fopen($fName, 'rb');
$feed = fread($fh, filesize($fName));
fclose($fh);
How do you do this using regex?
NOTE: I'm using $_GET because I wanted to use the parameter name rather than $argv[0]. See hamboy75's note here on the php website.

Use this regex: $fName = preg_replace('{\\\}','\\\\\\',$fName);
You need 3 \'s to match 1 and 6 to match 2. Also, it won't work without curly brackets.
If someone wiser than me wants to explain the why, I'd appreciate it. I just wanted to save someone else some head scratching.

Related

comma separated in text file in php

if(isset($_POST['submit']))
{
$file = $_FILES['file']['name'];
$fh = fopen($file,'r+');
// string to put username and passwords
$users = '';
while(!feof($fh)) {
$user = explode(' ',fgets($fh));
foreach ($user as $value)
{
$number= rand(1000,10000);
$final_number[] = $value .','. $number;
}
}
//print_r($final_number);
file_put_contents($_FILES['file']['name'], $final_number);
}
this is my code for appending a random text to a string with comma and save it in text file but when i am saving it it is not saving properly after comma it is going to next line which should not happen plzz.. help me
Your code starts with a very big issue: you try to open and read from a file that, most probably, doesn't exist.
$file = $_FILES['file']['name'];
$fh = fopen($file,'r+');
As you can read in the documentation, assuming that your form contains an input element of type file having the name file, $_FILES['file']['name'] is the original name of the uploaded file, on the user's computer. It is only the name and it is not the name of the file on the server. It is provided just as a hint for the file's content (check the filename extension) but you cannot rely on it.
The content of the file is temporarily stored on the webserver in a file whose path can be found in $_FILES['file']['tmp_name']. You should pass it to the PHP function is_uploaded_file() to be sure the file was uploaded and your script is not the victim of an injection attempt then, if you need to keep it, use move_uploaded_file() to move it where you need. If you don't move it, when your script ends the temporary file is deleted.
Another problem of your code is on the lines:
$user = explode(' ',fgets($fh));
foreach ($user as $value)
As explained in the documentation, the function fgets() called without a second argument reads a line from the input file, including the newline character that ends it. Since you split the line into words I think you don't need the newline character. You can remove it by using trim() with the string returned by fgets() before passing it to explode().
The last issue of the code is:
file_put_contents($_FILES['file']['name'], $final_number);
Because $final_number is an array1, file_put_contents() joins its elements to get a string and writes the string into file. This operation concatenates the random value generated for a $value with the next $value and there is no way to tell which is which after the data is stored in the file. You probably need to keep them on separate lines. Use function implode() on $final_number, with "\n" as its first argument and write the generated string into the file instead.
The last one: don't write the generated content to $_FILES['file']['name']. It is not safe! It contains a string received from the browser; a malicious user can put whatever path they want there and your script will overwrite a file that it shouldn't change.
Create a directory dedicated to store files generated by your code and generate filenames based on an always incremented counter (the current time() or microtime() f.e.) for the files you store there. Never trust the data you receive from the browser.
1 $final_number is used as $final_number[] = ... and, because it is not defined when this line of code is executed for the first time, PHP creates an empty array for you and stores it in $final_number. Don't rely on this feature. Always initialize your variables before their first use. Put $final_number = array(); before the while().
I am going to use a different approach than you, let's say that the data you want to save to the file is stored in the variable $data.
So to append this data to the file with a comma at first, we can use just two lines of code:
$previousFileContent = file_get_contents("filename.txt");
file_put_contents("filename.txt", trim($previousFileContent . "," . $data));

fwrite to front of file for my chatroom with php and ajax

I have a simple chatroom I've built. I actually want it to scroll up instead of down, meaning new messages are added to the top of the chat. This means I have to fwrite to the top of the file. I have done a lot of trial and error, as well as googling and overflowing, but haven't had success. Also, I understand that I need to use r+ likely, and not a, but I wanted to give the currently functional code, not the under construction code.
The two commented out lines are two ideas I tried. r+ continuously replaced the first line, and left text. If I typed 1 character, it left >r>>, if I typed 2 characters, it left >r>, if I typed 3 characters, it left r>, if I typed 4, it left >, and if I typed 5 or more, it left nothing.
I can't find much relevant information to this. Perhaps I'm using the wrong keywords. Please help me understand.
if(isset($_SESSION['name'])){
$text = $_POST['text'];
$fp = fopen("log.html", 'a');
//$fp = fopen("log.html", 'r+');
//fseek("log.html", 0)
fwrite($fp, "<center><div class='msgln'><b>".$_SESSION['name'].":</b> ".stripslashes(htmlspecialchars($text))."<br></div><br></center>");
fclose($fp);
}
A - Use a database. This is a poor implementation.
B - If you insist on using this implementation, Writing the beginning of a file resets the pointer and overwrites the file. Instead, grab data from current file, add it to new data, and rewrite the file.
C - There will be collision issues. Don't actually do this. But it will work.
Try:
if(isset($_SESSION['name'], $_POST['text'])){
$text = $_POST['text'];
$current_content = file_get_contents("log.html");
$new_content = "<center><div class='msgln'><b>".$_SESSION['name'].":</b> ".stripslashes(htmlspecialchars($text))."<br></div><br></center>".$current_content;
file_put_contents("log.html", $new_content);
}

Can't get fopen to open file

I can't tell you how stupid I feel having to ask this question, but I've been working on the most simple of commands (for two days) and can't find the problem. I 'borrowed' some code for a non repeating hit counter. I have tried to get it to work and I finally determined I'm not getting access to the simple txt files that store the hits or the one that stores the ip addresses. I've read the problems here, looked at the command in a 'Dummies' book and even watched YouTube videos and I'm blind to the problem. I've tried using a string for the file name and using the filename directly. I had the files in a sub folder on the server and thought that might be the issue so I moved them to the root with the same error. If someone can see why this isn't working I'd be eternally grateful.
This is only part of the whole code but it's where I determined that it fails.
$filename = 'countfix.txt';
$handle = fopen('$filename', 'r');
fread($handle, $current_inc)
or die ("Can't open file");
echo $current_inc;
fclose($handle);
Thanks.
This is wrong:
$handle = fopen('$filename', 'r'); // tries to open a file named $filename
It should be written this way:
$handle = fopen($filename, 'r'); // no quotes, opens countfix.txt
You might have meant to write this instead:
$handle = fopen("$filename", 'r');
wherein the double quotes will cause the real value of $filename to be substituted into the string (thus making the code work), but there is no point in doing that. Lose the quotes.
Additionally, this code doesn't do what it says:
fread($handle, $current_inc) or die ("Can't open file");
Here the error message is printed if you cannot read from the file, not when you fail to open it. You should check the return value of fopen instead or modify the message to be more accurate.
This is the right way to do it:
$handle = fopen("$filename", 'r');
You must enclose variables with doubble quotes, or not enclose them at all! This is how PHP is.
You might want to read this: what is the difference between single quoted and double quoted strings in php

PHP fopen("filename", w) creates files with ~1

I am trying to write a file in PHP. So far it works "kind of".
I have an array of names in the format {Rob, Kevin, Michael}. I use the line of code
foreach($Team as $user)
{
print_r($user);
//create a file for each user
$file = fopen("./employee_lists/".$user, 'w');
//I have also tried: fopen("employee_lists/$user", 'w');
// ... ... ...
//write some data to each file.
}
This works as expected: The print_r shows "Rob Kevin Michael", however, the filenames are saved are as follows: ROB~1, KEVIN~1, MICHAE~1
When I'm going on to use these files later in my code, and I want to relate the usernames of "Rob" to ROB~1, I'll have to take some extra step to do this. I feel like I'm using fopen incorrectly, but it does exactly what I want minus this little naming scheme issue.
It seems like your $user variable contains an invalid character for file system paths (my best guess would be a new line).
Try:
$file = fopen("./employee_lists/".trim($user), 'w');
You should sanitize $user before using it a as file name.
$pattern = '/(;|\||`|>|<|&|^|"|'."\n|\r|'".'|{|}|[|]|\)|\()/i';
// no piping, passing possible environment variables ($),
// seperate commands, nested execution, file redirection,
// background processing, special commands (backspace, etc.), quotes
// newlines, or some other special characters
$user= preg_replace($pattern, '', $user);
$user= '"'.preg_replace('/\$/', '\\\$', $user).'"'; //make sure this is only interpreted as ONE argument
By the way, it's a bad idea using an user name for a file name. It's better to use a numeric id.

Single quotes reversing behaviour in PHP

I was running over a sample script and hit on this particular issue.
The script starts off by setting
$docroot=$_SERVER['DOCUMENT_ROOT'];
For writing to a file,
#$fp = fopen("$docroot/../parts/partsorders.txt",'ab');
is used. But no matter what, this fails to write to the file.
After a tinkering with it for a while, I set the command to
#$fp = fopen('$docroot/../parts/partsorders.txt','ab');
used single quotes instead of double quotes and it worked fine!
My question is, isn't the former double quoted format supposed to work instead of the single quotes. What is happening here ?
Here is the stripped down code, guys (Assume that the file exists in the server) :
<?php
$docroot=$_SERVER['DOCUMENT_ROOT'];
$outputstring = "herpderp";
?>
<html>
<head>
<title>Quotes</title>
</head>
<body>
<?php
#$fp=fopen("$docroot/../parts/partsorders.txt","ab");
flock($fp, LOCK_EX);
if(!$fp) {
echo "<p><strong>Failed.</strong></p></body></html>";
exit;
}
fwrite($fp,$outputstring,strlen($outputstring));
flock($fp,LOCK_UN);
fclose($fp);
echo "<p>Order written.</p>";
?>
</body>
</html>
There are differences between single and double quoted strings in PHP. Single quoted strings do not cause the expansion of variable names while double quoted strings do. See here. Why your code works when you use the variable name with single quoted strings doesn't make sense to me. Furthermore, it's a bad idea to use # in front of your fopen commands, it will prevent you from seeing the error output.
The double quote one is the one that should evaluate $docroot for you. What the single quote should do is try to open a file that actually has $docroot as a string in it's path. Does
#$fp = fopen($docroot . '/../parts/partsorders.txt','ab');
yield the same result?
And do you use #to supress errors? In that case it should be before the function I think
$fp = #fopen($docroot . '/../parts/partsorders.txt','ab');
But don't do that when trying to find errors in your application. The thing is that you could very well get an error that it can't find the file and you just don't notice.
UPDATE
Thanks to pinkgothic for his comment, firstly for providing the correct terminology and secondly for pointing out that this answer is wrong.
I have experimented with the theory that shell is trying to expand the environment variable $docroot and found that shell expansion is not possible in fopen().
I tried the following code and got this error (I have a file called test.txt in my home directory)
$fp = fopen( '$HOME/test.txt', 'rb' );
//PHP Warning: fopen($HOME/test.txt): failed to open stream: No such file or directory in php shell code on line 1
So unless the OP has some configuration which allows shell expansion in fopen(), my answer is, as I say, incorrect.
The string $docroot/../parts/partsorders.txt is being sent directly to the operating system shell. As there is no $docroot variable set it is replaced by an empty string, so it is the same as using
#$fp = fopen('/../parts/partsorders.txt','ab');
Which is an absolute path starting from /, the document root.
#run from shell (bash)
~$ echo $docroot/../parts/partsorders.txt
/../parts/partsorders.txt
After my comment, I had a night's sleep and realised fopen() may not actually use/be like realpath() (which expects all segments to be set, even the ones that are irrelevant for the final normalised path).
It doesn't.
Accordingly, the reason your file is opened is actually fairly simple:
'$docroot/../parts/partsorders.txt'
...which is read as "pastorders.txt in the 'parts' folder which is a folder found in the folder above the '$docroot' folder which is in the current working directory" collapses to...
'parts/partsorders.txt'
...because fopen() simply vanishes $docroot/.. away without checking that $docroot exists. (Functions like realpath() do check it, which was throwing me off.)
So, your file is actually in <current working directory>/parts/partsorders.txt. (Since you're opening the file with the a flag, if it didn't exist there before, it was definitely created there.)
Whatever your $_SERVER['DOCUMENT_ROOT'] contains, it seems it's not what you want. Additionally, in some setups, you can't reasonably .. above $_SERVER['DOCUMENT_ROOT'] - permissions actually won't let you.
If that environment variable outright isn't set (if that's even possible; but I think this demonstrates the problem even if it isn't), the path is quite different:
"$docroot/../parts/partsorders.txt"
...becomes:
"/../parts/partsorders.txt"
...which tries to get up the hierarchy past the root point (/), which would of course not work.
I suggest echoing out or logging $_SERVER['DOCUMENT_ROOT'] and taking a look at what it actually contains, and if it's what you expect it to be.
What might be worth looking for is __DIR__ (or in older PHP versions, dirname(__FILE__)), which takes the directory the file. As long as the file knows where it is, you can just read out files relative to its location.

Categories