I have some files in server that users can download it but user must be logged in to download those files so files are in format of rar or zip. is there any way to validate that use is already logged before downloading files in php ?
<?php
session_start();
if (isset($_COOKIE['username']) AND isset($_COOKIE['hash']) {
if (isset($_SESSION['url']) {
Header("Location:".$_SESSION['url']);
}
}
?>
yeah below is approach to use
step1:prevent zip file direct access
order allow,deny
deny from all
step2:
<?php
function output_file($file, $name, $mime_type='')
{
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
$known_mime_types=array(
"htm" => "text/html",
"exe" => "application/octet-stream",
"zip" => "application/zip",
"doc" => "application/msword",
"jpg" => "image/jpg",
"php" => "text/plain",
"xls" => "application/vnd.ms-excel",
"ppt" => "application/vnd.ms-powerpoint",
"gif" => "image/gif",
"pdf" => "application/pdf",
"txt" => "text/plain",
"html"=> "text/html",
"png" => "image/png",
"jpeg"=> "image/jpg"
);
if($mime_type==''){
$file_extension = strtolower(substr(strrchr($file,"."),1));
if(array_key_exists($file_extension, $known_mime_types)){
$mime_type=$known_mime_types[$file_extension];
} else {
$mime_type="application/force-download";
};
};
//turn off output buffering to decrease cpu usage
#ob_end_clean();
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
// multipart-download and download resuming support
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
list($range) = explode(",",$range,2);
list($range, $range_end) = explode("-", $range);
$range=intval($range);
if(!$range_end) {
$range_end=$size-1;
} else {
$range_end=intval($range_end);
}
$new_length = $range_end-$range+1;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range-$range_end/$size");
} else {
$new_length=$size;
header("Content-Length: ".$size);
}
/* Will output the file itself */
$chunksize = 1*(1024*1024); //you may want to change this
$bytes_send = 0;
if ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length)
)
{
$buffer = fread($file, $chunksize);
echo($buffer);
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else
//If no permissiion
die('Error - can not open file.');
//die
die();
}
//Set the time out
set_time_limit(0);
//path to the file
$file_path='files/'.$_REQUEST['filename'];
//Call the download function with file path,file name and file type
if($_SESSION['userloggedin']){
output_file($file_path, ''.$_REQUEST['filename'].'', 'text/plain');
}else{
echo "login";
}
?>
You can do this like any other content you are serving. A php file does not have to return a text/html document. It can serve any data, including images, pdf's or executables. You just have to serve it with the right headers.
<?php
if(isset($_COOKIE['username']) && isset($_COOKIE['hash'])
{
//The user is logged in... we have no clue if the user is allowed to download the file
header( "Content-Type: image/jpeg" );
header( "Cache-Control: private, max-age=0, no-cache" );
file_get_contents( "images/image.jpg" );
exit();
} else {
header('HTTP/1.0 403 Forbidden');
exit();
}
The cache-control header is here to prevent servers between the client and your server from caching this request. ISP's sometimes do this to serve common files faster. The content-type header should be set to the correct mime-type based on what file you are serving. You can find a list of common mime types on wikipedia.
IMPORTANT
This answer uses 'file_get_contents(...)'. You should always make sure that the url that is passed to this function is sane. This means: It should point to an existing file, and it should only point to a file you actually want to serve. If someone passes '../../../.htaccess' you don't want to accidentally spill the contents of that file to the user!
Related
I am trying to play music dynamically from ajax response data but the problem is how to play audio file when it return to php variable?
I am using mediaelement.js pluging for audio player.
JAVASCRIPT
var player = new MediaElementPlayer('audio-player', {
//options
});
$.ajax({
url: '../play?song=songs_id',
type: "get",
success:function(data){
player.pause();
player.setSrc(data);
player.load();
player.play();
}
});
PHP
$song_id = 'folder/'.$_GET['song'];
// get the file request, throw error if nothing supplied
// hide notices
#ini_set('error_reporting', E_ALL & ~ E_NOTICE);
//- turn off compression on the server
#apache_setenv('no-gzip', 1);
#ini_set('zlib.output_compression', 'Off');
// sanitize the file request, keep just the name and extension
// also, replaces the file location with a preset one ('./myfiles/' in this example)
$file = $song_id;
$path_parts = pathinfo($file);
$file_name = $path_parts['basename'];
$file_ext = $path_parts['extension'];
$file_path = $song_id;
// allow a file to be streamed instead of sent as an attachment
$is_attachment = isset($_REQUEST['stream']) ? false : true;
// make sure the file exists
if (is_file($file_path))
{
$file_size = filesize($file_path);
$file = #fopen($file_path,"rb");
if ($file)
{
// set the headers, prevent caching
header("Pragma: public");
header("Expires: -1");
header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
header("Content-Disposition: attachment; filename=\"$file_name\"");
// set appropriate headers for attachment or streamed file
if ($is_attachment) {
header("Content-Disposition: attachment; filename=\"$file_name\"");
}
else {
header('Content-Disposition: inline;');
header('Content-Transfer-Encoding: binary');
}
// set the mime type based on extension, add yours if needed.
$ctype_default = "application/octet-stream";
$content_types = array(
"exe" => "application/octet-stream",
"zip" => "application/zip",
"mp3" => "audio/mpeg",
"mpg" => "video/mpeg",
"avi" => "video/x-msvideo",
);
$ctype = isset($content_types[$file_ext]) ? $content_types[$file_ext] : $ctype_default;
header("Content-Type: " . $ctype);
//check if http_range is sent by browser (or download manager)
if(isset($_SERVER['HTTP_RANGE']))
{
list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($size_unit == 'bytes')
{
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else
{
$range = '';
header('HTTP/1.1 416 Requested Range Not Satisfiable');
exit;
}
}
else
{
$range = '';
}
//figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);
//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty($seek_end)) ? ($file_size - 1) : min(abs(intval($seek_end)),($file_size - 1));
$seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($file_size - 1))
{
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$file_size);
header('Content-Length: '.($seek_end - $seek_start + 1));
} else {
}
header("Content-Length: $file_size");
header('Accept-Ranges: bytes');
set_time_limit(0);
fseek($file, $seek_start);
while(!feof($file))
{
print(#fread($file, 1024*8));
ob_flush();
flush();
if (connection_status()!=0)
{
#fclose($file);
exit;
}
}
// file save was a success
#fclose($file);
exit;
}
else
{
// file couldn't be opened
header("HTTP/1.0 500 Internal Server Error");
exit;
}
}
else
{
// file does not exist
header("HTTP/1.0 404 Not Found");
exit;
}
If i set player.setSrc(data); to player.setSrc('../play?song=songs_id'); then it worked fine but i don't want that. Any idea?
Your PHP code is doing all the work to process the desired URL, and you are basically using play?song=songs_id to set headers and send the file via this piece of code:
print(#fread($file, 1024*8));
ob_flush();
flush();
if (connection_status()!= 0)
{
#fclose($file);
exit;
}
As you can see, you are not using any return statement so you can use that URL to play your media. You are trying to even read the media through PHP. That's why if you use player.setSrc('../play?song=songs_id'); your code will work
I have a "contact us" form and everything is working but my error callback in the ajax runs instead of the success. I ajax is called, the PHP file runs, and I get an email to my localhost (using Mercury).
So why is my success callback not running? I have no idea how to find out what is causing the error especially since everything works.
The only thing I suspect is the file folders. The current structure is this. My html file and php file are in the root directory. The JS file is in a folder.
Here is a screenshot of the network tab in chrome debugger after I press submit
http://i.imgur.com/HfRYjj0.png
My Ajax:
$(document).ready(function(e) {
$("#main-contact-form").on('submit', (function(e) {
e.preventDefault();
$('#sendingemail').fadeIn();
$.ajax({
url : "../sendemail.php",
type : "POST",
data : new FormData(this),
contentType : false,
cache : false,
processData : false,
success : function(data) {
$('#sendingemail').fadeOut();
$('#emailsent').fadeIn();
},
error : function() {
alert("Error");
}
});
}));
});
My PHP:
<?php
// ini_set('display_errors', 'On');
// error_reporting(E_ALL);
header('Content-type: application/json');
// WE SHOULD ASSUME THAT THE EMAIL WAS NOT SENT AT FIRST UNTIL WE KNOW MORE.
// WE ALSO ADD AN ATTACHMENT KEY TO OUR STATUS ARRAY TO INDICATE THE STATUS OF OUR ATTACHMENT:
/*$status = array(
'type'=>'Error',
'message'=>'Couldn\'t send the Email at this Time. Something went wrong',
'attachement'=>'Couldn\'t attach the uploaded File to the Email.'
);*/
//Added to deal with Files
require_once ('PHPMailer/class.phpmailer.php');
if (isset($_FILES['uploaded_file'])) {
//require_once('/PHPMailer/class.smtp.php');
//Get the uploaded file information
$name_of_uploaded_file = basename($_FILES['uploaded_file']['name']);
//get the file extension of the file
$type_of_uploaded_file = substr($name_of_uploaded_file, strrpos($name_of_uploaded_file, '.') + 1);
$size_of_uploaded_file = $_FILES["uploaded_file"]["size"] / 1024;
//size in KBs
//Settings
$max_allowed_file_size = 10240;
// size in KB
$allowed_extensions = array("jpg", "jpeg", "gif", "bmp", "png");
//Validations
if ($size_of_uploaded_file > $max_allowed_file_size) {
$errors .= "\n Size of file should be less than $max_allowed_file_size (~10MB). The file you attempted to upload is too large. To reduce the size, open the file in an image editor and change the Image Size and resave the file.";
}
//------ Validate the file extension -----
$allowed_ext = false;
for ($i = 0; $i < sizeof($allowed_extensions); $i++) {
if (strcasecmp($allowed_extensions[$i], $type_of_uploaded_file) == 0) {
$allowed_ext = true;
}
}
if (!$allowed_ext) {
$errors .= "\n The uploaded file is not supported file type. " . " Only the following file types are supported: " . implode(',', $allowed_extensions);
}
//copy the temp. uploaded file to uploads folder - make sure the folder exists on the server and has 777 as its permission
$upload_folder = "temp/";
$path_of_uploaded_file = $upload_folder . $name_of_uploaded_file;
$tmp_path = $_FILES["uploaded_file"]["tmp_name"];
if (is_uploaded_file($tmp_path)) {
if (!copy($tmp_path, $path_of_uploaded_file)) {
$errors .= '\n error while copying the uploaded file';
}
}
}
//--end
$name = #trim(stripslashes($_POST['name']));
$clientemail = #trim(stripslashes($_POST['email']));
$subject = #trim(stripslashes($_POST['subject']));
$message = #trim(stripslashes($_POST['message']));
$body = 'Name: ' . $name . "\n\n" . 'Email: ' . $clientemail . "\n\n" . 'Subject: ' . $subject . "\n\n" . 'Message: ' . $message;
$email = new PHPMailer();
$email -> From = $clientemail;
$email -> FromName = $name;
$email -> Subject = $subject;
$email -> Body = $body;
$email -> AddAddress('root#localhost.com');
//Send to this email
// EXPLICITLY TELL PHP-MAILER HOW TO SEND THE EMAIL... IN THIS CASE USING PHP BUILT IT MAIL FUNCTION
$email -> isMail();
// THE AddAttachment METHOD RETURNS A BOOLEAN FLAG: TRUE WHEN ATTACHMENT WAS SUCCESSFUL & FALSE OTHERWISE:
// KNOWING THIS, WE MAY JUST USE IT WITHIN A CONDITIONAL BLOCK SUCH THAT
// WHEN IT IS TRUE, WE UPDATE OUR STATUS ARRAY...
if (isset($_FILES['uploaded_file'])) {
if ($email -> AddAttachment($path_of_uploaded_file, $name_of_uploaded_file)) {
//$status[] = 'The Uploaded File was successfully attached to the Email.';
}
}
// NOW, TRY TO SEND THE EMAIL ANYWAY:
try {
$success = $email -> send();
//$status['type'] = 'success';
$status[] = 'Thank you for contacting us. We will reply as soon as possible.';
} catch(Exception $e) {
//$status['type'] ='Error';
$status[] = 'Couldn\'t send the Email at this Time. Something went wrong';
}
// SIMPLY, RETURN THE JSON DATA...
die(json_encode($status));
I would like to return an error on a case from my php code that handles the upload.
Currently if the php upload fails the JS still thinks it successes which I presume is to do with the fact it returned fine.
I have tried returning false instead of a string but that still runs the this.on('success') function.
PHP
public function imageUpload(){
//Сheck that we have a file
if((!empty($_FILES["file"])) && ($_FILES['file']['error'] == 0)) {
//Check if the file is JPEG image and it's size is less than 350Kb
$filename = basename($_FILES['file']['name']);
$ext = substr($filename, strrpos($filename, '.') + 1);
if (($ext == "jpg") && ($_FILES["file"]["type"] == "image/jpeg") &&
($_FILES["file"]["size"] < 3500000)) {
//Determine the path to which we want to save this file
$newname = '/home/anglicvw/public_html/newdev/app/templates/default/images/testimages/'.$filename;
//Check if the file with the same name is already exists on the server
if (!file_exists($newname)) {
//Attempt to move the uploaded file to it's new place
if ((move_uploaded_file($_FILES['file']['tmp_name'],$newname))) {
echo "It's done! The file has been saved as: ".$newname;
} else {
echo "Error: A problem occurred during file upload!";
}
} else {
echo "Error: File ".$_FILES["file"]["name"]." already exists";
}
} else {
echo "Error: Only .jpg images under 350Kb are accepted for upload";
}
} else {
echo "Error: No file uploaded";
}
}
JS
$(document).ready(function(){
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone('div#imagesdropzone', { url: '/admin/imageUpload',
parallelUploads: 100,
maxFiles: 100,});
});
Dropzone.options.imagesdropzone = {
init: function() {
this.on('success', function( file, resp ){
console.log( file );
console.log( resp );
});
this.on('error', function( e ){
console.log('erors and stuff');
console.log( e );
});
}
};
Yes, its right. You have to set an HTTP Header.
Have a look at:
https://github.com/enyo/dropzone/wiki/FAQ#how-to-show-an-error-returned-by-the-server
If you have an HTTP Error and want to show it in the hover error message of DropzoneJS you can:
myDropzone.on("error", function(file, message, xhr) {
var header = xhr.status+": "+xhr.statusText;
$(file.previewElement).find('.dz-error-message').text(header);
});
(You need jQuery for that code [$().find();])
The other way would be to return a JSON error message via PHP:
//define text for error message
$output['error'] = 'No Token';
//return right HTTP code
if( $error ){
http_response_code (401);
}
else{
http_response_code (200);
}
//set Content-Type to JSON
header( 'Content-Type: application/json; charset=utf-8' );
//echo error message as JSON
echo json_encode( $output );
Where does this.on('success') take the information about the success/failure of the (internal) PHP upload process?
I guess from the HTTP header's status code, which is 200 (OK) even if the upload failed (it just prints some error text).
I recommend you to set a 500 header if the upload fails.
Use below php code snippet
public function imageUpload(){
//Сheck that we have a file
if((!empty($_FILES["file"])) && ($_FILES['file']['error'] == 0)) {
//Check if the file is JPEG image and it's size is less than 350Kb
$filename = basename($_FILES['file']['name']);
$ext = substr($filename, strrpos($filename, '.') + 1);
if (($ext == "jpg") && ($_FILES["file"]["type"] == "image/jpeg") &&
($_FILES["file"]["size"] < 3500000)) {
//Determine the path to which we want to save this file
$newname = '/home/anglicvw/public_html/newdev/app/templates/default/images/testimages/'.$filename;
//Check if the file with the same name is already exists on the server
if (!file_exists($newname)) {
//Attempt to move the uploaded file to it's new place
if ((move_uploaded_file($_FILES['file']['tmp_name'],$newname))) {
echo "It's done! The file has been saved as: ".$newname;
} else {
header('Error: A problem occurred during file upload!', true, 500);
//echo "Error: A problem occurred during file upload!";
}
} else {
header("Error: File ".$_FILES["file"]["name"]." already exists", true, 500);
//echo "Error: File ".$_FILES["file"]["name"]." already exists";
}
} else {
header("Error: Only .jpg images under 350Kb are accepted for upload", true, 500);
//echo "Error: Only .jpg images under 350Kb are accepted for upload";
}
} else {
header("Error: No file uploaded", true, 500);
//echo "Error: No file uploaded";
}
}
I have some files on my PHP server inside uploads folder. My problem is the following: I want to send a JSON asynchronous request from my client as to choose one of these files and create with this an image element as to display it in the browser.
JS code
var file_name="test.jpg";
$.ajax({
method:"POST",
dataType:"json",
url:"retrieve_photo.php",
data:{name:file_name},
success: function(data) {
var new_thumb = document.createElement("img");
document.getElementById('dragarea').appendChild(new_thumb);
...
}
})
PHP code (retrieve_photo.php):
<?php
$ds = DIRECTORY_SEPARATOR;
$storeFolder="uploads";
$file_name=$_POST[name];
$files = glob($storeFolder.$ds.$file_name);
if ( false!==$files ) {
....
}
header('Content-type: text/json');
header('Content-type: application/json');
echo json_encode($result);
?>
I do not know what to write as $result feeds data the right way. I 've tried
$result=readfile($storeFolder.$ds.$file_name);
but maybe not correctly.As to conclude I want to use data as to display an image to my browser.
Thank you
Maybe will be better do something like that?:
var image = new Image();
image.src = "blabla";
$(image).on('load', function(){
//do what you want
})
Why do you even use AJAX? Maybe i don't understand)
Since you don't use algorithm or functions in your PHP, you can do everything by Javascript / Jquery :
var img = $("<img />").attr('src', 'uploads/'+ file_name)
.on('load', function() {
if (!this.complete || typeof this.naturalWidth == "undefined") {
alert('Image not found');
} else {
$("#dragarea").append(img);
}
});
document.getElementByI('dragarea').appendChild(new_thumb);
Мaybe you mean? document.getElementById('dragarea').appendChild(new_thumb);
document.getElementById('dragarea').appendChild(new_thumb);
try this in your retrieve_photo.php
$filename = "test.jpg";
//Make sure $filename contains the appropriate path of the photo
$size = getimagesize($filename);
$file = $filename;
if ($size) {
header("Content-type:". $size['mime']);
header("Content-Length: " . filesize($file));
header("Content-Disposition: attachment; filename=$filename");
header('Content-Transfer-Encoding: base64');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Type: application/force-download");
readfile($file);
exit;
}
I'm using XAMPP as the server and well i can't seem to upload the image like the documentation of the editor showed me... here is the link:
http://editor.froala.com/server-integrations/php-image-upload
I already investigated about the problem and normaly they all say is the link that's not correct because you need to put the absolute url there , but even that doesn't seem to work.
Here is the code:
JS
$(document).ready(function(){
$('textarea').editable({inlineMode: false, height:200, imageUploadURL: 'upload_image.php', imageErrorCallback: function (data) {
// Bad link.
console.log(data);
}
});
});
upload_image.php:
<?php
// Allowed extentions.
$allowedExts = array("gif", "jpeg", "jpg", "png");
// Get filename.
$temp = explode(".", $_FILES["file"]["name"]);
// Get extension.
$extension = end($temp);
// An image check is being done in the editor but it is best to
// check that again on the server side.
// Do not use $_FILES["file"]["type"] as it can be easily forged.
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES["file"]["tmp_name"]);
if ((($mime == "image/gif")
|| ($mime == "image/jpeg")
|| ($mime == "image/pjpeg")
|| ($mime == "image/x-png")
|| ($mime == "image/png"))
&& in_array($extension, $allowedExts)) {
// Generate new random name.
$name = sha1(microtime()) . "." . $extension;
// Save file in the uploads folder.
move_uploaded_file($_FILES["file"]["tmp_name"], "C:\ xampp\htdocs\Swaggy\img\ " . $name);
// Generate response.
$response = new StdClass;
$response->link = "/swaggy/img/" . $name;
echo stripslashes(json_encode($response));
}
When i try to upload an image he forms an img tag in the editor in base 64 and then dissapears. The debugger shows me that the file upload_image.php has a 200 status and the error that shows me from console is this :
Object {code: 4, message: "Parsing response failed"}
It looks there is a problem with the PHP from your server and the response can't be parsed. You should check with Firebug what is the response from the server when you try to upload an image. finfo_file function for instance is available only starting with PHP 5.3. If your version is older this is the problem most probably.