Unable to create directory in php - php

I was trying out this tutorial for reading rss feeds with a php file and caching it.
I copied and pasted the source into my own project. I am using XAMPP on Mac OS X installation.
Here is the source:
First of all, I cannot create a directory with mkdir. It says permission denied.
Second, $feed = file_get_contents($path, true); is not returning a php object. I mean when i check it with if ( is_object($feed) && $feed->query->count ), I cannot get through.
Last, I cannot $cachefile = fopen($cache, 'wb');
<?php
$cache = dirname(__FILE__) . "/cache/feed";
echo filemtime($cache);
if(filemtime($cache))
{
// Get from server
if ( !file_exists(dirname(__FILE__) . '/cache') ) {
mkdir(dirname(__FILE__) . '/cache', 0777);
}
// YQL query (SELECT * from feed ... ) // Split for readability
$path = "http://query.yahooapis.com/v1/public/yql?q=";
$path .= urlencode("SELECT * FROM feed WHERE url='http://feeds.hindustantimes.com/HT-HomePage-TopStories'");
$path .= "&format=json";
// Call YQL, and if the query didn't fail, cache the returned data
$feed = file_get_contents($path, true);
print_r($feed);
// If something was returned, cache
if ( is_object($feed) && $feed->query->count ) {
$cachefile = fopen($cache, 'wb');
fwrite($cachefile, $feed);
fclose($cachefile);
echo 'writing to disk';
}
}
else
{
// We already have local cache. Use that instead.
$feed = file_get_contents($cache);
}
// Decode that shizzle
$feed = json_decode($feed);
print_r($feed);
// Include the view
//include('views/site.tmpl.php');
?>

Pretty sure XAMPP runs as the "nobody" user so you're going to have to give "nobody" permissions to the directories you want to be writable:
chown nobody:nobody dir_in_question
Keep in mind that XAMPP is a great dev server, but is not secure out of the box so be careful about using this in production. See this article for relevant issues.

Related

open file on client stored on server

I want to open a server stored html report file on a client machine.
I want to bring back a list of all the saved reports in that folder (scandir).
This way the user can click on any of the crated reports to open them.
So id you click on a report to open it, you will need the location where the report can be opend from
This is my dilemma. Im not sure how to get a decent ip, port and folder location that the client can understand
Here bellow is what Ive been experimenting with.
Using this wont work obviously:
$path = $_SERVER['DOCUMENT_ROOT']."/reports/saved_reports/";
So I though I might try this instead.
$host= gethostname();
$ip = gethostbyname($host);
$ip = $ip.':'.$_SERVER['SERVER_PORT'];
$path = $ip."/reports/saved_reports/";
$files = scandir($path);
after the above code I loop through each file and generate a array with the name, date created and path. This is sent back to generate a list of reports in a table that the user can interact with. ( open, delete, edit)
But this fails aswell.
So im officially clueless on how to approach this.
PS. Im adding react.js as a tag, because that is my front-end and might be useful to know.
Your question may be partially answered here: https://stackoverflow.com/a/11970479/2781096
Get the file names from the specified path and hit curl or get_text() function again to save the files.
function get_text($filename) {
$fp_load = fopen("$filename", "rb");
if ( $fp_load ) {
while ( !feof($fp_load) ) {
$content .= fgets($fp_load, 8192);
}
fclose($fp_load);
return $content;
}
}
$matches = array();
// This will give you names of all the files available on the specified path.
preg_match_all("/(a href\=\")([^\?\"]*)(\")/i", get_text($ip."/reports/saved_reports/"), $matches);
foreach($matches[2] as $match) {
echo $match . '<br>';
// Again hit a cURL to download each of the reports.
}
Get list of reports:
<?php
$path = $_SERVER['DOCUMENT_ROOT']."/reports/saved_reports/";
$files = scandir($path);
foreach($files as $file){
if($file !== '.' && $file != '..'){
echo "<a href='show-report.php?name=".$file. "'>$file</a><br/>";
}
}
?>
and write second php file for showing html reports, which receives file name as GET param and echoes content of given html report.
show-report.php
<?php
$path = $_SERVER['DOCUMENT_ROOT']."/reports/saved_reports/";
if(isset($_GET['name'])){
$name = $_GET['name'];
echo file_get_contents($path.$name);
}

Generation of zip file in php is slow

