Show Google Drive video on a website using service account - php

I'm trying to get a video from my google drive account and publish it on my website.
The idea is to authorize the access to the file using a service account, so the video will be "public" accessible without the user using his google credentials.
Right now for the images I download them and the show it from my server, but due to storage space I would prefer not doing the same for videos
Here's my code:
$client = getGoogleClient(); // Specify the CLIENT_ID of the app that accesses the backend
$service = new Google_Service_Drive($client);
switch ($type) {
case 1: //video
$startPos=strrpos($url['URL'], "file/d")+7;
if($startPos>7)
{
$endPos=strrpos($url['URL'],"/");
$url=substr($url['URL'],$startPos,$endPos-$startPos); //its the file id
}
// Get files from our request
$file = $service->files->get($url,array("fields"=>"webContentLink"));
$customData=$file->webContentLink;
$customclass="hasVideo";
break;
case 3: //img
if(is_null($img))
{
//we have to donwload the file and store it temporaly
//find img id
$startPos=strrpos($url['URL'], "file/d")+7;
if($startPos>7)
{
$endPos=strrpos($url['URL'],"/");
$url=substr($url['URL'],$startPos,$endPos-$startPos);
$content = $service->files->get($url, array("alt" => "media"));
// Open file handle for output.
$filePath="./cachedFiles/".uniqid().".jpg";
$outHandle = fopen($filePath, "w+");
// Until we have reached the EOF, read 1024 bytes at a time and write to the output file handle.
while (!$content->getBody()->eof())
fwrite($outHandle, $content->getBody()->read(1024));
// Close output file handle.
fclose($outHandle);
$connection->runQuery("UPDATE File_Elemento SET cachedFile='".$filePath."', lastCached='".date('Y-m-d H:m:s')."' WHERE ID=".$ID);
}
else
$type=0;
}
else
$filePath=$img;
require_once('./ImageCache/ImageCache.php');
$imagecache = new ImageCache\ImageCache();
$imagecache->cached_image_directory = dirname(__FILE__) . '/cachedImg';
$filePath = $imagecache->cache( $filePath );
break;
default:
break;
}
echo '<a onclick="showDetail(this,\''.$customData.'\')" class="grid-item '.($subject ? $subject : "Generico").' '.($customclass!="" ? $customclass : "").'"><div class="card newsCard">'.($type==3 ? '<img class="lazy-load imgPrev" data-src="'.$filePath.'">' : "").'<h3>'.$school.'</h3><h1>'.$name.'</h1>';
echo '<div class="prev">'.$subject.'</div><span class="goin mainColor">Visualizza</span></div></a>';
right now I tried to get the webContentLink and then put the url I get as source for a video tag, but I get a 403 error, so still I didn't authorize the access using the service account
Any help would be appreciated

Embedding the webContentLink to your website won't make this publicly available. The webContentLink is as restricted as the file itself: it can only be accessed by users with which the file has been shared.
So you should do one of these:
Make this video public (via Permissions: create, or through the UI itself) (role: reader and type: anyone).
Download it serve it from your server, as with your images.
Related:
Generating a downloadable link for a private file uploaded in the Google drive

Related

Azure File Storage using PHP

