Retaining indentation with file_get_contents - php

I'm fetching html code using the code below, it works without any problem, the only issue is the indented code isn't retained
for example the fetched code looks like:
<div>
data
</div
instead of
<div>
data
</div>
php:
<?php
function getFile($file)
{
if (file_exists($file)) {
$file = file_get_contents($file);
return $file;
} else {
return false;
}
}
I understand it isn't an "issue" but if it's possible to retain the correct indent code I'd like to, thank you.

Your current code does retain the indentation, if you want more indentation then this is just an example using your code. You could use spaces as shown or a tab.
Call it with $indent as the number of spaces that you want to add:
function getFile($file, $indent=false)
{
if (file_exists($file)) {
if($indent) {
$i = (str_repeat(' ', $indent);
$file = $i . implode($i, file($file));
} else {
$file = file_get_contents($file);
}
return $file;
} else {
return false;
}
}
An alternative would be to create an indent() function and then in the above just call it:
$file = indent(file_get_contents($file), 4);

It might be a content type encoding issue. file_get_contents will read the file contents using the default charset as configured in php.ini at setting default_charset, which is UTF-8 by default.
We can use mb_detect_encoding to ensure that it is the same as the default character set, if not we have the option to convert it to the detected encoding with mb_convert_encoding.
<?php
function getFile($file) {
if (file_exists($file)) {
$file = file_get_contents($file);
$detect_enc = mb_detect_encoding($file);
if ($detect_enc != ini_get('default_charset'))
$file = mb_convert_encoding($file, $detect_enc);
return $file;
} else {
return false;
}
}
nJoy!

Just a random guess: you probably have output of few spaces somewhere in your code before you output file content to the client.
To avoid that you need to clean output. You can do that inside this getFile() function:
function getFile($file)
{
if (file_exists($file)) {
$file = file_get_contents($file);
ob_clean(); // <-- clean the output if any happened before
return $file;
} else {
return false;
}
}
Or outside where you call it I guess something like:
...
ob_clean();
echo getFile($file);

Related

PHP Script ,php://input check for empty File

Hello i need help with my PHP script.
The Upload function works great, but many files are empty.
Can you help me please to check first IF file is empty or < 1 byte. and Ignore them.
<?php
$vist_page = "post2.php";
include "logger.php";
file_put_contents("outputfile.txt".uniqid(), file_get_contents("php://input"));
?>
Thanks ;)
One way to do that would be to use strlen() to check the length of the string, which could be done by replacing
file_put_contents("outputfile.txt".uniqid(), file_get_contents("php://input"));
with
$content = file_get_contents("php://input");
if (strlen($content)) {
file_put_contents("outputfile.txt".uniqid(), $content);
}
else {
// Your error response here
}
$filename = 'somefile.txt';
if (filesize($filename) < 1) {
//ignore
} else {
//do stuff here
}
filesize returns the file size in bytes
https://www.php.net/manual/en/function.filesize.php
this may be more effecient:
$filename = 'somefile.txt';
if (filesize($filename) > 0) {
//do stuff here
}

decoding eval(base64_decode))

