Codeigniter - Get several files, rename them and then zip it - php

I'm making a website, using codeigniter, that will enable users to download files a bit like gmail. By that I mean that the user can download only 1 file or all files in a zip folder.
Because there will be many files, I have encoded their names to avoid duplicates and stored their original names in a database which returns me an array like this:
Array
(
[0] => Array
(
[file_id] => 2
[file_name] => v6_copy.pdf
[file_path] => uploads/4/d5/67697ff58d09d3fb25d563bf85d3f1ac.pdf
)
[1] => Array
(
[file_id] => 3
[file_name] => v4_copy.pdf
[file_path] => uploads/7/cf/38212079635e93a8f8f4d4a3fc2a11ff.pdf
)
)
What I need to do is, get each file, rename them to their original names and then zip it in one zip. I'm currently trying to use the codeigniter zip helper, but I can't seem to be able to rename the files.
foreach ($query->result() as $row) // This returns what you see above
{
// I need to rename the file somewhere here
$this->zip->read_file($row->filename);
}
$this->zip->download('files_backup.zip');
Is there a way to do this without creating manually a directory, copying the files, renaming them and then zipping the file?
Any help most appreciated.

CodeIgniter's Zip Class apparently does not offer any means to rename entries. You can use PHP's native Zip Extension, which allows you to change the name when adding the file to the archive (and also later).
Example from PHP Manual
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->addFile('/path/to/index.txt', 'newname.txt');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}

Thanks to #Gordon 's answer, I found a solution.
He is completely right about Codeigniter not being able to rename a file, but I found a really quick change to the library and it seems to be working.
If you go to your system>librairies->Zip.php like mentioned by #Gordon, search for "read_file" and you'll find the function.
Then I simply added a argument to the function and modified some of the code thereafter, see below:
function read_file($path, $preserve_filepath = FALSE, $name = NULL) // Added $name
{
if ( ! file_exists($path))
{
return FALSE;
}
if (FALSE !== ($data = file_get_contents($path)))
{
if($name == NULL){ // Added a verification to see if it is set, if not set, then it does it's normal thing, if it is set, it uses the defined var.
$name = str_replace("\\", "/", $path);
if ($preserve_filepath === FALSE)
{
$name = preg_replace("|.*/(.+)|", "\\1", $name);
}
}
$this->add_data($name, $data);
return TRUE;
}
return FALSE;
}
I hope this helps others. Thanks again #Gordon

Related

Read files in batch process cpanel php

I have created one process to read information from files and save into database, everything works fine in my desenv environment, but when I have put files in my php host (production environment) the process fail when read files.
to execute my process, I have created one cron job on cpanel, whith the command bellow:
php -q /home/<hostfolder>/batch/index.php
When my process is executed by cron, the output say that don't have files. Bellow part of my code:
private $sourceFilesFolder = "/home/<host folder>/public_html/batch/arquivos";
private $destFilesFolder = "/home/<host folder>/public_html/batch/processados";
private $log;
private $trataException;
function __construct($log, $trataException) {
$this->log = $log;
$this->trataException = $trataException;
}
/**
* Read the source folder and select only files
* #return array - Array of valid files
*/
function selectFiles() {
// Save the first read of ftp folder
$listSourceFolder = scandir ( $this->sourceFilesFolder );
// Array tho save only valid files
$listFiles = array ();
// read the array with ftp content and save in listFiles only files
foreach ( $listSourceFolder as $file ) {
$verifica = $this->sourceFilesFolder . "\\" . $file;
// if is a file type, try save in listFiles array
if (($file != ".") && ($file != "..") && (!is_dir ( $verifica ))) {
// verifiy if the file exists
if (file_exists ( $verifica )) {
$this->log->gravaLog ( $file . " -> ADDED TO PROCESS" );
//verificaArquivoEmUso ( $verifica );
array_push ( $listFiles, $verifica );
} else
$this->log->gravaLog ( $file . "-> do not exist." );
} else
$this->log->gravaLog ( $file . "-> not is a file." );
}
return $listFiles;
}
In my folder I have two txt files and this appear in the $listSourceFolder variable, but when I check this files with file_exists, always return false.
First, I have put my code files in a bacth folder in /home/
In the second test, I move the files in ftp folder and put inside the bacth folder (same of my code).
In the third test, I moved all batch folder (with codes and txt files) to public_html folder.
Nothing work, always the same error, file not exists.
I tryed remove ths file_exists if, but occur erros on the next step of algoritm.
I have checked the file permissions, and all permissions are ok.
What is I can do???
You can try three things.
1 - chmod 777 (Give permission so php can read and write files)
2 - I know its practically impossible that your server has a lower version of php. Scandir only works php 5 above. So you might wanna check that.
3 - There's a module called "mod_speling", try put that on.
;)
It appears that you are using the incorrect path delimiter for *nix.
You might change your code to be the following instead:
$verifica = $this->sourceFilesFolder . "/" . $file;

