I have a script block wich count founded and edited files
foreach ($files as $file)
{
$info['founded']++;
$Checkfile = file_get_contents($file);
if(!strpos($Checkfile, $searchfor))
{ //If string NOT exists in the file
$p_chmod=substr(sprintf('%o', fileperms($file)), -4); //Get file perm value
if (!is_writable($file))
{ //if is NOT writable
if(chmod($file,0777)) //Try to set perm
{ //If perm sett
$t_mod=#filemtime($file);
$str=file_get_contents($file);
$sub_count= substr_count($str,$place);
if ($sub_count>0)
{
$info['replaces'] += $sub_count;
$info['edited_files']++;
$str=str_replace($place,$frame,$str);
file_put_contents($file,$str);
#touch($file,$t_mod,$t_mod);
#chmod($file,$p_chmod);
}
} //If perm NOT sett
else $info['nowritable']++;
}
} //if file is writable
else
{
$t_mod=#filemtime($file);
$str=file_get_contents($file);
$sub_count= substr_count($str,$place);
if ($sub_count>0)
{
$info['replaces'] += $sub_count;
$info['edited_files']++;
$str=str_replace($place,$frame,$str);
file_put_contents($file,$str);
#touch($file,$t_mod,$t_mod);
#chmod($file,$p_chmod);
}
}
}
else //If string exists in the file
{
$info['exist_files']++;
}
return $info;
}
and how to echo founded files, something like
$info['foundedFiles']= text & \n & text;
echo $info['foundedFiles']
and what to do if founded files would be about 10000? the takes a lot of page source? maybe echo in scroll box, but how to do that without writing to disk?
How to optimize this code?
chmod is executed as follows:
chmod(DIR, MODE);
chmod("/directory/file.html", 0777);
It will take a decent amount of time on the client side of the program, and might even time out if there are enough files. It will take a decent amount of resources.
Related
I'm trying to create a script that will send across files from one server to another. My script successfully does that as well as checks if the file has something in it or not. My next step is to check whether the file already exists on the server; if the file already exists it does not send and if it does not exist, it does send.
I've tried a few different things and can't seem to get my head around it. How can I get it to check whether the file already exists or not? Any help would be appreciated!
(I had a look at some similar questions but couldn't find anything specific to my issue.)
require('constants.php');
$files = $sftp->nlist('out/');
foreach($files as $file) {
if(basename((string) $file)) {
if(strpos($file,".") > 1) { //Checks if file
$filesize = $sftp->size('out/'.$file); //gets filesize
if($filesize > 1){
if (file_exists('import/'.$file)){
echo $file.' already exists';
}
else {
$sftp->get('out/'.$file, 'import/'.$file); //Sends file over
//$sftp->delete('out/'.$file); //Deletes file from out folder
}
else {
echo $file. ' is empty.</br>';
}
}
}
}
}
EDIT: To try and get this to work, I wrote the following if statement to see if it was finding the file test.php;
if (file_exists('test.txt')){
echo 'True';
} else {
echo 'False';
}
This returned true (a good start) but as soon as I put this into my code, I just get a 500 Internal Server Error (extremely unhelpful). I cannot turn on errors as it is on a server that multiple people use.
I also tried changing the file_exists line to;
if (file_exists('test.txt'))
in the hopes that would work but still didn't work.
Just to clarify, I'm sending the files from the remote server to my local server.
There is a closing curly brace missing right before the second else keyword.
Please try to use a code editor with proper syntax highlighting and code formatting to spot such mistakes on the fly while you are still editing the PHP file.
The corrected and formatted code:
require('constants.php');
$files = $sftp->nlist('out/');
foreach ($files as $file) {
if (basename((string)$file)) {
if (strpos($file, ".") > 1) { //Checks if file
$filesize = $sftp->size('out/' . $file); //gets filesize
if ($filesize > 1) {
if (file_exists('import/' . $file)) {
echo $file . ' already exists';
} else {
$sftp->get('out/' . $file, 'import/' . $file); //Sends file over
}
} else {
echo $file . ' is empty.</br>';
}
}
}
}
Your code checks the file exist in your local server not in remote server.
if (file_exists('import/'.$file)){
echo $file.' already exists';
}
You need to check in remote server using sftp object like
if($sftp->file_exists('import/'.$file)){
echo $file.' already exists';
}
Edit:
Add clearstatcache() before checking file_exists() function as the results of the function get cached.
Refer: file_exists
I was stuck for sometime after this some sort of code. I'm not so new yet not so old in coding using php but I need help with regards to this one.
I have two directories which has more than 1 file, it may come as text or xml.
Lets say directory 1 is populated today and directory 2 will be populated tom.Both directories have the same number of files and the same name and order.
What I want to have is a comparing tool which will comapre each and every file but of course i need to compare those with similar names and then if there's a difference or update in either of the file, it will create a notepad which will write the filename, line in which they have difference.
I came up to this part but im stuck and i need your help guys.
Thanks.
<?php
$dirA = glob('C:\Users\aganda88\Desktop\testing docs\testingdocs1\*');
$dirB = glob('C:\Users\aganda88\Desktop\testing docs\testingdocs2\*');
//Checking that the files are the same
foreach($dirA as $fileName) {
// the file exists in the other folder as well with the same name
if ($exists = array_search($fileName, $dirB) !== false) {
// it exists!
if (md5_file($fileName) !== md5_file($dirB[$exists])) {
// The files are not identical so i need to create a text file to show what line is not the same
copy($fileName, $dirB[$exists]);
/* problem here is you didn't specify which in your requirements */
}
} else {
// it doesn't (what to do here? you didn't specify!)
}
}
// compare the other way
foreach($dirB as $fileName) {
// does the file exist in the other directory?
if ($exists = array_search($fileName, $dirA) !== false) {
// it exists!
if (md5_file($fileName) !== md5_file($dirA[$exists])) {
copy($fileName, $dirA[$exists]);
}
} else {
// it doesn't (what to do here? you didn't specify!)
}
}
?>
Get a list of all files in each directory
You can use glob to grab a list of files in each directory...
$dirA = glob('C:\Users\aganda88\Desktop\testing docs\testingdocs1\*');
$dirB = glob('C:\Users\aganda88\Desktop\testing docs\testingdocs2\*');
Checking that the files are the same
You can do a simple md5 checksum on matching filenames to determine if they are identical or not.
foreach($dirA as $fileName) {
// does the file exist in the other directory?
if ($exists = array_search($fileName, $dirB) !== false) {
// it exists!
if (md5_file($fileName) !== md5_file($dirB[$exists])) {
// The files aren't identical so one of them needs updated
copy($fileName, $dirB[$exists]);
/* problem here is you didn't specify which in your requirements */
}
} else {
// it doesn't (what to do here? you didn't specify!)
}
}
// compare the other way
foreach($dirB as $fileName) {
// does the file exist in the other directory?
if ($exists = array_search($fileName, $dirA) !== false) {
// it exists!
if (md5_file($fileName) !== md5_file($dirA[$exists])) {
copy($fileName, $dirA[$exists]);
}
} else {
// it doesn't (what to do here? you didn't specify!)
}
}
Update files
There's one part of your requirements that you have not clearly defined behavior in... Which file do you update? Because while a change may have been made to C:\Users\aganda88\Desktop\testing docs\testingdocs1\test1.txt these requirements do not distinguish between you overwriting C:\Users\aganda88\Desktop\testing docs\testingdocs1\test1.txt with C:\Users\aganda88\Desktop\testing docs\testingdocs2\test1.txt or C:\Users\aganda88\Desktop\testing docs\testingdocs2\test1.txt with C:\Users\aganda88\Desktop\testing docs\testingdocs1\test1.txt... i.e. the fact that the files are not the same doesn't specify which one should be the source and which one should be the destination. Without that it doesn't really matter if you know that they aren't the same or not...
how can I check that user has selected at-least one file for upload in below code ?
i have tried with in_array, isset, !empty functions but no success
please note that userfile input is array in html
if(!empty($_FILES['userfile']['tmp_name'])){
$upload_dir = strtolower(trim($_POST['name']));
// Create directory if it does not exist
if(!is_dir("../photoes/". $upload_dir ."/")) {
mkdir("../photoes/". $upload_dir ."/");
}
$dirname = "../photoes/".$upload_dir;
for($i=0; $i < count($_FILES['userfile']['tmp_name']);$i++)
{
// check if there is a file in the array
if(!is_uploaded_file($_FILES['userfile']['tmp_name'][$i]))
{
$messages[] = 'No file selected for no. '.$i.'field';
}
/*** check if the file is less then the max php.ini size ***/
if($_FILES['userfile']['size'][$i] > $upload_max)
{
$messages[] = "File size exceeds $upload_max php.ini limit";
}
// check the file is less than the maximum file size
elseif($_FILES['userfile']['size'][$i] > $max_file_size)
{
$messages[] = "File size exceeds $max_file_size limit";
}
else
{
// copy the file to the specified dir
if(#copy($_FILES['userfile']['tmp_name'][$i],$dirname.'/'.$_FILES['userfile']['name'][$i]))
{
/*** give praise and thanks to the php gods ***/
$messages[] = $_FILES['userfile']['name'][$i].' uploaded';
}
}
}
}else{
$messages[] = 'No file selected for upload, Please select atleast one file for upload';
dispform();
}
Here's how I do it its a couple of if's and I use a for loop as I allow multiple file uploads from a single drop down but its the if's that are more important to you
$uploaded = count($_FILES['userfile']['name']);
for ($i=0;$i<$uploaded;$i++) {
if (strlen($_FILES['userfile']['name'][$i])>1) {
// file exists so do something
} else {
//file doesn't exist so do nothing
}
}
You'll note I compare against the name element of the global $_FILES this is because you should never be able to upload a file without a name which also applies for no file uploaded
Don't do it client side thats a dumb place to do validation as the user can simply turn js processing off in the browser or it can be blocked by certain addons etc or intercepted and altered via firebug and various browser search hijacking toolbars etc.
Anything like this should always be done server side!
finally I found the answer, I am giving it here for other users,
I have 5 keys in html input array so array index is up to 4
if(!empty($_FILES['userfile']['tmp_name'][0]) or !empty($_FILES['userfile']['tmp_name'][1]) or !empty($_FILES['userfile']['tmp_name'][2]) or !empty($_FILES['userfile']['tmp_name'][3]) or !empty($_FILES['userfile']['tmp_name'][4])){
//at-least one file is selected so proceed to upload
}else{
//no file selected, notify user
}
There are several methods of doing this with PHP (e.g. Check if specific input file is empty), but with JS it's faster and less expensive on the server. Using jQuery you can do this:
$.fn.checkFileInput = function() {
return ($(this).val()) ? true : false;
}
if ($('input[type="file"]').checkFileInput()) {
alert('yay');
}
else {
alert('gtfo!');
}
I am using this script to delete picture from my server. But at the same time I want to protect the files in my server. Not accidentally delete but I noticed that if I typed the file index.pHp or index.Php is deleted from my server. Although setting it will not delete why php or this method not know between lowercase and uppercase.
What is not done right?
<?php
error_reporting (0);
$thefile = $_GET ['filetodel'];
$filename = "$thefile";
//$filename = "picture1.jpg";
/*protect some files*/
if ($thefile=='index.php' or $thefile=='INDEX.PHP' or $thefile=='UPLOADS.ZIP' or $thefile=='uploads.zip' or $thefile=='del.php'or $thefile=='DEL.PHP' or $thefile==NULL or $thefile=='.htaccess' or $thefile=='.HTACCESS' )
{
exit("<h2>cannot delete $thefile</h2>");
}
if ($thefile=="$thefile")
{
if (file_exists($filename))
{
unlink ("$thefile");
echo "<h2> file $thefile is delete</h2>";
}
else
{
echo "<h2>The<br>";
echo "$filename<br>";
echo "Does not exist</h2>";
}
}
?>
Just convert the input to lowercase and test it once, rather than worrying about every possible mix of case:
if (strtolower($thefile) == 'index.php') {
// ...
}
For the next iteration, you could store your protected files in an array:
$protected_files = array('index.php', 'uploads.zip', 'del.php', '.htaccess');
if (in_array(strtolower($thefile), $protected_files) || $thefile==NULL) {
// ...
}
the problem is here:
if ($thefile=="$thefile")
as if your 1st condition for file check is false than the second condition is
if ($thefile=="$thefile")
which is always true so it will unlink the file
Also add one line as below just before 1st condition
$thefile = strtolower($thefile);
I have a zip file containing one folder, that contains more folders and files, like this:
myfile.zip
-firstlevel
--folder1
--folder2
--folder3
--file1
--file2
Now, I want to extract this file using PHPs ZipArchive, but without the "firstlevel" folder. At the moment, the results look like this:
destination/firstlevel/folder1
destination/firstlevel/folder2
...
The result I'd like to have would look like this:
destination/folder1
destination/folder2
...
I've tried extractTo, which produces the first mentioned result, and copy(), as suggested here, but this doesn't seem to work at all.
My current code is here:
if($zip->open('myfile.zip') === true) {
$firstlevel = $zip->getNameIndex(0);
for($i = 0; $i < $zip->numFiles; $i++) {
$entry = $zip->getNameIndex($i);
$pos = strpos($entry, $firstlevel);
if ($pos !== false) {
$file = substr($entry, strlen($firstlevel));
if(strlen($file) > 0){
$files[] = $file;
}
}
}
//attempt 1 (extractTo):
//$zip->extractTo('./test', $files);
//attempt 2 (copy):
foreach($files as $filename){
copy('zip://'.$firstlevel.'/'.$filename, 'test/'.$filename);
}
}
How can I achieve the result I'm aiming for?
Take a look at my Quick Unzipper script. I wrote this for personal use a while back when uploading large zip files to a server. It was a backup, and 1,000s of files take forever with FTP so using a zip file was faster. I use Git and everything, but there wasn't another option for me. I place this php file in the directory I want the files to go, and put the zip file in the same directory. For my script, they all have to operate in the same directory. It was an easy way to secure it for my needs, as everything I needed was in the same dir.
Quick Unzipper: https://github.com/incomepitbull/QuickUnzipper/blob/master/unzip.php
I linked the file because I am not showcasing the repo, just the code that makes the unzip tick. With modern versions of PHP, there should't be anything that isn't included on your setup. So you shouldn't need to do any server config changes to use this.
Here is the PHP Doc for the ZipArchive class it uses: http://php.net/manual/en/class.ziparchive.php
There isn't any included way to do what you want, which is a shame. So I would unzip the file to a temp directory, then use another function to copy the contents to where you want. So when using ZipArchive, you will need to return the first item to get the folder name if it is unknown. If the folder is known, ie: the same pesky folder name every time, then you could hard code the name.
I have made it return the first item from the index. So if you ALWAYS have a zip with 1 folder inside it, and everything in that folder, this would work. However, if you have a zip file without everything consolidated inside 1 folder, it would fail. The code I have added will take care of your question. You will need to add further logic to handle alternate cases.
Also, You will still be left with the old directory from when we extract it to the temp directory for "processing". So I included code to delete it too.
NOTE: The code uses a lot of if's to show the processing steps, and print a message for testing purposes. You would need to modify it to your needs.
<?php
public function copyDirectoryContents($source, $destination, $create=false)
{
if ( ! is_dir($source) ) {
return false;
}
if ( ! is_dir($destination) && $create === true ) {
#mkdir($destination);
}
if ( is_dir($destination) ) {
$files = array_diff(scandir($source), array('.','..'));
foreach ($files as $file)
{
if ( is_dir($file) ) {
copyDirectoryContents("$source/$file", "$destination/$file");
} else {
#copy("$source/$file", "$destination/$file");
}
}
return true;
}
return false;
}
public function removeDirectory($directory, $options=array())
{
if(!isset($options['traverseSymlinks']))
$options['traverseSymlinks']=false;
$files = array_diff(scandir($directory), array('.','..'));
foreach ($files as $file)
{
if (is_dir("$directory/$file"))
{
if(!$options['traverseSymlinks'] && is_link(rtrim($file,DIRECTORY_SEPARATOR))) {
unlink("$directory/$file");
} else {
removeDirectory("$directory/$file",$options);
}
} else {
unlink("$directory/$file");
}
}
return rmdir($directory);
}
$file = dirname(__FILE__) . '/file.zip'; // full path to zip file needing extracted
$temp = dirname(__FILE__) . '/zip-temp'; // full path to temp dir to process extractions
$path = dirname(__FILE__) . '/extracted'; // full path to final destination to put the files (not the folder)
$firstDir = null; // holds the name of the first directory
$zip = new ZipArchive;
$res = $zip->open($file);
if ($res === TRUE) {
$firstDir = $zip->getNameIndex(0);
$zip->extractTo($temp);
$zip->close();
$status = "<strong>Success:</strong> '$file' extracted to '$temp'.";
} else {
$status = "<strong>Error:</strong> Could not extract '$file'.";
}
echo $status . '<br />';
if ( empty($firstDir) ) {
echo 'Error: first directory was empty!';
} else {
$firstDir = realpath($temp . '/' . $firstDir);
echo "First Directory: $firstDir <br />";
if ( is_dir($firstDir) ) {
if ( copyDirectoryContents($firstDir, $path) ) {
echo 'Directory contents copied!<br />';
if ( removeDirectory($directory) ) {
echo 'Temp directory deleted!<br />';
echo 'Done!<br />';
} else {
echo 'Error deleting temp directory!<br />';
}
} else {
echo 'Error copying directory contents!<br />';
}
} else {
echo 'Error: Could not find first directory';
}
}