Move and delete a file from two servers - php

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

Related

How can I add daily limit of downloads to a user?

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

Uploading files in Fine-Uploader, fail to combine/merge chunks after successful upload

So I've been trying to get Chunked uploading working for a project I've been working on, I'm pretty new to things, in fact for all intensive purposes you can consider me a complete noob who is teaching himself, I'm using the Manual Upload Template from the website, and the Traditional Server Side Example files to gain an understanding of how the code works and trying to piece them together into a fully functional example for me to build from. I've been able to get most things working.
I've managed to get it uploading regular files into the files folder successfully if I upload a file without chunking it goes into my files directory, however if I use chunking it works to chunk up the file and upload it into a folder in my Chunks directory, but i cant seem to figure out how to get it to put the chunks back together and place it in the Files directory
My Firefox console gives me this response and stops after finishing uploading a file in chunks regardless of if I have my chunking success endpoint included in my code or not which makes me think it's got something to do with my chunking success endpoint not being set up correctly or something along those lines.
[Fine Uploader 5.11.8] All chunks have been uploaded for 0 - finalizing....fine-uploader.js:162:21
[Fine Uploader 5.11.8] Received response status 200 with body: {"success":true,"uuid":"79e7db33-9609-49cd-bcb1-2606bea6abd7","uploadName":null}fine-uploader.js:162:21
[Fine Uploader 5.11.8] Finalize successful for 0
I've spent about 2 days researching this with no avail, I don't seem to be getting errors, but as I said I'm pretty much a Noob when it comes to understanding this on my own. Any help is Greatly Appreciated.
Here Is my Uploader Code Body
<body>
<!-- Fine Uploader DOM Element
====================================================================== -->
<div id="fine-uploader-manual-trigger"></div>
<!-- Your code to create an instance of Fine Uploader and bind to the DOM/template
====================================================================== -->
<script>
var manualUploader = new qq.FineUploader({
debug: true,
element: document.getElementById('fine-uploader-manual-trigger'),
template: 'qq-template-manual-trigger',
request: {
endpoint: 'endpoint.php'
},
chunking: {
enabled: true
},
success: {
endpoint: "endpoint.php?done"
},
resume: {
enabled: true
},
thumbnails: {
placeholders: {
waitingPath: 'images/waiting-generic.png',
notAvailablePath: 'images/not_available-generic.png'
}
},
autoUpload: false,
showMessage: function(message) { //show message if any error occur during upload process
alert(message);
}
});
qq(document.getElementById("trigger-upload")).attach("click", function() {
manualUploader.uploadStoredFiles();
});
</script>
</body>
</html>
Here Is my Endpoint.php File
require_once "handler.php";
$uploader = new UploadHandler();
// Specify the list of valid extensions, ex. array("jpeg", "xml", "bmp")
$uploader->allowedExtensions = array(); // all files types allowed by default
// Specify max file size in bytes.
$uploader->sizeLimit = null;
// Specify the input name set in the javascript.
$uploader->inputName = "qqfile"; // matches Fine Uploader's default inputName value by default
// If you want to use the chunking/resume feature, specify the folder to temporarily save parts.
$uploader->chunksFolder = "chunks";
$method = $_SERVER["REQUEST_METHOD"];
if ($method == "POST") {
header("Content-Type: text/plain");
// Assumes you have a chunking.success.endpoint set to point here with a query parameter of "done".
// For example: /myserver/handlers/endpoint.php?done
if (isset($_GET["done"])) {
$result = $uploader->combineChunks("files");
}
// Handles upload requests
else {
// Call handleUpload() with the name of the folder, relative to PHP's getcwd()
$result = $uploader->handleUpload("files");
// To return a name used for uploaded file you can use the following line.
$result["uploadName"] = $uploader->getUploadName();
}
echo json_encode($result);
}
// for delete file requests
else if ($method == "DELETE") {
$result = $uploader->handleDelete("files");
echo json_encode($result);
}
else {
header("HTTP/1.0 405 Method Not Allowed");
}
?>
Here is my handler.php file, I'm just using the default traditional server side example.
class UploadHandler {
public $allowedExtensions = array();
public $sizeLimit = null;
public $inputName = 'qqfile';
public $chunksFolder = 'chunks';
public $chunksCleanupProbability = 0.001; // Once in 1000 requests on avg
public $chunksExpireIn = 604800; // One week
protected $uploadName;
/**
* Get the original filename
*/
public function getName(){
if (isset($_REQUEST['qqfilename']))
return $_REQUEST['qqfilename'];
if (isset($_FILES[$this->inputName]))
return $_FILES[$this->inputName]['name'];
}
public function getInitialFiles() {
$initialFiles = array();
for ($i = 0; $i < 5000; $i++) {
array_push($initialFiles, array("name" => "name" + $i, uuid => "uuid" + $i, thumbnailUrl => ""));
}
return $initialFiles;
}
/**
* Get the name of the uploaded file
*/
public function getUploadName(){
return $this->uploadName;
}
public function combineChunks($uploadDirectory, $name = null) {
$uuid = $_POST['qquuid'];
if ($name === null){
$name = $this->getName();
}
$targetFolder = $this->chunksFolder.DIRECTORY_SEPARATOR.$uuid;
$totalParts = isset($_REQUEST['qqtotalparts']) ? (int)$_REQUEST['qqtotalparts'] : 1;
$targetPath = join(DIRECTORY_SEPARATOR, array($uploadDirectory, $uuid, $name));
$this->uploadName = $name;
if (!file_exists($targetPath)){
mkdir(dirname($targetPath), 0777, true);
}
$target = fopen($targetPath, 'wb');
for ($i=0; $i<$totalParts; $i++){
$chunk = fopen($targetFolder.DIRECTORY_SEPARATOR.$i, "rb");
stream_copy_to_stream($chunk, $target);
fclose($chunk);
}
// Success
fclose($target);
for ($i=0; $i<$totalParts; $i++){
unlink($targetFolder.DIRECTORY_SEPARATOR.$i);
}
rmdir($targetFolder);
if (!is_null($this->sizeLimit) && filesize($targetPath) > $this->sizeLimit) {
unlink($targetPath);
http_response_code(413);
return array("success" => false, "uuid" => $uuid, "preventRetry" => true);
}
return array("success" => true, "uuid" => $uuid);
}
/**
* Process the upload.
* #param string $uploadDirectory Target directory.
* #param string $name Overwrites the name of the file.
*/
public function handleUpload($uploadDirectory, $name = null){
if (is_writable($this->chunksFolder) &&
1 == mt_rand(1, 1/$this->chunksCleanupProbability)){
// Run garbage collection
$this->cleanupChunks();
}
// Check that the max upload size specified in class configuration does not
// exceed size allowed by server config
if ($this->toBytes(ini_get('post_max_size')) < $this->sizeLimit ||
$this->toBytes(ini_get('upload_max_filesize')) < $this->sizeLimit){
$neededRequestSize = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
return array('error'=>"Server error. Increase post_max_size and upload_max_filesize to ".$neededRequestSize);
}
if ($this->isInaccessible($uploadDirectory)){
return array('error' => "Server error. Uploads directory isn't writable");
}
$type = $_SERVER['CONTENT_TYPE'];
if (isset($_SERVER['HTTP_CONTENT_TYPE'])) {
$type = $_SERVER['HTTP_CONTENT_TYPE'];
}
if(!isset($type)) {
return array('error' => "No files were uploaded.");
} else if (strpos(strtolower($type), 'multipart/') !== 0){
return array('error' => "Server error. Not a multipart request. Please set forceMultipart to default value (true).");
}
// Get size and name
$file = $_FILES[$this->inputName];
$size = $file['size'];
if (isset($_REQUEST['qqtotalfilesize'])) {
$size = $_REQUEST['qqtotalfilesize'];
}
if ($name === null){
$name = $this->getName();
}
// check file error
if($file['error']) {
return array('error' => 'Upload Error #'.$file['error']);
}
// Validate name
if ($name === null || $name === ''){
return array('error' => 'File name empty.');
}
// Validate file size
if ($size == 0){
return array('error' => 'File is empty.');
}
if (!is_null($this->sizeLimit) && $size > $this->sizeLimit) {
return array('error' => 'File is too large.', 'preventRetry' => true);
}
// Validate file extension
$pathinfo = pathinfo($name);
$ext = isset($pathinfo['extension']) ? $pathinfo['extension'] : '';
if($this->allowedExtensions && !in_array(strtolower($ext), array_map("strtolower", $this->allowedExtensions))){
$these = implode(', ', $this->allowedExtensions);
return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
}
// Save a chunk
$totalParts = isset($_REQUEST['qqtotalparts']) ? (int)$_REQUEST['qqtotalparts'] : 1;
$uuid = $_REQUEST['qquuid'];
if ($totalParts > 1){
# chunked upload
$chunksFolder = $this->chunksFolder;
$partIndex = (int)$_REQUEST['qqpartindex'];
if (!is_writable($chunksFolder) && !is_executable($uploadDirectory)){
return array('error' => "Server error. Chunks directory isn't writable or executable.");
}
$targetFolder = $this->chunksFolder.DIRECTORY_SEPARATOR.$uuid;
if (!file_exists($targetFolder)){
mkdir($targetFolder, 0777, true);
}
$target = $targetFolder.'/'.$partIndex;
$success = move_uploaded_file($_FILES[$this->inputName]['tmp_name'], $target);
return array("success" => true, "uuid" => $uuid);
}
else {
# non-chunked upload
$target = join(DIRECTORY_SEPARATOR, array($uploadDirectory, $uuid, $name));
if ($target){
$this->uploadName = basename($target);
if (!is_dir(dirname($target))){
mkdir(dirname($target), 0777, true);
}
if (move_uploaded_file($file['tmp_name'], $target)){
return array('success'=> true, "uuid" => $uuid);
}
}
return array('error'=> 'Could not save uploaded file.' .
'The upload was cancelled, or server error encountered');
}
}
/**
* Process a delete.
* #param string $uploadDirectory Target directory.
* #params string $name Overwrites the name of the file.
*
*/
public function handleDelete($uploadDirectory, $name=null)
{
if ($this->isInaccessible($uploadDirectory)) {
return array('error' => "Server error. Uploads directory isn't writable" . ((!$this->isWindows()) ? " or executable." : "."));
}
$targetFolder = $uploadDirectory;
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$tokens = explode('/', $url);
$uuid = $tokens[sizeof($tokens)-1];
$target = join(DIRECTORY_SEPARATOR, array($targetFolder, $uuid));
if (is_dir($target)){
$this->removeDir($target);
return array("success" => true, "uuid" => $uuid);
} else {
return array("success" => false,
"error" => "File not found! Unable to delete.".$url,
"path" => $uuid
);
}
}
/**
* Returns a path to use with this upload. Check that the name does not exist,
* and appends a suffix otherwise.
* #param string $uploadDirectory Target directory
* #param string $filename The name of the file to use.
*/
protected function getUniqueTargetPath($uploadDirectory, $filename)
{
// Allow only one process at the time to get a unique file name, otherwise
// if multiple people would upload a file with the same name at the same time
// only the latest would be saved.
if (function_exists('sem_acquire')){
$lock = sem_get(ftok(__FILE__, 'u'));
sem_acquire($lock);
}
$pathinfo = pathinfo($filename);
$base = $pathinfo['filename'];
$ext = isset($pathinfo['extension']) ? $pathinfo['extension'] : '';
$ext = $ext == '' ? $ext : '.' . $ext;
$unique = $base;
$suffix = 0;
// Get unique file name for the file, by appending random suffix.
while (file_exists($uploadDirectory . DIRECTORY_SEPARATOR . $unique . $ext)){
$suffix += rand(1, 999);
$unique = $base.'-'.$suffix;
}
$result = $uploadDirectory . DIRECTORY_SEPARATOR . $unique . $ext;
// Create an empty target file
if (!touch($result)){
// Failed
$result = false;
}
if (function_exists('sem_acquire')){
sem_release($lock);
}
return $result;
}
/**
* Deletes all file parts in the chunks folder for files uploaded
* more than chunksExpireIn seconds ago
*/
protected function cleanupChunks(){
foreach (scandir($this->chunksFolder) as $item){
if ($item == "." || $item == "..")
continue;
$path = $this->chunksFolder.DIRECTORY_SEPARATOR.$item;
if (!is_dir($path))
continue;
if (time() - filemtime($path) > $this->chunksExpireIn){
$this->removeDir($path);
}
}
}
/**
* Removes a directory and all files contained inside
* #param string $dir
*/
protected function removeDir($dir){
foreach (scandir($dir) as $item){
if ($item == "." || $item == "..")
continue;
if (is_dir($item)){
$this->removeDir($item);
} else {
unlink(join(DIRECTORY_SEPARATOR, array($dir, $item)));
}
}
rmdir($dir);
}
/**
* Converts a given size with units to bytes.
* #param string $str
*/
protected function toBytes($str){
$val = trim($str);
$last = strtolower($str[strlen($str)-1]);
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
/**
* Determines whether a directory can be accessed.
*
* is_executable() is not reliable on Windows prior PHP 5.0.0
* (http://www.php.net/manual/en/function.is-executable.php)
* The following tests if the current OS is Windows and if so, merely
* checks if the folder is writable;
* otherwise, it checks additionally for executable status (like before).
*
* #param string $directory The target directory to test access
*/
protected function isInaccessible($directory) {
$isWin = $this->isWindows();
$folderInaccessible = ($isWin) ? !is_writable($directory) : ( !is_writable($directory) && !is_executable($directory) );
return $folderInaccessible;
}
/**
* Determines is the OS is Windows or not
*
* #return boolean
*/
protected function isWindows() {
$isWin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
return $isWin;
}
}
Thanks for the help in making sure my code was correct, Kicked myself in the face for this one! As I was thinking for the longest time a incorrectly setup Apache Environment has been the root of all my problems.
I did not have .htaccess setup which seemed to fix all of my problems.
Here are the steps I followed to resolve my problem.
First Step
Open apache.conf file as
sudo vim /etc/apache2/apache2.conf
Second Step
remove comment sign (#) if you find it before this line ( line number 187 approx.)
AccessFileName .htaccess
Third Step
Then find the line where there is
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
replace "None" with "All"
AllowOverride All
Step Four
Activate ModRewrite:
sudo a2enmod rewrite
sudo service apache2 restart
Everything should be Good from here.

mkdir always sets folders to read-only?

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);
}
}
}
}