Read hidden extension of file from link

I need to read pdf extension file from some links which I crawled from a web. The links is saved in $link variable.
but sometimes, the extension doesn't written in the link, for example : http://tstc.bz/docs/490 besides 490 is a pdf file, the extension will exist when I click it. How to read that hidden extension ? thank you
I've tried using PATHINFO
if (strtolower(pathinfo($link,PATHINFO_EXTENSION)) === 'pdf'){
Use mime_content_type, documentation here, to fetch the type of the file you're trying to load.
If you are caching the content of the links, this is a good option, as you need to have the file locally. Otherwise, do like baba is suggesting, use get_headers with the link (documentation here), passing a non-zero value as the second parameter to have the keys in your result array. Then, it's simply a matter of reading [Content-Type] from your resulting array
You can use get_headers
$link = "http://tstc.bz/docs/490";
if (getPdf($link)) {
// yes its a PDF File
}
Function Used
function getPdf($link) {
$ext = strtolower(pathinfo($link, PATHINFO_EXTENSION));
if (empty($ext)) {
$type = array_change_key_case(get_headers($link, true), CASE_LOWER);
if (is_array($type['content-type']))
return false;
if (strtolower($type['content-type']) === "application/pdf") {
return true;
}
}
if ($ext === 'pdf') {
return true;
}
return false;
}

Check if a file was included or loaded

Is there any elegant way to check if a file was included by using include/include_once/require/require_once or if the page was actually loaded directly? I'm trying to set up a testing file inside class files while I'm creating them.
I'm looking for something similar to Python's if __name__ == "__main__": technique. Without setting globals or constants.
Quoted from: How to know if php script is called via require_once()?
I was looking for a way to determine if a file have been included or called directly, all from within the file. At some point in my quest I passed through this thread. Checking various other threads on this and other sites and pages from the PHP manual I got enlightened and came up with this piece of code:
if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
echo "called directly";
} else {
echo "included/required";
}
In essence it compares if the name of the current file (the one that
could be included) is the same as the file that is beeing executed.
Credit: #Interwebs Cowboy
you can do this by get_included_files — Returns an array with the names of included or required files and validate against __FILE__
I appreciate all the answers, but I didn't want to use any one's solution here, so I combined your ideas and got this:
<?php
// place this at the top of the file
if (count(get_included_files()) == 1) define ('TEST_SUITE', __FILE__);
// now I can even include bootstrap which will include other
// files with similar setups
require_once '../bootstrap.php'
// code ...
class Bar {
...
}
// code ...
if (defined('TEST_SUITE') && TEST_SUITE == __FILE__) {
// run test suite here
}
?>
if (defined('FLAG_FROM_A_PARENT'))
// Works in all scenarios but I personally dislike this
if (__FILE__ == get_included_files()[0])
// Doesn't work with PHP prepend unless calling [1] instead.
if (__FILE__ == $_SERVER['SCRIPT_FILENAME'])
// May break on Windows due to mixed DIRECTORY_SEPARATOR
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']))
// Doesn't work with files with the same basename but different paths
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))
// Seems to do the trick as long as document root is properly configured
Note: On WAMP Servers virtual-hosts sometimes inherit the default document root setting, causing $_SERVER['DOCUMENT_ROOT'] to display wrong path.
<?php
if (__FILE__ == $_SERVER['SCRIPT_FILENAME'])
{
//file was navigated to directly
}
?>
Taken from mgutt's answer to a slightly different question here. It's important to note this doesn't work if the script is run from command line but other than that it functions exactly like python's
if __name__ == '__main__':
as far as I can tell
They is no way to separate them as include/include_once/require/require_once but php has get_included_files and get_required_files which is the same thing and only returns array of all included files. Its does not separate it if its required or included.
Example a.php
include 'b.php';
include_once 'c.php';
require 'd.php';
var_dump(get_required_files());
Output
array
0 => string '..\lab\stockoverflow\a.php' (length=46) <---- Returns current file
1 => string '..\lab\stockoverflow\b.php' (length=46)
2 => string '..\lab\stockoverflow\c.php' (length=46)
3 => string '..\lab\stockoverflow\d.php' (length=46)
But you can do something like
$inc = new IncludeManager($file);
var_dump($inc->find("b.php")); // Check if a file is included
var_dump($inc->getFiles("require_once")); // Get All Required Once
Class Used
class IncludeManager {
private $list = array();
private $tokens = array();
private $find;
private $file;
private $type = array(262 => "include",261 => "include_once",259 => "reguire",258 => "require_once");
function __construct($file) {
$this->file = $file;
$this->_parse();
}
private function _parse() {
$tokens = token_get_all(file_get_contents($this->file));
for($i = 0; $i < count($tokens); $i ++) {
if (count($tokens[$i]) == 3) {
if (array_key_exists($tokens[$i][0], $this->type)) {
$f = $tokens[$i + 1][0] == 371 ? $tokens[$i + 2][1] : $tokens[$i + 1][1];
$this->list[] = array("pos" => $i,"type" => $this->type[$tokens[$i][0]],"file" => trim($f, "\"\'"));
}
}
}
}
public function find($find) {
$finds = array_filter($this->list, function ($v) use($find) {
return $v['file'] == $find;
});
return empty($finds) ? false : $finds;
}
public function getList() {
return $this->list;
}
public function getFiles($type = null) {
$finds = array_filter($this->list, function ($v) use($type) {
return is_null($type) ? true : $type == $v['type'];
});
return empty($finds) ? false : $finds;
}
}
get_included_files() return array where 0 index mean first "included" file. Because direct run mean "include" in this terms, you can simple check first index for equality for __FILE__:
if(get_included_files()[0] == __FILE__){
do_stuff();
}
This can not work on PHP 4, because PHP 4 not add run file in this array.
Here's a different idea.
Just include the file whenever you need it.
Inside the include file you can decide whether it needs to include the contents:
<?php
if (defined("SOME_UNIQUE_IDENTIFIER_FOR_THIS_FILE"))
return;
define("SOME_UNIQUE_IDENTIFIER_FOR_THIS_FILE", 1);
// Rest of code goes here
Working solution:
$target_file = '/home/path/folder/file.php'; // or use __FILE__
if ($x=function($e){return str_replace(array('\\'), '/', $e);}) if(in_array( $x($target_file), array_map( $x , get_included_files() ) ) )
{
exit("Hello, already included !");
}
I don't think get_included_files is the perfect solution, what if your main script included some other scripts before the check? My suggestion is to check whether __FILE__ equals realpath($argv[1]):
<?php
require('phpunit/Autoload.php');
class MyTests extends PHPUnit_Framework_TestCase
{
// blabla...
}
if (__FILE__ == realpath($argv[0])) {
// run tests.
}
I took a similar approach to this issue when I cam across it. The solution I found was to load each file as needed in an include_once method. Hope this helps.
$FILES = get_included_files(); // Retrieves files included as array($FILE)
$FILE = __FILE__; // Set value of current file with absolute path
if(!in_array($FILE, $FILES)){ // Checks if file $FILE is in $FILES
include_once "PATH_TO_FILE"; // Includes file with include_once if $FILE is not found.
}
I have the following function established to check files loaded:
ARRAY_DUMP($FILES);
function ARRAY_DUMP($array){
echo "
<span style='font-size:12px;'>".date('h:i:s').":</span>
<pre style='font-size:12px;'>", print_r($array, 1), "</pre>
";
}
Output:
currentArray
(
[0] => /home/MY_DOMAIN/hardeen/index.php
[1] => /home/MY_DOMAIN/hardeen/core/construct.php
[2] => /home/MY_DOMAIN/hardeen/core/template.php
[3] => /home/MY_DOMAIN/hardeen/bin/tags.php
[4] => /home/MY_DOMAIN/hardeen/bin/systemFunction.php
)
It's sooo simple..
I have made something like this:
//code for file.php
if (!isset($file_included)){
echo "It was loaded!";
} else {
echo "It was included!";
}
//code for loader.php
//proves that atleast loader.php has loaded,
//not the file we targeted first..
$file_included = true;
include("../file.php");
And that's it.. as simple as in python.

