Read hidden extension of file from link - php

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

Related

Check if the text file was empty

I'd like to know how to check if a text file is empty or not. It means that there is no text even some space, i.e. it was blank
function keyRemain($path)
{
$ambil = file_get_contents("data/$path/keywords.txt");
$kw = explode(",", $ambil);
if (count($kw) > 1) {
return false;
} else {
return true;
}
}
You have to check the empty function along with trim
function keyRemain($path)
{
$ambil = trim(file_get_contents("data/$path/keywords.txt"));
var_dump($ambil); // check the output here
if(!empty($ambil)) {
return false;
} else {
return true;
}
}
Maybe this was not the answer, just the another way to check the file. Before this was happend, the code appear instead the class. After i cut it and move it outside of the class it work perfectly without any errors.
file_get_contents() will read the whole file while filesize() uses stat() to detirmine the file size. Use filesize(), it should consume less disk I/O.
That's the answer found here, on stack...
You can also (on same link there's this answer):
clearstatcache();
if(filesize($path_to_your_file)) {
// your file is not empty
}

Save file to memory and later write back

I wish to read a file using PHP, and later write it to a directory which doesn't exist at the time of reading the file. I can't create the directory first as described below. I do not wish to save it in a temporary directory to prevent possible overwrites. Am I able to read the file, save it in memory, and later write the file?
WHY I WISH TO DO THIS: I have the following method which empties a directory. I now have a need to do so but keep one file in the root of the emptied directory. I recognize I could modify this method to do so, but I rarely need to do so, and may wish another approach. Instead, before calling this method, I would like to copy the file in question, empty the directory, and then put it back.
/**
* Empty directory. Include subdirectories if $deep is true
*/
public static function emptyDir($dirname,$deep=false)
{
$dirname=(substr($dirname, -1)=='/')?$dirname:$dirname.'/';
if(!is_dir($dirname)){return false;}
// Loop through the folder
$dir = dir($dirname);
while (false !== $entry = $dir->read())
{
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
elseif(is_file($dirname.$entry)) {
unlink($dirname.$entry);
}
elseif($deep && is_dir($dirname.$entry)){
self::deltree($dirname.$entry);
}
}
// Clean up
$dir->close();
return true;
}
Provided this is all done withing the same request, then yes you can.
Just save the file contents to a variable, then write it back again:
$temp = file_get_contents('path/to/file.ext');
className::emptyDir($dir);
file_put_contents('path/to/file.ext', $temp);
Yes, it could be done. Just add a property to your class. So in your class property, there will be the content of the file, while the object is exists, and it did set. It could be a class variable (static) also, so you do not need to instantiate if you do not want.
class anything {
var $fileContent = '';
public static function emptyDir($dirname,$deep=false) {
//....
}
public function setFileContent($fileOrUrlToRead) {
$this->fileContent = file_get_contents($fileOrUrlToRead);
}
public function saveFile($fileName) {
file_put_contents($fileName, $this->fileContent);
}
}
$anything = new anything();
$anything->setFileContent('url_or_path_of_file_to_get');
anything::emptyDir('./media/files/');
$anything->saveFile('./media/files/something.txt');
You can use the session to save the needed information.

FileIFrameField with Parsing

I'm using SilverStripe 2.4.7 and I want to add a method that parses the file which I have just uploaded with FileIFrameField. The thing that has me stumped is where to put this. I was thinking of the onAfterWrite method but the file only gets uploaded after the rest of the fields have been saved for the first time so I'm not sure this would work.
My question is: What is the best practice for this kind of thing?
Edit
I have this line of code where $filename is the path to my uploaded file but I keep getting a "no such file or directory error". I have even tried hardcoding in the filepath but get the same error.
$fh = fopen($filename, 'r');
the best way to parse a new file would be to hook into the uploadfield save method, for the FileIframeField you can do that by sub classing it and overwriting save()
(in SilverStripe 3 there is a new class called UploadField, in UploadField you would need to overwrite UploadField->upload(SS_HTTPRequest $request), and the file there would be accesable like this: $tmpfile = $request->postVar($this->getName()); )
below, and example on how to do it in FileIframeField:
class myFileIFrameField extends FileIFrameField {
public function save($data, $form) {
if (
!isset($data['FileSource'])
|| ($data['FileSource'] == 'new' && (!isset($_FILES['Upload']) || !$_FILES['Upload']))
|| ($data['FileSource'] == 'existing' && (!isset($data['ExistingFile']) || !$data['ExistingFile']))
) {
$form->sessionMessage(_t('FileIFrameField.NOSOURCE', 'Please select a source file to attach'), 'required');
Director::redirectBack();
return;
}
$fileContent = false;
if($data['FileSource'] == 'new') {
$fileContent = file_get_contents($_FILES['Upload']['tmp_name']);
}
elseif($data['FileSource'] == 'existing') {
$fileObject = DataObject::get_by_id('File', $data['ExistingFile']);
$fileContent = file_get_contents($fileObject->getFullPath());
}
if ($fileContent) {
// parse the $fileContent here
}
// if you want to still save the file into a relation,
//meaning if you want to have the actually FileIframeField behaviour still in tact then call
return parent::save($data, $form);
// other wise, if you do not want to save the relation and you don't want to save the file to the server
// thenn do NOT call parent::save, just do:
// Director::redirectBack();
}
}

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

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

Restrict allowed file upload types PHP

Right now I have a function which takes my uploaded file, checks the extension, and if it matches an array of valid extensions it's processed. It's a contact list importer.
What I need to figure out is how to be sure that file (in this case a .csv) is actually what it says it is (ex. not an excel file that just got renamed as a .csv).
Our servers run PHP 5.2.13
Here's the current validation function I have
public static function validateExtension($file_name,$ext_array) {
$extension = strtolower(strrchr($file_name,"."));
$valid_extension="FALSE";
if (!$file_name) {
return false;
} else {
if (!$ext_array) {
return true;
} else {
foreach ($ext_array as $value) {
$first_char = substr($value,0,1);
if ($first_char <> ".") {
$extensions[] = ".".strtolower($value);
}
else {
$extensions[] = strtolower($value);
}
}
foreach ($extensions as $value) {
if ($value == $extension) {
$valid_extension = "TRUE";
}
}
if ($valid_extension==="TRUE") {
return true;
} else {
return false;
}
}
}
}
EDIT: I'm now trying to do
exec('file -ir '.$myFile)
When I run this command in terminal I'm given a usable response. When I run the same command through php, I'm given something different. Any ideas why? I've tried it with exec, passthru, shell_exec. And the server does not have safe mode running.
Forget extension checking, it's not reliable enough.
Also, I think traditional MIME magic sniffing will fail here, because there is no usable header (This is just my guess, though.)
In this specific case, I'd say it's feasible to take a quick peek at the contents, for example read the first ten lines or so. If they are all no longer than x bytes, and each line contains the same number of semicolons (or whatever your CSV parser takes as separators), it's a CSV file.

Categories