Software, your way.
burger menu icon
WillMaster

WillMaster > LibraryWebsite Development and Maintenance

FREE! Coding tips, tricks, and treasures.

Possibilities weekly ezine

Get the weekly email website developers read:

 

Your email address

name@example.com
YES! Send Possibilities every week!

Multi-domain Software Updater

This software began from a client's request for an easy way to update the multi-domain licensed Master Form .PHP when there was an upgrade. The client has a number of customers who are using Master Form .PHP on their domains.

The idea was this: Update one domain. Then run a script to update the other domains.

As sometimes happens, the project expanded. The resulting software can transfer more than just PHP scripts. But it still remains within its original intent of updating software files from one domain to another.

The primary challenge was making the system secure, trying to think like a hacker who wanted to get files from someone else's server.

Security

The security was solved this way:

  • At every destination domain, the subdirectory where the files will be updated has a short PHP script. Upload this script once into that directory and you'll be good to go for receiving updates from then on.

  • The source domain also contains a PHP script, the source file sending script. This script needs to be launched in a browser. It can't be nudged from somewhere else and have it send files to an incorrect destination.

  • For additional security, the destination scripts and the source sending script all contain an identical security key, a string of characters that are compared to authorize the file transfer.

Because server access is needed to get the PHP scripts installed, and because of the security key requirement, hackers would need to break into the server itself to use the scripts — and if they did that then they would already have server access and wouldn't need the scripts to wreak havoc.

Features

Security Key
The security key is a unique string of characters to make each installation secure within itself. Its purpose is to prevent other installations of Multi-domain Software Updater from using your installation.

Multiple Destinations
The files can be copied from the source directory to any number of directories at other domains.

Overwrite Protection
A setting in the source sending script tells the destination script whether or not it is okay to overwrite any existing file with the same name. Because this is an updater, overwrite is generally desired. But there may be occasions when it is not okay to do so.

Non-transfer Files
Specify the names of files in the source directory that are not to be transferred to destination directories. Configuration files are an example; each destination is likely to have its own settings and you don't want to replace them with the wrong ones.

Two Transfer Modes
There are plain text files and binary files, each type transferred in a different manner. Plain text files generally are source code used for web pages, like PHP, HTML, CSS, JavaScript, and CGI files. A customization in the source sending script tells the software which file extensions are plain text.

File Permissions
If the file is a Perl CGI script, it can be given 755 permissions automatically when it is saved at the new location.

Because Multi-domain Software Updater is an updater, it will transfer files only from one directory. It will not walk subdirectories to transfer those files — files that are likely to be databases and settings unique to the installation of the domain where they exist.

The Software

As mentioned, Multi-domain Software Updater comes as two PHP scripts. The source sending script sends the file information. The destination script receives the file information.

The two PHP scripts are below, each followed with customization notes.

We'll do the destination script first, for two reasons. It has less customizations. And it needs to be installed before the source sending script customization can be finalized.

The Destination Script —

Save this file on your hard drive as Destination.php or other PHP file name that works for your implementation. The instructions assume Destination.php is its file name.

After customization, upload Destination.php into the subdirectory of every domain that will receive file updates from the source domain. The source sending script will contact Destination.php with information it needs for the file transfer.

<?php
/*
   Multi-domain Software Updater -- Destination
   Version 1.0
   April 20, 2018
   Will Bontrager Software LLC
   https://www.willmaster.com/

   This software is provided "AS IS," without 
   any warranty of any kind, without even any 
   implied warranty such as merchantability 
   or fitness for a particular purpose.
   Will Bontrager Software LLC grants you 
   a royalty free license to use this software 
   provided this notice appears on all copies. 
*/

/* Two places to customize. */

// (1) Specify a security key that the sending script must use 
//     for a valid file transfer. Must be identical to that 
//     specified in Source.php or whatever the source 
//     sending script file name is. */

$CustomKey = '"ZQ/hN9ASE}gHuo:k"';

// (2) Between the lines with the PERMISSION755 string of 
//     text, type the file name extensions that need to 
//     have 755 permissions. Specifying a period before the 
//     extension is optional. Separate extensions with one 
//     or more linefeeds, spaces, and/or commas in any 
//     combination.

$ExtFor755 = <<<PERMISSION755
cgi, 
.pl
PERMISSION755;