PHP, Check if URL and a file exists ?

I create a plugin for WordPress that requires two files to be exists in order to operate normaly.
The first file is defined as a file system path and the second file is defined as a URL.
Let's say the first file is that:
/home/my_site/public_html/some_folder/required_file.php
and the second file is that:
http://www.my_site.com/some_folder/required_url_file.php
Note that both files are not the same file into the file system. The required_file.php has other content than the required_url_file.php and they act absolutly diferent
Any idea on how to validate the existance of both files ?
You can check both:
$file = '/home/my_site/public_html/some_folder/required_file.php';
$url = 'http://www.my_site.com/some_folder/required_url_file.php';
$fileExists = is_file($file);
$urlExists = is_200($url);
$bothExists = $fileExists && $urlExists;
function is_200($url)
{
$options['http'] = array(
'method' => "HEAD",
'ignore_errors' => 1,
'max_redirects' => 0
);
$body = file_get_contents($url, NULL, stream_context_create($options));
sscanf($http_response_header[0], 'HTTP/%*d.%*d %d', $code);
return $code === 200;
}
Based on Maor H. code sample, here is a function I am using in my plugins:
/**
* Check if an item exists out there in the "ether".
*
* #param string $url - preferably a fully qualified URL
* #return boolean - true if it is out there somewhere
*/
function webItemExists($url) {
if (($url == '') || ($url == null)) { return false; }
$response = wp_remote_head( $url, array( 'timeout' => 5 ) );
$accepted_status_codes = array( 200, 301, 302 );
if ( ! is_wp_error( $response ) && in_array( wp_remote_retrieve_response_code( $response ), $accepted_status_codes ) ) {
return true;
}
return false;
}
I've made this a method in a helper class, however putting this in your theme's functions.php file should make it generally accessible everywhere. However you should always be writing in classes and instantiating them. It is much better for isolating your plugin and theme functionality.
With this in place you can simply use:
if (webItemExists('http://myurl.com/thing.png')) {
print 'it iexists';
}
Most often you will be using WordPress calls to access all items via a relative or fully qualified URL. If you have a relative reference to something such as /uploads/2012/12/myimage.png you can convert those to a fully qualified URL v. a WordPress relative URL by simply adding get_site_url(). $string when calling the webItemExists() function.
As for validating the URL, none of these answers are considering the correct, WordPress way to carry out this task.
For this task wp_remote_head() should be used.
Here's an article I've written about How To Check Whether an External URL Exists with WordPress’ HTTP API. Check it out and figure out how it works.
$file_exists = file_exists($path);
$url_accessable = http_get($url, array("timeout"=>10), $info); // should not be FALSE
$status_code = $info['response_code'] //should be 200
This seems to work for me:
function url_file_exists($url) {
$context = stream_context_create(array('http' =>array('method'=>'HEAD')));
$fd = #fopen($url, 'rb', false, $context);
if ($fd!==false) {
fclose($fd);
return true;
}
return false;
}
If you have PECL http_head function available, you could check if it returns status code 200 for the remote file.
To check if you can access the local file, could use file_exists, but this does not grant that you will be able to access that file. To check if you can read that file, use is_readable.
To check if a file exists, use the file_exists method.
As of PHP 5.0.0, this function can also be used with some URL
wrappers. Refer to Supported Protocols and Wrappers to determine which
wrappers support stat() family of functionality.
if(! (file_exists($url1) && file_exists($url2)) ) {
die("Files don't exist - throw error here.");
}
// Continue as usual - files exist at this point.
remote:
$file = 'http://www.my_site.com/some_folder/required_url_file.php'
if ( #fclose(#fopen($file,"r")) ) echo "File exists!";
local:
$file = '/home/my_site/public_html/some_folder/required_file.php';
if ( is_file($file) ) echo "File exists!";
Use function file_exists()
file_exists('http://www.my_site.com/some_folder/required_url_file.php');
will get you results as True or false.
Checking if a file exists:
if (file_exists('path/to/file.txt')) {
echo "File exists!";
} else {
echo "File doesn't exist.";
}
Checking if a URL is valid:
$data = #file_get_contents("http://url.com/");
if (!$data) {
echo "URL not valid.";
} else {
echo "URL is valid.";
}
Notes:
Ideally you shouldn't try and predict the filesystem. Whilst methods such as file_exists are very helpful, they shouldn't be relied upon and instead you should attempt to write to files, read from them, etc, and then catch and handle any exceptions or errors that occur.

Using a :default for file names on include templates in SMARTY 3

Although I don't think the question was as good as it could be, let me try to explain better here.
I have a site using SMARTY 3 as the template system. I have a template structure similar to the below one:
/templates/place1/inner_a.tpl
/templates/place1/inner_b.tpl
/templates/place2/inner_b.tpl
/templates/place2/inner_c.tpl
/templates/default/inner_a.tpl
/templates/default/inner_b.tpl
/templates/default/inner_c.tpl
These are getting included on the parent template using
{include file="{$temp_folder}/{$inner_template}"}
So far great. What I wanted to do is having a default for, in the case that the file {$temp_folder}/{$inner_template} does not exists, it uses the equivalent file at default/{$inner_template}.
i.e. If I do {include file="place1/inner_c.tpl"}, since that file does not exists it in fact includes "default/inner_c.tpl"
Is it possible?
You'll have to do it in php, smarty doesn't have a way to check if a file exists.
You could write your own template handler too.
<?php
// put this function somewhere in your application
function make_template ($resource_type, $resource_name, &$template_source, &$template_timestamp,
&$smarty_obj)
{
if( $resource_type == 'file' ) {
if ( ! is_readable ( $resource_name )) {
// create the template file, return contents.
$template_source = "This is a new template.";
require_once SMARTY_CORE_DIR . 'core.write_file.php';
smarty_core_write_file( array( 'filename'=>$smarty_obj->template_dir . DIRECTORY_SEPARATOR . $resource_name, 'contents'=>$template_source ), $smarty_obj );
return true;
}
} else {
// not a file
return false;
}
}
// set the default handler
$smarty->default_template_handler_func = 'make_template';
?>

Categories