Error on ftp-file close operation - php

I'm using php to access file by ftp.
My file read function is:
function _rfile ($file = null) {
if ( is_readable($file) ) {
if ( !($fh = fopen($file, 'r')) ) return false;
$data = fread($fh, filesize($file));
fclose($fh);
return $data;
}
return false;
}
I am getting an error on file close operation in this function with one of my ftp host.
error:
fclose(): FTP server error 550:550 The specified network name is no
longer available.
This function worked fine for some other ftp host's.
Could smb advice a solution?

It may due to the access permission settings.
Please look at this link. http://forums.iis.net/t/1107644.aspx

Related

Permission denied from a subfolder

Context
PHP 5.6
IIS
Windows 11
Issue
I am trying to write a file in a specific folder but it gives me permission denied.
So, I verified the permissions and everything seemed all right. Because this is in a development environment, I decided to change the permissions to be "Every one can do anything" to the "root" folder where all my files are written. I tried to replace all the permissions underneath. I tried to remove the inherited permissions. Nothing does it.
I then tried to write a file in the "root" folder. It worked.On the subfolder, it worked. On the subsubfolder. It worked. In the subfolder chain there is a point when it doesn't work, but before the real subfolder.
Here is the path hierachy when it crashes.
$f = new \wee\common\IO\File();
$f->write("DRIVE:/BASE_PATH/files/-/00.jpg", "hello"); // WORKS
$f->write("DRIVE:/BASE_PATH/files/-/mod/00.jpg", "hello"); // WORKS
$f->write("DRIVE:/BASE_PATH/files/-/mod/com.ci.company/00.jpg", "hello"); // WORKS
$pathLength = strlen("DRIVE:/BASE_PATH/files/-/mod/com.ci.company/site/00.jpg"); // Real path length is 85
$f->write("DRIVE:/BASE_PATH/files/-/mod/com.ci.company/site/00.jpg", "hello"); // FAILS
$f->write("DRIVE:/BASE_PATH/files/-/mod/com.ci.company/site/WorkersManager/00.jpg", "hello");
$f->write("DRIVE:/BASE_PATH/files/-/mod/com.ci.company/site/WorkersManager/workers/00.jpg", "hello");
The class \wee\common\IO\File is my creation, but works at a lot of other places.
The exact error message I am getting is:
fopen(DRIVE:/BASE_PATH/files/-/mod/com.ci.company/site/00.jpg): failed to open stream: Permission denied
Just to be 100% clear: The "root" folder is DRIVE:/BASE_PATH/files/
Edit #1
Here is the implementation of the write method of the File class.
public function write($fileName, $data, $lock = false) {
$this->_write($fileName, $data, $lock);
}
private function _write($fileName, $data, $lock = false, $openMode = 'w') {
if ($data === null)
$data = "";
$fh = fopen($fileName, $openMode) or die("can't open file"); // FAILS HERE
if ($lock) {
flock($fh, LOCK_EX);
}
fwrite($fh, (is_array($data) ? join("\n", $data) : $data));
if ($lock) {
fflush($fh);
flock($fh, LOCK_UN);
}
fclose($fh);
}
The issue was coming from PHP 5.6.26. Using PHP 5.6.40 fixed it.
I reset to my original permissions and everything is fine!

How to read csv file from zip file on remote server with php?

