Пример #1
0
/**
 * Run all system actions based on the value of $_REQUEST['act'].
 */
function ft_do_action()
{
    if (!empty($_REQUEST['act'])) {
        // Only one callback action is allowed. So only the first hook that acts on an action is run.
        ft_invoke_hook('action', $_REQUEST['act']);
        # mkdir
        if ($_REQUEST['act'] == "createdir" && CREATE === TRUE) {
            $_POST['newdir'] = trim($_POST['newdir']);
            if ($_POST['type'] == 'file') {
                // Check file against blacklists
                if (strlen($_POST['newdir']) > 0 && ft_check_filetype($_POST['newdir']) && ft_check_file($_POST['newdir'])) {
                    // Create file.
                    $newfile = ft_get_dir() . "/{$_POST['newdir']}";
                    if (file_exists($newfile)) {
                        // Redirect
                        ft_set_message(t("File could not be created. File already exists."), 'error');
                        ft_redirect("dir=" . $_REQUEST['dir']);
                    } elseif (@touch($newfile)) {
                        // Redirect.
                        ft_set_message(t("File created."));
                        ft_redirect("dir=" . $_REQUEST['dir']);
                    } else {
                        // Redirect
                        ft_set_message(t("File could not be created."), 'error');
                        ft_redirect("dir=" . $_REQUEST['dir']);
                    }
                } else {
                    // Redirect
                    ft_set_message(t("File could not be created."), 'error');
                    ft_redirect("dir=" . $_REQUEST['dir']);
                }
            } elseif ($_POST['type'] == 'url') {
                // Create from URL.
                $newname = trim(substr($_POST['newdir'], strrpos($_POST['newdir'], '/') + 1));
                if (strlen($newname) > 0 && ft_check_filetype($newname) && ft_check_file($newname)) {
                    // Open file handlers.
                    $rh = fopen($_POST['newdir'], 'rb');
                    if ($rh === FALSE) {
                        ft_set_message(t("Could not open URL. Possible reason: URL wrappers not enabled."), 'error');
                        ft_redirect("dir=" . $_REQUEST['dir']);
                    }
                    $wh = fopen(ft_get_dir() . '/' . $newname, 'wb');
                    if ($wh === FALSE) {
                        ft_set_message(t("File could not be created."), 'error');
                        ft_redirect("dir=" . $_REQUEST['dir']);
                    }
                    // Download anf write file.
                    while (!feof($rh)) {
                        if (fwrite($wh, fread($rh, 1024)) === FALSE) {
                            ft_set_message(t("File could not be saved."), 'error');
                        }
                    }
                    fclose($rh);
                    fclose($wh);
                    ft_redirect("dir=" . $_REQUEST['dir']);
                } else {
                    // Redirect
                    ft_set_message(t("File could not be created."), 'error');
                    ft_redirect("dir=" . $_REQUEST['dir']);
                }
            } else {
                // Create directory.
                // Check input.
                // if (strstr($_POST['newdir'], ".")) {
                // Throw error (redirect).
                // ft_redirect("status=createddirfail&dir=".$_REQUEST['dir']);
                // } else {
                $_POST['newdir'] = ft_stripslashes($_POST['newdir']);
                $newdir = ft_get_dir() . "/{$_POST['newdir']}";
                $oldumask = umask(0);
                if (strlen($_POST['newdir']) > 0 && @mkdir($newdir, DIRPERMISSION)) {
                    ft_set_message(t("Directory created."));
                    ft_redirect("dir=" . $_REQUEST['dir']);
                } else {
                    // Redirect
                    ft_set_message(t("Directory could not be created."), 'error');
                    ft_redirect("dir=" . $_REQUEST['dir']);
                }
                umask($oldumask);
                // }
            }
            # Move
        } elseif ($_REQUEST['act'] == "move" && ft_check_fileactions() === TRUE) {
            // Check that both file and newvalue are set.
            $file = trim(ft_stripslashes($_REQUEST['file']));
            $dir = trim(ft_stripslashes($_REQUEST['newvalue']));
            if (substr($dir, -1, 1) != "/") {
                $dir .= "/";
            }
            // Check for level.
            if (substr_count($dir, "../") <= substr_count(ft_get_dir(), "/") && ft_check_move($dir) === TRUE) {
                $dir = ft_get_dir() . "/" . $dir;
                if (!empty($file) && file_exists(ft_get_dir() . "/" . $file)) {
                    // Check that destination exists and is a directory.
                    if (is_dir($dir)) {
                        // Move file.
                        if (@rename(ft_get_dir() . "/" . $file, $dir . "/" . $file)) {
                            // Success.
                            ft_set_message(t("!old was moved to !new", array('!old' => $file, '!new' => $dir)));
                            ft_redirect("dir={$_REQUEST['dir']}");
                        } else {
                            // Error rename failed.
                            ft_set_message(t("!old could not be moved.", array('!old' => $file)), 'error');
                            ft_redirect("dir={$_REQUEST['dir']}");
                        }
                    } else {
                        // Error dest. isn't a dir or doesn't exist.
                        ft_set_message(t("Could not move file. !old does not exist or is not a directory.", array('!old' => $dir)), 'error');
                        ft_redirect("dir={$_REQUEST['dir']}");
                    }
                } else {
                    // Error source file doesn't exist.
                    ft_set_message(t("!old could not be moved. It doesn't exist.", array('!old' => $file)), 'error');
                    ft_redirect("dir={$_REQUEST['dir']}");
                }
            } else {
                // Error level
                ft_set_message(t("!old could not be moved outside the base directory.", array('!old' => $file)), 'error');
                ft_redirect("dir={$_REQUEST['dir']}");
            }
            # Delete
        } elseif ($_REQUEST['act'] == "delete" && ft_check_fileactions() === TRUE) {
            // Check that file is set.
            $file = ft_stripslashes($_REQUEST['file']);
            if (!empty($file) && ft_check_file($file)) {
                if (is_dir(ft_get_dir() . "/" . $file)) {
                    if (DELETEFOLDERS == TRUE) {
                        ft_rmdir_recurse(ft_get_dir() . "/" . $file);
                    }
                    if (!@rmdir(ft_get_dir() . "/" . $file)) {
                        ft_set_message(t("!old could not be deleted.", array('!old' => $file)), 'error');
                        ft_redirect("dir={$_REQUEST['dir']}");
                    } else {
                        ft_set_message(t("!old deleted.", array('!old' => $file)));
                        ft_redirect("dir={$_REQUEST['dir']}");
                    }
                } else {
                    if (!@unlink(ft_get_dir() . "/" . $file)) {
                        ft_set_message(t("!old could not be deleted.", array('!old' => $file)), 'error');
                        ft_redirect("dir={$_REQUEST['dir']}");
                    } else {
                        ft_set_message(t("!old deleted.", array('!old' => $file)));
                        ft_redirect("dir={$_REQUEST['dir']}");
                    }
                }
            } else {
                ft_set_message(t("!old could not be deleted.", array('!old' => $file)), 'error');
                ft_redirect("dir={$_REQUEST['dir']}");
            }
            # Rename && Duplicate && Symlink
        } elseif ($_REQUEST['act'] == "rename" || $_REQUEST['act'] == "duplicate" || $_REQUEST['act'] == "symlink" && ft_check_fileactions() === TRUE) {
            // Check that both file and newvalue are set.
            $old = trim(ft_stripslashes($_REQUEST['file']));
            $new = trim(ft_stripslashes($_REQUEST['newvalue']));
            if ($_REQUEST['act'] == 'rename') {
                $m['typefail'] = t("!old was not renamed to !new (type not allowed).", array('!old' => $old, '!new' => $new));
                $m['writefail'] = t("!old could not be renamed (write failed).", array('!old' => $old));
                $m['destfail'] = t("File could not be renamed to !new since it already exists.", array('!new' => $new));
                $m['emptyfail'] = t("File could not be renamed since you didn't specify a new name.");
            } elseif ($_REQUEST['act'] == 'duplicate') {
                $m['typefail'] = t("!old was not duplicated to !new (type not allowed).", array('!old' => $old, '!new' => $new));
                $m['writefail'] = t("!old could not be duplicated (write failed).", array('!old' => $old));
                $m['destfail'] = t("File could not be duplicated to !new since it already exists.", array('!new' => $new));
                $m['emptyfail'] = t("File could not be duplicated since you didn't specify a new name.");
            } elseif ($_REQUEST['act'] == 'symlink') {
                $m['typefail'] = t("Could not create symlink to !old (type not allowed).", array('!old' => $old, '!new' => $new));
                $m['writefail'] = t("Could not create symlink to !old (write failed).", array('!old' => $old));
                $m['destfail'] = t("Could not create symlink !new since it already exists.", array('!new' => $new));
                $m['emptyfail'] = t("Symlink could not be created since you didn't specify a name.");
            }
            if (!empty($old) && !empty($new)) {
                if (ft_check_filetype($new) && ft_check_file($new)) {
                    // Make sure destination file doesn't exist.
                    if (!file_exists(ft_get_dir() . "/" . $new)) {
                        // Check that file exists.
                        if (is_writeable(ft_get_dir() . "/" . $old)) {
                            if ($_REQUEST['act'] == "rename") {
                                if (@rename(ft_get_dir() . "/" . $old, ft_get_dir() . "/" . $new)) {
                                    // Success.
                                    ft_set_message(t("!old was renamed to !new", array('!old' => $old, '!new' => $new)));
                                    ft_redirect("dir={$_REQUEST['dir']}");
                                } else {
                                    // Error rename failed.
                                    ft_set_message(t("!old could not be renamed.", array('!old' => $old)), 'error');
                                    ft_redirect("dir={$_REQUEST['dir']}");
                                }
                            } elseif ($_REQUEST['act'] == 'symlink') {
                                if (ADVANCEDACTIONS == TRUE) {
                                    if (@symlink(realpath(ft_get_dir() . "/" . $old), ft_get_dir() . "/" . $new)) {
                                        @chmod(ft_get_dir() . "/{$new}", PERMISSION);
                                        // Success.
                                        ft_set_message(t("Created symlink !new", array('!old' => $old, '!new' => $new)));
                                        ft_redirect("dir={$_REQUEST['dir']}");
                                    } else {
                                        // Error symlink failed.
                                        ft_set_message(t("Symlink to !old could not be created.", array('!old' => $old)), 'error');
                                        ft_redirect("dir={$_REQUEST['dir']}");
                                    }
                                }
                            } else {
                                if (@copy(ft_get_dir() . "/" . $old, ft_get_dir() . "/" . $new)) {
                                    // Success.
                                    ft_set_message(t("!old was duplicated to !new", array('!old' => $old, '!new' => $new)));
                                    ft_redirect("dir={$_REQUEST['dir']}");
                                } else {
                                    // Error rename failed.
                                    ft_set_message(t("!old could not be duplicated.", array('!old' => $old)), 'error');
                                    ft_redirect("dir={$_REQUEST['dir']}");
                                }
                            }
                        } else {
                            // Error old file isn't writeable.
                            ft_set_message($m['writefail'], 'error');
                            ft_redirect("dir={$_REQUEST['dir']}");
                        }
                    } else {
                        // Error destination exists.
                        ft_set_message($m['destfail'], 'error');
                        ft_redirect("dir={$_REQUEST['dir']}");
                    }
                } else {
                    // Error file type not allowed.
                    ft_set_message($m['typefail'], 'error');
                    ft_redirect("dir={$_REQUEST['dir']}");
                }
            } else {
                // Error. File name not set.
                ft_set_message($m['emptyfail'], 'error');
                ft_redirect("dir={$_REQUEST['dir']}");
            }
            # upload
        } elseif ($_REQUEST['act'] == "upload" && ft_check_upload() === TRUE && (LIMIT <= 0 || LIMIT > ROOTDIRSIZE)) {
            // If we are to upload a file we will do so.
            $msglist = 0;
            foreach ($_FILES as $k => $c) {
                if (!empty($c['name'])) {
                    $c['name'] = ft_stripslashes($c['name']);
                    if ($c['error'] == 0) {
                        // Upload was successfull
                        if (ft_validate_filename($c['name']) && ft_check_filetype($c['name']) && ft_check_file($c['name'])) {
                            if (file_exists(ft_get_dir() . "/{$c['name']}")) {
                                $msglist++;
                                ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("File already exists"), 'error');
                            } else {
                                if (@move_uploaded_file($c['tmp_name'], ft_get_dir() . "/{$c['name']}")) {
                                    @chmod(ft_get_dir() . "/{$c['name']}", PERMISSION);
                                    // Success!
                                    $msglist++;
                                    ft_set_message(t('!file was uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))));
                                    ft_invoke_hook('upload', ft_get_dir(), $c['name']);
                                } else {
                                    // File couldn't be moved. Throw error.
                                    $msglist++;
                                    ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("File couldn't be moved"), 'error');
                                }
                            }
                        } else {
                            // File type is not allowed. Throw error.
                            $msglist++;
                            ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("File type not allowed"), 'error');
                        }
                    } else {
                        // An error occurred.
                        switch ($_FILES["localfile"]["error"]) {
                            case 1:
                                $msglist++;
                                ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("The file was too large"), 'error');
                                break;
                            case 2:
                                $msglist++;
                                ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("The file was larger than MAXSIZE setting."), 'error');
                                break;
                            case 3:
                                $msglist++;
                                ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("Partial upload. Try again"), 'error');
                                break;
                            case 4:
                                $msglist++;
                                ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("No file was uploaded. Please try again"), 'error');
                                break;
                            default:
                                $msglist++;
                                ft_set_message(t('!file was not uploaded.', array('!file' => ft_get_nice_filename($c['name'], 20))) . ' ' . t("Unknown error"), 'error');
                                break;
                        }
                    }
                }
            }
            if ($msglist > 0) {
                ft_redirect("dir=" . $_REQUEST['dir']);
            } else {
                ft_set_message(t("Upload failed."), 'error');
                ft_redirect("dir=" . $_REQUEST['dir']);
            }
            # Unzip
        } elseif ($_REQUEST['act'] == "unzip" && ft_check_fileactions() === TRUE) {
            // Check that file is set.
            $file = ft_stripslashes($_REQUEST['file']);
            if (!empty($file) && ft_check_file($file) && ft_check_filetype($file) && strtolower(ft_get_ext($file)) == 'zip' && is_file(ft_get_dir() . "/" . $file)) {
                $escapeddir = escapeshellarg(ft_get_dir() . "/");
                $escapedfile = escapeshellarg(ft_get_dir() . "/" . $file);
                if (!@exec("unzip -n " . $escapedfile . " -d " . $escapeddir)) {
                    ft_set_message(t("!old could not be unzipped.", array('!old' => $file)), 'error');
                    ft_redirect("dir={$_REQUEST['dir']}");
                } else {
                    ft_set_message(t("!old unzipped.", array('!old' => $file)));
                    ft_redirect("dir={$_REQUEST['dir']}");
                }
            } else {
                ft_set_message(t("!old could not be unzipped.", array('!old' => $file)), 'error');
                ft_redirect("dir={$_REQUEST['dir']}");
            }
            # chmod
        } elseif ($_REQUEST['act'] == "chmod" && ft_check_fileactions() === TRUE && ADVANCEDACTIONS == TRUE) {
            // Check that file is set.
            $file = ft_stripslashes($_REQUEST['file']);
            if (!empty($file) && ft_check_file($file) && ft_check_filetype($file)) {
                // Check that chosen permission i valid
                if (is_numeric($_REQUEST['newvalue'])) {
                    $chmod = $_REQUEST['newvalue'];
                    if (substr($chmod, 0, 1) == '0') {
                        $chmod = substr($chmod, 0, 4);
                    } else {
                        $chmod = '0' . substr($chmod, 0, 3);
                    }
                    // Chmod
                    if (@chmod(ft_get_dir() . "/" . $file, intval($chmod, 8))) {
                        ft_set_message(t("Permissions changed for !old.", array('!old' => $file)));
                        ft_redirect("dir={$_REQUEST['dir']}");
                        clearstatcache();
                    } else {
                        ft_set_message(t("Could not change permissions for !old.", array('!old' => $file)), 'error');
                        ft_redirect("dir={$_REQUEST['dir']}");
                    }
                } else {
                    ft_set_message(t("Could not change permissions for !old.", array('!old' => $file)), 'error');
                    ft_redirect("dir={$_REQUEST['dir']}");
                }
            } else {
                ft_set_message(t("Could not change permissions for !old.", array('!old' => $file)), 'error');
                ft_redirect("dir={$_REQUEST['dir']}");
            }
            # logout
        } elseif ($_REQUEST['act'] == "logout") {
            ft_invoke_hook('logout', $_SESSION['ft_user_' . MUTEX]);
            $_SESSION = array();
            if (isset($_COOKIE[session_name()])) {
                setcookie(session_name(), '', time() - 42000, '/');
            }
            session_destroy();
            // Delete persistent cookie
            setcookie('ft_user_' . MUTEX, '', time() - 3600);
            ft_redirect();
        }
    }
}
Пример #2
0
/**
 * Implementation of hook_action.
 */
