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.
Related
i've a function from my simple library and called on some controllers
$activeUrl = str_replace(base_url(),"",current_url());
erporate_acl::has_permission($activeUrl);
and then here is my library code, here the code try to matching current URI ($param) data from database :
public static function has_permission($param){
$CI =& get_instance();
$CI->load->model('acl_model');
$user = $CI->session->userdata('user');
$arrPerms = $CI->acl_model->permissions($user);
$currentMeth = strtolower(str_replace("::", "/", $param));
$result = "";
if (!empty($arrPerms))
{
if (strpos($currentMeth,'edit') !== false || strpos($currentMeth,'view') !== false || strpos($currentMeth,'delete') !== false) {
$str = preg_replace('#\/[^/]*$#', '', $currentMeth);
$result = in_array($str, $arrPerms);
}else{
$result = in_array($currentMeth, $arrPerms);
}
}else{
$result = false;
}
if ($result == false) {
show_error("<font size='+1'>Sorry, You Don't Allowed to Access !</font><br><a href='".#$_SERVER['HTTP_REFERER']."'>Back to Previous Page</a>");
}
}
the point of my script above is matching in_array if in_array return false then we got error message, else allowed to access the page
Is it possible to create permission without checking URI segment ?
Thank you and sorry for my bad English
You can use the following:
$this->router->class to get the controller class that is being used;
$this->router->method to get the method being called;
$this->router->directory to get the directory in case you have sub-folders in your url being used.
This way you don't really need to check the url that's being used. You can just check the controller and method.
This is an agnostic way from the routes. In case you have something like:
users/get/1
user/marco-monteiro
ACL based on the uri segment can be hard in these situations. Using the methods I mentioned it gets easier.
When I try this:
$phar = new PharData('./phar.tar', 0, null, Phar::TAR);
$phar->addEmptyDir('test');
file_put_contents('phar://./phar.tar/test/foo.txt', 'bar');
I get the following error:
Warning: file_put_contents(phar://./phar.tar/test/foo.txt): failed to
open stream: Cannot create phar './phar.tar', file extension (or
combination) not recognised or the directory does not exist
I'm able to use file_get_contents but shouldn't file_put_contents work too?
To make things even weirder, I tried the idea #hakre suggested in his comment and it works!
$phar = new PharData('./phar.tar', 0, null, Phar::TAR);
$phar->addEmptyDir('test');
if (file_exists('./phar.phar') !== true)
{
symlink('./phar.tar', './phar.phar');
}
file_put_contents('phar://./phar.phar/test/foo.txt', 'bar');
var_dump(file_get_contents('phar://./phar.tar/test/foo.txt')); // string(3) "bar"
Introduction
I think this basically has to do with the fact that you are working with Phar::TAR files because
file_put_contents("phar://./test.tar/foo.txt", "hello world");
^
|+---- Note this tar
Returns
Warning: file_put_contents(phar://./test.tar/foo.txt): failed to open stream: Cannot create phar './test.tar', file extension (or combination) not recognized or the directory does not exist
While
file_put_contents("phar://./test.phar/foo.txt", "hello world"); // Works file
^
|+---- Note This phar
Returns
//No Errors
Know Issue
If you look at a detail example in the PHP doc , this has been a known issue for the past 2 years and the example given are as follows
Example
$p = new PharData(dirname(__FILE__) . '/phartest.zip', 0, 'phartest', Phar::ZIP);
$p->addFromString('testfile.txt', 'this is just some test text');
// This works
echo file_get_contents('phar://phartest.zip/testfile.txt');
// This Fails
file_put_contents('phar://phartest.zip/testfile.txt', 'Thist is text for testfile.txt');
$context = stream_context_create(array(
'phar' => array(
'compress' => Phar::ZIP
)
));
// This Fails
file_put_contents('phar://phartest.zip/testfile.txt', 'Thist is text for testfile.txt', 0, $context);
// This works but only with 'r' readonly mode.
$f = fopen('phar://C:\\Inetpub\\wwwroot\\PACT\\test\\phartest.zip\\testfile.txt', 'r');
Working Alternative
Don't use .tar or .zip has your file extension but set compression as demonstrated in the PHP DOC
What do i mean ?
$context = stream_context_create(array(
'phar' => array(
'compress' => Phar::GZ //set compression
)
));
file_put_contents('phar://sample.phar/somefile.txt', "Sample Data", 0, $context);
^
|= Use phar not tar
Advice
I really think you should stick with PharData is realizable and proven to work. The only way to make
I must use file_put_contents
Then write your own wrapper and register it with stream_wrapper_register here is a simple Prof of Concept
stream_wrapper_register("alixphar", "AlixPhar");
file_put_contents('alixphar://phar.tar/test/foo.txt', 'hey');
^
|+-- Write with alixphar
echo file_get_contents('alixphar://phar.tar/test/foo.txt'),PHP_EOL;
echo file_get_contents('phar://phar.tar/test/foo.txt'),PHP_EOL;
Output
hey <----- alixphar
hey <----- phar
Note: This class should not be used in production ... It just an Example and would fail some test cases
class AlixPhar {
private $pos;
private $stream;
private $types;
private $dir;
private $pharContainer, $pharType, $pharFile, $pharDir = null;
private $fp;
function __construct() {
$this->types = array(
"tar" => Phar::TAR,
"zip" => Phar::ZIP,
"phar" => Phar::PHAR
);
// your phar dir to help avoid using path before the phar file
$this->dir = __DIR__;
}
private function parsePath($path) {
$url = parse_url($path);
$this->pharContainer = $url['host'];
$this->pharType = $this->types[pathinfo($this->pharContainer, PATHINFO_EXTENSION)];
if (strpos($url['path'], ".") !== false) {
list($this->pharDir, $this->pharFile, , ) = array_values(pathinfo($url['path']));
} else {
$this->pharDir = $url['path'];
}
}
public function stream_open($path, $mode, $options, &$opened_path) {
$this->parsePath($path);
$this->stream = new PharData($this->dir . "/" . $this->pharContainer, 0, null, $this->pharType);
if (! empty($this->pharDir))
$this->stream->addEmptyDir($this->pharDir);
if ($mode == "rb") {
$this->fp = fopen("phar://" . $this->pharContainer . "/" . $this->pharDir . "/" . $this->pharFile, $mode);
}
return true;
}
public function stream_write($data) {
$this->pos += strlen($data);
$this->stream->addFromString($this->pharDir . "/" . $this->pharFile, $data);
return $this->pos;
}
public function stream_read($count) {
return fread($this->fp, $count);
}
public function stream_tell() {
return ftell($this->fp);
}
public function stream_eof() {
return feof($this->fp);
}
public function stream_stat() {
return fstat($this->fp);
}
}
I have some answers for you - hopefully this will help you out.
First of all, with file_put_contents(), I've noticed some weirdness. First, what I did is follow the example of the link you posted. I was able to add the $context variable, but still had the error. What worked well for me was changing the file name to phar.phar. Perhaps the phar:// handler can't understand a .tar extension?
Anyway, this appears to be working code - but I don't recommend it
$context = stream_context_create(array('phar' =>
array('compress' => Phar::GZ)),
array('metadata' => array('user' => 'cellog')));
file_put_contents('phar://./phar.phar/test/foo.txt', 'bar', 0, $context);
Instead, use this.
Use me - I'm recommended
$phar = new PharData('./phar.tar', 0, null, Phar::TAR);
$phar->addEmptyDir('test');
$phar->addFile('./bar', 'foo.txt');
If you really need to use file_put_contents() instead, perhaps there's a different problem that exists that maybe we can help with. Thanks and good luck!
I've got a couple other alternative approaches which I think are a bit tidier. They avoid custom wrappers, symlinks or creating extra files in order to use the addFile function.
Option A
Use the addFromString function which works similarly to file_put_contents. The code below creates a TAR archive, adds a file to it and compresses it too.
$phar = new PharData("./archive.tar", 0, null, Phar::TAR);
$phar->addFromString('out/fileA.txt','The quick brown fox jumped over the lazy dog');
$phar->compress(Phar::GZ); # Creates archive.tar.gz
Option B
If you really need to use file_put_contents for some reason. You can create a PHAR archive using it, then reopen it and convert it to another archive type.
file_put_contents('phar://archive2.phar/out/fileB.txt', "Colourless green ideas sleep furiously");
$tarphar = new Phar('archive2.phar');
$tar = $tarphar->convertToData(Phar::TAR); # Creates archive2.tar
$zip = $tarphar->convertToData(Phar::ZIP); # Creates archive2.zip
$tgz = $tarphar->convertToData(Phar::TAR, Phar::GZ, '.tar.gz'); # Creates archive2.tar.gz
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.
My site is running in LAMP, my image CDN is in nginx.
I want to do is:
Check if a requested image has a copy in CDN server, if yes then loan the copy in cdn server, otherwise, load the local copy for user.
Is there a programmatically way to check whether the remote CDN image is exist?
(perhaps determine the header? as I notice that if request image isn't exist, it returns 404)
I use this method to ping distant files:
/**
* Use HTTP GET to ping an url
*
* /!\ Warning, the return value is always true, you must use === to test the response type too.
*
* #param string $url
* #return boolean true or the error message
*/
public static function pingDistantFile($url)
{
$options = array(
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_URL => $url,
CURLOPT_FAILONERROR => true, // HTTP code > 400 will throw curl error
);
$ch = curl_init();
curl_setopt_array($ch, $options);
$return = curl_exec($ch);
if ($return === false)
{
return curl_error($ch);
}
else
{
return true;
}
}
You can also use the HEAD method but maybe your CDN as disabled it.
So long as the copy is public, you could just check for a 404 with cURL. See this question detailing how to do it.
You can use file_get_contents for this:
$content = file_get_contents("path_to_your_remote_img_file");
if ($content === FALSE)
{
/*Load local copy*/
}
else
{
/*Load $content*/
}
Oh and one more thing- if you only want to display the image with an img tag, you can simply do this- using img tags onerror attribute- if the image does not exist on the server, the onerror attribute will display the local file:
<img src="path_to_your_remote_img_file" onerror='this.src="path_to_your_local_img_file"'>
You can read a similar question on this here: detect broken image using php
Another easier way – without cURL:
$headers = get_headers('http://example.com/image.jpg', 1);
if($headers[0] == 'HTTP/1.1 200 OK')
{
//image exist
}
else
{
//some kind of error
}
<?php
if (is_array(getimagesize("http://www.imagelocation.com/image.png"))){
// Image ok
} else {
// Image not ok
}
?>
I've just started working with the PHP API for Rackspace Cloud Files. So far so good-- but I am using it as sort of a poor man's memcache, storing key/value pairs of serialized data.
My app attempts to grab the existing cached object by its key ('name' in the API language) using something like this:
$obj = $this->container->get_object($key);
The problem is, if the object doesn't exist, the API throws a fatal error rather than simply returning false. The "right" way to do this by the API would probably be to do a
$objs = $this->container->list_objects();
and then check for my $key value in that list. However, this seems way more time/CPU intensive than just returning false from the get_object request.
Is there a way to do a "search for object" or "check if object exists" in Cloud Files?
Thanks
I sent them a pull request and hope it'll get included.
https://github.com/rackspace/php-cloudfiles/pull/35
My pull-request includes an example, for you it would be similar to this:
$object = new CF_Object($this->container, 'key');
if ($object->exists() === false) {
echo "The object '{$object->name}' does not exist.";
}
I have more general way to check if object exists:
try {
$this->_container->get_object($path);
$booExists = true;
} catch (Exception $e) {
$booExists = false;
}
If you dump the $object, you'll see that content_length is zero. Or, last modified will be a zero length string.
Example:
$object = new CF_Object($container, 'thisdocaintthere.pdf');
print_r($object->content_length);
There is also, deep in the dumped parent object, a 404 that will return, but it's private, so you'd need to some hackin' to get at it.
To see this, do the following:
$object = new CF_Object($container, 'thisdocaintthere.pdf');
print_r($object->container->cfs_http);
You'll see inside that object a response_status that is 404
[response_status:CF_Http:private] => 404
I know I'm a little late to the party, but hopefully this will help someone in the future: you can use the objectExists() method to test if an object is available.
public static function getObject($container, $filename, $expirationTime = false)
{
if ($container->objectExists($filename)) {
$object = $container->getPartialObject($filename);
// return a private, temporary url
if ($expirationTime) {
return $object->getTemporaryUrl($expirationTime, 'GET');
}
// return a public url
return $object->getPublicUrl();
}
// object does not exist
return '';
}
Use like...
// public CDN file
$photo = self::getObject($container, 'myPublicfile.jpg');
// private file; temporary link expires after 60 seconds
$photo = self::getObject($container, 'myPrivatefile.jpg', 60);
If you do not want to import opencloud to perform this check you can use the following:
$url = 'YOUR CDN URL';
$code = FALSE;
$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);
if($code!='200') {
echo 'failed';
} else {
echo 'exists';
}