/*
* GProFTPD - A GTK+ frontend for the ProFTPD standalone server.
* Copyright (C) 2001 - 2006 Magnus Loef (Magnus-swe) <magnus-swe@telia.com>
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "widgets.h"
#include "gettext.h"
#include "functions.h"
#include "reread_conf.h"
#include "show_info.h"
#include "apply_user.h"
#include "allocate.h"
#include "populate_users.h"
#include "populate_user_settings.h"
#include "populate_conf_tab.h"
#include "dir_treeview_funcs.h"
extern char global_server_address[1024];
extern char global_server_port[1024];
extern char global_server_type[1024];
extern int activated;
extern int use_ratio;
extern int use_quota;
/* Temporary for option deprecations */
extern char global_version[1024];
/* The current directory beeing added and limited */
//gchar *dir; // ???
extern gchar *homedir;
/* The 18 checkbox values */
gchar *dir_val[19]; // ???
char *user_profile; // ???
extern long num_rows;
extern int row_pos;
/* Fixme mod: group, comment and shell */
void apply_user(struct w *widgets)
{
/* Change the selected users configuration. */
/* First delete the user from the conf then add it */
FILE *fp;
long conf_size;
int password_length = 0;
gchar *info;
char *old_buffer, *new_buffer, *config, *address_buffer, *port_buffer;
long profile_size = 0;
int user_changed = 0;
int found = 0;
gchar *UserUsername;
char *temp_user;
G_CONST_RETURN gchar *username;
G_CONST_RETURN gchar *groupname;
G_CONST_RETURN gchar *comment;
G_CONST_RETURN gchar *password;
G_CONST_RETURN gchar *login_from;
G_CONST_RETURN gchar *max_logins;
G_CONST_RETURN gchar *br=NULL, *brc=NULL, *fr=NULL, *frc=NULL;
/* Get the settings from the entries */
username = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_entry[0]));
password = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_entry[1]));
groupname = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_entry[2]));
comment = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_entry[3]));
login_from = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_entry[5]));
max_logins = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_spinbutton[0]));
/* Ratios */
if( use_ratio )
{
br = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_spinbutton[1]));
brc = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_spinbutton[2]));
fr = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_spinbutton[3]));
frc = gtk_entry_get_text(GTK_ENTRY(widgets->user_set_spinbutton[4]));
}
if( password!=NULL )
password_length = strlen(password);
/* If the user has written a password thats less then MIN_PASS_LEN chars long */
if( password_length > 0 && password_length < MIN_PASS_LEN )
{
info = g_strdup_printf(_("The minimum password length is %d.\n"), MIN_PASS_LEN);
show_info(info);
g_free(info);
return;
}
/* Set global num_rows */
num_rows = 0;
gtk_tree_model_foreach(GTK_TREE_MODEL(widgets->directory_store), (GtkTreeModelForeachFunc) num_rows_func, widgets);
/* There must be atleast one directory */
if( num_rows < 1 )
{
info = g_strdup_printf(_("Missing ftp home directory. Scroll down and add one first.\n"));
show_info(info);
g_free(info);
return;
}
/* (Global char) Statics + entries + number of rows (dirlen + APPE STOR STOU etc) */
profile_size = 16384 + 1400 + (num_rows * 16384);
/* Allocate the user profile */
user_profile = allocate(profile_size);
/* Set the users home dir and its values globally */
row_pos = 0; /* Only get the home directory */
gtk_tree_model_foreach(GTK_TREE_MODEL(widgets->directory_store), (GtkTreeModelForeachFunc) dirs_foreach, widgets);
/* Create the user profile... */
/* Home directory */
snprintf(user_profile, 16384, "\n<Anonymous %s>\n", homedir); // ERROR!!!
/* Username */
strcat(user_profile, "User ");
strcat(user_profile, username);
strcat(user_profile, "\n");
/* Groupname */
strcat(user_profile, "Group ");
strcat(user_profile, groupname);
strcat(user_profile, "\n");
/* Require password */
if( ! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[1])) )
strcat(user_profile, "AnonRequirePassword off\n");
else
strcat(user_profile, "AnonRequirePassword on\n");
/* Maximum logins */
strcat(user_profile, "MaxClients ");
strcat(user_profile, max_logins);
strcat(user_profile, " \"");
strcat(user_profile, "The server is full, hosting %m users");
strcat(user_profile, "\"\n");
/* Static Welcome and chdir msgs */
strcat(user_profile, "DisplayLogin welcome.msg\n");
// Fedora backported all but this!
// if( strstr(global_version, "1.2.") || strstr(global_version, "1.3.0") )
// strcat(user_profile, "DisplayFirstChdir .msg\n");
// else
// strcat(user_profile, "DisplayChdir .msg\n");
/* Ratio Module (reversed br/fr order in the gui) */
if( use_ratio )
{
strcat(user_profile, "UserRatio ");
strcat(user_profile, username);
strcat(user_profile, " ");
strcat(user_profile, fr);
strcat(user_profile, " ");
strcat(user_profile, frc);
strcat(user_profile, " ");
strcat(user_profile, br);
strcat(user_profile, " ");
strcat(user_profile, brc);
strcat(user_profile, "\n");
}
/* Logins from, if nothing is specified we allow everything */
if( login_from == NULL || strlen(login_from) < 3 )
{
strcat(user_profile, "<Limit LOGIN>\n");
strcat(user_profile, "Allow from all\nDeny from all\n");
strcat(user_profile, "</Limit>\n");
}
else
{
strcat(user_profile, "<Limit LOGIN>\n");
strcat(user_profile, "Allow from ");
strcat(user_profile, login_from);
strcat(user_profile, "\nDeny from all\n");
strcat(user_profile, "</Limit>\n");
}
/* Append the Limit CMDs for the home directory */
append_limit_cmds();
/* Append all other directories to the user profile */
row_pos = 1;
gtk_tree_model_foreach(GTK_TREE_MODEL(widgets->directory_store), (GtkTreeModelForeachFunc) dirs_foreach, widgets);
/* If not checked, dont show this user in the statistics (picked up by gprostats) */
if( ! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[2])) )
strcat(user_profile, "#gplockstats\n");
/* Profile end */
strcat(user_profile, "</Anonymous>\n");
if( homedir!=NULL )
g_free(homedir);
/* We have the new profile, insert it where the old user was located in the selected server */
UserUsername = g_strdup_printf("User %s\n", username);
address_buffer = allocate(8192+15);
port_buffer = allocate(8192+3);
if( strstr((char *)global_server_type, "Virtualhost") )
sprintf(address_buffer, "<VirtualHost %s>\n", global_server_address);
else
sprintf(address_buffer, global_server_address);
sprintf(port_buffer, "Port %s\n", global_server_port);
/* Make changes for this users settings */
if((fp=fopen(PROFTPD_CONF, "r"))==NULL)
{
free(address_buffer); free(port_buffer);
return;
}
fseek(fp, 0, SEEK_END);
conf_size = ftell(fp);
rewind(fp);
old_buffer = allocate(conf_size+3);
config = allocate(conf_size+profile_size+3);
/* If the selected server is a vhost we collect everything up to
the first vhost with the same name as the selected one */
if( strstr((char *)global_server_type, "Virtualhost") )
{
if( conf_size > 1 )
while(fgets(old_buffer, conf_size, fp)!=NULL)
{
strcat(config, old_buffer);
/* If its the correct address */
if( ! strcmp(old_buffer, address_buffer) )
{
while(fgets(old_buffer, conf_size, fp)!=NULL)
{
strcat(config, old_buffer);
/* This server was not the right one */
if( strstr(old_buffer, "</VirtualHost>") )
break;
if( ! strcmp(old_buffer, port_buffer) )
{
found = 1;
break;
}
}
}
if( found )
break;
}
}
/* We have scrolled to the correct VirtualHost or its the default server */
new_buffer = allocate(8192);
/* Change the selected users settings */
if( conf_size > 1 )
while(fgets(old_buffer, conf_size, fp)!=NULL)
{
if( strstr(old_buffer, "<Anonymous ") )
{
/* Save this directory incase its not the correct user */
strcat(new_buffer, old_buffer);
while(fgets(old_buffer, conf_size, fp)!=NULL)
{
/* This is the correct user in the correct server */
if( strstr(old_buffer, UserUsername)
&& ! strstr(old_buffer, "AllowUser")
&& ! strstr(old_buffer, "DirFakeUser") && ! user_changed )
{
/* The new profile is added */
strcat(config, user_profile);
new_buffer[0]='\0';
user_changed = 1;
/* The old profile is deleted */
while(fgets(old_buffer, conf_size, fp)!=NULL)
{
if( strstr(old_buffer, "</Anonymous") )
break;
/* Some more safety breaks */
if( strstr(old_buffer, "<Anonymous") )
break;
if( strstr(old_buffer, "</VirutalHost") )
break;
if( strstr(old_buffer, "<VirutalHost") )
break;
}
}
else
{
if( strlen(new_buffer) > 0 )
{
strcat(config, new_buffer);
new_buffer[0]='\0';
}
strcat(config, old_buffer);
break;
}
}
}
else
strcat(config, old_buffer);
}
free(old_buffer);
free(new_buffer);
g_free(UserUsername);
fclose(fp);
free(address_buffer); free(port_buffer);
free(user_profile);
if( ! user_changed )
{
info = g_strdup_printf(_("Error: user not found, couldnt change its settings.\n"));
show_info(info);
g_free(info);
free(config);
return;
}
/* Write the new config with the changed users settings */
if((fp=fopen(PROFTPD_CONF, "w+"))==NULL)
{
free(config);
return;
}
fputs(config, fp);
fclose(fp);
free(config);
/* Ban or unban the user in ftpusers depending on the selection */
if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[0])) )
{
/* Ban the user */
if( ! is_banned((char *)username) )
{
if((fp=fopen(GP_FTPUSERS, "a"))==NULL)
{
}
else
{
fputs("\n", fp);
fputs(username, fp);
fputs("\n", fp);
fclose(fp);
}
}
}
else
{
/* Remove the user from ftpusers if its there */
if( is_banned((char *)username) )
{
if((fp=fopen(GP_FTPUSERS, "r"))==NULL)
{
}
else
{
fseek(fp, 0, SEEK_END);
conf_size = ftell(fp);
rewind(fp);
config = allocate(conf_size+4096);
old_buffer = allocate(conf_size+4096);
temp_user = allocate(8192);
if( conf_size > 1 )
while(fgets(old_buffer, conf_size, fp)!=NULL)
{
sscanf(old_buffer, "%s", temp_user);
if( ! strcmp(temp_user, username) )
{
}
else
strcat(config, old_buffer);
}
fclose(fp);
free(old_buffer);
free(temp_user);
if((fp=fopen(GP_FTPUSERS, "w+"))==NULL)
{
}
else
{
fputs(config, fp);
fclose(fp);
}
free(config);
}
}
}
/* Change the users password if its >= MIN_PASS_LEN */
if( password_length >= MIN_PASS_LEN )
{
#ifndef USE_DARWIN
if( user_exists(username) )
#elif USE_DARWIN
if( niutil_user_exists(username) )
#endif
{
#ifndef USE_DARWIN
password_user(username, password);
#elif USE_DARWIN
niutil_password_user(username, password);
#endif
info = g_strdup_printf(_("\nThe Password was changed.\n"));
show_info(info);
g_free(info);
}
else
{
info = g_strdup_printf(_("The password was not changed.\nThe user didnt exist in shadow or passwd.\n"));
show_info(info);
g_free(info);
}
}
fix_newlines_in_conf();
/* Update the userlist */
populate_users(widgets);
/* Populate the user settings (it also populates the directories) */
populate_user_settings(widgets);
/* Populate the conf tab */
populate_conf_tab(widgets);
/* Update the server */
reread_conf(widgets);
}
syntax highlighted by Code2HTML, v. 0.9.1