How should I protect a static Wordpress file directory from the outside world? - wordpress

I'm taking over the admin of a WP site that serves static docs from a dedicated directory. The current directory resides on the top level (/public_html/docs) which seems susceptible to snooping. The site sits behind a login firewall.
The file directory contains >500 individual files, so uploading and hand-editing individual links seems absurd. (At least to me.)
Should I move this directory to a more secure location within the WP directory? Or, what is the preferred way to configure .htaccess?

At a minimum I would disable Directory Listing by using an .htaccess file that sits inside your /public_html/docs directory.
IndexIgnore *
Possibly a more secure method would be to move the docs directory outside your public_html directory. Then use a PHP script that can serve your document by passing a variable, such as www.site.com/serve_doc.php?name=xxxx.pdf.
Here is some code to accomplish this:
// get the file name
$file = $_GET['name'];
$dir = "/home/xxxx/docs/";
$fp = fopen($dir.$file, 'rb');
if(!$fp) { exit; }
// open the file
$finfo = finfo_open();
$filetype = finfo_file($finfo, $file, FILEINFO_MIME);
finfo_close($finfo);
$filename = $file;
// send the right headers
header("Cache-Control: ");// leave blank to avoid IE errors
header("Pragma: ");// leave blank to avoid IE errors
header("Content-Type: " .$filetype );
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Length: " . filesize($dir.$file));
// dump the file and stop the script
fpassthru($fp);
exit();
Of course you'll want to add some authentication to validate whether the user should be able to call this PHP script. One possible way would be to call the Wordpress function is_user_logged_in in that script before serving the file.

Related

Unable to access analytics.txt once uploaded, returns 404

I've been asked to add an analytics.txt file to a wordpress website so I've created the file and uploaded it to the server document root but when I go to it via the url www.examples.com/analytics.txt all I get is a 404 error.
I've checked the file permissions and I've cleared the wordpress cache but neither have helped.
Any ideas?
The folder structure is as follows:
wp-admin
wp-content
wp-includes
analytics.txt <-- added this file, but cannot seem to access it via a web browser
index.php
etc...
This is NOT the solution but it is a work-around while I carry on trying to figure out why wordpress won't allow me to access my file.
So if you're desperate and HAVE to get it sorted right now, here is what you could do, but I warn you, it's ugly! Open your index.php file and you should see something like this:
<?php
define('WP_USE_THEMES', true);
require( dirname( __FILE__ ) . '/wp-blog-header.php' );
?>
Make a backup copy first and then add the wrapping if statement:
<?php
if ($_SERVER[REQUEST_URI] == '/analytics.txt') {
die('Put the text that you were instructed to put into your analytics.txt file in here');
} else {
define('WP_USE_THEMES', true);
require( dirname( __FILE__ ) . '/wp-blog-header.php' );
}
?>
Like I said, this is a dirty solution but when needs must and the client is getting impatient, this could help in the mean time.
Hoping that someone will have a better solution though!
I was able to get this to work with the following for the Sage theme:
Upload the analytics.txt through the theme administration panel
Copy the url of the upload and remove the hostname. For me it looked like this: app/uploads/2018/09/analytics.txt
Open the functions.php file and add the following:
function analytics_txt_rewrite(){
add_rewrite_rule('^analytics\.txt$','<route to your analytics.txt file>','top');
}
add_action('init','analytics_txt_rewrite');
Flush and regenerate the rewrite rules database: From WordPress Administration Screens, Select Settings -> Permalinks and just click Save Changes without any changes.

How can I compress / gzip my mimified .js and .css files before publishing to AWS S3?

I ran Google pagespeed and it suggests compressing my .js and .css
Eliminate render-blocking JavaScript and CSS in above-the-fold content
Show how to fix
Enable compression
Compressing resources with gzip or deflate can reduce the number of bytes sent over the network.
Enable compression for the following resources to reduce their transfer size by 210.9KiB (68% reduction).
Compressing http://xx.com/content/bundles/js.min.js could save 157.3KiB (65% reduction).
Compressing http://xx.com/content/bundles/css.min.css could save 35.5KiB (79% reduction).
Compressing http://xx.com/ could save 18.1KiB (79% reduction).
During my publish I have a step that uses Windows Powershell to move a .js and .css mimified bundle to S3 and this goes to cloudfront.
Is there some step I could add in the PowerShell script that would compress the .js and .css files?
Also once the files are compressed then do I have to do anything more than change the name so as to tell my browser that it will need to try and accept a gzip file?
You can add to your upload script the needed code to gzip compress the files.
Some example code could be this:
function Gzip-FileSimple
{
param
(
[String]$inFile = $(throw "Gzip-File: No filename specified"),
[String]$outFile = $($inFile + ".gz"),
[switch]$delete # Delete the original file
)
trap
{
Write-Host "Received an exception: $_. Exiting."
break
}
if (! (Test-Path $inFile))
{
"Input file $inFile does not exist."
exit 1
}
Write-Host "Compressing $inFile to $outFile."
$input = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
$buffer = New-Object byte[]($input.Length)
$byteCount = $input.Read($buffer, 0, $input.Length)
if ($byteCount -ne $input.Length)
{
$input.Close()
Write-Host "Failure reading $inFile."
exit 2
}
$input.Close()
$output = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None)
$gzipStream = New-Object System.IO.Compression.GzipStream $output, ([IO.Compression.CompressionMode]::Compress)
$gzipStream.Write($buffer, 0, $buffer.Length)
$gzipStream.Close()
$output.Close()
if ($delete)
{
Remove-Item $inFile
}
}
From this site: Gzip creation in Powershell
Powershell community extensions has a scriptlet for gZipping files, and it's very easy to use:
Write-Gzip foo.js #will create foo.js.gz
mv foo.js.gz foo.js -Force
You don't have to rename your files, just add a Content-Encoding header and set it to gzip.
Since Amazon S3 is intended to only serve static files, it doesn't compress files (assets), that's why you need to compress them by yourself:
Compress your .js and .css with gzip: I don't know about howto with PowerShell, but I do with Python, I suggest to make a python deployment script (even better a fabfile) and integrate the compression and push code on it.
"Also once the files are compressed then do I have to do anything more than change the name so as to tell my browser that it will need to try and accept a gzip file?" : Good Questions ! It is not necessary to change the name of the compressed file, I suggest to don't rename. However, you:
MUST set also the header "Content-Encoding:gzip" otherwise browsers will not know the file.
Must set the headers 'Content-Type': type (type = 'application/javascript' or 'text/css')
Must set the header 'x-amz-acl': 'public-read': to make it public accessible.
I suggest also to set the header "Cache-Control:max-age=TIME" (example: TIME=31104000, for 360 days): To help browsers caching it (Better performance)
This will work whether served from origin or with cloudfront. But remember, if you serve them with cloudfront, You will need to invalidate all the files after each push, otherwise the old version will live up to 24 hours from the push. Hope this helps, I can provide a python solution if needed.