/* No other customization required. */
/* ******************************** */
$List755 = array();
if( ! count($_POST) ) { ExitWithMessage(); }
if( get_magic_quotes_gpc() ) { StripOnlySlashes($_POST); }
if( $_POST['CustomKey'] != $CustomKey ) { ExitWithMessage(); }
if( empty($_POST['Overwrite']) and file_exists($_POST['FileName']) ) { ExitWithMessage("File {$_POST['FileName']} exists."); }
if( isset($_POST['FileURL']) and $_POST['FileURL'] ) { file_put_contents($_POST['FileName'],file_get_contents($_POST['FileURL'])); }
elseif( isset($_POST['FileContent']) and $_POST['FileContent'] ) { file_put_contents($_POST['FileName'],$_POST['FileContent']); }
foreach( preg_split('/\W+/',strtolower(trim($ExtFor755,",. \t\n\r\0\x0B"))) as $ext ) { $List755[trim($ext)] = true; }
$ext = strtolower(preg_replace('/^[^\.]*\./','',$_POST['FileName']));
if( isset($List755[$ext]) ) { chmod($_POST['FileName'],0755); }
ExitWithMessage('OK');
function ExitWithMessage($s='Inappropriate access.')
{
   echo $s;
   exit;
}
function StripOnlySlashes(&$arr) { array_walk_recursive($arr, 'StripOnlySlashesFromArrayItems'); }
function StripOnlySlashesFromArrayItems(&$item, $key) { $item = trim(stripslashes($item)); }
?>

Customizations —

There are two customization steps.

  1. Find the $CustomKey = '"ZQ/hN9ASE}gHuo:k"'; line in the above source code. The "ZQ/hN9ASE}gHuo:k" is a security key. It is recommended to change it before installing the Multi-domain Software scripts.

    Whatever security key you specify here will need to be specified in the customization area of the source sending script.

  2. Between the two lines containing the PERMISSION755 string of characters, list the file name extensions of files that require 755 permissions. Specifying a period before the extension is optional.

    Separate extensions with one or more linefeeds, spaces, and/or commas in any combination.

    The most common extensions that require 755 permissions are already listed in the script. Add any others that you need.

The Source Sending Script —

Save this file on your hard drive as Source.php or other PHP file name that works for your implementation. The instructions assume Source.php is its file name.

After customization, upload Source.php into the subdirectory that contains the files that will be sent to destination directories where Destination.php is installed. To run Source.php, type its URL into your browser.

<?php
/*
   Multi-domain Software Updater -- Source Sending
   Version 1.0
   April 20, 2018
   Will Bontrager Software LLC
   https://www.willmaster.com/

   This software is provided "AS IS," without 
   any warranty of any kind, without even any 
   implied warranty such as merchantability 
   or fitness for a particular purpose.
   Will Bontrager Software LLC grants you 
   a royalty free license to use this software 
   provided this notice appears on all copies. 
*/

/* Five places to customize. */

// (1) Specify a security key that the sending script must use 
//     for a valid file transfer. Must be identical to that 
//     specified in Destination.php or whatever the destination  
//     script file name is. */

$CustomKey = '"ZQ/hN9ASE}gHuo:k"';

// (2) Between the lines with the DESTINATIONS string of 
//     text, type the URLs of the Destination.php file for 
//     each of the destinations that are to receive the file 
//     transfer. Type one URL per line.

$Destinations = <<<DESTINATIONS
http://domain.com/books/Destination.php
https://example.com/testing/Destination.php
DESTINATIONS;

// (3) Is it okay to overwrite existing file with same name 
//     at destination? Specify true for meaning okay to 
//     overwrite and specify false for meaning no overwrite.

$Overwrite = false; // Use true or false, no quotes.

// (4) Between the lines with the NOTRANSFER string of 
//     text, type the file names that should not transfer 
//     to the destination (the file name of this script 
//     is already exempted). Separate file names with one 
//     or more linefeeds, spaces, and/or commas in any 
//     combination.

$ExemptedFiles = <<<NOTRANSFER
config.php
NOTRANSFER;

// (5) Between the lines with the PLAINTEXTSOURCE string of 
//     text, type the file name extensions that are plain  
//     text files. That would be .php, .html, .css, .js, 
//     and other file name extensions that contain only 
//     plain text and are not binary files. Specifying a 
//     period before the extension is optional. Separate 
//     extensions with one or more linefeeds, spaces, 
//     and/or commas in any combination.

$PlainTextExtensions = <<<PLAINTEXTSOURCE
php html htm xhtml 
.css, .cgi, pl pm, 
.js txt
PLAINTEXTSOURCE;

