I have code for getting files list in php, but if file name contain & character it doesn't display that file.
Here's the code:
Ps. I'm not php programmer and I really don't know what is this error.
All help will be very appreciated
Thanks so much in advance.
<?php
include_once('config.inc.php');
$current_dir = 'root';
if(array_key_exists('directory',$_POST)) {
$current_dir = $_POST['directory'];
}
// Creating a new XML using DOMDocument
$file_list = new DOMDocument('1.0');
$xml_root = $file_list->createElement('filelist');
$xml_root = $file_list->appendChild($xml_root);
// Setting the 'currentPath' attribute of the XML
$current_path = $file_list->createAttribute('currentPath');
$current_path->appendChild($file_list->createTextNode($current_dir));
$xml_root->appendChild($current_path);
// Replacing the word 'root' with the real root path
$current_dir = substr_replace($current_dir, $root, 0, 4);
$di = new DirectoryIterator($current_dir);
// Creating the XML using DirectoryIterator
while($di->valid())
{
if(false == $di->isDot())
{
if($di->isDir() && true != in_array($di->getBasename(),$h_folders))
{
$fl_node = $file_list->createElement('dir');
$xml_root->appendChild($fl_node);
}else if($di->isFile() && true !== in_array($di->getBasename(),$h_files)
&& true !== in_array(get_ext($di->getBasename()),$h_types))
{
$fl_node = $file_list->createElement('file');
$xml_root->appendChild($fl_node);
}else
{
$di->next();
continue;
}
$name = $file_list->createElement('name',$di->getBasename());
$fl_node->appendChild($name);
$path = substr_replace($di->getRealPath(), 'root', 0, strlen($root));
$path_node = $file_list->createElement('path', $path);
$fl_node->appendChild($path_node);
$di->next();
}else $di->next();
}
function get_ext($filename)
{
$exp = '/^(.+)\./';
return preg_replace($exp,'',$filename);
}
// Returning the XML to Flash.
echo $file_list->saveXML();
?>
The & character is used in HTML to write entities.
If you want to display arbitrary text in HTML, you need to escape it by calling htmlentities().
If you give some source I can help, file content not file name.
Example how get list of files:
$c = "/some/path/to/file/here";
if(is_dir($c)){
foreach(scandir($c) as $file){
if($file != '.' && $file != '..'){
$d = $c.DIRECTORY_SEPARATOR.$file;
echo " \"". realpath($d) ."\"\n";
}
}
}
Related
My aim is to parse DOCX file with PHP for all hyperlinks in format:
<start of hyperlink(number of the first element of hyperlink in text)>,
<end of hyperlink(number of the last element of hyperlink in text)>,
<hyperlink text>
For example:
input: "Hello, absolutely terrible{adjective: distressing}(you cannot see this in .docx file) world!"
output: {19, 26, "adjective: distressing"}
For now I've done code to parse all the hyperlinks as plain text, but I cannot get numbers of its position in text. Here is my code:
define("dir", "Dictations");
define("test_file", "Dictation_Text.docx");
/**
* #param $filename
* #return string
*/
function getHyperLinks($filename) {
$explode_result = explode('.', $filename);
$extension = end($explode_result);
if ($extension == "docx") {
$dataFile = "word/document.xml";
}
else {
return "DOCX files only supported";
}
$zip = new ZipArchive;
if ($zip->open($filename) === true) {
if (($zip_index = $zip->locateName($dataFile)) !== false) {
$data = $zip->getFromIndex($zip_index);
$parser = xml_parser_create();
xml_parse_into_struct($parser, $data, $values, $indexes);
xml_parser_free($parser);
$result = Array();
foreach ($indexes["W:HYPERLINK"] as $ind) {
if ($values[$ind]["type"] == "open") {
$result[] = $values[$ind]["attributes"]["W:ANCHOR"];
}
}
return $result;
}
else {
return "File " . $filename . " couldn't be found in " . document;
}
}
else {
return "Couldn't open archive " . $filename;
}
}
#TODO: getting filename from front by $_GET
$document = dir . "/" . test_file;
$result = getHyperLinks($document);
if (is_array($result)) {
foreach ($result as $res) {
echo $res . "\n";
}
}
else {
echo $result;
}
So I couldn't find any XML attribute of starting position of hyperlink, please tell me how to get it or some way to get it from XMLObject or maybe show me another more convenient way to parse DOCX file to get all the info I need.
Your approach looks generally fine, but you're looking in the wrong file.
.docx link elements aren't stored in document.xml. Weird, right?
word/_rels/document.xml.rels has all that data (or header1.xml.rels, etc.).
If you want to see the format, re-name your .docx to a .zip. Then you can extract it and view all the .xml files inside. Each link gets a line of XML, so if all you need are the links, you may not need to parse from document.xml at all.
If you do need context, you'll go by the association of the "Id" variable on each Relationship.
I have pdf files which are report cards of students.The report card names format is <student full name(which can have spaces)><space><studentID>.I need to download files.For this I have used the following code.
if(file_exists($folder_path.'/') && is_dir(folder_path)) {
$report_files = glob(folder_path.'/*'.'_*\.pdf' );
if(count($report_files)>0)
{
$result_data = '';
$result_data = rename_filenamespaces($report_files);
var_dump($result_data);//this shows the edited filename
foreach ($result_data as $file) {
if (strpos($file,$_GET['StudentID']) !== false) {
//code for showing the pdf docs to download
}
}
}
}
//function for renaming if filename has spaces
function rename_filenamespaces($location)
{
$new_location = $location;
foreach ($location as $file) {
//check file has spaces and filename has studentID
if((strpos($file," ")!==false)&& (strpos($file,$_GET['StudentID']) !== false))
{
$new_filename = str_replace(" ","-",$file);
rename($file,$new_filename);
$new_location = $new_filename;
}
}
return $new_location;
}
The variable $result_data gives me the filename without spaces,but the for each loop is showing Warning:Invalid argument supplied for foreach(). But the filename is changed in the server directory immediately after running the function. This warning shows only for first time. I am unable to solve this.
$new_location = $new_filename;
$new_location is a array
$new_filename is a string
You have to use $new_location[$index]
or try
foreach ($new_location as &$file) {
...
...
$file = $new_filename;
I have been trying to modify some PHP to allow my page to get to a directory and its sub-directories to get video files to display dynamically on my page, I'm using the scripts as follows
$imagetypes = array("video/ogv", "video/webm", "video/mp4");
$dir = "../uploadedVideo/*/";
function getImages($dir)
{
global $imagetypes;
// array to hold return value
$retval = array();
// add trailing slash if missing
if(substr($dir, -1) != "/") $dir .= "/";
// full server path to directory
$fulldir = "{$_SERVER['DOCUMENT_ROOT']}/$dir";
$d = #dir($fulldir) or die("getVideo: Failed opening directory $dir for reading");
while(false !== ($entry = $d->read())) {
// skip hidden files
if($entry[0] == ".") continue;
// check for image files
$f = escapeshellarg("$fulldir$entry");
$mimetype = trim(`file -bi $f`);
foreach($imagetypes as $valid_type) {
if(preg_match("#^{$valid_type}#", $mimetype)) {
$retval[] = array(
'file' => "/$dir$entry",
'size' => getimagesize("$fulldir$entry")
);
break;
}
}
}
$d->close();
return $retval;
}
This the top of my page before the HTML
This the div I'm looking to display static images or thumbnail, which when clicked on will be viewed in the page
<div class="vidSelect">
<?php
// fetch image details
$video = getImages("video");
// display on page
foreach($video as $vid) {
echo "<div class=\"vidContainer\" src=\"{$vid['file']}\"
{$vid['size'][3]}></div>\n";
} ?>
</div>
I haven't as yet sorted the video player, as I'm just looking to get the videos to show up first but have run out of ideas and skills to get any further.
It looks as if something is being seen as 3 div containers are being created although there are five sub directories within one main directory I want to access, Any help would be most gratefully received
So I see your Type is wrong from the comments. Also the Source is not correct.
function getImages($dir) {
global $imagetypes;
// array to hold return value
$retval = array();
// add trailing slash if missing
if (substr($dir, -1) != "/") $dir. = "/";
// full server path to directory
$fulldir = "{$_SERVER['DOCUMENT_ROOT']}/$dir";
$d = #dir($fulldir) or die("getVideo: Failed opening directory $dir for reading");
while (false !== ($entry = $d - > read())) {
// skip hidden files
if ($entry[0] == ".") continue;
// check for image files
$f = escapeshellarg("$fulldir$entry");
$mimetype = trim(`file - bi $f`);
foreach($imagetypes as $valid_type) {
if (preg_match("#^{$valid_type}#", $mimetype)) {
$retval[] = array(
'file' = > "$dir$entry",
'size' = > getimagesize("$fulldir$entry"));
break;
}
}
}
$d - > close();
return $retval;
}
Then in your HTML:
< div class = "vidSelect" >
<? php
// fetch image details
$video = getImages("video");
// display on page
foreach($video as $vid) {
echo "<div class='vidContainer' src='{$vid['file']}' type='{$vid['size']['mime']}'></div>\n";
} ?>
< /div>
I have a python script I wrote that I need to port to php. It recursively searches a given directory and builds a string based on regex searches. The first function I am trying to port is below. It takes a regex and a base dir, recursively searches all files in that dir for the regex, and builds a list of the string matches.
def grep(regex, base_dir):
matches = list()
for path, dirs, files in os.walk(base_dir):
for filename in files:
fullpath = os.path.join(path, filename)
with open(fullpath, 'r') as f:
content = f.read()
matches = matches + re.findall(regex, content)
return matches
I never use PHP except for basic GET param manipulation. I grabbed some directory walking code from the web, and am struggling to make it work like the python function above due to my utter lack of the php API.
function findFiles($dir = '.', $pattern = '/./'){
$prefix = $dir . '/';
$dir = dir($dir);
while (false !== ($file = $dir->read())){
if ($file === '.' || $file === '..') continue;
$file = $prefix . $file;
if (is_dir($file)) findFiles($file, $pattern);
if (preg_match($pattern, $file)){
echo $file . "\n";
}
}
}
Here is my solution:
<?php
class FileGrep {
private $dirs; // Scanned directories list
private $files; // Found files list
private $matches; // Matches list
function __construct() {
$this->dirs = array();
$this->files = array();
$this->matches = array();
}
function findFiles($path, $recursive = TRUE) {
$this->dirs[] = realpath($path);
foreach (scandir($path) as $file) {
if (($file != '.') && ($file != '..')) {
$fullname = realpath("{$path}/{$file}");
if (is_dir($fullname) && !is_link($fullname) && $recursive) {
if (!in_array($fullname, $this->dirs)) {
$this->findFiles($fullname, $recursive);
}
} else if (is_file($fullname)){
$this->files[] = $fullname;
}
}
}
return($this->files);
}
function searchFiles($pattern) {
$this->matches = array();
foreach ($this->files as $file) {
if ($contents = file_get_contents($file)) {
if (preg_match($pattern, $contents, $matches) > 0) {
//echo $file."\n";
$this->matches = array_merge($this->matches, $matches);
}
}
}
return($this->matches);
}
}
// Usage example:
$fg = new FileGrep();
$files = $fg->findFiles('.'); // List all the files in current directory and its subdirectories
$matches = $fg->searchFiles('/open/'); // Search for the "open" string in all those files
?>
<html>
<body>
<pre><?php print_r($matches) ?></pre>
</body>
</html>
Be aware that:
It reads each file to search for the pattern, so it may require a lot of memory (check the "memory_limit" configuration in your PHP.INI file).
It does'nt work with unicode files. If you are working with unicode files you should use the "mb_ereg_match" function rather than the "preg_match" function.
It does'nt follow symbolic links
In conclusion, even if it's not the most efficient solution at all, it should work.
I will try to explain as well as possible what I'm trying to do.
I have a folder on a server with about 100 xml files. These xml files are content pages with text and references to attachment filenames on the server that will be pushed to a wiki through an API.
It's all working fine 1 XML file at a time but I want to loop through each one and run my publish script on them.
I tried with opendir and readdir and although it doesn't error it only picks up the one file anyway.
Could someone give me an idea what I have to do. I'm very new to PHP, this is my first PHP project so my code is probably not very pretty!
Here's my code so far.
The functions that gets the XML content from the XML file:
<?php
function gettitle($file)
{
$xml = simplexml_load_file($file);
$xmltitle = $xml->xpath('//var[#name="HEADLINE"]/string');
return $xmltitle[0];
}
function getsummary($file)
{
$xml = simplexml_load_file($file);
$xmlsummary = $xml->xpath('//var[#name="summary"]/string');
return $xmlsummary[0];
}
function getsummarymore($file)
{
$xml = simplexml_load_file($file);
$xmlsummarymore = $xml->xpath('//var[#name="newslinetext"]/string');
return $xmlsummarymore[0];
}
function getattachments($file)
{
$xml = simplexml_load_file($file);
$xmlattachments = $xml->xpath('//var[#name="attachment"]/string');
return $xmlattachments[0];
}
?>
Here's the main publish script which pushes the content to the wiki:
<?php
// include required classes for the MindTouch API
include('../../deki/core/dream_plug.php');
include('../../deki/core/deki_result.php');
include('../../deki/core/deki_plug.php');
//Include the XML Variables
include('loadxmlfunctions.php');
//Path to the XML files on the server
$path = "/var/www/dekiwiki/skins/importscript/xmlfiles";
// Open the XML file folder
$dir_handle = #opendir($path) or die("Unable to open $path");
// Loop through the files
while ($xmlfile = readdir($dir_handle)) {
if($xmlfile == "." || $xmlfile == ".." || $xmlfile == "index.php" )
continue;
//Get XML content from the functions and put in the initial variables
$xmltitle = gettitle($xmlfile);
$xmlsummary = getsummary($xmlfile);
$xmlsummarymore = getsummarymore($xmlfile);
$xmlattachments = getattachments($xmlfile);
//Build the variables for the API from the XML content
//Create the page title - replace spaces with underscores
$pagetitle = str_replace(" ","_",$xmltitle);
//Create the page path variable
$pagepath = '%252f' . str_replace("'","%27",$pagetitle);
//Strip HTML from the $xmlsummary and xmlsummarymore
$summarystripped = strip_tags($xmlsummary . $xmlsummarymore, '<p><a>');
$pagecontent = $summarystripped;
//Split the attachments into an array
$attachments = explode("|", $xmlattachments);
//Create the variable with the filenames
$pagefilenames = '=' . $attachments;
$pagefilenamefull = $xmlattachments;
//Create the variable with the file URL - Replace the URL below to the correct one
$pagefileurl = 'http://domain/skins/importscript/xmlfiles/';
//authentication
$username = 'admin';
$password = 'password';
// connect via proxy
$Plug = new DreamPlug('http://domain/#api');
// setup the deki api location
$Plug = $Plug->At('deki');
//authenticate with the following details
$authResult = $Plug->At('users', 'authenticate')->WithCredentials($username, $password)->Get();
$authToken = $authResult['body'];
$Plug = $Plug->With('authtoken', $authToken);
// Upload the page content - http://developer.mindtouch.com/Deki/API_Reference/POST:pages//%7Bpageid%7D//contents
$Plug_page = $Plug->At('pages', '=Development%252f' . $pagetitle, 'contents')->SetHeader('Expect','')->Post($pagecontent);
// Upload the attachments - http://developer.mindtouch.com/MindTouch_Deki/API_Reference/PUT:pages//%7Bpageid%7D//files//%7Bfilename%7D
for($i = 0; $i < count($attachments); $i++){
$Plug_attachment = $Plug->At('pages', '=Development' . $pagepath, 'files', '=' . $attachments[$i])->SetHeader('Expect','')->Put($pagefileurl . $attachments[$i]);
}
}
//Close the XMl file folder
closedir($dir_handle);
?>
Thanks for any help!
To traverse a directory of XML files you can just do:
$files = glob("$path/*.xml");
foreach($files as $file)
{
$xml = simplexml_load_file($file);
$xmltitle = gettitle($xml);
$xmlsummary = getsummary($xml);
$xmlsummarymore = getsummarymore($xml);
$xmlattachments = getattachments($xml);
}
I also recommend you make a minor adjustment to your code so simplexml doesn't need to parse the same file four times to get the properties you need:
function gettitle($xml)
{
$xmltitle = $xml->xpath('//var[#name="HEADLINE"]/string');
return $xmltitle[0];
}
function getsummary($xml)
{
$xmlsummary = $xml->xpath('//var[#name="summary"]/string');
return $xmlsummary[0];
}
function getsummarymore($xml)
{
$xmlsummarymore = $xml->xpath('//var[#name="newslinetext"]/string');
return $xmlsummarymore[0];
}
function getattachments($xml)
{
$xmlattachments = $xml->xpath('//var[#name="attachment"]/string');
return $xmlattachments[0];
}
Try changing your while loop to and see if that helps out better:
while (false !== ($xmlfile = readdir($dir_handle)))
Let me know.
EDIT:
By using the old way, there could have been a directory name that could have evaluated to false and stopped the loop, the way I suggested is considered the right way to loop over a directory while using readdir taken from here