I've made a Wordpress plugin that requires a site visitor to browse to a .php file in a subfolder in the plugin.
However, I've noticed that if the visitor is not logged in, the PHP script redirects to a 404 page.
I need to stop this redirection, and allow the script to be executed.
How would I do this?
WordPress doesn't block PHP files with a 404 page by default. It could be your host, htaccess, or a variety of other issues.
Either way, you don't want to call the PHP file directly if this is a WordPress plugin. If you did call it directly, you would not have access to WordPress (for example, you cannot use get_option or bloginfo()).
Rather, you should include it using PHP's include function from within your plugin. See plugin_dir_path for information about getting your plugin's working directory.
You can hook a page to call your function pretty easily. For example:
function call_my_php_script() {
if ( isset($_GET['myscript']) && $_GET['myscript'] == 'run' ) {
include( plugin_dir_path( __FILE__ ) . 'scripts/my-script.php' );
exit;
}
}
add_action('init', 'call_my_php_script');
And then access your script via: http://example.org/?myscript=run
You may want to store your plugin directory in a global/constant variable, as the plugin_dir_path function only works for the original plugin file.
Related
I have a large number of custom PHP scripts running under a child theme in WordPress.
To trigger a script, the user sees a WordPress page which attaches a custom template from a template PHP file in the child theme folder, which then initiates a call, require or include to other scripts in the same or a different folder under the child theme.
I want to prevent any of these PHP scripts being accessed other than through the main WordPress site pages, for example through direct access URL or other ‘unauthorised’ methods.
Most of these scripts are only used by a logged in user, but a few are accessed by users who aren’t logged in.
I tried using this commonly used code even when called from a script within WordPress environment:
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
at the top of all my scripts, but found that it returned nothing (ie exited) even when a script was executed from another script.
I was wondering whether some kind of code along the lines of (sorry - mix of English and PHP:-))
if ((called from WordPress) || (called from a script in the child theme folder or subfolders))
{execute} ELSE {die}
Update #1
I've tried 'tricking' WordPress into thinking the target script is part of the WP environment (to pass the ABSPATH test) by adding the following to functions.php
function load_my_scripts() {
$my_script = 'MyScriptName';
$path = '/wp-content/themes/mytheme/MDB/' . $my_script . ".php";
if ($path) {
wp_enqueue_script($my_script,$path);
}
}
add_action( 'wp_enqueue_scripts', 'load_my_scripts' );
I've confirmed this enqueues the script to $wp_scripts but it still fails the ABSPATH test when accessed from another script within WordPress.
Appreciate any advice on how best to approach this. Many thanks in advance.
I set up my htaccess file to redirect to a PHP script when users try to access /wp-content/uploads/2020/05/test.pdf. The PHP script is in my root directory. The redirect works just fine. In the script, I have the following code:
require_once('wp-load.php');
if (is_user_logged_in()) {
wp_redirect('https://mywesbite.com/page1/');
exit;
} else {
wp_redirect('https://mywesbite.com/page2/');
exit;
}
I tested this on a few different Wordpress websites and in two of them it works as expected. If the user is logged in they will go to page1. However, on the website that I need it to work for, it always takes them to page2. I've tried deactivating all the plugins and changing the theme to the same as the websites the code works with. Still doesn't work. This makes me think it has something to do with the server setup. It's on Managed WordPress through GoDaddy. Is it possible that there is some server configuration that is preventing it from working correctly like the other websites? That's the only difference that I can think of.
I found out the login cookie was not being recognized in the PHP script. I suspect that it has something to do with the server setup, but couldn't pinpoint the issue.
I did however find a workaround. Rather than having the script located in the root directory, you can create a template file within your child theme and have the script there. Then have the redirect point to a page you create with the template. Everything worked as expected once I made this change.
<?php
/**
* Template Name: Redirect Template
*
*/
if (is_user_logged_in()) {
wp_redirect('https://mywesbite.com/page1/');
exit;
} else {
wp_redirect('https://mywesbite.com/page2/');
exit;
}
?>
I'm developing a wordpress plugin and was wondering how I can make it so only my plugn can access its own files. basically looking for something similar to this:
defined('ABSPATH') or die();
I think I saw something like this in someone elses plugin once:
defined('PLUGINNAME') or die();
I didn't understand how it worked, but was wondering if there is anything similar that will only allow my plugin to "require_once(plugin_dir_path(__ FILE __).'secondpluginfile.php');" its own files. (spaces between __ and FILE because otherwise stackoverflow tries to make it bold instead) Not sure if this restriction is built into wordpress(probobly not because some plugins have add-ons), or if I have to add something to make this happen. do I just put the pluginname or something in the "defined()" function, or do I need to set something up first?
So basically, if your plugin was a single php file, all the functions and logic included in the file would be accessible to the rest of the application once the plugin was installed and activated.
Most plugins are not designed that way, however. The plugin filename that acts as the entry point to your plugin usually loads the rest of the files in your plugin directory either by simply including them or calling classes and functions based on events occurring on the site via hooks.
So, if you want only your plugin to be able to access its own files you could do a few things.
First of all, add defined('ABSPATH') or die(); at the top of the main plugin file. As user Ifty wrote, "ABSPATH is a constant defined in wp-config.php line 86. When wordpress will try to execute your plugin, the ABSPATH constant will be defined. But if someone else try to execute your plugins file directly, ABSPATH will not be defined and in that case your script will not get executed."
So that protects your file from being accessed directly outside the context of Wordpress.
To protect your plugin's files from the rest of the site itself, simple wrap any include or require_once statement or code in your main plugin file in a function or class which is only called based on conditions you set. For example
<?php
/*
Plugin Name: Example plugin
Plugin URI: http://stackoverflow.com/
Version: 1.0
*/
defined('ABSPATH') or die();
add_action('your-custom-action', 'protector_function');
function protector_function(){
if ( current_user_can('manage_options') ) { //checks if user is admin you can use whichever conditions you want here
require_once plugin_dir_path( __FILE__ ) . 'filename-with-plugin-code.php';
// any other plugin code here
}
}
You can define your own action and call it using do_action() (reference) so that you can ensure your plugin code is only called where you have specified throughout the application.
Wordpress plugins exist to extend the functionality of Wordpress so if you do not want your code to be accessed from Wordpress in any way at all, I am not sure a plugin is the correct solution.
Hope this helps!
You can put
defined('ABSPATH') or die();
at the beginning of your plugins code. Actually what it does is check if ABSPATH is defined or not. If it's not defined then it will execute die() and stop executing your plugin file.
ABSPATH is a constant defined in wp-config.php line 86. When wordpress will try to execute your plugin, the ABSPATHconstant will be defined. But if someone else try to execute your plugins file directly, ABSPATHwill not be defined and in that case your script will not get executed.
Another way of accomplishing the same result is to check for add_action function.
if ( !function_exists( 'add_action' ) ) {
echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
exit;
}
Code Reference: Akismet Plugin. You can take a look at their source code. As far as I know this plugin comes with wordpress package.
I have been building a wordpress plugin that displays information on the site. This data has been POSTed via cURL to a page in my plugins/[plugin_name]/inc/ directory (update.php) and runs the relevant function required to update the database. The pluging works fine, but when I submitted it for review, I have two remaining issues that I can't seem to solve:
1. Allowing Direct File Access to plugin files
...avoid this by putting this code at the top of all php files:
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
Surely I need direct access to this file to send the POST data to? Or is there another way I should do this?
2. Calling core loading files directly
Including wp-config.php, wp-blog-header.php, wp-load.php, or pretty much any other WordPress core file that you have to call directly via an include is not a good idea and we cannot approve a plugin that does so unless it has a very good reason to load the file(s). It is prone to failure since not all WordPress installs have the exact same file structure.
Usually plugins will include wp-config.php or wp-load.php in order to gain access to core WordPress functions, but there are much better ways to do this. It's best if you tie your processing functions (the ones that need but don't have access to core functions) into an action hook, such as "init" or "admin_init".
At the top of the same file (update.php) I have included as such:
require( dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '\wp-load.php' );
Because I need to access the core wp functions and classes such as
$wpdb->prepare
And I'm not sure how I can otherwise do this. I would appreciate any help with these problems!
As for 1. You should create a method in your plugin that handles the post data and runs the CURL request.
As for 2. I think you can get away with global $wpdb;
https://codex.wordpress.org/Class_Reference/wpdb
Here's what I did, if anyone else has this question:
1. I added this function and hook to my plugin file:
//GET POST DATA IF APPLICABLE
function wp_getpostdata() {
if ( isset( $_POST['user'] ) && isset( $_POST['pass'] ) && isset( $_POST['op'] )) {
require 'inc/update.php';
exit;
} // end if
} // end wp_getpostdata
add_action( 'init', 'wp_getpostdata' );`
2. Removed the wp-load include and added
global $wpdb;
to my update.php file as Kyra suggested. And finally...
3. Changed the POST target to my website address.
Works like a charm - hope others find it useful!
Fatal error: Call to undefined function add_action() in D:\xampp\htdocs\excel\wp-content\plugins\DatabaseToExcel\download.php on line 13
I am creating a plugin to export database table to excel sheet. Mainly I have two files in my plugin, I am sending a post request to download.php file with the table name which will be exported. I want to be sure on download.php file that the admin is logged in, but when I am calling any of WordPress Core function, fatal error occurs. I am including wp-load.php and others files like this -
require_once('../../../wp-load.php');
require_once('../../../wp-config.php');
require_once('../../../wp-includes/load.php');
In this case, functions like auth_redirect() working fine without any error. But I want to upload this plugin to www.wordpress.org.
They said that including files using this method is not good and we can not approve it because of file structures in another WordPress installation can vary and in that case it will not work.
Here is the reply from wordpress.org-
In download.php, which is STILL not protected by the way
require_once('../../../wp-load.php');
require_once('../../../wp-config.php');
require_once('../../../wp-includes/load.php');
Including wp-config.php, wp-blog-header.php, wp-load.php, or pretty much any other WordPress core file that you have to call directly via an include is not a good idea and we cannot approve a plugin that does so unless it has a very good reason to load the file(s). It is prone to failure since not all WordPress installs have the exact same file structure.
Usually plugins will include wp-config.php or wp-load.php in order to gain access to core WordPress functions, but there are much better ways to do this. It's best if you tie your processing functions (the ones that need but don't have access to core functions) into an action hook, such as "init" or "admin_init".
Please consult the Plugins API reference for more information: http://codex.wordpress.org/Plugin_API
For other possibilities, or to better understand why we disallow this, read this: http://ottopress.com/2010/dont-include-wp-load-please/
If you're trying to use it because you need to access WordPress functions outside of WordPress, we'd actually much rather you didn't do that at all. Your plugin should be inside WordPress, only accessible to people who are logged in and authorized, if it needs that kind of access. Your plugin's pages should be called via the dashboard like all the other settings panels, and in that way, they'll always have access to WordPress functions.
This is my very first WordPress plugin and after many hours of struggling and reading all of these, I do not have solution.
Include your download.php file after WP files are loaded. Here's example of code to place in your plugin's main file (or loader):
add_action('wp_loaded', 'pluginPrefix_include_download_script');
function pluginPrefix_include_download_script() {
require('download.php');
}
You can also use other actions like admin_init if you need this file to be loaded earlier.
You can also specify path to a file using plugin_dir_path(__FILE__) this will return path to your plugin directory and you can use it like this:
function pluginPrefix_include_download_script() {
$pluginDirPath = plugin_dir_path(__FILE__);
require($pluginDirPath.'download.php');
}
this may become handy if your download.php located in subfolder (e.g. inc/). In this case your include function may look like this:
require($pluginDirPath.'inc/download.php')