How do i locate wordpress plugin directory?

I am trying to add a function from plugin 1(wp job manager) to plugin 2(woocommerce).
I have decided to do this by including the php file from plugin 1, however I am unable to locate the file directory. I have used:
include( plugin_dir_path( __FILE__ ) . 'wp-job-manager/includes/class-wp-job-manager-applications.php');
but it returns the following error:
Warning:
include(/home/content/p3pnexwpnas05_data02/78/2394078/html/wp-content/themes/listify-child/wp-job-manager/includes/class-wp-job-manager-applications.php): failed to open stream: No such file or directory in
/home/content/p3pnexwpnas05_data02/78/2394078/html/wp-content/themes/listify-child/functions.php
on line 77
Please advise me as I've been stuck on this issue for really long... Thanks!!!
Wordpress setups have a constant ABSPATH defined (look at the bottom lines of wp_config.php) which points to the full and absolute path of the Wordpress setup, so in your case echo ABSPATH; would return /home/content/p3pnexwpnas05_data02/78/2394078/html/.
For most installations, appending wp-content/plugins/ to that string would point you to your plugins directory.
However, in a Wordpress configuration one can also customize the wp-content and or plugins directory to their own preference, so building plugins on ABSPATH.'wp-content/plugins/ is not recommended. Unfortunately Wordpress simply doesn't have a get_absolute_pluginspath() function or something available. A trick would be to fetch the plugins-URL, and remove the site-URL from it, so the remaining data is wp-content/plugins/ (or whatever the user has made of it). In code:
$plugins_directory = ABSPATH.str_replace(site_url()."/","",plugins_url())."/";
Which in your case would return:
/home/content/p3pnexwpnas05_data02/78/2394078/html/wp-content/plugins/
You probably mean:
plugin_dir_path(__FILE__)
That gives you the directory path to the file that statement is in. So what that returns depends on where you run it. If you use this statement
include( plugin_dir_path(__FILE__) . 'wp-job-manager/includes/class-wp-job-manager-applications.php');
in the main plugin file for wp_job_manager (probably wp_job_manager.php), then plugin_dir_path(__FILE__) give the path of the directory that file is in (the plugin directory).
If you use it in some other file, you will need to adjust the rest of the path string accordingly.

Move image from public:// to folder inside module in drupal 7

i want to move a uploaded file locate in public:// to a folder inside mymodule.
I try
$dirname = dirname(__file__);
$fullpath = strpos($dirname, '\\') === false ? $dirname . '/' . $file->filename : $dirname . '\\' . $file->filename;
$go = file_move($file, $fullpath);
and i got this error
The specified file public://xxx.BMP could not be moved, because the destination is invalid. More information is available in the system log.
But de $destination is valid and is mymodule's folder!!
Can anyone helpme to move-it?
Thanks!!!
Generally, moving files to the module folder isn't good idea.
But, if you want to do this, use path, relative to drupal root or absolute file path.
Also, check folder permission for your module's directory (by default, module folders is read-only).
If this not helps, i recommend you to check system log for more detailed error explanation.
Best is to move the files in public://
$dest = 'public://';
$file = file_move($file, $dest)

moving Drupal 6 site - get blank white page

I moved Drupal from one Linux server to another by copying files to PC then back to new server. I made changes to settings.php to reflect new database name. I got PHPmyADMIN working, so I know database and server are running.
When I run index.php, I get white screen. However in index.php when I echo out menu_execute_active_handler(), I get some part of my home page without menus. I think that this means that I am getting through bootstrap but failing somewhere else. Any ideas?
index.php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$return = menu_execute_active_handler();
echo $return ;
Turn display_errors on in your php.ini file.
Your new server probably has them disabled.
Put this code in your index.php to see the error
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

Resources