I want to run a single webpage to display files, which are stored in an Azure File Storage. It must be Azure File storage because these files came from a Docker container, which is mounted, to that file storage.
I have a Azure Container Instance witch stores PDF files in an Azure File Storage. Now I run a WebApp (PHP) that shall read all the PDFs.
I’ve installed the Microsoft Azure Storage File PHP SDK but have no clue how to use it. Even the sample.php did not help me coming forward. It would be very helpful if someone could help me a bit a simple sniped.
I see you want to directly display a PDF file from Azure File Storage in a web page. Generally, the best practice is to generate the url with sas token of a file in Azure File Storage.
So I followed the GitHub repo Azure/azure-storage-php to install Azure File Storage SDK for PHP in my sample project, here is my sample code and its dependencies.
The file structure of my sample project is as the figure below.
The content of my composer.json file is as below.
{
"require": {
"microsoft/azure-storage-file": "*"
}
}
My sample PHP file demo.php is as below, that's inspired by the function generateFileDownloadLinkWithSAS of the offical sample azure-storage-php/samples/FileSamples.php.
<?php
require_once "vendor/autoload.php";
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\File\FileSharedAccessSignatureHelper;
$accountName = "<your account name>";
$accountKey = "<your account key>";
$shareName = "<your share name>";
$fileName = "<your pdf file name>";
$now = date(DATE_ISO8601);
$date = date_create($now);
date_add($date, date_interval_create_from_date_string("1 hour"));
$expiry = str_replace("+0000", "Z", date_format($date, DATE_ISO8601));
$helper = new FileSharedAccessSignatureHelper($accountName, $accountKey);
$sas = $helper->generateFileServiceSharedAccessSignatureToken(
Resources::RESOURCE_TYPE_FILE,
"$shareName/$fileName",
'r', // Read
$expiry // A valid ISO 8601 format expiry time, such as '2020-01-01T08:30:00Z'
);
$fileUrlWithSAS = "https://$accountName.file.core.windows.net/$shareName/$fileName?$sas";
echo "<h1>Demo to display PDF from Azure File Storage</h1>";
echo "<iframe src='$fileUrlWithSAS' width='800' height='500' allowfullscreen webkitallowfullscreen></iframe>";
?>
The result of my web page is as the figures below in Chrome and Firefox.
The result in Chrome:
The result in Firefox:
Update: The code to list files in a file share, as below.
<?php
require_once "vendor/autoload.php";
use MicrosoftAzure\Storage\File\FileRestProxy;
$accountName = "<your account name>";
$accountKey = "<your account key>";
$shareName = "<your share name>";
$connectionString = "DefaultEndpointsProtocol=https;AccountName=$accountName;AccountKey=$accountKey";
$fileClient = FileRestProxy::createFileService($connectionString);
$list = $fileClient->listDirectoriesAndFiles($shareName);
function endsWith( $str, $sub ) {
return ( substr( $str, strlen( $str ) - strlen( $sub ) ) === $sub );
}
foreach($list->getFiles() as &$file) {
$fileName = $file->getName();
if(endsWith($fileName, ".pdf")) {
echo $fileName."\n";
}
};
?>

Restrict access of an uploaded file to only the original author in a web application

Ex: a user login to a website and uploads a profile pic. I want to restrict the access to only allow the user that uploads the pic gets to have access.
So, if a second person somehow gets the URL to the pic, he or she still can not access it because she or he doesn't have the right permission(https://example.com/profile_pic_mike_1). Right now i have it so that the user can upload a profile pic but then anyone that has the URL are able to type in the browser and see the pic. I dont want that.
This is a project for fun so all suggestions are welcome.
Create a script that's only accessible to logged in users. Have that script fetch the image and display on screen.
Your users access the following url:
example.com/image.php?name=image
You then have image.php fetch the file from disk/database, and return it to the user. A quick example assuming you're working with jpeg images (excluding error checking):
<?php
if(!logged_in())
die('Unauthorized');
$filename = '/path/to/images/' . $_GET['name'];
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
header('content-type: ' . image_type_to_mime_type(IMAGETYPE_JPEG));
echo $contents;
Other image mime types can be found here: image_type_to_mime_type
You can code a PHP file that will check if user is logged in, or if users have the permission to access the file.
I'll assume your public directory is public_html.
For the storage of images, you'll need to store them outside of the public directory (public_html).
Example Code (e.g. image.php?file=profile_pic_mike_1). image.php is in public_html and profile_pic_mike_1 will be in the directory that is not accessible to the public.
<?php
// checking for $_SESSION, change accordingly to your method
session_start();
if(!$_SESSION['logged_in']){
session_destroy();
header("Location:index.php");
}
// $_GET['file'] will be profile_pic_mike_1
if(isset($_GET['file'])){
$file_dir = "../";
$file = $file_dir . $_GET["file"];
// get if user has the permission
// if yes, assign `true` to $permission ($permission = true;)
if (!file_exists($file)) {
echo "File not found.";
} else if (!$permission) {
echo "You do not have the permission to view this image.";
} else {
// You'll need to change the Content-type accordingly
header("Content-type: image/png");
readfile($file);
exit;
}
}
?>
List of Content-type for images: http://php.net/manual/en/function.image-type-to-mime-type.php.
You'll need to check if the user has the permission to view the file, one way to do it by saving the permissions in a MySQL DB.
You'll have to write the functions and flesh out a bit, but it gives you an idea:
<?php
$username = get_username_from_url();
$user = get_logged_in_user();
if(!$user || ($username !== $user->name)) {
// access denied, send appropriate header and exit.
}
// keep your images outside your web root (not public).
// e.g. /path/to/app/data/uploads/unique_id.jpg
$avatar_path = get_avatar_file_path_by_user($user);
// send image file
header("Content-type: image/jpeg"); // or appropriate content type.
readfile($avatar_path);