I have a script which put images, floor plans and video into a zip file, it can reach 500mb easily but most of the time average is 150mb.
The generation of the zip file is extremely slow and i can't figurate why. Is there any tips to improve my script?
It took me 10 min to create the zip file in the server just for 100mb.
if( !empty( $files ) ){
$random_nbr = mt_rand(1,5646866662);
$path = 'webroot/img/tmp/' . $random_nbr;
if (!file_exists(\Cake\Core\Configure::read('pathTo') . 'webroot/img/tmp')) {
mkdir(\Cake\Core\Configure::read('pathTo') . 'webroot/img/tmp', 0777, true);
}
$destination = \Cake\Core\Configure::read('pathTo') . $path . '_media.zip';
$media_url = \Cake\Core\Configure::read('websiteUrl') . '/img/tmp/' . $random_nbr . '_media.zip';
$zip = new ZipArchive();
$zip->open( $destination, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE );
// Photos
if (isset($files['photos'])):
foreach( $files['photos'] as $f ){
$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
// Original
$parsed_file = $f['original_file'];
$download_file = file_get_contents($parsed_file, false,$context);
$zip->addFromString('photos/original/' . basename($parsed_file), $download_file);
// Web with or without a watermark
$web = $this->Images->state_image(1270, $f['id'], 0, '');
$web = $web->response('jpg');
$zip->addFromString('photos/web/' . $f['name'], $web);
// High Res Web with or without a watermark
$web = $this->Images->state_image(2000, $f['id'], 0, '');
$web = $web->response('jpg');
$zip->addFromString('photos/high_res_web/' . $f['name'], $web);
}
endif;
// Floor Plan
if (isset($files['floorplan'])):
foreach( $files['floorplan'] as $f ){
$parsed_file = $f['original_file'];
$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
$download_file = file_get_contents($parsed_file, false,$context);
$zip->addFromString('floorplan/' . basename($parsed_file), $download_file);
}
endif;
// Video
if (isset($files['video'])):
foreach( $files['video'] as $f ){
$parsed_file = $f['original_file'];
$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
$download_file = file_get_contents($parsed_file, false,$context);
$zip->addFromString('floorplan/' . basename($parsed_file), $download_file);
}
endif;
$zip->close();
echo $media_url;
die();
}
Outside of dedicated hardware, there probably is not much you'll be able to do to speed up the actual zipping process. You could try exec()'ing the system zip utility rather than using PHP to do it, but that may not change things.
What you can do though (if the host allows it) is background the process and provide a status page so users can see how long until their file is ready. I've done this in the past for similar problems.
What I did was have a table in the database that would store information about the zip file to be created, and a list of all the files to be added to the zip file. Then I'd exec() off a background script with the ID of the newly created DB record.
The background process would read the DB for all the details and begin creating the zip file. Periodically it would update the DB with a % complete. When finished it'd update the DB with the file system path to the newly generated zip file.
Then I had another page for the end user that displayed a progress bar. The page would periodically make an Ajax request to the server to get the new % complete for the file and update the bar accordingly. When the file was complete it would change to a download link for them to begin downloading the file.
There was another cron job process that would periodically go through and delete all the temp files older than 5 days. If users needed the file again they had to have it re-generated.

On creating zip file by php I get two files instead of one

