I have the following PHP code to display the content of a directory in my website:
<?php
$conn = ftp_connect("host") or die("Could not connect");
ftp_login($conn,"username","password");
if ($_GET['dir'] != null) {
ftp_chdir($conn, "logs/{$_GET['dir']}");
}
else
{
ftp_chdir($conn, "logs");
}
$files = ftp_nlist($conn,"");
foreach($files as $value) {
echo "{$value}";
}
ftp_close($conn);
?>
This is my webpage
When I click on the subdirectory1 or subdirectory2, I get the content of it (some images). Then when I click on one of the images, I get the content of the root directory of my website.
How can I display only the image when a visitor clicks on it? Note that I don't want to download it or anything - I just want to display it in the browser when a visitor clicks on it.
You need to establish which of the returned items are files and which are directories. For that you are better of using ftp_rawlist as it allows to extract more data. Then create links for each case and so you can process them appropriately. Here's a possible implementation:
$ftpHost = 'hostname';
$ftpUser = 'username';
$ftpPass = 'password';
$startDir = 'logs';
if (isset($_GET['file'])) {
// Get file contents (can also be fetched with cURL)
$contents = file_get_contents("ftp://$ftpUser:$ftpPass#$ftpHost/$startDir/" . urldecode($_GET['file']));
// Get mime type (requires PHP 5.3+)
$finfo = new finfo(FILEINFO_MIME);
$mimeType = $finfo->buffer($contents);
// Set content type header and output file
header("Content-type: $mimeType");
echo $contents;
}
else {
$dir = (isset($_GET['dir'])) ? $_GET['dir'] : '';
$conn = ftp_connect($ftpHost) or die("Could not connect");
ftp_login($conn, $ftpUser, $ftpPass);
// change dir to avoid ftp_rawlist bug for directory names with spaces in them
ftp_chdir($conn, "$startDir/$dir");
// fetch the raw list
$list = ftp_rawlist($conn, '');
foreach ($list as $item) {
if(!empty($item)) {
// Split raw result into pieces
$pieces = preg_split("/[\s]+/", $item, 9);
// Get item name
$name = $pieces[8];
// Skip parent and current dots
if ($name == '.' || $name == '..')
continue;
// Is directory
if ($pieces[0]{0} == 'd') {
echo "<a href='?dir={$dir}/{$name}'><strong>{$name}</strong></a><br />";
}
// Is file
else {
echo "<a href='?file={$dir}/{$name}'>{$name}</a><br />";
}
}
}
ftp_close($conn);
}
You'll need to add a function which checks which type of file we're handling.
If it's a directory show the regular link (the one you're using now) and if it's an image
show a link with the path of the image.
Because $value contains the name of the file you can use end(explode('.',$value)); to find the ext. of the file (php , jpg , gif , png).
Use another condition with the piece of information and you can identify if it's a picture or not.
In order to build the path of the image you'll need to use the $_GET['dir'] variable's value.
For instance:
<a href='<?=$_GET['dir']?>/Flower.gif'>Flower.gif</a>
I hope you got the idea.
Related
I have multiple sites, and have a text file on our main site with a list of domains to whitelist. I want to be able to edit this global file from each of the websites.
I have a couple of problems that I'm running into:
file_exists() and ftp_delete() are not finding the file even though it exists on the remote server.
ftp_fput() is adding a blank text file in the correct place with a zero filesize.
Here is my code:
// Check if we are updating the whitelist
if(isset($_POST['Submit'])){
// Make sure we have something to add or remove
if (isset($_POST['update']) && $_POST['update'] != '') {
// Get the text we need to add or remove
$add_or_remove_this = $_POST['update'];
eri_update_global_whitelist( $add_or_remove_this, 'add' );
// Say it was done
echo '<br>Script Completed...<br>';
}
}
echo '<form method="post">
<textarea name="update" cols="50" rows="10"></textarea><br><br>
<input name="Submit" type="submit" value="Update"/>
</form>';
function eri_update_global_whitelist( $string, $add_or_remove = 'add' ) {
// Validate the string
$domains = explode( ',', str_replace(' ', '', strtolower($string)) );
print_r($domains); // <-- WORKS AS EXPECTED
// Add invalid domains here
$invalid = [];
// Cycle
foreach ($domains as $key => $domain) {
// Check if it contains a dot
if (strpos($domain, '.') === false) {
// If not, remove it
unset($domains[$key]);
// Add it to invalid array'
$invalid[] = $domain;
}
}
print_r($domains); // <-- WORKS AS EXPECTED
// Only continue if we have domains to work with
if (!empty($domains)) {
// The whitelist filename
$filename = 'email_domain_whitelist.txt';
// File path on remote server
$file_url = 'https://example.com/eri-webtools-plugin/data/'.$filename;
// Get the file content
$file_contents = file_get_contents( $file_url );
// Only continue if we found the file
if ($file_contents) {
// Explode the old domains
$old_domains = explode( ',', str_replace(' ', '', $file_contents) );
print_r($old_domains); // <-- WORKS AS EXPECTED
// Are we adding or removing
if ($add_or_remove == 'add') {
// Merge the arrays without duplicates
$new_domains = array_unique (array_merge ($old_domains, $domains));
} else {
// Loop through them
foreach ($old_domains as $key => $old_domain) {
// Check if it matches one of the new domains
if (in_array($old_domain, $domains)) {
// If so, remove it
unset($old_domains[$key]);
}
}
// Change var
$new_domains = $old_domains;
}
print_r($new_domains); // <-- WORKS AS EXPECTED
// Include the ftp configuration file
require_once $_SERVER['DOCUMENT_ROOT'].'/wp-content/plugins/eri-webtools-plugin/ftp_config.php';
// Establishing ftp connection
$ftp_connection = ftp_connect($ftp_server)
or die("<br>Could not connect to $ftp_server");
// If connected
if ( $ftp_connection ) {
// Log in to established connection with ftp username password
$login = ftp_login( $ftp_connection, $ftp_username, $ftp_userpass );
// If we are logged in
if ( $login ){
echo '<br>Logged in successfully!'; // <-- WORKS AS EXPECTED
// Make passive
ftp_pasv($ftp_connection, true);
// File path to delete
$file_to_delete = 'https://example.com/eri-webtools-plugin/data/'.$filename; // <-- NOT SURE HOW TO USE ABSOLUTE PATH ON REMOTE SERVER ??
// Delete the old file
if (file_exists($file_to_delete)) {
if (ftp_delete($ftp_connection, $file_to_delete)) {
echo '<br>Successfully deleted '.$filename;
} else {
echo '<br>There was a problem while deleting '.$filename;
}
} else {
echo '<br>File does not exist at: '.$file_to_delete; // <-- RETURNS
}
// Create a new file
$open = fopen($filename, 'r+');
// If we didn't die, let's implode it
$new_domain_string = implode(', ', $new_domains);
print_r('<br>'.$new_domain_string); // <-- WORKS AS EXPECTED
// Write to the new text file
if (fwrite( $open, $new_domain_string )) {
echo '<br>Successfully wrote to file.'; // <-- RETURNS
} else {
echo '<br>Cannot write to file.';
}
// Add the new file
if (ftp_fput($ftp_connection, '/eri-webtools-plugin/data/2'.$filename, $open, FTP_ASCII)) {
echo '<br>Successfully uploaded '.$filename; // <-- RETURNS
} else {
echo '<br>There was a problem while uploading '.$filename;
}
} else {
echo '<br>Could not login...';
}
// Close the FTP connection
if(ftp_close($ftp_connection)) {
echo '<br>Connection closed Successfully!'; // <-- RETURNS
} else {
echo '<br>Connection could not close...';
}
} else {
echo '<br>Could not connect...';
}
} else {
echo '<br>Could not find the file...';
}
} else {
echo '<br>No valid domains to add or remove...';
}
// Check for invalid domains
if (!empty($invalid)) {
echo '<br>Invalid domains found: '.implode(', ', $invalid);
}
}
Finally figured it out. I ditched ftp_fput() and replaced it with ftp_put(). Then I referred to the temporary file location on the local server instead of the fopen() like so:
ftp_put($ftp_connection, '/eri-webtools-plugin/data/'.$filename, $filename, FTP_ASCII)
So to explain what's going on (in case someone else runs into this):
// Name the temporary path and file, preferably the same name as what you want to call it.
// The path doesn't need to be specified. It just gets temporarily stored at the root and then deleted afterwards.
$filename = 'filename.txt';
// Create a new file by opening one that doesn't exist
// This will be temporarily stored on the local server as noted above
$fp = fopen($filename, 'w+');
// Write to the new file
fwrite( $fp, 'Text content in the file' );
// Add the file where you want it
ftp_put($ftp_connection, '/desination_folder/'.$filename, $filename, FTP_ASCII);
// Close the file
fclose($fp);
I ended up finding out that using ftp_put() will replace a file if it already exists, so there is no need to delete the old one like I was trying to.
I want to upload 1000 images in just one click via URL. I have 1000 Image URLs stored in MYSQL database.
So please any one give me PHP code to upload that 1000 images via URL through mysql database.
Currently I am using the bellow code:-
It upload one image per click by posting URL of image...
But i want to upload 1000 image in one click by getting URLs from databse
$result = mysql_query("SELECT * FROM thumb") or die(mysql_error());
// keeps getting the next row until there are no more to get
while($row = mysql_fetch_array( $result )) {
echo "<div>";
$oid = $row['tid'];
$th= $row['q'];
echo "</div>";
$thi = $th;
$get_url = $post["url"];
$url = trim('$get_url');
if($url){
$file = fopen($url,"rb");
$directory = "thumbnail/";
$valid_exts = array("php","jpeg","gif","png","doc","docx","jpg","html","asp","xml","JPEG","bmp");
$ext = end(explode(".",strtolower(basename($url))));
if(in_array($ext,$valid_exts)){
$filename = "$oid.$ext";
$newfile = fopen($directory . $filename, "wb");
if($newfile){
while(!feof($file)){
fwrite($newfile,fread($file,1024 * 8),1024 * 8);
}
echo 'File uploaded successfully';
echo '**$$**'.$filename;
}
else{
echo 'File does not exists';
}
}
else{
echo 'Invalid URL';
}
}
else{
echo 'Please enter the URL';
}
}
Thanks a lot.... …
The code you have is outdated and a lot more complex than needed. This is not a site where you get code because you ask, this is a learning environment.
I'll give you an example on which you can continue:
// Select the images (those we haven't done yet):
$sItems = mysql_query("SELECT id,url FROM thumb WHERE imported=0") or die(mysql_error());
// Loop through them:
while( $fItems = mysql_fetch_assoc($sItems) ){
$imgSource = file_get_contents($fItems['url']); // get the image
// Check if it didn't go wrong:
if( $imgSource!==false ){
// Which directory to put the file in:
$newLocation = $_SERVER['DOCUMENT_ROOT']."/Location/to/dir/";
// The name of the file:
$newFilename = basename($fItems['url'], $imgSource);
// Save on your server:
file_put_content($newLocation.$newFilename);
}
// Update the row in the DB. If something goes wrong, you don't have to do all of them again:
mysql_query("UPDATE thumb SET imported=1 WHERE id=".$fItems['id']." LIMIT 1") or die(mysql_error());
}
Relevant functions:
file_get_contents() - Get the content of the image
file_put_contents() - Place the content given in this function in a file specified
basename() - given an url, it gives you the filename only
Important:
You are using mysql_query. This is deprecated (should no longer be used), use PDO or mysqli instead
I suggest you make this work from the commandline and add an echo after the update so you can monitor progress
So I am using this script to upload a file to a directory and show it live.
<?php
function UploadImage($settings = false)
{
// Input allows you to change where your file is coming from so you can port this code easily
$inputname = (isset($settings['input']) && !empty($settings['input']))? $settings['input'] : "fileToUpload";
// Sets your document root for easy uploading reference
$root_dir = (isset($settings['root']) && !empty($settings['root']))? $settings['root'] : $_SERVER['DOCUMENT_ROOT'];
// Allows you to set a folder where your file will be dropped, good for porting elsewhere
$target_dir = (isset($settings['dir']) && !empty($settings['dir']))? $settings['dir'] : "/uploads/";
// Check the file is not empty (if you want to change the name of the file are uploading)
if(isset($settings['filename']) && !empty($settings['filename']))
$filename = $settings['filename'] . "sss";
// Use the default upload name
else
$filename = preg_replace('/[^a-zA-Z0-9\.\_\-]/',"",$_FILES[$inputname]["name"]);
// If empty name, just return false and end the process
if(empty($filename))
return false;
// Check if the upload spot is a real folder
if(!is_dir($root_dir.$target_dir))
// If not, create the folder recursively
mkdir($root_dir.$target_dir,0755,true);
// Create a root-based upload path
$target_file = $root_dir.$target_dir.$filename;
// If the file is uploaded successfully...
if(move_uploaded_file($_FILES[$inputname]["tmp_name"],$target_file)) {
// Save out all the stats of the upload
$stats['filename'] = $filename;
$stats['fullpath'] = $target_file;
$stats['localpath'] = $target_dir.$filename;
$stats['filesize'] = filesize($target_file);
// Return the stats
return $stats;
}
// Return false
return false;
}
?>
<?php
// Make sure the above function is included...
// Check file is uploaded
if(isset($_FILES["fileToUpload"]["name"]) && !empty($_FILES["fileToUpload"]["name"])) {
// Process and return results
$file = UploadImage();
// If success, show image
if($file != false) { ?>
<img src="<?php echo $file['localpath']; ?>" />
<?php
}
}
?>
The thing I am worried about is that if a person uploads a file with the same name as another person, it will overwrite it. How would I go along scraping the filename from the url and just adding a random string in place of the file name.
Explanation: When someone uploads a picture, it currently shows up as
www.example.com/%filename%.png.
I would like it to show up as
www.example.com/randomstring.png
to make it almost impossible for images to overwrite each other.
Thank you for the help,
A php noob
As contributed in the comments, I added a timestamp to the end of the filename like so:
if(isset($settings['filename']) && !empty($settings['filename']))
$filename = $settings['filename'] . "sss";
// Use the default upload name
else
$filename = preg_replace('/[^a-zA-Z0-9\.\_\-]/',"",$_FILES[$inputname]["name"]) . date('YmdHis');
Thank you for the help
I have a function that takes uploaded files (WORDPRESS) and adds them to a (newly created) zip file.
every new file is added to the zip (if is not yet created - the first file will create one ) and also to a comment with the list of the files.
function Ob99_generate_zip_file($meta) {
// we always need post_id , right ?
if( isset($_GET['post_id']) ) {
$post_id = $_GET['post_id'];
} elseif( isset($_POST['post_id']) ) {
$post_id = $_POST['post_id'];
}
//setting some more variables.
$file = wp_upload_dir();// take array
$file2 = wp_upload_dir();//debug
$zipname = $file['path'].'file.zip'; // set zip file name
$file = trailingslashit($file['basedir']).$meta['file'];// construct real path
// Without this next condition the function dies. WHY ??
list($orig_w, $orig_h, $orig_type) = #getimagesize($file); // not help to comment
if (!$orig_type == IMAGETYPE_GIF || !$orig_type == IMAGETYPE_PNG|| !$orig_type == IMAGETYPE_JPEG) {
//why other filetypes not working ??
return ;
}
$zip = new ZipArchive; // initiatte class
$zip->open($zipname , ZipArchive::CREATE); // open buffer
$new_filename = substr($file,strrpos($file,'/') + 1); //we do not need nested folders
$zip->addFile($file,$sitename.'/'.$new_filename); // we add the file to the zip
if (file_exists($zipname)){
$comment = $zip->getArchiveComment(); // if the file already exist read the comment
}
else { // if not - let´s give it a cool retro header
$comment_head = '*********************************'. PHP_EOL ;
$comment_head .= '****** <<< FILE CONTENT >>> *****'. PHP_EOL ;
$comment_head .= '*********************************'. PHP_EOL ;
}
$comment = $comment_head . $comment ;// add header before comment
$comment = $comment . PHP_EOL . PHP_EOL . $meta['file'] ; // add new file name
$zip->setArchiveComment($comment); // and comment
$zip->addFromString('filelist.txt', $comment); // create txt file with the same list
$zip->close()or die('can not create zip file'.$file.print_r($meta).'---- DEBUG SEPERATOR ---- '.print_r($file2)); // FINISHED or DIE with debug
}
My problem : if I try to upload any file other than an image - the function will DIE .
I have added a condition for checking imagetype - but I would like to know why it is crashing and how to make it work without said condition ...
Does the zip function have any problems with PDF , doc or anyother ? is that a wordpress problem ?
The problem section seems to be where you're asking PDFs, etc. their image size. Why don't you try:
$image_size = getimagesize($file);
if($image_size===false)
{
// This is not an image
// Do what you want to PDFs, etc.
}
else
{
// This is an image
// Find out image type, dimensions, etc.
}
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