function ft_edit_action($act)
{
    global $ft;
    if ($act == 'savefile') {
        $file = trim(ft_stripslashes($_REQUEST["file"]));
        if (ft_check_fileactions() === TRUE) {
            // Save a file that has been edited.
            // Delete any locks on this file.
            ft_edit_lock_clear($file, ft_get_dir());
            // Check for edit or cancel
            if (strtolower($_REQUEST["submit"]) != strtolower(t("Cancel"))) {
                // Check if file type can be edited.
                if (ft_check_dir(ft_get_dir()) && ft_check_edit($file) && ft_check_fileactions() === TRUE && ft_check_filetype($file) && ft_check_filetype($file)) {
                    $filecontent = ft_stripslashes($_REQUEST["filecontent"]);
                    if ($_REQUEST["convertspaces"] != "") {
                        $filecontent = str_replace("    ", "\t", $filecontent);
                    }
                    if (is_writeable(ft_get_dir() . "/{$file}")) {
                        $fp = @fopen(ft_get_dir() . "/{$file}", "wb");
                        if ($fp) {
                            fputs($fp, $filecontent);
                            fclose($fp);
                            ft_set_message(t("!old was saved.", array('!old' => $file)));
                            ft_redirect("dir={$_REQUEST['dir']}");
                        } else {
                            ft_set_message(t("!old could not be edited.", array('!old' => $file)), 'error');
                            ft_redirect("dir={$_REQUEST['dir']}");
                        }
                    } else {
                        ft_set_message(t("!old could not be edited.", array('!old' => $file)), 'error');
                        ft_redirect("dir={$_REQUEST['dir']}");
                    }
                } else {
                    ft_set_message(t("Could not edit file. This file type is not editable."), 'error');
                    ft_redirect("dir={$_REQUEST['dir']}");
                }
            } else {
                ft_redirect("dir=" . rawurlencode($_REQUEST['dir']));
            }
        }
    }
}
Пример #3
0
/**
 * Implementation of hook_action.
 */
