Need to bulletproof this image parser function - php

I've got a function below which reads the contents of wp-content/uploads and writes out all images that it finds there.
The problem is that it's reading off the blog title to determine the image path and when the blog title has a dot in it, there's trouble
Blog title is abc123.com
site url is abc123.com
test image filename is abc123-1.jpg
img tag SHOULD become:
<img src='http://abc123.com/wp-content/uploads/abc123-1.jpg' />
actual image tag written from the function below is:
<img src='http://abc123.com/wp-content/uploads/abc123.com-1.jpg' />
My question is, how did the ".com" get inserted into the filename???
Function follows...
function get_images()
{
global $options;
foreach ($options as $value) {
if (get_settings( $value['id'] ) === FALSE) { $$value['id'] = $value['std']; } else { $$value['id'] = get_settings( $value['id'] ); }
}
if($cb_custom_images !== "")
{
echo $cb_custom_images;
}
else
{
$dir = 'wp-content/uploads/';
$url = get_bloginfo('url').'/wp-content/uploads/';
$imgs = array();
if ($dh = opendir($dir))
{
while (($file = readdir($dh)) !== false)
{
if (!is_dir($file) && preg_match("/\.(bmp|jpeg|gif|png|jpg|)$/i", $file))
{
array_push($imgs, $file);
}
}
closedir($dh);
} else {
die('cannot open ' . $dir);
}
foreach ($imgs as $idx=>$img)
{
$class = ($idx == count($imgs) - 1 ? ' class="xlast"' : '');
echo '<img src="' . $url . $img . '" alt="' .$img . '"' . $class . ' />';
}
}
}