What is the best way to resolve a relative path (like realpath) for non-existing files?

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);
}

how #usedby tag work in phpdoc

By using #usedby tag hyperlink is not coming in documentation.
Class Content
{
/**
* simple db class variable
* #access public
*/
var $_db=null; // db
/**
* s3 class instance
*/
private $_s3=null; // s3
/**
* application variable array for creating instance of each object
* #var array
* #usedby Content::upload() this is compared
*/
public $application=array(
'image'=>array(
'createthumb'=>'createimagethumb'
),
'audio'=>array(
'createthumb'=>'createaudiothumb'
),
'video'=>array(
'createthumb'=>'createvideothumb'
),
'link'=>array(
'createthumb'=>'createlinkthumb'
)
);
/**
* for uploading new content or you can say add new content :)
*
* #return json of new contents
**/
function upload()
{
if ($_POST['gibname']=='' or $_POST['gibview']=='') {
$msg=createmessage(false, 'Please enter gibname and gib view where you want to place content');
}
$maxFileSize = 100 * 1024 * 1024; // Max file size 100 MB
$thumb = $status =$imgWidth = $imgHeight = '';
$headers = apache_request_headers(); // Get file size from Apache headers
$fileSize=(int)$headers['Content-Length'];
$fileType = (string)$headers['Content-Type']; // Get MIME type from Apache headers
$clientfileType = $fileType;
if (preg_match("/^multipart/", $fileType) ) $fileType = $_FILES['qqfile']['type'];
if ($fileType=='application/octet-stream') $fileType="video/flv";
if ($fileSize == 0) {
return array('success'=>false, 'error'=>"File is empty.");
}
if ($fileSize > $maxFileSize) {
return array('success'=>false, 'error'=>"File is too large.");
}
$pathinfo = pathinfo($_REQUEST['qqfile']); // Put data of pathinfo() array into $pathinfo
$filename = $pathinfo['filename'];// Get file name - eg: myphoto
$ext = $pathinfo['extension']; // Get extension - eg: .jpg
if ($ext=='') $ext=substr(strrchr($_FILES['qqfile']['name'], '.'), 1);
$originalName = $filename.'.'.$ext;
$randName = uniqid(); // Generate unique id for the current object
$fileTempName = $randName . '.' . $ext; // Unique file name with extension
$fullTempName = "uploads/".$fileTempName; // Set temp directory where files will be written temporarily // Complete temp file name and path
if (!preg_match("/^multipart/", $clientfileType)) { // Upload the file to temp directory on .net server
$input = fopen("php://input", "r");
$fp = fopen($fullTempName, "w");
while ($data = fread($input, 1024)) {
fwrite($fp,$data);
}
fclose($fp);
fclose($input);
} else
move_uploaded_file($_FILES["qqfile"]["tmp_name"], $fullTempName);
$objecttype=mb_substr($fileType,0,-mb_strlen(strrchr($fileType,"/")));
//for uploading of link url is neccesssary
if ($_POST['url']!='' or $_POST['refername']!='') {
$objecttype="link";
$url=$_POST['url'];
$filename=$_POST['filename'];
} else {
$url=CLOUDFRONT.$fileTempName;
$filename=$fileTempName;
}
if (class_exists($objecttype) && $_POST['refername']=='') {
$object=new $objecttype();
$str=$this->application[$objecttype]['createthumb'];
$thumb=$object->{$str}($fullTempName,$fileType);
$thumbnail=$thumb['thumb'];
$preview=$thumb['preview'];
$imgWidth=$object->imagewidth;
$imgHeight=$object->imageheight;
$resize=$object->resize;
}
}
While #usedby is not the warning is coming telling unknown tag .
phpdocumentor version is 1.4.3
why it is saying the unknown tag .
The "#usedby" tag is not a code documentation tag that phpDocumentor looks for in your docblocks. There is a "#uses" tag that says "this particular element uses the one I'm listing in this tag". phpDocumentor will see this tag, show this tag on the element's doc, make a link to the other element, and put a #usedby tag in the documentation for that other element.
In short, you put #uses in ThisElement's docblock to point from ThisElement to ThatElement, and phpDocumentor will put #usedby in ThatElement's documentation to point from ThatElement back to ThisElement.

Categories