php file_put_contents giving me permission errors

The site I am working on- http://24.236.131.128/
This is a site using the snapchat API. I can log into my snapchat account and SHOULD see the snaps I have that are unopened.
I can log in just fine, and view my friends or list of snaps. I can NOT, however, get the image to display or save to the path.
I get a Warning:
file_put_contents(media/download/from_lolnope47_to_lolnope47_id_959644398384684466r.jpg): failed to open stream: Permission denied in C:\inetpub\wwwroot\index.php on line 114 View pic...
the C:\inetpub\wwwroot\media\download\ folder has full permissions set to the IUSR account for IIS, not too sure if that's the problem?
Any suggestions?
EDIT:
Here is the function to download the snap:
if ($id == 'download')
{
echo '<title>Download picture</title>';
$snapchat = new Snapchat($_SESSION['name'],$_SESSION['pass']);
$snapid = $_GET['snapid'];
$sender = $_GET['sender'];
$recipient = $_GET['recipient'];
$data = $snapchat->getMedia($snapid);
$prePath = 'media/download/from_'.$sender.'_to_'.$recipient.'_id_'.$snapid.'.jpg';
if (file_exists($prePath))
{
$finalPath = 'media/download/from_'.$sender.'_to_'.$recipient.'_id_'.$snapid.rand(0,100).'.jpg';
}
else
{
$finalPath = 'media/download/from_'.$sender.'_to_'.$recipient.'_id_'.$snapid.'.jpg';
}
//echo "<img src='$data'></img>";
file_put_contents($finalPath, $data);
echo 'View pic...';
}
Try saving the image to the same folder where your php script is, you also need to set permissions all to the same user that php.exe is running, in last case scenario set permissions all to user everyone ( this is dangerous!).
Try using the full path C:/inetpub/wwwroot/media/download/... instead of the relative path media/download

PHP Foreach and jQuery

I am working on a piece of code that I am wanting to "spice" up with jQuery but I can't think of a way to actually make it work. I am sure its simple, I just need a little advice to get me going.
I am wanting to create a piece of code that makes an Ajax request out to start a big loop that will download files and then upload them to an S3 bucket of mine. The place where I am stuck is I am wanting to send back a request back to the browser everytime a file is uploaded and output a string of text to the screen upon completion.
I don't have any of the frontend code working... just trying to get my head wrapped around the logic first... any ideas?
PHP Backend Code:
<?php
public function photos($city) {
if(isset($city))
$this->city_name = "{$city}";
// grab data array from Dropbox folder
$postcard_assets = $this->conn->getPostcardDirContent("{$this->city_name}", "Photos", TRUE);
$data = array();
foreach($postcard_assets['contents'] as $asset) {
//only grab contents in root folder... do not traverse into sub folders && make sure the folder is not empty
if(!$asset['is_dir'] && $asset['bytes'] > 0) {
// get information on file
$file = pathinfo($asset['path']);
// download file from Dropbox
$original_file = $this->conn->downloadFile(str_replace(" ", "%20", $asset['path']));
// create file name
$file_name = $this->cleanFileName($file['basename']);
// write photo to TMP_DIR ("/tmp/photos/") for manipulation
$fh = fopen(self::TMP_DIR . $file_name, 'w');
fwrite($fh, $original_file);
fclose($fh);
// Resize photo
$this->resize_photo($file_name);
// hash file name
$raw_file = sha1($file_name);
// create S3 hashed name
$s3_file_name = "1_{$raw_file}.{$file['extension']}";
// Upload manipulated file to S3
$this->s3->putObject($s3_file_name, file_get_contents(self::TMP_DIR . $file_name), $this->photo_s3_bucket, 'public-read');
// check to see if file exists in S3 bucket
$s3_check = $this->s3->getObjectInfo($s3_file_name, $this->photo_s3_bucket);
// if the file uploaded successully to S3, load into DB
if($s3_check['content-length'] > 0) {
$data['src'] = $s3_file_name;
$data['width'] = $this->width;
$data['height'] = $this->height;
Photo::create_postcard_photo($data, "{$this->city_name}");
// Now that the photo has been uploaded to S3 and saved in the DB, remove local file for cleanup
unlink(self::TMP_DIR . $file_name);
echo "{$file_name} uploaded to S3 and resized!<br />";
}
}
}
// after loop is complete, kill script or nasty PHP header warnings will appear
exit();
}
?>
The main problem is that with PHP, the output is buffered so it won't return a line at a time. You can try and force the flush but it's not always reliable.
You could add an entry to the DB for each file that is exchanged and create a seperate API to get the details of what has completed.
Generally, Jquery will wait till the request has finished before it allows you to manipulate data from a HTTP request.