I'm struggling around with a simple PHP functionality: Creating a ZIP Archive with some files in.
The problem is, it does not create only one file called filename.zip but two files called filename.zip.a07600 and filename.zip.b07600. Pls. see the following screenshot:
The two files are perfect in size and I even can rename each of them to filename.zip and extract it without any problems.
Can anybody tell me what is going wrong???
function zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path = array(), $files_array = array()) {
// Archive File Name
$archive_file = $archiveDir."/".$archive_file_name;
// Time-to-live
$archiveTTL = 86400; // 1 day
// Delete old zip file
#unlink($archive_file);
// Create the object
$zip = new ZipArchive();
// Create the file and throw the error if unsuccessful
if ($zip->open($archive_file, ZIPARCHIVE::CREATE) !== TRUE) {
$response->res = "Cannot open '$archive_file'";
return $response;
}
// Add each file of $file_name array to archive
$i = 0;
foreach($files_array as $value){
$expl = explode("/", $value);
$file = $expl[(count($expl)-1)];
$path_file = $file_path[$i] . "/" . $file;
$size = round((filesize ($path_file) / 1024), 0);
if(file_exists($path_file)){
$zip->addFile($path_file, $file);
}
$i++;
}
$zip->close();
// Then send the headers to redirect to the ZIP file
header("HTTP/1.1 303 See Other"); // 303 is technically correct for this type of redirect
header("Location: $archive_file");
exit;
}
The code which calls the function is a file with a switch-case... it is called itself by an ajax-call:
case "zdl":
$files_array = array();
$file_path = array();
foreach ($dbh->query("select GUID, DIRECTORY, BASENAME, ELEMENTID from SMDMS where ELEMENTID = ".$osguid." and PROJECTID = ".$osproject.";") as $subrow) {
$archive_file_name = $subrow['ELEMENTID'].".zip";
$archiveDir = "../".$subrow['DIRECTORY'];
$files_array[] = $archiveDir.DIR_SEPARATOR.$subrow['BASENAME'];
$file_path[] = $archiveDir;
}
zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path, $files_array);
break;
One more code... I tried to rename the latest 123456.zip.a01234 file to 123456.zip and then unlink the old 123456.zip.a01234 (and all prior added .a01234 files) with this function:
function zip_file_exists($pathfile){
$arr = array();
$dir = dirname($pathfile);
$renamed = 0;
foreach(glob($pathfile.'.*') as $file) {
$path_parts = pathinfo($file);
$dirname = $path_parts['dirname'];
$basename = $path_parts['basename'];
$extension = $path_parts['extension'];
$filename = $path_parts['filename'];
if($renamed == 0){
$old_name = $file;
$new_name = str_replace(".".$extension, "", $file);
#copy($old_name, $new_name);
#unlink($old_name);
$renamed = 1;
//file_put_contents($dir."/test.txt", "old_name: ".$old_name." - new_name: ".$new_name." - dirname: ".$dirname." - basename: ".$basename." - extension: ".$extension." - filename: ".$filename." - test: ".$test);
}else{
#unlink($file);
}
}
}
In short: copy works, rename didn't work and "unlink"-doesn't work at all... I'm out of ideas now... :(
ONE MORE TRY: I placed the output of $zip->getStatusString() in a variable and wrote it to a log file... the log entry it produced is: Renaming temporary file failed: No such file or directory.
But as you can see in the graphic above the file 43051221.zip.a07200 is located in the directory where the zip-lib opens it temporarily.
Thank you in advance for your help!
So, after struggling around for days... It was so simple:
Actually I work ONLY on *nix Servers so in my scripts I created the folders dynamically with 0777 Perms. I didn't know that IIS doesn't accept this permissions format at all!
So I remoted to the server, right clicked on the folder Documents (the hierarchically most upper folder of all dynamically added files and folders) and gave full control to all users I found.
Now it works perfect!!! The only thing that would be interesting now is: is this dangerous of any reason???
Thanks for your good will answers...
My suspicion is that your script is hitting the PHP script timeout. PHP zip creates a temporary file to zip in to where the filename is yourfilename.zip.some_random_number. This file is renamed to yourfilename.zip when the zip file is closed. If the script times out it will probably just get left there.
Try reducing the number of files to zip, or increasing the script timeout with set_time_limit()
http://php.net/manual/en/function.set-time-limit.php

Uploading files remotely on Selenium WebDriver using PHP