function ft_log_action($act)
{
    global $ft;
    // Prune old records.
    if ($act == 'log_prune' && isset($ft['plugins']['log']['settings']['viewlogs']) && $ft['plugins']['log']['settings']['viewlogs'] === TRUE) {
        $offset = date('Y-m-d', strtotime('-7 months', gmmktime()));
        $sql = "DELETE FROM log WHERE timestamp <= '" . $ft['db']['link']->quote($offset) . "'";
        $result = $ft['db']['link']->query($sql);
        ft_set_message(t('Log pruned'));
        // Redirect.
        ft_redirect("act=log");
    }
    // View CSV log.
    if ($act == 'log_csv' && isset($ft['plugins']['log']['settings']['viewlogs']) && $ft['plugins']['log']['settings']['viewlogs'] === TRUE) {
        header('Content-type: text/plain;charset=UTF-8');
        $headers = array(t('Type'), t('Message'), t('Location'), t('Timestamp'), t('User'));
        $items = ft_log_do_query($_GET['type'], $_GET['from_day'], $_GET['from'], $_GET['to_day'], $_GET['to']);
        print str_putcsv($headers, ';') . "\n";
        foreach ($items as $row) {
            print str_putcsv($row, ';') . "\n";
        }
        exit;
    }
}
Пример #4
0
/**
 * Implementation of hook_action.
 */