PHP Transfer File on server to Rackspace Cloud Files

I am trying to script some code that will search a specified folder on the server for the latest file with a specific file extension (in my case .zip) and transfer that file to Rackspace's Cloud Files. The code below is as far i got and i keep getting the error:
Fatal error: Uncaught exception 'IOException' with message 'Could not open file for reading: Resource id #8' in /home/test/public_html/cloudapi/cloudfiles.php:1952 Stack trace: #0 /home/test/public_html/final.php(60): CF_Object->load_from_filename(Resource id #8) #1 {main} thrown in /home/test/public_html/cloudapi/cloudfiles.php on line 1952
The code that i'm using below was originally done for uploading content via an html upload form & i'm trying to adapt the same code to use a local server file instead of an uploaded file. You will see commented code with was previously for an upload script to show you how the upload script had worked.
<?php
// include the Cloud API.
require('cloudapi/cloudfiles.php');
// START - Script to find recent file with the extension .zip in current folder
$show = 2; // Leave as 0 for all
$dir = ''; // Leave as blank for current
if($dir) chdir($dir);
$files = glob( '*.zip');
usort( $files, 'filemtime_compare' );
function filemtime_compare( $a, $b )
{
return filemtime( $b ) - filemtime( $a );
}
$i = 0;
foreach ( $files as $file )
{
++$i;
if ( $i == $show ) break;
$value = $file; //Variable $value contains the filename of the recent file to be used in Cloud Files API
}
// END - Script to find recent file with the extension .zip in current folder
// START - Rackspace API code to upload content to cloud files container
// Rackspace Connection Details;
$username = "randomusername"; // put username here
$key = "234887347r93289f28h3ru283h2fuh23093402398"; // api key
// Connect to Rackspace
$auth = new CF_Authentication($username, $key);
$auth->authenticate();
$conn = new CF_Connection($auth);
//Set the Container you want to use
$container = $conn->get_container('Backups');
//Temp store the file
//$localfile = $_FILES['uploadfile']['tmp_name'];
//$filename = $_FILES['uploadfile']['name'];
$localfile = fopen($value, "r");
$filename = $value;
//Uploading to Rackspace Cloud
$object = $container->create_object($filename);
$object->load_from_filename($localfile);
echo "Your file has been uploaded";
// END - Rackspace API code to upload content to cloud files container
?>
I know this is an old thread. But for the benefit of people who may land at this page while searching for a solution...
The problem with your code is:
The following statement opens the file for reading
$localfile = fopen($value, "r");
However when you place the load_from_filename call, the routine again tries to open the same file and fails because you already have it open in $localfile.
So comment out the previous command and you should be able to run the script successfully.
Error's being thrown in because content type not defined from read file.

Categories