I would like to read a zip file from a remote server. I currently have to following code :
private $sftp;
public function __construct($username, $password, $serverName)
{
$this->sftp = new Net_SFTP($serverName);
if (!$this->sftp->login($username, $password)) {
exit('Login Failed');
}
}
public function buildRecords() {
$sftp = $this->sftp;
$sftp -> chdir(Constants::QUICKCHECK_OUTPUT_DIRECTORY);
echo $sftp->pwd(); // show that we're in the 'test' directory
// print_r($sftp->nlist());
foreach($sftp->nlist() as $zipFile) {
$handle = fopen("zip://" . $zipFile,'r');
while($line = fgetcsv($handle)) {
print_r($line);
}
}
}
When I run this code and call these methods I get the error
Warning: fopen(zip://test.zip): failed to open stream: operation failed in /var/www/html/update_alerts2.php on line 67
How do I fix this error? (I'm using the phpseclib to sftp)
fopen will not magically be able to access files on a remote server only because you have logged into the server using phpseclib before.
You have to use phpseclib functions to retrieve the file contents.
Unfortunately phpseclib does not offer a way to read remote file contents by lines/chunks. But as it is CSV file, it is probably OK to load from file to memory at once. For that you can use SFTP::get, if you do not specify the $local_file argument:
$contents = $sftp->get($zipFile);
$lines = explode("\n", $contents);
foreach ($lines as $line)
{
if (strlen($line) > 0)
{
$fields = str_getcsv($line);
print_r($fields);
}
}

Open content.xml in a odt-file directly via php [duplicate]

I need to read the content of a single file, "test.txt", inside of a zip file. The whole zip file is a very large file (2gb) and contains a lot of files (10,000,000), and as such extracting the whole thing is not a viable solution for me. How can I read a single file?
Try using the zip:// wrapper:
$handle = fopen('zip://test.zip#test.txt', 'r');
$result = '';
while (!feof($handle)) {
$result .= fread($handle, 8192);
}
fclose($handle);
echo $result;
You can use file_get_contents too:
$result = file_get_contents('zip://test.zip#test.txt');
echo $result;
Please note #Rocket-Hazmat fopen solution may cause an infinite loop if a zip file is protected with a password, since fopen will fail and feof fails to return true.
You may want to change it to
$handle = fopen('zip://file.zip#file.txt', 'r');
$result = '';
if ($handle) {
while (!feof($handle)) {
$result .= fread($handle, 8192);
}
fclose($handle);
}
echo $result;
This solves the infinite loop issue, but if your zip file is protected with a password then you may see something like
Warning: file_get_contents(zip://file.zip#file.txt): failed to open
stream: operation failed
There's a solution however
As of PHP 7.2 support for encrypted archives was added.
So you can do it this way for both file_get_contents and fopen
$options = [
'zip' => [
'password' => '1234'
]
];
$context = stream_context_create($options);
echo file_get_contents('zip://file.zip#file.txt', false, $context);
A better solution however to check if a file exists or not before reading it without worrying about encrypted archives is using ZipArchive
$zip = new ZipArchive;
if ($zip->open('file.zip') !== TRUE) {
exit('failed');
}
if ($zip->locateName('file.txt') !== false) {
echo 'File exists';
} else {
echo 'File does not exist';
}
This will work (no need to know the password)
Note: To locate a folder using locateName method you need to pass it like folder/ with a
forward slash at the end.

PHP: fopen error handling

I do fetch a file with
$fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb");
$str = stream_get_contents($fp);
fclose($fp);
and then the method gives it back as image. But when fopen() fails, because the file did not exists, it throws an error:
[{"message":"Warning: fopen(uploads\/Team\/img\/1.png): failed to open stream: No such file or directory in C:\...
This is coming back as json, obviously.
The Question is now: How can i catch the error and prevent the method from throwing this error directly to the client?
You should first test the existence of a file by file_exists().
try
{
$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( !file_exists($fileName) ) {
throw new Exception('File not found.');
}
$fp = fopen($fileName, "rb");
if ( !$fp ) {
throw new Exception('File open failed.');
}
$str = stream_get_contents($fp);
fclose($fp);
// send success JSON
} catch ( Exception $e ) {
// send error message if you can
}
or simple solution without exceptions:
$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( file_exists($fileName) && ($fp = fopen($fileName, "rb"))!==false ) {
$str = stream_get_contents($fp);
fclose($fp);
// send success JSON
}
else
{
// send error message if you can
}
You can use the file_exists() function before calling fopen().
if(file_exists('uploads/Team/img/'.$team_id.'.png')
{
$fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb");
$str = stream_get_contents($fp);
fclose($fp);
}
[{"message":"Warning: fopen(uploads\/Team\/img\/1.png): failed to open stream: No such file or directory in C:\...
the error is clear: you've put the wrong directory, you can try what you whant but it'll not work. you can make it work with this:
take your file and put it in the same folder of your php file
(you'll be able to move it after don't worry, it's about your error)
or on a folder "higher" of your script (just not outside of your www
folder)
change the fopen to ('./$team_id.'png',"rb");
rerun your script file
don't forget this : you can't access a file that is'nt in your "www" folder
(he doesn't found your file because he give you her name: the name come from the $team_id variable)
Generically - This is probably the best way to do file-io in php (as mentioned by #Cendak here)
$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( file_exists($fileName) && ($fp = fopen($fileName, "rb"))!==false ){
$str = stream_get_contents($fp);
fclose($fp);
// send success JSON
}else{
// send an error message if you can
}
But it does not work with PHP 7.3, these modifications do,
if(file_exists($filename) && ($fp = fopen($filename,"r") !== false)){
$fp = fopen($filename,"r");
$filedata = fread($fp,filesize($filename));
fclose($fp);
}else{
$filedata = "default-string";
}

PHP not writing to file from one source

I have an issue I can't seem to find the solution for. I am trying to write to a flat text file. I have echoed all variables out on the screen, verified permissions for the user (www-data) and just for grins set everything in the whole folder to 777 - all to no avail. Worst part is I can call on the same function from another file and it writes. I can't see to find the common thread here.....
function ReplaceAreaInFile($AreaStart, $AreaEnd, $File, $ReplaceWith){
$FileContents = GetFileAsString($File);
$Section = GetAreaFromFile($AreaStart, $AreaEnd, $FileContents, TRUE);
if(isset($Section)){
$SectionTop = $AreaStart."\n";
$SectionTop .= $ReplaceWith;
$NewContents = str_replace($Section, $SectionTop, $FileContents);
if (!$Handle = fopen($File, 'w')) {
return "Cannot open file ($File)";
exit;
}/*
if(!flock($Handle, LOCK_EX | LOCK_NB)) {
echo 'Unable to obtain file lock';
exit(-1);
}*/
if (fwrite($Handle, $NewContents) === FALSE) {
return "Cannot write to file ($File)";
exit;
}else{
return $NewContents;
}
}else{
return "<p align=\"center\">There was an issue saving your settings. Please try again. If the issue persists contact your provider.</p>";
}
}
Try with...
$Handle = fopen($File, 'w');
if ($Handle === false) {
die("Cannot open file ($File)");
}
$written = fwrite($Handle, $NewContents);
if ($written === false) {
die("Invalid arguments - could not write to file ($File)");
}
if ((strlen($NewContents) > 0) && ($written < strlen($NewContents))) {
die("There was a problem writing to $File - $written chars written");
}
fclose($Handle);
echo "Wrote $written bytes to $File\n"; // or log to a file
return $NewContents;
and also check for any problems in the error log. There should be something, assuming you've enabled error logging.
You need to check for number of characters written since in PHP fwrite behaves like this:
After having problems with fwrite() returning 0 in cases where one
would fully expect a return value of false, I took a look at the
source code for php's fwrite() itself. The function will only return
false if you pass in invalid arguments. Any other error, just as a
broken pipe or closed connection, will result in a return value of
less than strlen($string), in most cases 0.
Also, note that you might be writing to a file, but to a different file that you're expecting to write. Absolute paths might help with tracking this.
The final solution I ended up using for this:
function ReplaceAreaInFile($AreaStart, $AreaEnd, $File, $ReplaceWith){
$FileContents = GetFileAsString($File);
$Section = GetAreaFromFile($AreaStart, $AreaEnd, $FileContents, TRUE);
if(isset($Section)){
$SectionTop = $AreaStart."\n";
$SectionTop .= $ReplaceWith;
$NewContents = str_replace($Section, $SectionTop, $FileContents);
return $NewContents;
}else{
return "<p align=\"center\">There was an issue saving your settings.</p>";
}
}
function WriteNewConfigToFile($File2WriteName, $ContentsForFile){
file_put_contents($File2WriteName, $ContentsForFile, LOCK_EX);
}
I did end up using absolute file paths and had to check the permissions on the files. I had to make sure the www-data user in Apache was able to write to the files and was also the user running the script.

Categories