Version: 1.3.4
Type: Class
Category: Networking
License: GNU General Public License
Description: @name: class BPFTPAdmin @file: classBPFTPAdmin.php @author: Niklas Forsberg @email: niklas.forsberg@bildelstorget.se @description: Class for administer a BulletProof FTP Server using PHP. The class can for example be called from within a administration web page in order to have a FTP administration on your own website so you can control your FTP server from all over the world (a protected web page would ofcourse be a preffered one!). I use this class myself in a server administration page which I wrote, where I also can administer things like mailserver, webserver, firewall etc. This is one way to use it, but ofcourse there are a lot of other ways in which it can be used. Very well-documented! Easy to use for beginners aswell as pro's!
<?php
/**
* @name: class BPFTPAdmin
* @file: classBPFTPAdmin.php
* @author: Niklas Forsberg
* @email: niklas.forsberg@bildelstorget.se
* @version: 1.3.5 build #2 (preview edition)
*
*
* @description:
* Class for administer a BulletProof FTP Server using PHP.
* The class can for example be called from within a administration web page
* in order to have a FTP administration on your own website so you can control
* your FTP server from all over the world (a protected web page would ofcourse
* be a preffered one!).
*
* I use this class myself in a server administration page which I wrote, where
* I also can administer things like mailserver, webserver, firewall etc.
* This is one way to use it, but ofcourse there are a lot of other ways in which
* it can be used.
*
*
* @origin:
* This class was originally written by Niklas Forsberg as a
* project for administer a BulletProof FTP Server running on a WinXP box.
*
*
* @usage:
* IMPORTANT: In order to use this class, you need to disable the configuration
* directive "Allow multiple instances" in your BulletProof FTP Server Setup.
*
* Open BulletProof FTP Server and use short command CTRL+M, or click your
* way to: Setup -> Main -> General, and you will find the configuration
* directive under the headline "System".
*
* You should not have to make any special configurations for your FTP server in order
* to get the class up and rolling (except for the Important-notice above), though there can
* be something that I have forgot when I wrote this class. If you find anything other
* than the multiple instances option, please contact me and I will do my best to solve it.
*
*
* Usage - Table of contents:
* Step 1: Identifying the class (silent or not)
* Step 2: Putting the server online
* Step 3: Putting the server offline
* Step 4: Terminate BulletProof FTP Server instance
* Step 5: Close the server for new connections
* Step 6: Opening up a closed server
* Step 7: Other available methods
* Step 8: Group configuration example
*
*
* Step 1: Identifying the class
* To use the class from within a PHP-document, you will first need to identify the class.
* The class can be runned in either silent or default mode.
* If the class is running in silent mode, then no announcements will be returned from the
* methods of the class. Like for example, if you put the server offline (using method GoOffline)
* a message will be returned that tells you that the server went offline or something alike.
* Why use silent mode then? Well, some scripts need to operate quietly and maybe doesn't want
* any messages printed out to their functions, so that's why!
*
* Silent mode is off by default, which means that any announcement will be returned.
* If you want to use silent mode you need to add the "silent" argument to the identifier, like:
*
* Use default (not silent): $FTP = new BPFTPAdmin();
* Use silent mode: $FTP = new BPFTPAdmin(silent);
*
* Just as easy as that! But by using silent mode that doesn't mean that ALL messages will be
* turned off. Error messages will still be returned if something went wrong while trying to
* do something, like executing a FTP-command for example.
* But hopefully, you will not see any error messages if the class is used properly.
*
*
* Step 2: Putting the server online
* To make your BulletProof FTP Server go online, the only thing you need to do is to call the
* method "GoOnline" (with optional port number) like:
*
* $FTP->GoOnline(21);
*
* This will first terminate any instance of BulletProof FTP Server running, and then start a
* new instance of BulletProof FTP Server, aswell as putting it back online using the port number
* specified in the first (and only) argument.
* If silent mode is set to off, then a progress list will appear to show the current execution.
*
* If no port number is specified, then the class will use port 21 as default.
*
*
* Step 3: Putting the server offline
* To make the server go offline you need to call the method "GoOffline" which is used like this:
*
* $FTP->GoOffline();
*
* No special arguments is needed. When this method is called, it will simply put the server
* in offline-mode, though BulletProof FTP Server is still running.
* If you want to terminate the whole instance, use the method "Shutdown" (see step 4).
*
*
* Step 4: Terminate BulletProof FTP Server instance
* If you for some reason want to terminate BulletProof FTP Server (shutting down the software),
* then there is a method for that aswell. This method is called "Shutdown" and is used like this:
*
* $FTP->Shutdown();
*
* No special arguments is needed. If you want to make the server go offline but still want the
* instance of BulletProof FTP Server to be active, use the "GoOffline" method instead.
*
*
* Step 5: Close the server for new connections
* If you want to close the server for any new connections, then this method should be called.
* It simply does what it says - closing the server for any new connections. Use it like this:
*
* $FTP->Close();
*
* When called, BulletProof FTP Server will close itself for any new connections and no new
* connections will be allowed before the server is opened again (see step 6).
*
*
* Step 6: Opening up a closed server
* To open up a closed server and allow new connections, use the method "Open".
* The method opens up the server if it's closed for new connections. It is used like this:
*
* $FTP->Open();
*
* No special arguments is needed.
*
*
* Step 7: Other available methods
* Besides all the methods explained above, there are a lots of other methods which can be
* used together with the class in order to administer the BulletProof FTP Server.
*
* In order to use any of these methods, simply call them by using the command:
*
* $FTP->Method(arguments) (where Method is the name of the method and arguments is any argument(s).
*
* Following methods are supported in this version:
*
* KickAll: Description: Kicks all users currently logged on to the server
* Arguments: No argument needed
* Usage example: $FTP->KickAll();
* Added in ver.: 1.0
*
* Reload: Description: Reloads the Groups and Users ini-files
* Arguments: No argument needed
* Usage example: $FTP->Reload();
* Added in ver.: 1.0
*
* GiveArgument: Description: Send an argument/command to the BPFTP Server instance
* See your BPFTP Server manual for possible commands.
* Arguments: Command (str command)
* Usage example: $FTP->GiveArgument("-exit"); = Send argument -exit to
* BPFTP Server instance (which shuts it down)
* Added in ver.: 1.0
*
* AddGroup: Description: Adds a new group account with specified values
* Arguments: Groupname, Config array (str groupname, array config)
* Usage example: $FTP->AddGroup("Web users", $conf_array) = Add group "Web users"
* with the values given in array $conf_array
* (see step 8 for a config example)
* Added in ver.: 1.3.0
*
* DeleteGroup: Description: Deletes a specified group account
* Arguments: Groupname (str groupname)
* Usage example: $FTP->DeleteGroup("Web users"); = Delete group "Web users"
* Added in ver.: 1.3.1
*
* EditGroup: Description: Modifies a specified group account with new values and a new group name (optional)
* Arguments: Groupname, Config array, New groupname (str groupname, array config, str new_groupname)
* Usage example: $FTP->EditGroup("Web users", $conf_array, "Leechers"); = Modify group "Web users"
* with new name "Leechers" and new configuration from array $conf_array
* (see step 8 for a config example)
* Added in ver.: 1.3.1
*
*
* Step 8: Group configuration example
* This is a example of a configuration array for a group account.
* All available configuration directives can be found below.
*
* $group_ini = array("EnablePass" => "0",
* "TimeOut" => "600",
* "MaxUsers" => "1",
* "MaxConPerIp" => "2",
* "RelativePath" => "1",
* "AddLinks" => "1",
* "TreatLinksAs" => "0",
* "ResolveLNK" => "1",
* "ShowLoginMsg" => "1",
* "LoginMsgFile" => "Welcome to my FTP!",
* "RatioUp" => "1",
* "RatioDown" => "1",
* "RatioCredit" => "0",
* "RatioMethod" => "0",
* "QuotaCurrent" => "0",
* "QuotaMax" => "10240000",
* "MaxSpeedRcv" => "51200",
* "MaxSpeedSnd" => "51200",
* "Notes" => "This is a user group.",
* "Stat_Login" => "0",
* "Stat_LastLogin" => "2005-01-01 00:00:00",
* "Stat_LastIP" => "127.0.0.1",
* "Stat_FilesUp" => "0",
* "Stat_KBUp" => "0",
* "Stat_FailedUp" => "0",
* "Stat_FilesDown" => "0",
* "Stat_KBDown" => "0",
* "Stat_FailedDown" => "0",
* "Dir0" => "C:\\",
* "Attr0" => "R--A-LS-"
* );
*
*
* @support:
* Support for PHP4 > (aswell as PHP5).
* A BulletProof FTP server is needed in order to use the class methods.
* If you don't have it installed, you should probably not use this class ;-)
*
*/
/**
* License:
*
* Copyright (C) 2005 Niklas Forsberg
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this file; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// ****
// **** class BPFTPAdmin
// ****
/** Configuration directives needed for the class. */
$_CONF['serverpath'] = 'C:\Program\BPFTP Server'; # Path to where BulletProof FTP Server is installed (without ending slash!
$_CONF['serverexe'] = 'bpftpserver.exe'; # The name of the BulletProof FTP Server executable.
$_CONF['groupfile'] = 'Groups.ini'; # The name of the file which holds all the group accounts.
$_CONF['thisver'] = '1.0.4 build #4'; # Version number of the class (DO NOT EDIT!).
/** class BPFPAdmin
* Class for administrate a local BulletProof FTP Server. */
class BPFTPAdmin {
/** object serverPath
* Path to where BulletProof FTP Server is installed, which
* is defined in the configuration directive 'serverpath'. */
var $serverPath;
/** object serverExecutable
* The name of the executable file which BulletProof FTP Server uses.
* In normal conditions this -should- be 'bpftpserver.exe'. */
var $serverExecutable;
/** object silentMode
* Contains the value for running the class in silent mode or not.
* Default value for silent mode is disabled (all announcements will be shown). */
var $silentMode;
/** constructor BPFTPAdmin(str silentmode)
* Method which is called upon a initialization of the class BPFTPAdmin
* All nescessary objects will be defined within the constructor for usage
* within the entire class.
* Before the class will be allowed to proceed, a control check will be
* made to see if all configuration directives are set properly. */
function BPFTPAdmin($silentmode='') {
/** Make the configuration array $_CONF global so the configuration
* directives can be used within the constructor. */
global $_CONF;
/** Take contents from the configuration directive 'serverpath' and
* place it in object serverPath. */
$this->serverPath = $_CONF['serverpath'];
/** Take contents from the configuration directive 'serverexe' and
* place it in object serverExecutable. */
$this->serverExecutable = $_CONF['serverexe'];
/** Take contents of $silentmode and put them in to object silentMode.
* If argument 'silent' is -not- passed with the class initialization, then
* all announcements will be printed out on the screen. */
$this->silentMode = $silentmode;
/** Check to see if the path to the server is set up correctly by
* checking if the BulletProof FTP Server ini-file exists. Return true if ini-file
* -do- exists. Otherwise, return false. */
if(!file_exists("$this->serverPath\\FTPsrv.ini")) {
/** If the ini-file could not be found, return false with error message. */
$this->ReturnError("<b>FATAL ERROR:</b> Server configuration file could not be found!", "1");
return false;
}
}
/** method GiveMsg(str message)
* Method for returning announcements to class upon calling. */
function GiveMsg($msg) {
/** If object silentMode is -not- set to 'silent', then return all messages. */
if($this->silentMode != "silent") {
/** Print out announcement on the screen. */
print "$msg";
}
/** If object silentMode -is- set to 'silent', then -do not- return any
* messages at all to make the operations silent. */
else {
// Do not print anything out (if in silent mode)
}
}
/** method ReturnError(str errormessage, str errornumber)
* Method for returning error messages to class upon calling. */
function ReturnError($err, $errnum) {
print "$err";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<font size=2>";
print "Error no. #$errnum, ";
print "returned on ";
print date("r");
print ".</font>";
print "<br>\n";
print "<br>\n";
}
/** method GiveArgument(str argument)
* Method for giving an argument to the BulletProof FTP Server instance. */
function GiveArgument($arg) {
$WshShell = new COM("WScript.Shell");
$WshShell->Run("\"" . $this->serverPath . "\\" . $this->serverExecutable . "\"" . " $arg", 7, false);
}
/** method GoOnline(str port, str silent)
* Method for opening a new instance of the BulletProof FTP Server
* using the port number specified in string '$port' (default is 21). */
function GoOnline($port='21', $silent=FALSE) {
/** Flush the output buffer and turn off output buffering. */
@ob_end_flush();
/** Terminate the instance of BulletProof FTP Server so a new instance can be made. */
$this->GiveArgument("-exit");
if(!$silent) {
$this->GiveMsg("Shutting down any instance of BulletProof FTP Server, this could take a while...<br><br>");
}
/** Flush the output buffer. */
flush();
/** Wait a while to make sure that the BulletProof FTP Server will be terminated. */
sleep(5);
/** Give the port-command to BulletProof FTP Server to open a new
* instance using the port number specified in string '$port'. */
$this->GiveArgument("-p:$port");
if(!$silent) {
$this->GiveMsg("Shutdown complete, preparing to go online...<br><br>");
}
/** Flush the output buffer. */
flush();
/** Wait a while to make sure that the BulletProof FTP Server will be initialized. */
sleep(5);
/** Give argument 'online' to make the BulletProof FTP Server go online. */
$this->GiveArgument("-online");
if(!$silent) {
$this->GiveMsg("BulletProof FTP Server is now ready to accept connections on port $port.<br><br>");
}
}
/** method GoOffline(str silent)
* Method for making the BulletProof FTP Server go offline. */
function GoOffline($silent=FALSE) {
/** Give the 'offline' argument to BulletProof FTP Server to make it go offline. */
$this->GiveArgument("-offline");
if(!$silent) {
$this->GiveMsg("BulletProof FTP Server went offline.<br><br>");
}
}
/** method Reload(str silent)
* Method for reloading the group and user ini-files. */
function Reload($silent=FALSE) {
/** Give the 'reload' argument to BulletProof FTP Server to reload group and user accounts. */
$this->GiveArgument("-reload");
if(!$silent) {
$this->GiveMsg("The group and user ini-files were successfully reloaded by BulletProof FTP Server.<br><br>");
}
}
/** method Close(str silent)
* Method for closing the BulletProof FTP Server for any new connections. */
function Close($silent=FALSE) {
/** Give the 'close' argument to BulletProof FTP Server to close it for new connections. */
$this->GiveArgument("-close");
if(!$silent) {
$this->GiveMsg("BulletProof FTP Server is now closed for any new connections.<br><br>");
}
}
/** method Open(str silent)
* Method for opening the BulletProof FTP Server for any new connections.
* This method can be called in order to re-open a server which have been closed by the Close method. */
function Open($silent=FALSE) {
/** Give the 'open' argument to BulletProof FTP Server to re-open it for new connections. */
$this->GiveArgument("-open");
if(!$silent) {
$this->GiveMsg("BulletProof FTP Server is now open and ready to accept any new onnections.<br><br>");
}
}
/** method KickAll(str silent)
* Method for kicking all users currently connected to the BulletProof FTP Server. */
function KickAll($silent=FALSE) {
/** Give the 'kickall' argument to BulletProof FTP Server to kick all currently connected users. */
$this->GiveArgument("-kickall");
if(!$silent) {
$this->GiveMsg("Successfully kicked all users who currently were connected to the BulletProof FTP Server.<br><br>");
}
}
/** method Shutdown(str silent)
* Method for shutting down the BulletProof FTP Server instance. See also method GoOffline. */
function Shutdown($silent=FALSE) {
/** Give the 'exit' argument to BulletProof FTP Server to terminate any instance of BulletProof FTP server. */
$this->GiveArgument("-exit");
if(!$silent) {
$this->GiveMsg("Shutdown of BulletProof FTP Server instance complete.<br><br>");
}
}
/** method AddGroup(str groupname, array config, str silent)
* Method for adding a new group with the groupname specified in string '$groupname'. */
function AddGroup($groupname=FALSE, $config=FALSE, $silent=FALSE) {
/** Make the configuration array $_CONF global so the configuration
* directives can be used within this method. */
global $_CONF;
/** Check to see if all nescessary values are passed to the method.
* I any nescessary value is missing, then return false with error. */
if(!$groupname) {
$this->ReturnError("<b>FATAL ERROR:</b> Command failed! No group name specified!", "2");
exit;
}
if(!$config) {
$this->ReturnError("<b>FATAL ERROR:</b> Command failed! No configuration array specified!", "3");
exit;
}
/** If the group ini-file could not be found, return error message. */
if(!@file_exists("$this->serverPath\\" . $_CONF['groupfile'])) {
$this->ReturnError("<b>FATAL ERROR:</b> The group ini-file does not exist on the specified location!", "4");
exit;
}
/** Make sure that the group does -not- already exists. If the group -do-
* exists, then return false with a error message. Proceed if the group does not exist. */
if(!$groupfile_lines = @file("$this->serverPath\\" . $_CONF['groupfile'])) {
$this->ReturnError("<b>FATAL ERROR:</b> The group ini-file does not exist on the specified location!", "5");
exit;
}
foreach($groupfile_lines as $groupfile_linenum => $groupfile_line) {
if(strtolower($groupfile_line) == strtolower("[$groupname]\r\n")) {
$this->ReturnError("<b>FATAL ERROR:</b> Group \"$groupname\" already exists. Command aborted!", "6");
exit;
}
}
/** If the groupfile is writeable, then proceed adding of new group. */
if(@is_writeable("$this->serverPath\\" . $_CONF['groupfile'])) {
/** If the groupfile can't be opened, return error message. */
if(!$GroupHandle = fopen("$this->serverPath\\" . $_CONF['groupfile'], "a")) {
$this->ReturnError("<b>FATAL ERROR:</b> Cannot open file " . $_CONF['groupfile'] . "!", "7");
exit;
}
/** Attempt to write the group identifier to the groupfile. If data could not
* be written to the groupfile, then return error message. */
if(@fwrite($GroupHandle, "[$groupname]\r\n") === FALSE) {
$this->ReturnError("<b>FATAL ERROR:</b> Cannot write data to " . $_CONF['groupfile'] . " file!", "8");
exit;
}
/** Get all configuration directives from the array $config and attempt to
* insert them to the groupfile. */
foreach($config as $conf_string => $conf_value) {
/** If data could not be written to the groupfile, then return error message. */
if(@fwrite($GroupHandle, "$conf_string=$conf_value\r\n") === FALSE) {
$this->ReturnError("<b>FATAL ERROR:</b> Cannot write data to " . $_CONF['groupfile'] . " file!", "9");
exit;
}
}
/** Attempt to write ending linebreaks to the groupfile. If data could not
* be written to the groupfile, then return error message. */
if(@fwrite($GroupHandle, "\r\n") === FALSE) {
$this->ReturnError("<b>FATAL ERROR:</b> Cannot write data to " . $_CONF['groupfile'] . " file!", "10");
exit;
}
/** If new group were added successfully, then send argument 'reload' to the
* BulletProof FTP Server in order to reload the group and user ini-files. */
$this->GiveArgument("-reload");
if(!$silent) {
$this->GiveMsg("Successfully added new group \"$groupname\" to BulletProof FTP Server.<br><br>");
}
/** Close the file handle for the groupfile. */
fclose($GroupHandle);
}
/** If the groupfile is -not- writeable, return error message. */
else {
$this->ReturnError("<b>FATAL ERROR:</b> Could not append file " . $_CONF['groupfile'] . " for writing!", "11");
exit;
}
}
/** method DeleteGroup(str groupname, str silent)
* Method for deleting a BulletProof FTP Server group. */
function DeleteGroup($groupname=FALSE, $silent=FALSE) {
/** Make the configuration array $_CONF global so the configuration
* directives can be used within this method. */
global $_CONF;
/** If the group ini-file could not be found, return error message. */
if(!file_exists("$this->serverPath\\" . $_CONF['groupfile'])) {
$this->ReturnError("<b>FATAL ERROR:</b> The group ini-file does not exist on the specified location!", "12");
exit;
}
/** Make sure that the group -do- exists. If the group -do not- exists,
* then return false with a error message. Proceed deletion of group if the group -do- exist. */
if(!$groupfile_lines = @file("$this->serverPath\\" . $_CONF['groupfile'])) {
$this->ReturnError("<b>FATAL ERROR:</b> The group ini-file does not exist on the specified location!", "13");
exit;
}
foreach($groupfile_lines as $groupfile_linenum => $groupfile_line) {
if(strtolower($groupfile_line) == strtolower("[$groupname]\r\n")) {
$group_exists = TRUE;
}
}
/** If the specified group in string '$groupname' does not exist, then return
* error message and abort the deletion of group. */
if(!$group_exists) {
$this->ReturnError("<b>FATAL ERROR:</b> Group \"$groupname\" does not exist. Command aborted!", "14");
exit;
}
/** If the specified group in string '$groupname' -do- exists, then attempt
* to delete it from the group ini-file. */
else {
/** Get all group accounts from the group ini-file in to a string.
* Return false with error message if the group ini-file could -not- be read. */
if(!$groupfile = @file_get_contents("$this->serverPath\\" . $_CONF['groupfile'])) {
$this->ReturnError("<b>FATAL ERROR:</b> Could not get contents of group ini-file! Command aborted.", "15");
exit;
}
/** Remove the specified group in string '$groupname' from the group ini-file and
* return all other group accounts in to the string '$new_groupfile'. */
$new_groupfile = eregi_replace("\[$groupname\][^[]*.[\r\n]", "", $groupfile);
/** If the groupfile is writeable, then proceed re-adding of all groups
* -except- the group which should be deleted. */
if(is_writeable("$this->serverPath\\" . $_CONF['groupfile'])) {
/** If the groupfile can't be opened, return error message. */
if(!$GroupHandle = @fopen("$this->serverPath\\" . $_CONF['groupfile'], "w")) {
$this->ReturnError("<b>FATAL ERROR:</b> Cannot open file " . $_CONF['groupfile'] . "!", "16");
exit;
}
/** Attempt to re-write all groups, except the group which should be deleted,
* to the groupfile. If data could not be written to the groupfile, then return error message. */
if(@fwrite($GroupHandle, $new_groupfile) === FALSE) {
$this->ReturnError("<b>FATAL ERROR:</b> Cannot write data to " . $_CONF['groupfile'] . " file!", "17");
exit;
}
/** If the group were deleted successfully, then send argument 'reload' to the
* BulletProof FTP Server in order to reload the group and user ini-files. */
$this->GiveArgument("-reload");
if(!$silent) {
$this->GiveMsg("Successfully deleted group \"$groupname\" from the BulletProof FTP Server.<br><br>");
}
/** Close the file handle for the groupfile. */
fclose($GroupHandle);
}
/** If the groupfile is -not- writeable, return error message. */
else {
$this->ReturnError("<b>FATAL ERROR:</b> Could not append file " . $_CONF['groupfile'] . " for writing!", "18");
exit;
}
}
}
/** method EditGroup(str groupname, array config, str new_groupname, str silent)
* Method for editing (updating) an existing BulletProof FTP Server group. */
function EditGroup($groupname, $config, $new_groupname=FALSE, $silent=FALSE) {
/** Make the configuration array $_CONF global so the configuration
* directives can be used within this method. */
global $_CONF;
/** If the group ini-file could not be found, return error message. */
if(!file_exists("$this->serverPath\\" . $_CONF['groupfile'])) {
$this->ReturnError("<b>FATAL ERROR:</b> The group ini-file does not exist on the specified location!", "19");
exit;
}
/** Check to see if a new groupname is defined. If a new groupname -is-
* defined, then update the group using the new groupname. */
if(!$new_groupname) {
$new_groupname = $groupname;
}
/** Call method DeleteGroup in order to delete the group. We need to delete
* the group first so that we can re-add the group using the new configurations. */
$this->DeleteGroup($groupname, silent);
/** Call method AddGroup in order to re-add the specified group with
* the new settings (and new groupname, if it's defined). */
$this->AddGroup($new_groupname, $config, silent);
/** If the group got updated successfully, then return message. */
if(!$silent) {
$this->GiveMsg("Group \"$groupname\" successfully updated!");
}
}
}
?>