#native_company# #native_desc#
#native_cta#

BulletProof FTP Admin

By Niklas Forsberg
on January 9, 2005

Version: 1.3.4

Type: Class

Category: Networking

License: GNU General Public License

Description: @name: class BPFTPAdmin
@file: classBPFTPAdmin.php
@author: Niklas Forsberg
@email: [email protected]

@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:   [email protected]
*  @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:ProgramBPFTP 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->serverPathFTPsrv.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]rn")) {
                                $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]rn") === 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_valuern") === 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, "rn") === 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]rn")) {
                                $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][^[]*.[rn]", "", $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!");
                }

        }

}

?>