/* No other customization required. */
/* ******************************** */
$BaseURL = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
$Message[] = $BaseURL;
$BaseURL .= $_SERVER['HTTP_HOST'];
$Message[] = $BaseURL;
$BaseURL .= (preg_replace('!/[^/]*$!','',$_SERVER['PHP_SELF']));
$Message[] = $BaseURL;
$SelfFileName = GetTheFileName($_SERVER['PHP_SELF']);
$Dests = $Exempted = $PlainText = array();
foreach( preg_split('/[\r\n]+/',trim($Destinations)) as $url ) { $Dests[] = trim($url); }
foreach( preg_split('/[\s,]+/',trim($ExemptedFiles,", \t\n\r\0\x0B")) as $exmp ) { $Exempted[trim($exmp)] = true; }
foreach( preg_split('/\W+/',strtolower(trim($PlainTextExtensions,",. \t\n\r\0\x0B"))) as $ext ) { $PlainText[trim($ext)] = true; }
foreach( glob('*') as $file )
{
   if( (!$file) or (!is_file($file)) ) { continue; }
   $fname = GetTheFileName($file);
   if( $fname == $SelfFileName ) { continue; }
   if( isset($Exempted[$fname]) ) { continue; }
   $postdata = array();
   $postdata['FileName'] = $fname;
   $postdata['CustomKey'] = $CustomKey;
   $postdata['Overwrite'] = $Overwrite;
   $ext = strtolower(preg_replace('/^[^\.]*\./','',$fname));
   if( empty($PlainText[$ext]) ) { $postdata['FileURL'] = "$BaseURL/$fname"; }
   else { $postdata['FileContent'] = file_get_contents($file); }
   foreach( $Dests as $url )
   {
      $options = array(
         CURLOPT_RETURNTRANSFER => true,
         CURLOPT_HEADER         => false,
         CURLOPT_CONNECTTIMEOUT => 120,
         CURLOPT_TIMEOUT        => 120,
         CURLOPT_FOLLOWLOCATION => false,
         CURLOPT_USERAGENT      => "Cross Domain Copy {$_SERVER['PHP_SELF']}",
         CURLOPT_POST           => 1,
         CURLOPT_POSTFIELDS     => $postdata,
         CURLOPT_VERBOSE        => false
      );
      $ch = curl_init($url);
      curl_setopt_array($ch,$options);
      $content = curl_exec($ch);
      $err = curl_errno($ch);
      $errmsg = curl_error($ch);
      curl_close($ch);
      if( $err ) { $content = $errmsg; }
      echo "<pre>Transfer to $url\n\t$fname: $content</pre>";
   }
}
function GetTheFileName($s) { return preg_replace('!^.*/!','',$s); }
?>

There are five customization steps.

  1. This first step is like the first step for the Destination.php script.

    Find the $CustomKey = '"ZQ/hN9ASE}gHuo:k"'; line in the above source code. The "ZQ/hN9ASE}gHuo:k" is a security key. It is recommended to change it before installing the Multi-domain Software scripts.

    Whatever security key you specify here will need to be specified in the customization area of the Destination.php script.

  2. Between the two lines containing the DESTINATIONS string of characters, list the URLs of each of the Destination.php scripts installed for this purpose. The URLs may be to any number of domains and to any public directories.

    Specify each URL on a separate line.

    The script source code above has two example URLs listed.

  3. The value false in the $Overwrite = false; line tells the software to avoid overwriting any existing files at the destination domains and subdirectories.

    To allow overwriting, which generally is the case when updating files, replace false with the word true (no quotes).

  4. Between the two lines containing the NOTRANSFER string of characters, type the file names of each file that should not be copied to the destinations. The file name Source.php (or whatever you end up naming the file) is already exempted.

    Separate file names with one or more linefeeds, spaces, and/or commas in any combination.

  5. Between the two lines containing the PLAINTEXTSOURCE string of characters, list the file name extensions of files that contain plain text, files that are not binary files. That would be .php, .html, .css, .js, and other file name extensions that contain only plain text and are not binary files. Specifying a period before the extension is optional.

    Separate extensions with one or more linefeeds, spaces, and/or commas in any combination.

    The most common plain text file name extensions are already listed in the script. Add any others that you need.

Software can be updated quickly and easily on many domains by using Multi-domain Software Updater.

(This article first appeared with an issue of the Possibilities newsletter.)

Will Bontrager

Was this article helpful to you?
(anonymous form)

Support This Website

Some of our support is from people like you who see the value of all that's offered for FREE at this website.

"Yes, let me contribute."

Amount (USD):

Tap to Choose
Contribution
Method

All information in WillMaster Library articles is presented AS-IS.

We only suggest and recommend what we believe is of value. As remuneration for the time and research involved to provide quality links, we generally use affiliate links when we can. Whenever we link to something not our own, you should assume they are affiliate links or that we benefit in some way.

How Can We Help You? balloons
How Can We Help You?
bullet Custom Programming
bullet Ready-Made Software
bullet Technical Support
bullet Possibilities Newsletter
bullet Website "How-To" Info
bullet Useful Information List

© 1998-2001 William and Mari Bontrager
© 2001-2011 Bontrager Connection, LLC
© 2011-2024 Will Bontrager Software LLC