function ft_db_action($act)
{
    global $ft;
    // Delete a database table.
    if ($act == 'db_delete_submit' && isset($ft['plugins']['db']['settings']['flushtables']) && $ft['plugins']['db']['settings']['flushtables'] === TRUE) {
        // Check for cancel.
        if (strtolower($_REQUEST["ft_submit"]) == strtolower(t("Cancel"))) {
            ft_redirect("act=db");
        }
        // Check if table exists.
        $display_value = htmlentities($_POST['value']);
        if (is_array($ft['db']) && is_array($ft['db']['tables']) && count($ft['db']['tables']) > 0) {
            // Drop table.
            $result = $ft['db']['link']->query('DROP TABLE ' . $ft['db']['link']->quote($_POST['value']));
            if ($result) {
                ft_set_message(t('Database table !table dropped.', array('!table' => $display_value)));
            } else {
                ft_set_message(t("Database table !table could not be dropped.", array('!table' => $display_value)), 'error');
            }
        } else {
            ft_set_message(t("Database table !table could not be removed because it doesn't exists.", array('!table' => $display_value)), 'error');
        }
        // Redirect.
        ft_redirect("act=db");
    }
}
Пример #5
0
/**
 * Implementation of hook_action.
 */
function ft_config_action($act)
{
    global $ft;
    // Change the default settings and plugins.
    if ($act == 'config_default_submit') {
        // Check for cancel.
        if (strtolower($_REQUEST["ft_submit"]) == strtolower(t("Cancel"))) {
            ft_redirect("act=config");
        }
        // Loop through settings.
        $ext = ft_settings_external_load();
        foreach ($ft['default_settings'] as $k => $v) {
            if (isset($_POST['setting_setting'][$k])) {
                if ($_POST['setting_setting'][$k] == 'TRUE') {
                    $ext['settings'][$k] = TRUE;
                } elseif ($_POST['setting_setting'][$k] == 'FALSE') {
                    $ext['settings'][$k] = FALSE;
                } elseif (($k == 'UPLOAD' || $k == 'FILEACTIONS') && $_POST['setting_setting'][$k] == 'OTHER') {
                    // UPLOAD and FILEACTIONS can have an 'other' value.
                    if (empty($_POST['setting_other_setting'][$k])) {
                        // If the other value is empty, turn off the setting.
                        $ext['settings'][$k] = FALSE;
                    } else {
                        $ext['settings'][$k] = ft_settings_external_clean($_POST['setting_other_setting'][$k]);
                    }
                } else {
                    $ext['settings'][$k] = ft_settings_external_clean($_POST['setting_setting'][$k]);
                }
            }
        }
        // Loop through plugins. Reset existing plugins.
        $ext['plugins'] = array();
        foreach ($_POST['plugins'] as $plugin_name => $plugin_status) {
            if ($plugin_status != '') {
                // Plugin enabled.
                $ext['plugins'][$plugin_name] = TRUE;
                // Check if there are settings attached to this plugin.
                if (isset($_POST['setting_plugins']) && is_array($_POST['setting_plugins']) && isset($_POST['setting_plugins'][$plugin_name])) {
                    $ext['plugins'][$plugin_name] = array();
                    $ext['plugins'][$plugin_name]['settings'] = array();
                    foreach ($_POST['setting_plugins'][$plugin_name] as $plugin_setting_name => $plugin_setting_value) {
                        if ($plugin_setting_value == 'TRUE') {
                            $ext['plugins'][$plugin_name]['settings'][$plugin_setting_name] = TRUE;
                        } elseif ($plugin_setting_value == 'FALSE') {
                            $ext['plugins'][$plugin_name]['settings'][$plugin_setting_name] = FALSE;
                        } else {
                            $ext['plugins'][$plugin_name]['settings'][$plugin_setting_name] = ft_settings_external_clean($plugin_setting_value);
                        }
                    }
                }
            }
        }
        // Save new settings.
        if (function_exists('ft_settings_external_load') && function_exists('ft_settings_external_save')) {
            // Save.
            if (ft_settings_external_save($ext)) {
                ft_set_message(t("Settings saved."), 'ok');
            } else {
                ft_set_message(t("Settings could not be saved. Config file could not be updated."), 'error');
            }
        } else {
            ft_set_message(t("External config file not found."), 'error');
            ft_redirect("act=config_default");
        }
        ft_redirect("act=config");
        // Add new group or edit group.
    } elseif ($act == 'user_add_submit_group' || $act == 'user_edit_submit_group') {
        // Check for cancel.
        if (strtolower($_REQUEST["ft_submit"]) == strtolower(t("Cancel"))) {
            ft_redirect("act=config");
        }
        $group = array();
        $group_name = (string) $_POST['user_group'];
        $group_name = ft_settings_external_clean($group_name);
        $group_old = '';
        if ($act == 'user_edit_submit_group') {
            $group_old = (string) $_POST['group_old'];
            $group_old = ft_settings_external_clean($group_old);
        }
        // Loop through defaults.
        if (!empty($_POST['setting_default']) && is_array($_POST['setting_default'])) {
            foreach ($_POST['setting_default'] as $setting => $v) {
                // Differs from default. Add setting.
                if ($v != '') {
                    if ($_POST['setting_setting'][$setting] == 'TRUE') {
                        $group[$setting] = TRUE;
                    } elseif ($_POST['setting_setting'][$setting] == 'FALSE') {
                        $group[$setting] = FALSE;
                    } elseif (($setting == 'UPLOAD' || $setting == 'FILEACTIONS') && $_POST['setting_setting'][$setting] == 'OTHER') {
                        // UPLOAD and FILEACTIONS can have an 'other' value.
                        if (empty($_POST['setting_other_setting'][$setting])) {
                            // If the other value is empty, turn off the setting.
                            $group[$setting] = FALSE;
                        } else {
                            $group[$setting] = ft_settings_external_clean($_POST['setting_other_setting'][$setting]);
                        }
                    } else {
                        $group[$setting] = ft_settings_external_clean($_POST['setting_setting'][$setting]);
                    }
                }
            }
        }
        // Loop through group plugins.
        if (!empty($_POST['plugins']) && is_array($_POST['plugins'])) {
            $group['plugins'] = array();
            foreach ($_POST['plugins'] as $plugin_name => $plugin_status) {
                if ($plugin_status != '') {
                    // Plugin enabled. Add to group.
                    $group['plugins'][$plugin_name] = TRUE;
                    // Check if there are settings attached to this plugin.
                    if (isset($_POST['setting_plugins']) && is_array($_POST['setting_plugins']) && isset($_POST['setting_plugins'][$plugin_name])) {
                        // $group['plugins'][$plugin_name] = array('test', 'test2');
                        $group['plugins'][$plugin_name] = array();
                        $group['plugins'][$plugin_name]['settings'] = array();
                        foreach ($_POST['setting_plugins'][$plugin_name] as $plugin_setting_name => $plugin_setting_value) {
                            if ($plugin_setting_value == 'TRUE') {
                                $group['plugins'][$plugin_name]['settings'][$plugin_setting_name] = TRUE;
                            } elseif ($plugin_setting_value == 'FALSE') {
                                $group['plugins'][$plugin_name]['settings'][$plugin_setting_name] = FALSE;
                            } else {
                                $group['plugins'][$plugin_name]['settings'][$plugin_setting_name] = ft_settings_external_clean($plugin_setting_value);
                            }
                        }
                    }
                }
            }
        }
        // Make sure group name is not in use or that we're editing without changing name.
        if (!isset($ft['groups'][$group_name]) || $act == 'user_edit_submit_group' && $group_name == $group_old) {
            // New group okay.
            if (function_exists('ft_settings_external_load') && function_exists('ft_settings_external_save')) {
                $ext = ft_settings_external_load();
                if (!isset($ext['groups'])) {
                    $ext['groups'] = array();
                }
                // Splice in new/updated user.
                $ext['groups'][$group_name] = $group;
                // Save.
                if (ft_settings_external_save($ext)) {
                    ft_set_message(t("!group was added/updated.", array('!group' => $group_name)), 'ok');
                } else {
                    ft_set_message(t("Group could not be added/updated. Config file could not be updated."), 'error');
                }
            } else {
                ft_set_message(t("External config file not found."), 'error');
                ft_redirect("act=user_add_group");
            }
        } else {
            // New group name already in use.
            ft_set_message(t("Group could not be added. Name already in use."), 'error');
            ft_redirect("act=user_add_group");
        }
        ft_redirect("act=config");
    } elseif ($act == 'user_add_submit' || $act == 'user_edit_submit') {
        // Adding new user or editing user.
        // Check for cancel.
        if (strtolower($_REQUEST["ft_submit"]) == strtolower(t("Cancel"))) {
            ft_redirect("act=config");
        }
        $user = (string) $_POST['user_user'];
        $user_old = '';
        if (!empty($_POST['user_old'])) {
            $user_old = (string) $_POST['user_old'];
        }
        $pass = (string) $_POST['user_pass'];
        $pass2 = (string) $_POST['user_pass2'];
        $group = (string) $_POST['user_group'];
        // Make sure passwords match.
        if ($pass == $pass2) {
            // Strip tags and other nasty characters.
            $user = ft_settings_external_clean($user);
            $user_old = ft_settings_external_clean($user_old);
            $pass = ft_settings_external_clean($pass);
            $group = ft_settings_external_clean($group);
            // Make sure there are no empty strings.
            if (strlen($user) > 0 && (strlen($pass) > 0 || $act == 'user_edit_submit')) {
                // Check that user doesn't already exists. Or that we're editing a user.
                if (!ft_check_user($user) || $act == 'user_edit_submit' && $user == $user_old) {
                    // Make new user.
                    $new = array();
                    $new['password'] = $pass;
                    if (!empty($group) && isset($ft['groups']) && isset($ft['groups'][$group])) {
                        $new['group'] = $group;
                    }
                    // If we're editing and the password is blank load existing password.
                    if ($act == 'user_edit_submit' && empty($pass)) {
                        $new['password'] = $ft['users'][$user_old]['password'];
                    }
                    if (function_exists('ft_settings_external_load') && function_exists('ft_settings_external_save')) {
                        $ext = ft_settings_external_load();
                        // Splice in new/updated user.
                        $ext['users'][$user] = $new;
                        // Remove old user.
                        if ($act == 'user_edit_submit' && $user != $user_old) {
                            unset($ext['users'][$user_old]);
                        }
                        // Save.
                        if (ft_settings_external_save($ext)) {
                            ft_set_message(t("!user was added/updated.", array('!user' => $user)), 'ok');
                        } else {
                            ft_set_message(t("User could not be added/updated. Config file could not be updated."), 'error');
                        }
                    } else {
                        ft_set_message(t("External config file not found."), 'error');
                    }
                } else {
                    ft_set_message(t("User could not be added. Username already in use."), 'error');
                }
            } else {
                ft_set_message(t("You must enter both a username and a password."), 'error');
            }
        } else {
            ft_set_message(t("Passwords didn't match."), 'error');
        }
        ft_redirect("act=config");
    } elseif ($act == 'user_delete_submit') {
        // Check for cancel.
        if (strtolower($_REQUEST["ft_submit"]) == strtolower(t("Cancel"))) {
            ft_redirect("act=config");
        }
        $ext = ft_settings_external_load();
        if ($_POST['type'] == 'user') {
            $msg = t("User was deleted.");
            // Remove user.
            unset($ext['users'][$_POST['value']]);
        } elseif ($_POST['type'] == 'group') {
            $msg = t("Group was deleted.");
            // Remove group.
            unset($ext['groups'][$_POST['value']]);
            // Loop through users and remove.
            foreach ($ext['users'] as $user => $v) {
                if ($v['group'] == $_POST['value']) {
                    unset($ext['users'][$user]);
                }
            }
        }
        // Save config file.
        if (ft_settings_external_save($ext)) {
            ft_set_message($msg);
        } else {
            ft_set_message(t("Config file could not be updated."), 'error');
        }
        ft_redirect("act=config");
    }
}