I am trying to decode this code.
I know it can be done by changing eval to echo. But in this case its not working. Is i am making any mistake. This is my encoded_file.php code:
i have tried to change eval to echo but its not working file.
I also tried this decoder:
<?php
// Open and read the content of the encoded file into a variable
$file = file_get_contents('encoded_file.php');
// Strip php tags
$file = str_replace('<?php', "", $file);
$file = str_replace('<?', "", $file);
// Make sure to get rid of short tags....
$file = str_replace('?>', "", $file);
// Strip new lines
$file = str_replace("\n", "", $file);
// Add semi colon to get around a parsing issue.
$file = $file.';';
// Change the Eval function
$file = str_replace('eval', 'echo ', $file);
// Function to eval the new string
function deval()
{
global $file;
ob_start();
eval($file);
$contents = ob_get_contents();
ob_end_clean();
return($contents);
}
// Run the code thru once
$file = deval();
// Counter
$cnt = 1;
// Loop it till it's decoded
while(preg_match('/^\?><\?php eval/', $file))
{
$file = str_replace('?><?php eval', 'echo', $file);
$file = str_replace('?><?', "", $file);
$file = deval();
$cnt;
}
//clean up some tags
$file = str_replace('?><?php', "", $file);
$file = str_replace('?><?', "", $file);
echo $cnt,' iterations<br/><br/>';
echo $file;
?>
but it also not working well. Any solution how to decode it or what's wrong in my decoder code.
Here are the steps which are needed to decode this (note - I've renamed variables/functions for clarity):
1. We see that this script reads content of itself, so we can assume - we cannot change this file
so lets create new file with this content and change this file:
$encoded=file('another_file.txt');
2. Then we can change first eval to echo and all other evals should be commented:
here is first line:
echo base64_decode("aWYoIWZ1bmN0aW9uX2V4aXN0cygiWWl1bklVWTc2YkJodWhOWUlPOCIpKXtmdW5jdGlvbiBZaXVuSVVZNzZiQmh1aE5ZSU84KCRnLCRiPTApeyRhPWltcGxvZGUoIlxuIiwkZyk7JGQ9YXJyYXkoNjU1LDIzNiw0MCk7aWYoJGI9PTApICRmPXN1YnN0cigkYSwkZFswXSwkZFsxXSk7ZWxzZWlmKCRiPT0xKSAkZj1zdWJzdHIoJGEsJGRbMF0rJGRbMV0sJGRbMl0pO2Vsc2UgJGY9dHJpbShzdWJzdHIoJGEsJGRbMF0rJGRbMV0rJGRbMl0pKTtyZXR1cm4oJGYpO319");
this will give us:
if(!function_exists("getSubString"))
{
function getSubString($g,$b=0)
{
$a=implode("\n",$g);
$d=array(655,236,40);
if($b==0) $f=substr($a,$d[0],$d[1]);
elseif($b==1) $f=substr($a,$d[0]+$d[1],$d[2]);
else $f=trim(substr($a,$d[0]+$d[1]+$d[2]));
return $f;
}
}
3. Now we can remove first echo/eval and go to 2nd one:
here is 2nd line:
echo base64_decode(getSubString($encoded));
give us:
if(!function_exists("decodeCode"))
{
function decodeCode($a,$h)
{
if($h==sha1($a))
{
return(gzinflate(base64_decode($a)));
}
else
{
echo("Error: File Modified");
}
}
}
4. we can remove it and go to last eval:
here is it:
echo decodeCode(getSubString($encoded,2),getSubString($encoded,1));
and we see final code:
/**
* #site #####
* #copyright 2010
*/
include 'config.php';
$id=$_GET['id'];
if(isset($id))
{
header("Content-type: image/jpeg");
$url='http://#####/siteuploads/thumb/'.$id;
$path=pathinfo($url);
header('Content-Disposition: attachment; filename="'.$path['basename'].'"');
$img=imagecreatefromjpeg($url);
$red=imagecolorallocate($img,255,155,255);
imagestring($img,2,1,2,$site,$red);
echo imagejpeg($img);
}

Exporting PHP code from with a PHP file

I need to practically generate a .PHP file using a PHP script or PHP command. The file generate will contain the following code:
<?php
class TextToSpeech {
public $mp3data;
function __construct($text="") {
$text = trim($text);
if(!empty($text)) {
$text = urlencode($text);
$lang_en="http://translate.google.com/translate_tts?tl=en&q={$text}";
$lang_ro="http://translate.google.com/translate_tts?tl=ro&q={$text}";
$lang_fr="http://translate.google.com/translate_tts?tl=fr&q={$text}";
$language=$lang_en;
$this->mp3data = file_get_contents($language);
}
}
function setText($text) {
$text = trim($text);
if(!empty($text)) {
$text = urlencode($text);
$en="http://translate.google.com/translate_tts?tl=en&q={$text}";
$ro="http://translate.google.com/translate_tts?tl=ro&q={$text}";
$fr="http://translate.google.com/translate_tts?tl=fr&q={$text}";
$lang=$en;
$this->mp3data = file_get_contents($lang);
return $this->mp3data;
} else { return false; }
}
function saveToFile($filename) {
$filename = trim($filename);
if(!empty($filename)) {
return file_put_contents($filename,$this->mp3data);
} else { return false; }
}
}
?>
I want to do this because I want to have multiple choices regarding the language:
$language=$lang_en;
and
$lang=$en;
Not sure what your question is here. Generating a PHP file is no different than generating any other kind of file. Build a string of the source code you want to write, then a simple file_put_contents('filename.php', $contents); will do the trick.
Edit: Where are $en and $lang_en coming from? Also, could these not be passed as parameters to the function? Why must they be hard-coded?
$contents = '
<?php
// your PHP here
';
file_put_contents('filename.php', $contents);
You may also want to read up on heredocs for large blocks of text, but unfortunately those will replace your variables unless you escape them all with a backslash.

php fgets function stuck the server

I have function build_additional_docs which calls another function that do few actions, but first it's call to function read_all_file, which extract the file to string variable and return it.
It's worked perfect when the function create_file_node has been called from another function.
but when it's called from build_additional_docs, the client wait to server untill time out...
I think that the function fail on fgets().
Additional comment: When I call function create_file_node whith with the same files, and the different is that file name is static string, and I have no foreach loop, the code works again...
here is my code:
function build_additional_docs($dir_name, $addDocsArr){
foreach ($addDocsArr as $doc) {
if($summery != ''){
$fileName = $dir_name . '\\' . $doc;
create_file_node($fileName);
}
}
function create_file_node($fileName){ global $base_url;
try{
$text = read_all_file($fileName);
}
catch (Exception $ex){
// some message here
}
return 0;
}
function read_all_file($file_name){
$file_handle = fopen($file_name, "r");
while (!feof($file_handle)) {
$line[] = fgets($file_handle);
}
fclose($file_handle);
return implode('',$line);
}
Found the mistake!
$addDocsArr variable is return value from explode() function for split string to seperated files names. The returned array include strings of file name with spacial characters that cannot be seen...
so when i add the code:
$fileName = $dir_name . '\\' . substr($doc, 0,strlen($doc) - 1);
the code worked.

Byte Order Mark causing session errors

I have an PHP app with houndreds of files. The problem is that one or several files apparently have a BOM in them, so including them causes error when creating the session... Is there a way how to reconfigure PHP or the server or how can I get rid of the BOM? Or at least identify the source? I would prefer a PHP solution if available
The real solution of course is to fix your editor settings (and the other team members as well) to not store files with UTF byte order mark. Read on here: https://stackoverflow.com/a/2558793/43959
You could use this function to "transparently" remove the BOM before including another PHP file.
Note: I really recommend you to fix your editor(s) / files instead of doing nasty things with eval() which i demonstrate here.
This is just a proof of concept:
bom_test.php:
<?php
function bom_safe_include($file) {
$fd = fopen($file, "r");
// read 3 bytes to detect BOM. file read pointer is now behind BOM
$possible_bom = fread($fd, 3);
// if the file has no BOM, reset pointer to beginning file (0)
if ($possible_bom !== "\xEF\xBB\xBF") {
fseek($fd, 0);
}
$content = stream_get_contents($fd);
fclose($fd);
// execute (partial) script (without BOM) using eval
eval ("?>$content");
// export global vars
$GLOBALS += get_defined_vars();
}
// include a file
bom_safe_include("test_include.php");
// test function and variable from include
test_function($test);
test_include.php, with BOM at beginning
test
<?php
$test = "Hello World!";
function test_function ($text) {
echo $text, PHP_EOL;
}
OUTPUT:
kaii#test$ php bom_test.php
test
Hello World!
I have been able to identify the files that carried BOM inside them with this script, maybe it helps someone else with the same problem in the future. Works without eval().
function fopen_utf8 ($filename) {
$file = #fopen($filename, "r");
$bom = fread($file, 3);
if ($bom != b"\xEF\xBB\xBF")
{
return false;
}
else
{
return true;
}
}
function file_array($path, $exclude = ".|..|libraries", $recursive = true) {
$path = rtrim($path, "/") . "/";
$folder_handle = opendir($path);
$exclude_array = explode("|", $exclude);
$result = array();
while(false !== ($filename = readdir($folder_handle))) {
if(!in_array(strtolower($filename), $exclude_array)) {
if(is_dir($path . $filename . "/")) {
// Need to include full "path" or it's an infinite loop
if($recursive) $result[] = file_array($path . $filename . "/", $exclude, true);
} else {
if ( fopen_utf8($path . $filename) )
{
//$result[] = $filename;
echo ($path . $filename . "<br>");
}
}
}
}
return $result;
}
$files = file_array(".");
vim $(find . -name \*.php)
once inside vim:
:argdo :set nobomb | :w

Categories