Are you sure your test file is named abc123-1.jpg? I just copied your code into a file and added dummy scaffolding, including a wp-content/uploads/abc123-1.jpg file.
I got the correct result when I ran the script:
% php img.php
<img src="http://abc123.com/wp-content/uploads/abc123-1.jpg" alt="abc123-1.jpg" class="xlast" />
`

I think it is preg_match issue try to remove character after jpg

Is there a abc123.com-1.jpg file in that directory?
That could be the problem.

Sorry about this one guys, nothing wrong with the function. I had a legacy file that this file relied on that was incompatible. After updating that file, all is well.
Now I just have to figure this one out (assuming I've got any cred left after this one :-) Do we get mulligans around here?

Related

PHP Is there a way to display my list from the foreach separately?

I want to display the links separately. One list would include all the .html links and the other all the .jpg links.
right now it displays this and I understand why it is doing it, but when i do another foreach outside or even right before the echo, its like nothing is passing into it.
.jpg
.html
.jpg
.html
I need it to display like this
HTML-Backup HTML
.jpg .html
.jpg .html
php Code
$array = array();
$html= "";
$htmlBackup= "";
if(file_exists("uploads/" . $_POST["prefix"] .'/'))
{
$dir = 'uploads/' . $_POST["prefix"] . '/';
$files = preg_grep('~\.(jpeg|jpg|png)$~', scandir($dir));
$prefixDir = scandir($dir);
foreach($prefixDir as $dir_files)
{
$secondDir = $dir . $dir_files;
//$finalDir=scandir($secondDir);
if((is_dir($secondDir)))
{
$finalDir=preg_grep('~\.(html|jpg)$~', scandir($secondDir));
$i = 0;
foreach($finalDir as $lastDir)
{
if(strpos($lastDir, "HTML5.jpg") !== false)
{
echo''.$lastDir.' </br>';
//variable to store list of dir
$html=$lastDir;
} else if(strpos($lastDir, "HTML5.html") !== false )
{
echo''.$lastDir.' </br>';
//variable to store the list of dir
$htmlBackup=$lastDir;
}
}
}
}
}
Don't put <br> at the end of each echo. Do it after the inner loop so all links from the same directory will be on the same line.
foreach($prefixDir as $dir_files)
{
$secondDir = $dir . $dir_files;
//$finalDir=scandir($secondDir);
if((is_dir($secondDir)))
{
$finalDir=preg_grep('~\.(html|jpg)$~', scandir($secondDir));
$i = 0;
foreach($finalDir as $lastDir)
{
if(strpos($lastDir, "HTML5.jpg") !== false)
{
echo''.$lastDir.'';
//variable to store list of dir
$html=$lastDir;
} else if(strpos($lastDir, "HTML5.html") !== false )
{
echo''.$lastDir.'';
//variable to store the list of dir
$htmlBackup=$lastDir;
}
}
echo "<br>";
}
}
I found a solution by including arrays.
foreach($prefixDir as $dir_files)
{
$secondDir = $dir . $dir_files;
//$finalDir=scandir($secondDir);
if((is_dir($secondDir)))
{
$finalDir=preg_grep('~\.(html|jpg)$~', scandir($secondDir));
$i = 0;
foreach($finalDir as $lastDir)
{
if(strpos($lastDir, "HTML5.html") !== false || strpos($lastDir, "H5.html") !== false)
{
//variable to store the list of dir
array_push($html_array, $lastDir);
array_push($html_dir,$secondDir.'/'.$lastDir);
}
else if(strpos($lastDir, "HTML5.jpg") !== false || strpos($lastDir, "H5.jpg")!== false )
{
//variable to store list of dir
array_push($html_backup_array, $lastDir);
array_push($html_backup_dir,$secondDir.'/'.$lastDir);
}
}
}
}
and then display them under in another foreach as I want
if(!empty($html_array))
{
echo "<p>";
echo ("<p><span class='heading'>HTML5 Units</span></p>");
foreach (array_combine($html_dir, $html_array) as $html_dirr => $html_arrays)
{
echo (''.$html_arrays.'');
echo "<br>";
}
echo "</p>";
}

PHP preg_match: linking single or multiple images via class function

Hey fellow programmers,
What I'm trying to accomplish is a dynamic way to source images from a directory with the use of a class image.
I'm stuck at supplying an exact string which returns a match but when trying to echo " with the returned match if the whole string is not provided then the image is linked with a partial string plus the extension.
<?php $image = new image; ?>
calling the class function with:
<?php $image -> get_image('this_string_1',''); ?>
The Image directory contents
<?php $path = $_SERVER['DOCUMENT_ROOT'].'/images/;'?>
this_string_1.png
this_string_2.png
this_string_3.png
The class:
<?php
class image{
function get_image($name,$class){
if(strlen($class)==0){ $class="default"; }
####[ Checks the type of image
global $doc_root,$html_path;
if($handle = opendir($doc_root.'/images/')){
while(false !==($value = readdir($handle))){
if($value !== '..' && $value!=='.'){
$extention;
$ext_jpeg = substr($value,-3);
if($ext_jpeg=='jpg'){
$extention=".jpg";
}
$ext_png = substr($value,-3);
if($ext_png=='png'){
$extention=".png";
}
$ext_gif = substr($value,-3);
if($ext_gif=='gif'){
$extention='.gif';
}
}
switch($extention){
case '.jpg':
if(preg_match("/$name/",$value,$result)){
foreach($result as $jpg){
echo '<img class="'.$class.'" src="'.$html_path.'/images/'.$jpg.'.jpg">';
}
}
break;
case '.png':
if(preg_match("/$name/",$value,$result)){
foreach($result as $png){
echo '<img class="'.$class.'" src="'.$html_path.'/images/'.$png.'.png">';
}
}
break;
case '.gif':
if(preg_match("/$name/",$value,$result)){
foreach($result as $gif){
echo '<img class="'.$class.'"src="'.$html_path.'/images/'.$gif.'.gif">';
}
}
break;
}
}
}
}
}
?>
I'm sure there are many ways to accomplish something like this. Any advice would be greatly appreciated.
As per Martins advice.
I have removed the if and switch statements and replaced it with "substr" in the second if statement.
<?php
class image{
function get_image($name,$class){
if(strlen($class)==0){ $class="default"; }
global $doc_root,$html_path;
if($handle = opendir($doc_root.'/images/')){
while(false !==($value = readdir($handle))){
if($value !== '..' && $value!=='.' && substr($value, 0, -4)==$name){
echo '<img src="'.$html_path.'/images/'.$value.'">';
}
}
}
}
}
?>
1) I do not see much point of your sequence of if statements to assign $extention. Why don't you just do $extention = substr($value,-4)?
2) The switch($extention) has to be inside the if($value !== '..' && $value!=='.')
3) What are you trying to achieve by the preg_match?
If you just want to match name completely, just do substr($value, 0, -4) == $name. Well this rely on extension having 3 characters, what's not perfect, but you rely on that already.

PHP Directory Tree - Deleting Folders

I have found a script that lists all directories and files in them, and allows for the deletion of files.
I have two problems:
1) How do I add the function to delete a folder (With all the contents in it)
2) How do I make the script not to allow a user to browse up a directory? (For e.g. a user's folder is ./files/$userid/. I want it so that a user won't be able to go to or make any changes to ./files/ or a folder other then ./files/$userid/
$script = basename(__FILE__); // the name of this script
$path = !empty($_REQUEST['path']) ? $_REQUEST['path'] : dirname('./files/' . (string)$userid . '/'); // the path the script should access
$unlink = $_REQUEST['unlink'];
if(!empty($unlink)){
$unlink = realpath("$path/$unlink");
if(is_writable($unlink) && !unlink($unlink)){
echo "<div class=\"error\">Unable to delete file: $unlink</div>";
}
}
echo "<p>Browsing Location: {$path}</p>";
$directories = array();
$files = array();
// Check we are focused on a dir
if (is_dir($path)){
chdir($path); // Focus on the dir
if ($handle = opendir('.')){
while (($item = readdir($handle)) !== false) {
// Loop through current directory and divide files and directorys
if(is_dir($item)){
array_push($directories, realpath($item));
}
else{
array_push($files, ($item));
}
}
closedir($handle); // Close the directory handle
}
else {
echo "<p class=\"error\">Directory handle could not be obtained.</p>";
}
}
else{
echo "<p class=\"error\">Path is not a directory</p>";
}
// List the directories as browsable navigation
echo "<h2>Navigation</h2>";
echo "<ul>";
foreach($directories as $directory){
$delete = is_writable($file) ? "<a class=\"unlink\" href=\"{$script}?path={$path}&unlink={$directory}\">delete</a>" : '';
echo ($directory != $path) ? "<li>{$directory}</li>" : "";
}
echo "</ul>";
echo "<h2>Files</h2>";
echo "<ul>";
foreach($files as $file){
// Comment the next line out if you wish see hidden files while browsing
if(preg_match("/^\./", $file) || $file == $script){continue;} // This line will hide all invisible files.
$delete = is_writable($file) ? "<a class=\"unlink\" href=\"{$script}?path={$path}&unlink={$file}\">delete</a>" : '';
echo '<li>' . $file . " $delete</li>";
}
echo "</ul>";
1) Try use this function to delete folder recursively (see manual, User contributed notes section http://php.net/manual/en/function.rmdir.php):
function delTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}
2) Better develop some filemanager to allow users browse certain folders. Or see some ready solutions: http://www.jquery4u.com/plugins/10-jquery-file-manager-plugins/

PHP glob() regex pattern

I have a folder that contains logos for sponsors. In my website, a user can belong to a sponsor and the sponsor_id is set in session when the user logs in.
Here is my code:
function sponsor_logos($sponsor_id) {
$logos = glob("resources/content/sites/{$sponsor_id}*");
foreach($logos as $logo) {
if(file_exists("{$logo}"))
echo "<img src='/{$logo}' />";
}
}
The above works, but a sponsor can have multiple logos. So the multiple logos are saved like so: sponsor_id.jpg, sponsor_id_2.jpg, sponsor_id_3.jpg
I am not the strongest at regex, so any help is greatly appreciated! thanks!
You better open directory and check all files in it (if there are not so much files). You could do it like that:
function sponsor_logos($sponsor_id) {
if ($dh = opendir('resources/content/sites/')) {
while (($file = readdir($dh)) !== false) {
if(strpos($file, $sponsor_id . '.') === 0) {
$sponsor_files[] = $file;
}
else if(strpos($file, $sponsor_id . '_') === 0) {
$sponsor_files[] = $file;
}
}
closedir($dh);
}
foreach($sponsor_files as $logo) {
echo "<img src='resources/content/sites/" . $logo . "' />";
}
}
But best solution is to have normal naming scheme.
use this regex sponsor_id(_\d+)?\.jpg

How to get all files from a directory and then make them into a javascript function?

For a project I'm working on now I have to manually add the functions to play songs like this
function song(){
mySong.src="song1.mp3";
mySong.play();
document.getElementById("p2").innerHTML="Now Playing:Song1";
}
But I want to be able to search a directory with php, and generate those functions from php, so I don't have to manually add each song. This is my test code, I know I did it wrong but I can't seem to get it right!
<?php
Header("content-type: application/x-javascript");
if ($handle = opendir('/wamp/www/songs/')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo 'function $entry(){mySong.src=$entry; mySong.play();
document.getElementById("p2").innerHTML="Now Playing:" $entry;}';
echo "$entry";
}
}
closedir($handle);
}
?>
Have the JS function defined in your page, with a parameter for the song source:
function song(entry){
mySong.src=entry;
mySong.play();
document.getElementById("p2").innerHTML="Now Playing: " + entry;
}
In your PHP, you'll most likely want to echo a link to play each of the songs inside that folder, right?
Do this:
<?php
//Header("content-type: application/x-javascript");
if ($handle = opendir('/wamp/www/songs/')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo '' . $entry . '<br />';
}
}
closedir($handle);
}
?>
Note that this will show the file's path name with extension, for better display you'd just have to do some string manipulation with php/js substr/substring and explode/split.
Alright, I rewrote the code to work with your given example:
JS (head)
function song(entry){
var mySong=document.getElementById("song1");
mySong.src=entry;
mySong.play();
document.getElementById("p2").innerHTML="Now Playing: " + entry;
}
PHP + HTML (body)
<?php
//Header("content-type: application/x-javascript");
$path = '/wamp/www/songs/';
if ($handle = opendir($path)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo '' . $entry . '<br />';
}
}
closedir($handle);
}
?>
<p id="p2"></p>
<audio id="song1" controls="controls">
<source src="" type="audio/mpeg" />
</audio>
This will work for mp3 files played in browsers with HTML5 support.
Note that Firefox doesn't support .mp3 playback inside <audio> tags, see: Why doesn't Firefox support the MP3 file format in <audio>
Thus this solution (with your <audio>) will give satisfying results in Chrome only (not tested on opera and safari). You may want to fallback to another solution for more compatibility.
If you want compatibility with IE and Firefox, you can try using an <embed>:
JS
function song(entry){
var mySong=document.createElement('embed');
mySong.src=entry;
mySong.width='250px';
mySong.height='60px';
document.getElementById("song1").innerHTML= '';
document.getElementById("song1").appendChild(mySong);
document.getElementById("p2").innerHTML="Now Playing: " + entry;
}
PHP + HTML
<?php
//Header("content-type: application/x-javascript");
$path = '/wamp/www/songs/';
if ($handle = opendir($path)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo '' . $entry . '<br />';
}
}
closedir($handle);
}
?>
<p id="p2"></p>
<div id="song1"></div>
This will be effectively cross-browser, but may request a plugin installation for Firefox.
you have an issue with your quotes. Single quotes do not parse variables. Also, you have some quotes in the wrong place.
<?php
Header("content-type: application/x-javascript");
if ($handle = opendir('/wamp/www/songs/')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo "function $entry(){mySong.src='$entry';mySong.play();document.getElementById('p2').innerHTML='Now Playing: $entry';}";
}
}
closedir($handle);
}
?>
but you will have another issue with this...your songs probably aren't going to conform to proper function names...you're going to have to rethink this "function for each song" thing...

Categories