i am trying to create folders from within php. Whenever i use the mkdir function with permission 0777 i get a read-only folder. I want this folder to be read & write.
The parent folder (drive/) is fully writable and readable for every user.
This is what i use: mkdir(ABSPATH . 'drive/' . $folderName, 0777);
I have also tried to use it without any additional paramaters: mkdir(ABSPATH . 'drive/' . $folderName);
Any ideas why this is and how to fix this so that i can generate folders that has write access?
In a shared environment, mkdir fails to set the permissions properly. A workaround is to set the chmod with chmod() after you've created the directory.
You can have write permission too with mkdir..Here is the code
<?php
$dir = 'myDir';
// create new directory with 744 permissions if it does not exist yet
// owner will be the user/group the PHP script is run under
if ( !file_exists($dir) ) {
mkdir ($dir, 0744);
}
file_put_contents ($dir.'/test.txt', 'Hello File');
Found the source from here
the issue probably is the mask :)
if (!function_exists('mkdir_r')) {
/**
* create directory recursively
* #param $dirName
* #param int $rights
* #param string $dir_separator
* #return bool
*/
function mkdir_r($dirName, $rights = 0744, $dir_separator = DIRECTORY_SEPARATOR) {
$dirs = explode($dir_separator, $dirName);
$dir = '';
$created = false;
foreach ($dirs as $part) {
$dir .= $part . $dir_separator;
if (!is_dir($dir) && strlen($dir) > 0) {
$created = mkdir($dir, $rights);
}
}
return $created;
}
}
if (!function_exists('ensure_dir')) {
/**
* ensure directory exist if not create
* #param $dir_path
* #param int $mode
* #param bool $use_mask
* #param int $mask
* #return bool
*/
function ensure_dir($dir_path, $mode = 0744, $use_mask = true, $mask = 0002) {
// set new mask
$old_mask = $use_mask && $mask != null
? umask($mask)
: null;
try {
return is_dir($dir_path) || mkdir_r($dir_path, $mode);
} finally {
if ($use_mask && $old_mask != null) {
// restore original mask
umask($old_mask);
}
}
}
}
Related
So I really need help I bought some PHP file manager and I found out that this function is missing so I cannot use it. I know HTML a lot but PHP is a new thing for me so any help would be great. I need to add a daily limit for each user of downloads.
Some code below from the file I think is the one to modify(but not sure):
<?php
if (!class_exists('Downloader', false)) {
class Downloader
{
/**
* Checks if file is under user folder
*
* #param string $checkPath path to check
*
* #return true/false
*/
public function subDir($checkPath)
{
global $gateKeeper;
if ($gateKeeper->getUserInfo('dir') == null) {
return true;
} else {
$userdirs = json_decode($gateKeeper->getUserInfo('dir'), true);
foreach ($userdirs as $value) {
$pos = strpos($checkPath, $value);
if ($pos !== false) {
return true;
}
}
}
return false;
}
/**
* The safe way
*
* #param string $checkfile file to check
* #param string $path relative path to call the functionf from /ajax/
*
* #return true/false
*/
public function checkFile($checkfile, $path = '')
{
global $setUp;
$fileclean = base64_decode($checkfile);
$file = $path.'../'.urldecode($fileclean);
$filepathinfo = Utils::mbPathinfo($fileclean);
$filename = $filepathinfo['basename'];
$safedir = $filepathinfo['dirname'];
$safedir = str_replace(array('/', '.'), '', $safedir);
$realfile = realpath($file);
$realsetup = realpath($path.'.'.$setUp->getConfig('starting_dir'));
$avoidDir = array('vfm-admin', 'etc');
$avoidFile = array('index.php', 'vfm-thumb.php', '.htaccess', '.htpasswd');
if (strpos($realfile, $realsetup) !== false
&& !in_array($safedir, $avoidDir)
&& !in_array($filename, $avoidFile)
&& file_exists($file)
) {
return true;
}
return false;
}
/**
* Check download lifetime
*
* #param string $time time to check
*
* #return true/false
*/
public function checkTime($time)
{
global $setUp;
$lifedays = (int)$setUp->getConfig('lifetime');
$lifetime = 86400 * $lifedays;
if (time() <= $time + $lifetime) {
return true;
}
return false;
}
/**
* Get file info before processing download
*
* #param string $getfile file to download
* #param string $playmp3 check audio
*
* #return $headers array
*/
public function getHeaders($getfile, $playmp3 = false)
{
$headers = array();
$audiofiles = array('mp3','wav');
$trackfile = './'.urldecode(base64_decode($getfile));
$file = '.'.$trackfile;
$filepathinfo = Utils::mbPathinfo($file);
$filename = $filepathinfo['basename'];
$dirname = $filepathinfo['dirname'].'/';
$ext = $filepathinfo['extension'];
$file_size = Utils::getFileSize($file);
$disposition = 'inline';
if (strtolower($ext) == 'pdf') {
$content_type = 'application/pdf';
} elseif (strtolower($ext) == 'zip') {
$content_type = 'application/zip';
$disposition = 'attachment';
} elseif (in_array(strtolower($ext), $audiofiles)
&& $playmp3 == 'play'
) {
$content_type = 'audio/mp3';
} else {
$content_type = 'application/force-download';
}
$headers['file'] = $file;
$headers['filename'] = $filename;
$headers['file_size'] = $file_size;
$headers['content_type'] = $content_type;
$headers['disposition'] = $disposition;
$headers['trackfile'] = $trackfile;
$headers['dirname'] = $dirname;
return $headers;
}
/**
* Download files
*
* #param string $file path to download
* #param string $filename file name
* #param string $file_size file size
* #param string $content_type header content type
* #param string $disposition header disposition
* #param bool $android android device
*
* #return file served
*/
public function download(
$file,
$filename,
$file_size,
$content_type,
$disposition = 'inline',
$android = false
) {
// Gzip enabled may set the wrong file size.
if (function_exists('apache_setenv')) {
#apache_setenv('no-gzip', 1);
}
if (ini_get('zlib.output_compression')) {
#ini_set('zlib.output_compression', 'Off');
}
#set_time_limit(0);
session_write_close();
header("Content-Length: ".$file_size);
if ($android) {
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
} else {
header("Content-Type: $content_type");
header("Content-Disposition: $disposition; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Expires: -1");
}
if (ob_get_level()) {
ob_end_clean();
}
readfile($file);
return true;
}
}
}
You need to create a new table/column in Database in which you would store amount of downloads for user (how many times he already downloaded). Number with limit of downloads you can keep in const variable or in DB too, depends how you want to manage that.
Then, everytime that user wants to download file, just make simple check - alreadyDownloadedTimes >= limitDownloadTimes in simple if statement.
Profit of having limit in DB is that you can make function in admin panel to easily change its value in DB instead of diving into code.
There is too much code to write it here so I will point it:
1. Create column with number representing limit of downloads (in new Table - you can combine it with other limits)
2. Create column with number representing how many times user already downloaded (needs to be updated when user downloads).
3. Make queries for UPDATE (when user downloads) and SELECT (for number representing limit) + optionally queries for managing these limits (if you want to have full control in admin panel or you have premium accounts etc.)
4. Everytime that user downloads file, make simple check if limit is reached - if not, let it go, if yes, block the download option.
5. Make cron job for reseting that value in DB (amount of downloads per user) every 24hrs
I'm using ZipArchive and I want to extract ZIP file.
I can see a comment in the docs for ZipArchive::extractTo:
Note, in Linux (possibly other *nix platforms too) there is no way to extract hidden files ( aka filename starting with a '.') from a Zip archive.
And very important note: I need it to work on both *nix and Windows platforms.
So how to properly extract ZIP file into dir, including hidden files?
Thanks in advance,
JK.
You could use the system() or exec() functions if the server allows them :
system("unzip archive.zip");
There are although shell_exec() and passthru().
Hope it helps.
EDIT
Since OP looking for pure-php solution here is a user implemented function for php manual (Zip Functions) :
<?php
/**
* Unzip the source_file in the destination dir
*
* #param string The path to the ZIP-file.
* #param string The path where the zipfile should be unpacked, if false the directory of the zip-file is used
* #param boolean Indicates if the files will be unpacked in a directory with the name of the zip-file (true) or not (false) (only if the destination directory is set to false!)
* #param boolean Overwrite existing files (true) or not (false)
*
* #return boolean Succesful or not
*/
function unzip($src_file, $dest_dir=false, $create_zip_name_dir=true, $overwrite=true)
{
if ($zip = zip_open($src_file))
{
if ($zip)
{
$splitter = ($create_zip_name_dir === true) ? "." : "/";
if ($dest_dir === false) $dest_dir = substr($src_file, 0, strrpos($src_file, $splitter))."/";
// Create the directories to the destination dir if they don't already exist
create_dirs($dest_dir);
// For every file in the zip-packet
while ($zip_entry = zip_read($zip))
{
// Now we're going to create the directories in the destination directories
// If the file is not in the root dir
$pos_last_slash = strrpos(zip_entry_name($zip_entry), "/");
if ($pos_last_slash !== false)
{
// Create the directory where the zip-entry should be saved (with a "/" at the end)
create_dirs($dest_dir.substr(zip_entry_name($zip_entry), 0, $pos_last_slash+1));
}
// Open the entry
if (zip_entry_open($zip,$zip_entry,"r"))
{
// The name of the file to save on the disk
$file_name = $dest_dir.zip_entry_name($zip_entry);
// Check if the files should be overwritten or not
if ($overwrite === true || $overwrite === false && !is_file($file_name))
{
// Get the content of the zip entry
$fstream = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
file_put_contents($file_name, $fstream );
// Set the rights
chmod($file_name, 0777);
echo "save: ".$file_name."<br />";
}
// Close the entry
zip_entry_close($zip_entry);
}
}
// Close the zip-file
zip_close($zip);
}
}
else
{
return false;
}
return true;
}
I'd like some help please. I have this PHP script inside my Post_model constructor
$dir = FCPATH . 'uploads' . DIRECTORY_SEPARATOR . 'posts';
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
which shows me this error:
Severity: Warning
Message: mkdir(): Permission denied
The main idea is that the project has the ability to create users and these users can upload images, or create folders-albums which are stored in the uploads folder.
I've been struggling to fix this error the last days and can't find a solution. I have tried this code and on Windows and works great, but not on Linux (Ubuntu 14.04)
Please try chmod 777 -R . in your directory
Even i had same problem , i tried with umask, it worked. you can do like this,
$old = umask(0);
mkdir($dir, 0755, true);
umask($old);
[How to Create Directory in PHP / CodeIgniter]
(http://codedpoint.16mb.com/index.php/viewCode?topic=Create%20Directory%20-%20CodeIgnitor)
I suggest you manually create 'uploads' folder and give it 777 permission (not recursive) and then in your php script do the following:
if(!is_dir('./uploads/posts')) //create the folder if if does not already exists
{
mkdir('./uploads/posts',0755,TRUE);
}
by this, every time your script tries to create a new directory, it will have the permission to do so since you are creating the new directory inside uploads which has 777.
the issue probably is the mask :)
if (!function_exists('mkdir_r')) {
/**
* create directory recursively
* #param $dirName
* #param int $rights
* #param string $dir_separator
* #return bool
*/
function mkdir_r($dirName, $rights = 0744, $dir_separator = DIRECTORY_SEPARATOR) {
$dirs = explode($dir_separator, $dirName);
$dir = '';
$created = false;
foreach ($dirs as $part) {
$dir .= $part . $dir_separator;
if (!is_dir($dir) && strlen($dir) > 0) {
$created = mkdir($dir, $rights);
}
}
return $created;
}
}
if (!function_exists('ensure_dir')) {
/**
* ensure directory exist if not create
* #param $dir_path
* #param int $mode
* #param bool $use_mask
* #param int $mask
* #return bool
*/
function ensure_dir($dir_path, $mode = 0744, $use_mask = true, $mask = 0002) {
// set mask
$old_mask = $use_mask && $mask != null
? umask($mask)
: null;
try {
return is_dir($dir_path) || mkdir_r($dir_path, $mode);
} finally {
if ($use_mask && $old_mask != null) {
// restore original
umask($old_mask);
}
}
}
}
At work, we have a website on which we publish PDF files which are available for download (mostly user notices etc.). We also manage our internal database for updates and to generate CD's and USB Sticks with all PDF files on it, which are shipped out with the products.
So I build a platform where all plants that produce these PDF files can upload them. From time to time, a person will take care of updating the system (sync both servers).
I would like to have a link next to the files with a delete option. I already have that using a simple php script.
<?php
$deleter = new Deleter("./");
class Deleter {
var $filename;
var $ignorelist = array (
'.',
'..',
'index.php',
'del.php',
'deletefile.php'
);
function Deleter($path="./") {
$this->__construct($path);
}
function __construct($path="./") {
$this->filename = basename(__FILE__);
array_push($this->ignorelist, $this->filename);
// insert page header
$this->createHeader();
// condition: create initial file list?
if (isset($_GET['delete']) && !empty($_GET['delete'])) {
// a path has been set, escape and use
$path = basename($_GET['delete']);
$path = urldecode($path);
//$path = mysql_real_escape_string($path);
// condition : Step 2: seek deletion confirmation?
if (!isset($_GET['confirm']) || $_GET['confirm'] != 'aye') {
$this->createConfirmationStep($path);
// step 3: delete!
} else {
$this->createShowDelete($path);
}
// step 1: no files selected, create file list
} else {
echo '
<p>These files are on the server:</p>
<ul>
';
$this->createFileList($path);
echo '</ul>';
}
// insert page footer
$this->createFooter();
}
/**
* Step 1: Create a list of all files within a specific directory
*
* #param string $path The server path to look for files in
* #return array $fileList Array of all files, with file/directory details
* #access public
*/
function createFileList($path) {
// condition : if the path isn't set, assume one
if (!isset($path)) {
$path = "./";
}
// temporary arrays to hold separate file and directory content
$filelist = array();
$directorylist = array();
// get the ignore list, in local scope
$ignorelist = $this->ignorelist;
// Open directory and read contents
if (is_dir($path)) {
// loop through the contents (PHP4 compat)
$dh = opendir($path);
while (false !== ($file = readdir($dh))) {
// skip over any files in the ignore list
if (!in_array($file, $ignorelist)) {
// condition : if it is a directory, add to dir list array
if (is_dir($path.$file)) {
$directorylist[] = array(
"path" => $path,
"file" => $file,
"filetype" => 'directory',
"date" => date("M d Y, H:i", filemtime($path.$file."")),
"filecount" => $this->countRelevantFiles($path.$file),
"filesize" => 0
);
// file, add to file array
} else {
$filelist[] = array(
"path" => $path,
"file" => $file,
"filetype" => $this->getFileType($path.$file) . " file",
"date" => date("M d Y, H:i", filemtime($path.$file."")),
"filecount" => 0,
"filesize" => $this->getFileSize(filesize($path.$file))
);
}
}
}
}
// merge file and directory lists
$finalList = array_merge($directorylist, $filelist);
// loop through each file
foreach ($finalList as $key => $value) {
// condition : add trailing slash for directories
$trailingslash = ($value['filetype'] == 'directory' ) ? '/' : '';
// condition : if it is a directory, display count of subfiles
if ($value['filetype'] == 'directory') {
$fileending = ($value['filecount'] == 1) ? 'item' : 'items';
$filedetails = ' (contains '.$value['filecount'].' '.$fileending.')';
// else, if it is a file, display file size
} else {
$filedetails = ' ('.$value['filesize'].')';
}
// create the html for each project
echo '
<li class="' . $value['filetype'].'" id="file_' . urlencode($value['file']) . '">
<strong>' . $value['file'] . '</strong> /
';
echo '
<a href="./'.$this->filename.'?delete='.urlencode($value['file'].$trailingslash).'">
Delete
</a>
</li>
';
}
}
/**
* count the number of files in a directory, not including the list of ignorable files
*
* #param string $path The server path to look for files in
* #return int $count The number of relevant files
* #access private
*/
function countRelevantFiles($path, $count = 0) {
// open the directory
if (is_dir($path)) {
// loop through all files, checking if we should count the current one
$dh = opendir($path);
while (false !== ($file = readdir($dh))) {
if (!in_array($file, $this->ignorelist)) {
$count++;
if(is_dir($path."/".$file)) {
$count = $this->countRelevantFiles($path."/".$file, $count);
}
}
}
}
// return the result
return $count;
}
/**
* list all sub-files of a directory
*
* #param string $path The server path to look for files in
* #return void
* #access private
*/
function listFilesToDelete($path) {
// open the directory
if (is_dir($path)) {
// loop through all files, checking if we should count the current one
$dh = opendir($path);
while (false !== ($file = readdir($dh))) {
if (!in_array($file, $this->ignorelist)) {
echo '<li>'.$path.'/'.$file.'</li>';
if(is_dir($path."/".$file)) {
$this->listFilesToDelete($path."/".$file);
}
}
}
}
}
/**
* Delete files
*
* #param string $path The server path to delete
* #return void
* #access private
*/
function delete($path) {
// Simple delete for a file
if (is_file($path)) {
echo '<li>deleting file: ' . $path . '</li>';
if (copy($path, "../trash/".$path)) {
unlink($path);
}
}
}
/**
* Create a nice readable filesize from the number of bytes in a file
*
* #param int $size the size in bytes
* #param string $retstring
*
* #return string the size in nice words
*/
function getFileSize($size, $retstring = null)
{
$sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
if ($retstring === null) { $retstring = '%01.2f %s'; }
$lastsizestring = end($sizes);
foreach ($sizes as $sizestring) {
if ($size < 1024) { break; }
if ($sizestring != $lastsizestring) { $size /= 1024; }
}
if ($sizestring == $sizes[0]) { $retstring = '%01d %s'; } // Bytes aren't normally fractional
return sprintf($retstring, $size, $sizestring);
}
/**
* Function to find a file type for a given filename
*
* #param string $file filename/path
* #return string $extension file type
*/
function getFileType($file="") {
// get file name
$filearray = explode("/", $file);
$filename = array_pop($filearray);
// condition : if no file extension, return
if(strpos($filename, ".") === false) return false;
// get file extension
$filenamearray = explode(".", $filename);
$extension = $filenamearray[(count($filenamearray) - 1)];
return $extension;
}
/* Page Building Methods */
/**
* Create page header
*/
function createHeader(){
echo '
';
}
/**
* Create page footer
*/
function createFooter(){
echo '
';
}
/**
* Create confirmation step
*/
function createConfirmationStep($path){
echo '
<p>� back to file list</p>
<p>Please confirm that you want to delete the following files:</p>
<p class="confirm">Delete</p>
<ol>
<li>'.$path.'</li>
';
$this->listFilesToDelete($path);
echo '
</ol>
<p class="confirm">Delete</p>
';
}
/**
* Show the files you're deleting
*/
function createShowDelete($path){
echo '
<p>� back to file list</p>
<p>The following items have been removed:</p>
<ol>
';
$this->delete($path);
echo '
</ol>
<p><strong>Deletion complete.</strong></p>
<p>� back to file list</p>
';
}
}
?>
Now what I would like this to do is delete a file on one server e.g. server1.com/files/ and move the same file from server2.com/files/ to server2.com/trash/
I have full access to both servers. Is there any way to do that?
since you didn't tell us on what OS you're running you php script, I'm assuming you have a linux.
since you need to do that from one server, you'd need to have a passwordless ssh access to the other server. then you'd need to create a bash script that utilizes mv and rsync to do the file manipulations you need. and then you can use php's exec() function to execute and send the filename param to the shell script from a web page.
I think it's better to configure rsync over ssh with --delete option. Something like this
/usr/bin/rsync -avz --delete /path/files -e "ssh" userforsync#$SECONDARYSERVER:/path/files
where is $SECONDARYSERVER is dns name or ip. To make this work you should accept authentication by public key on secondary server and add public key to authorized keys
I'm trying to enforce a root directory in a filesystem abstraction. The problem I'm encountering is the following:
The API lets you read and write files, not only to local but also remote storages. So there's all kinds of normalisation going on under the hood. At the moment it doesn't support relative paths, so something like this isn't possible:
$filesystem->write('path/to/some/../relative/file.txt', 'file contents');
I want to be able to securely resolve the path so the output is would be: path/to/relative/file.txt.
As is stated in a github issue which was created for this bug/enhancement (https://github.com/FrenkyNet/Flysystem/issues/36#issuecomment-30319406) , it needs to do more that just splitting up segments and removing them accordingly.
Also, since the package handles remote filesystems and non-existing files, realpath is out of the question.
So, how should one go about when dealing with these paths?
To quote Jame Zawinski:
Some people, when confronted with a problem, think "I know, I'll use regular expressions."
Now they have two problems.
protected function getAbsoluteFilename($filename) {
$path = [];
foreach(explode('/', $filename) as $part) {
// ignore parts that have no value
if (empty($part) || $part === '.') continue;
if ($part !== '..') {
// cool, we found a new part
array_push($path, $part);
}
else if (count($path) > 0) {
// going back up? sure
array_pop($path);
} else {
// now, here we don't like
throw new \Exception('Climbing above the root is not permitted.');
}
}
// prepend my root directory
array_unshift($path, $this->getPath());
return join('/', $path);
}
I've resolved how to do this, this is my solution:
/**
* Normalize path
*
* #param string $path
* #param string $separator
* #return string normalized path
*/
public function normalizePath($path, $separator = '\\/')
{
// Remove any kind of funky unicode whitespace
$normalized = preg_replace('#\p{C}+|^\./#u', '', $path);
// Path remove self referring paths ("/./").
$normalized = preg_replace('#/\.(?=/)|^\./|\./$#', '', $normalized);
// Regex for resolving relative paths
$regex = '#\/*[^/\.]+/\.\.#Uu';
while (preg_match($regex, $normalized)) {
$normalized = preg_replace($regex, '', $normalized);
}
if (preg_match('#/\.{2}|\.{2}/#', $normalized)) {
throw new LogicException('Path is outside of the defined root, path: [' . $path . '], resolved: [' . $normalized . ']');
}
return trim($normalized, $separator);
}
./ current location
../ one level up
function normalize_path($str){
$N = 0;
$A =explode("/",preg_replace("/\/\.\//",'/',$str)); // remove current_location
$B=[];
for($i = sizeof($A)-1;$i>=0;--$i){
if(trim($A[$i]) ===".."){
$N++;
}else{
if($N>0){
$N--;
}
else{
$B[] = $A[$i];
}
}
}
return implode("/",array_reverse($B));
}
so:
"a/b/c/../../d" -> "a/d"
"a/./b" -> "a/b"
/**
* Remove '.' and '..' path parts and make path absolute without
* resolving symlinks.
*
* Examples:
*
* resolvePath("test/./me/../now/", false);
* => test/now
*
* resolvePath("test///.///me///../now/", true);
* => /home/example/test/now
*
* resolvePath("test/./me/../now/", "/www/example.com");
* => /www/example.com/test/now
*
* resolvePath("/test/./me/../now/", "/www/example.com");
* => /test/now
*
* #access public
* #param string $path
* #param mixed $basePath resolve paths realtively to this path. Params:
* STRING: prefix with this path;
* TRUE: use current dir;
* FALSE: keep relative (default)
* #return string resolved path
*/
function resolvePath($path, $basePath=false) {
// Make absolute path
if (substr($path, 0, 1) !== DIRECTORY_SEPARATOR) {
if ($basePath === true) {
// Get PWD first to avoid getcwd() resolving symlinks if in symlinked folder
$path=(getenv('PWD') ?: getcwd()).DIRECTORY_SEPARATOR.$path;
} elseif (strlen($basePath)) {
$path=$basePath.DIRECTORY_SEPARATOR.$path;
}
}
// Resolve '.' and '..'
$components=array();
foreach(explode(DIRECTORY_SEPARATOR, rtrim($path, DIRECTORY_SEPARATOR)) as $name) {
if ($name === '..') {
array_pop($components);
} elseif ($name !== '.' && !(count($components) && $name === '')) {
// … && !(count($components) && $name === '') - we want to keep initial '/' for abs paths
$components[]=$name;
}
}
return implode(DIRECTORY_SEPARATOR, $components);
}