I've been searching around StackOverflow (and other resources) on how to remotely upload files on Selenium WebDriver with PHP. I've read this http://saucelabs.com/blog/index.php/2012/03/selenium-tips-uploading-files-in-remote-webdriver/, and it mentions that you need to use a "setFileDetector" method somehow to change the way the WebDriver library you're using works.
This should work fine if I was using Ruby or Java. Most PHP frameworks on the other hand don't have this method.
Can anybody tell me how to do this in PHP? Specifically, I'm using the phpwebdriver library http://code.google.com/p/php-webdriver-bindings/
I was able to determine that the JsonWireProtocol to upload a file would be /session/<sessionId>/file by checking out the raw log on the SauceLabs.com blog post (https://saucelabs.com/jobs/1a408cf60af0601f49052f66fa37812c/selenium-server.log) so with that, I created this function to add-in to the php-webdriver-bindings library:
/**
* Send a file to your Remote WebDriver server
* This will return the local URL of the file you uploaded, which will then
* let you use sendKeys in file input elements
* #params String $value - a local or remote file to send
* #return String $resopnseValue - the local directory where the file resides on the remote server
*/
public function sendFile($value) {
$file = #file_get_contents($value);
if( $file === false ) {
return false;
}
$file = base64_encode($file);
$request = $this->requestURL . "/file";
$session = $this->curlInit($request);
$args = array( 'file' => $file );
$postargs = json_encode($args);
$this->preparePOST($session, $postargs);
$response = trim(curl_exec($session));
$responseValue = $this->extractValueFromJsonResponse($response);
return $responseValue;
}
Add this to the WebDriver.php file.
To use, just do something like this:
...
$file_location = $webdriver->sendFile('http://test.com/some/file.zip');
$file_input = $webdriver->findElementBy(LocatorStrategy::id, 'uploadfile');
$file_input->sendKeys(array($file_location));
I hope this will help other developers, spent like 3 hours looking for the answer to this.
Update:
I had to change this due to getting this error:
Expected there to be only 1 file. There were: 0
Hopefully putting this here would get Google results (I tried searching for the error message on Google and the only results it could find were the references to the source code on Google Code).
To solve this problem, I was able to deduce that the file you send actually needs to be zipped. So I've augmented the source code to use PHP's ZipArchive library. I will keep the old code on top for record-keeping, but please use the new code here:
public function sendFile($value, $file_extension = '')
{
$zip = new ZipArchive();
$filename_hash = sha1(time().$value);
$zip_filename = "{$filename_hash}_zip.zip";
if( $zip->open($zip_filename, ZIPARCHIVE::CREATE) === false ) {
echo 'WebDriver sendFile $zip->open failed\n';
return false;
}
$file_data = #file_get_contents($value);
if( $file_data === false ) {
throw new Exception('WebDriver sendFile file_get_contents failed');
}
$filename = "{$filename_hash}.{$file_extension}";
if( #file_put_contents($filename, $file_data) === false ) {
throw new Exception('WebDriver sendFile file_put_contents failed');
}
$zip->addFile($filename, "{$filename_hash}.{$file_extension}");
$zip->close();
$zip_file = #file_get_contents($zip_filename);
if( $zip_file === false ) {
throw new Exception('WebDriver sendFile file_get_contents for $zip_file failed');
}
$file = base64_encode($zip_file);
$request = $this->requestURL . "/file";
$session = $this->curlInit($request);
$args = array( 'file' => $file );
$postargs = json_encode($args);
$this->preparePOST($session, $postargs);
$response = trim(curl_exec($session));
return $this->extractValueFromJsonResponse($response);
}
Update: Turns out, you need to set two parameters on the $zip->addFile() method. Edited the above code to reflect the changes.

Remote Zip Extraction > Can't seem to get this to the finish line

The purpose of this code is to grab an update.zip file from a remote server, unzip it and save it to a local directory, updating, overwriting or creating the updated files.
I've almost got a non cURL version of this working, but I'd rather use this version. The first problem I have is that the path to the tmp folder is incorrect. I need a better method of sniffing that out (temporarily hardcoded)...
The 2nd problem is that the code's not working, but its not throwing an error. Its executing the $x branch but no zip extraction is taking place.
require('../../../wp-blog-header.php'); //enables wp security check and ABSPATH
$payload = file_get_contents('http://myserver.com/upgrade.zip'); //grab the file from the remote server
$target = ABSPATH .'wp-content/themes/mytheme/'; // this is the destination for the unzipped files
openZip($payload);
function openZip($file_to_open, $debug = false) {
global $target;
$file = ABSPATH . '/tmp/'.md5($file_to_open).'.zip'; //this should be home/myfolder/tmp but ABSPATH is giving the wrong path to the tmp directory.
$client = curl_init($file_to_open);
curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);
$fileData = curl_exec($client);
file_put_contents($file, $fileData);
$zip = new ZipArchive();
$x = $zip->open($file);
if($x === true) { //this is true, but no zip extraction?
$zip->extractTo($target);
$zip->close();
unlink($file);
} else {
if($debug !== true) {
unlink($file);
}
die("There was a problem. Please try again!");
}
}
The most likely cause here is that you're not actually writing the zip file data in your file_put_contents() call inside openZip. If you pass a zero-length file to $zip->open(), it will happily go about its way returning (bool)true, even though you obviously will not be able to extract anything from it. See this example.

Categories