Table of Contents
Introduction
Webmin is designed to allow the easy addition of new modules without changing
any of the existing code. A module can be thought of as something like a
Netscape or Photoshop plugin - it can be written by someone other than
the developers of Webmin, and distributed under a and licence the
developer chooses.
A module should be written to administer one service or server, such as
the Unix password file or the Apache web server. Some complex system
functions may even be split over several modules - for example, disk
partitioning, mounting disks and disk quota management are 3 separate modules
in the standard Webmin distribution.
Modules can theoretically be written in any language. However, to make
use of the Webmin API Perl version 5.002 or above should be used. A module
should be written entirely in Perl, with no C functions or external binary
programs. The aim is for modules to be as portable as possible across different
Unix systems and CPU types.
Required Files
Every module has its own directory under the Webmin base directory, in which
all the module's CGI programs and configuration files must be stored. For
example, if the Webmin base was /usr/local/webmin-0.62, a module
called foobar would be installed in /usr/local/webmin-0.62/foobar.
For a module to be displayed on the main Webmin menu, it must contain at
least the following two files.
- images/icon.gif
- The icon displayed on the main menu for this module. The icon should be
48x48 pixels, and should use the same colour scheme as the other
icons on the main menu.
- module.info
- This file contains information about the module and the operating
systems it runs under. Each line of the file is in the format
name=value
Required names and their values are:
- name
- A short name for this module, such as FooAdmin.
- desc
- A longer description for the module, such as Foo Web Server.
This is the text that will appear below the icon on the main menu.
- op_support
- A space-separated list of operating systems that this module supports.
The module will only be displayed on the main menu if the OS Webmin
is running on is in the list, or if there is no os_support
line at all.
- depends
- A space-separated list of other modules upon which this module depends.
If module A depends upon module B, then Webmin will prevent module B
from being deleted while A is still installed. Similarly, Webmin will
prevent A from being installed if B has not been.
The list can also contain a Webmin version (such as 0.75) that the
module depends upon. In that case, installation of this module by
an older version of Webmin will not be allowed.
(Versions 0.70 and above)
- category
- This value determines which tab on the main Webmin page your module
will be categorised under. Supported values are webmin,
system, servers and hardware. If your
module.info file has no category line, it will appear
under the Others category.
(Versions 0.77 and above)
Each icon on the main menu is a link to the module directory. Thus you must
have an index.cgi or index.html file to be displayed when
the user clicks on the icon.
When you first create a new module, it will not be in the ACL of any Webmin
user and so you will not be able to see it in the main menu. To make your
module visible, you must either edit the file /etc/webmin/webmin.acl,
or use the Webmin Users module to grant yourself access.
Module CGI Programs
The Webmin web server treats files with the extension .cgi as CGI
programs, just like most other web servers. All the forms, menus and other
pages in your module will be generated by CGI programs, so knowledge of the
basic concepts of CGI programming and HTML are necessary for writing a
module.
Assuming your module is being written in perl, you should begin by writing
a perl script that contains functions used by the CGI programs in your module.
This script is usually called something like lib.pl or
foobar-lib.pl. A minimal example of such a script might look like :
# foobar-lib.pl
# Common functions used for managing the foobar user list
do '../web-lib.pl'; (1)
&init_config(); (2)
# list_users() (3)
# Returns a list of all foobar users
sub list_users
{
...
}
|
The 3 important features of the example above are :
- do '../web-lib.pl';
The file web-lib.pl in the Webmin root directory contains
a large number of functions that are useful for developing Webmin
modules. All CGI programs should indirectly or directly require
this module.
- &init_config();
This function (defined in web-lib.pl) initializes the following
global variables :
- %config
Contains the current configuration for this module. This typically
is used to store user editable options and operating system specific
information. Module config files are described in more detail
below.
- %gconfig
Contains the global Webmin configuration. See below for more
details.
- $module_name
The name of this module, which is just the name of the directory
the module is in.
- $module_config_directory
The directory in which this module's config file is stored.
If your module creates permanent files or programs for some
reason (such as print driver scripts), they should be created
in or under this directory.
- $tb
The background colour for table headers.
- $cb
The background colour for table bodies.
- $scriptname
The name of the CGI program currently being run, relative to
the directory it is in (such as save_foo.cgi).
- $remote_user
The username that the current user logged into Webmin with.
- $base_remote_user
The username whose permissions are currently in effect. Most of
the time this will be the same as $remote_user, but if
you have the 'Configure Unix user authentication' option setup
in the Webmin Users module, this will be set to the name of the
user whose permissions are used.
- $current_theme
The name of theme in effect for the current user.
- $root_directory
The root directory of the Webmin install, such as
/usr/libexec/webmin.
- $module_root_directory
The root directory of the current module, such as
/usr/libexec/webmin/modulename.
- The list_users function
This is an example of a function that might be used by various CGI
programs in this module. Some module library files may also include another
file containing functions specific to the current operating system or
configuration. See the proc-lib.pl in the proc module
as an example.
Common Functions
The file web-lib.pl contains a number of functions useful for
generating HTML, parsing files and all the other things Webmin modules
need to do. The functions available in Webmin 0.61 are listed below in
order of usefulness :
- init_config()
- Initializes global configuration variables. See the example above for
more details.
Note that prior to version 0.73, the init_config function had
to be passed the name of the module as a parameter. From 0.73 onwards,
the module name is worked out automatically.
- ReadParse()
- This function takes any CGI parameters passed to your program (from
form inputs or after the ? in the URL) and places them in the associative
array %in. If a CGI parameter has multiple values (for example,
from a list that allows multiple selections) then those values are
separated by null characters ('\0' in perl).
- header(title, image, [help], [config], [noindex], [noroot], [text], [header], [body])
- The header function is used by almost all programs to output
the HTTP header line (Content-type: text/plain), HTML title,
background and title image. The parameters passed to this function are :
- title - The HTML title of this page. Also used as the
ALT text for the title image.
- image - The URL of an image to display at the top of the
page. In the standard Webmin modules title images are drawn
using The GIMP in 50-point
helvetica, with a transparent background.
From Webmin version 0.75, if an empty string is given for this
parameter then a title image will be automatically generated.
To save on disk space, module writers should use this option
in future.
- help - If this parameter is defined then a Help link
is added to the title on the left hand side, linking to the
given help page.
- config - If this parameter is non-zero, a Config link
is added to the left of the title image. This links to a CGI
program that allows the user to edit the configuration of this
module, as defined by the config.info file. See below
for more details.
- noindex - By default, the header function will
add a Module Index link to the left of the title image linking
to the index for this module. If this parameter is given and
non-zero, this link will not be displayed.
- noroot - By default, a Webmin Index link to the Webmin
main menu will be added to the left of the title image. If given,
this parameter will suppress the addition of that link.
- text - HTML to be displayed to the right of the title
image. This can be anything you like, as long as it fits in the
small area available.
- header - HTML to be displayed in the <head> section
of the page. This parameter is only supported in Webmin versions
0.74 and above.
- body - Extra HTML tags to be include in the <body>
tag. This parameter is only supported in Webmin versions
0.79 and above.
If this function is called by a Usermin module and the config
parameter is set, your code must have called
create_user_config_dirs beforehand, in order to setup the
~/.usermin/modulename directory. Instead of a Module
Config link being included in the header, one called Preferences will
be instead, which allows the user to edit his own personal settings
for the module. The actual settings that can be changed are determined
by the uconfig.info file in the module directory, which has the
same format as config.info described below.
- footer(link, text, [link, text], ...)
- Outputs a small left-facing arrow and a link with the text "Return to
text". Any CGI program that calls header must also call
this function at the end in order to complete the page's HTML properly.
In Webmin versions 0.92 and above, you can specify multiple link
and text parameters to have the function generate multiple
footer links, like so :
&footer("", "module index", "list.cgi", "users list");
- redirect(url)
- Given a relative or absolute URL, outputs a HTTP header to redirect
the browser to that URL. This function will not work if called after
header, and vice-versa.
- error(message)
- This function is typically used by CGI programs that process the
input from a form, to inform the user of invalid input or some
processing error. It assumes that a global variable called
$whatfailed contains the first part of the error message,
with the parameter being the rest. For example :
$whatfailed = "Failed to save user";
if (!$in{'name'}) { &error("Missing username"); }
if ($in{'name'} =~ /a/) { &error("'$in{'name'}' is not a valid username"); }
- ReadParseMime()
- When writing a CGI program that handles input from a form using
enctype=multipart/form-data this function must be called
instead of ReadParse() to fill the %in array
with form inputs. You must add the enctype tag to any forms
using file-upload inputs.
- hlink(text, page)
(Versions 0.63 and above)
- Returns HTML for a link to a help page. The first parameter is the
text of the link and the second the name of the help page.
See the section on help below for more information.
- tempname()
- Returns a pathname in /tmp that can be used as a temporary
file. The actual filename will always be under the /tmp/.webmin
directory, which is only writable by root but world readable, so if your
temp file is going to contain security-critical information it should be
chowned to mode 700 before writing.
- indexof(value, array)
- Returns the index of some value in an array, or -1 if not found.
- check_ipaddress(string)
- Returns 1 if the given string is a valid IP address like 10.254.1.100,
0 if not.
- urlize(string)
- Converts an arbitrary string to a form suitable for use in a URL. For
example, don't jump! would be converted to
don%27t+jump%21.
- find_byname(name)
- Given a name, searches for processes matching that name and returns
their PIDs. If none are found, an empty list is returned.
- kill_byname(name, signal)
- Given a name, searches for processes matching that name and kills them
with the given signal.
- kill_byname_logged(name, signal)
(Versions 0.91 and above)
- Like the kill_logged function, but also records
the command executed for later logging by webmin_log.
- wait_for(filehandle, [regexp]+)
- Given a perl filehandle and a list of regular expressions, this function
reads from the filehandle until one of the expressions matches. It then
returns the regexp number, and fills the global array @matches
with the values of any bracketed sections of the matching expression.
- has_command(command)
- Searches the PATH for the given command. Returns 1 if found, 0 if not.
- foreign_require(module, file)
(Versions 0.70 and above)
- Before calling functions from another module with foreign_call(),
you must use this function to bring in the appropriate library. The
module parameter is the name of the module you want to call
functions in, and the file parameter the name of a library
file in that module directory.
- foreign_call(module, function, [arg]*)
(Versions 0.70 and above)
- Calls a function in another module, and returns the results. The
module parameter must by the module name, function
the name of the function to call in that module, and any remaining
parameters the arguments to pass to that function. For example :
&foreign_require("proc", "proc-lib.pl");
@procs = &foreign_call("proc", "list_processes");
&foreign_call("proc", "renice_proc", $pid, -10);
The example above calls the proc module to get a list of
processes, and then again to change the priority of some process.
In Webmin versions 0.960 and above, you can use the normal Perl syntax
for calling functions in other modules, like :
&foreign_require("proc", "proc-lib.pl");
@procs = &proc::list_processes();
&proc::renice_proc($pid, -10);
- foreign_config(module)
(Versions 0.70 and above)
- Returns an associative array containing config options from some
other module.
- foreign_check(module)
(Versions 0.70 and above)
- Checks if some other module exists and is supported under the current
operating system. If yes, return 1 - otherwise, returns 0. You should
call this before calling foreign_call to access functions in
other modules.
- get_module_acl([user], [module])
(Versions 0.72 and above)
- Returns a hash containing the ACL for the given user and module.
If no user is specified, the current user is used. If no module is
specified, the caller's module is user. See below for more information
on module ACLs.
- save_module_acl(acl, [user], [module])
(Versions 0.72 and above)
- Saves the given module ACL hash. If no user is specified, the current
user is used. If no module is specified, the caller's module is user.
See below for more information on module ACLs.
- get_system_hostname()
(Versions 0.70 and above)
- Returns the hostname of the system Webmin is running on. More reliable
that the standard Perl hostname() function.
- file_chooser_button(field, type, form)
- Returns HTML for a javascript button that allows the user to select
a file or directory on the server. The parameters are :
- field - The name of the HTML field into which the chosen
filename will be placed.
- type - 0 for a file chooser, 1 for a directory chooser.
- form - The form number containing the field. Typically 0.
- user_chooser_button(field, multiple, form)
(Versions 0.63 and above)
- Returns HTML for a javascript button that allows the user to select
a user or users from those on the server. The parameters are :
- field - The name of the HTML file into which the chosen user
or users will be placed.
- multiple - 0 for selecting a single user, 1 for selecting multiple
users.
- form - The form number containing the field. Typically 0.
- group_chooser_button(field, multiple, form)
(Versions 0.63 and above)
- Just like the user_chooser_button function above, but for the
selection of groups instead.
- http_download(host, port, page, destination, [\error], [\callback])
- Makes a HTTP connection to a webserver host and port to request some
page. The contents of this page are then stored in the destination file.
If the user has configured his Webmin installation to use a proxy
server, then the HTTP request will go through that proxy.
The optional error and callback functions are only supported
in Webmin versions 0.93 and above. If error is supplied, it must
be a reference to a scalar that will be set with an error message if
the download fails, instead of the function simply calling the standard
error function in the case of a failure.
The callback parameter can be a reference to a function that will
be called back to at various stages of the download process. When called,
the first parameter indicates the status, and the second some additional
information. Possible status codes are :
- Server has been contacted
The second parameter is 1 if the requested URL is a redirect, or 0
if a normal file.
- Download has started
The second parameter is the size of the file being downloaded, if
it is known.
- Some data has been received
The second parameter is the amount of data received so far. This will
be called for every 1kb (or less) of data received.
- Download complete
- Redirected to new URL
The second parameter is the new URL to which the request has been
redirected.
If you just want to display the progress of a download in the way that
some of the code Webmin modules do, the standard function
progress_callback can be passed as the 6th parameter to
http_download. However, you must set the global variable
$progress_callback_url to the URL or name of the file being
downloaded, for use in the progress messages.
- ftp_download(host, file, destination, [\error], [\callback])
- Makes an FTP connection to some host and requests the download of
a file. The contents of this file are then stored in the given
destination file. If an FTP proxy is configured, the download will be
made via the proxy.
The optional error and callback parameters are only
supported in Webmin versions 0.93 and above, and behave in exactly
the same way as in the http_download function, documented
above.
- to_ipaddress(hostname)
- Given a hostname, this function returns a string like 10.254.1.100
representing the IP addresss for that hostname.
- generate_icon(image, title, link)
- Outputs HTML for an icon with the given image, title and link. All Webmin
icons should be 48 x 48 pixels, with a transparent background.
- icons_table(\links, \titles, \icons, [columns])
- The main Webmin page and many modules use grids of icons, each linking
to a different option, domain, share or suchlike. This function generates
an icons grid based on the lists given as parameters. links is
a reference to an array of URLs, titles a reference to an
array of messages to appear below icons, and icons a reference
to an array of image URLs.
If a 4th parameter is given, it is taken as the number of icons to
display per row. If unspecified, each row will contain 4 icons.
- replace_file_line(file, line, [newline]*)
- This function removes one line from a file and replaces it with 0 or
more new lines. This is done by reading the entire file into memory
and writing out the modified version.
- read_file_lines(file)
- Returns a reference to an array containing the lines from the given
file, with any newline (\n) characters removed. The caller can then
modify this array by adding, removing or changing lines using functions
like push and splice. flush_file_lines can
then be called to write changes back to the original files.
- flush_file_lines()
- Writes back to disk the arrays of lines for any files requested by
calling the read_file_lines function. A newline (\n) character
is added to each line.
- read_file(file, \array)
- Reads a file in key=value format into the given associative array.
- write_file(file, \array)
- Writes the contents of an associative array to the given file
in key=value format.
- read_env_file(file, \array)
(Versions 0.79 and above)
- Reads a file of /bin/sh variable assignments in key=value or key = "value"
format into the given associative array.
- write_env_file(file, \array, export)
(Versions 0.79 and above)
- Writes the contents of an associative array to the given file
in /bin/sh variable assignment format. If the third parameter is true,
each variable assignment is preceded with export.
- html_escape(string)
- Given a text string, converts the characters <, > and & to
<, > and & respectively.
- trunc(string, length)
- Truncates a string of space-separated words so that it is less than
or equals to the given length, without chopping off part of a word.
- unique([value]+)
- Given a list of values, returns an array with duplicates removed.
- sysprint(handle, [value]+)
- Calls the perl syswrite function to print to the given
filehandle without any buffering.
- include(file)
- Copies the content from the given file to STDOUT.
- copy_data(fromhandle, tohandle)
- Reads from one filehandle and writes to another until the first
runs out of data.
- fast_wait_for(handle, [string]+)
- This function works like wait_for, but matches exact strings
instead of regular expressions.
- make_date(time_t)
- Given a Unix time_t value (seconds since 1970), returns a date-time
string in the format dd/mm/yyyy hh:mm
- get_webmin_version()
(Versions 0.70 and above)
- Returns the version of Webmin this module is running under.
- text(message, [parameter]*)
(Versions 0.75 and above)
- Looks up the given message in the appropriate language translation
file, replaces the text $1, $2 and so on with
the rest of the parameters, and returns the result. See the section
on internationalisation for more.
- encode_base64(string)
(Versions 0.75 and above)
- Returns the given string encoded in base64 format, with a return
at the end of each line.
- get_module_info(name, noclone)
(Versions 0.76 and above)
- Returns a hash containing information about the given module, with the
keys desc, os_support and dir.
If the second parameter is set, details of the underlying module will
be returned when requesting information on a cloned module.
- list_languages()
(Versions 0.76 and above)
- Returns a list of hashes, one for each supported language. This function
is generally for internal use only.
- lock_file(filename)
(Versions 0.81 and above)
- Obtains an exclusive lock on the given file, if necessary waiting until
the lock is released if it is held by another program. Locking is done
by creating a .lock file contain the PID of the process, which
guarantees that locks will not be held forever by dead processes. Locks
can be made on files, directories and symbolic links, and should be made
before any of those are created, modified or deleted.
- unlock_file(filename)
(Versions 0.81 and above)
- Releases a lock grabbed by the lock_file function. If the logging
of file changes is enabled, a diff of the old and new file contents will
be done when this function is called.
- unlock_all_files()
(Versions 0.81 and above)
- Releases all locks currently held by this program, by calling
unlock_file multiple times.
- webmin_log(action, type, object, params)
(Versions 0.81 and above)
- As explained in the Action Logging section below, this function
writes to the detailed logfile the given parameters identifying the
action performed by the calling program.
- system_logged(command)
(Versions 0.81 and above)
- This function is exactly the same as the Perl system statement,
but also records the command executed for later logging by
webmin_log.
- backquote_logged(command)
(Versions 0.81 and above)
- This function is similar to the Perl backquote ` operator in that it
executes the given command and returns its output, but it also records
the command executed for later logging by webmin_log.
- kill_logged(command)
(Versions 0.81 and above)
- This function is exactly the same as the Perl kill statement,
but also records the signal and PIDs for later logging by
webmin_log.
- rename_logged(command)
(Versions 0.81 and above)
- Renames a file like the Perl rename function, but also records
the event for later logging by webmin_log. While you could
just lock the old and new files before renaming, that would generate
two large and rather useless diffs.
- remote_foreign_require(server, module, file)
(Versions 0.82 and above)
- The remote_ series of functions are similar to the
foreign_ functions, but instead of just allowing you to call
code in another module they allow you to call code on another Webmin
server. Each server that you want to call remote functions on must first
be registered in the Webmin Servers module, with the Link type
option set to Login via Webmin and a username and password entered.
Before calling functions from a module on another server with
remote_foreign_call, you must use this function to bring in
the appropriate library. The server parameter is the hostname
of the remote Webmin server, the module parameter is the
name of the module you want to call functions in, and the file
parameter the name of a library file in that module directory.
- remote_foreign_call(server, module, function, [arg]*)
(Versions 0.82 and above)
- Calls a function in some module on another server and returns the results.
You must already have called remote_foreign_require for the
same server and module before trying to use this function. The
function parameter is the name of a function to call in
the remote module, and the parameters after function are
arguments that will be passed to it. For example :
&remote_foreign_require("www.blah.com", "apache", "apache-lib.pl");
@servers = &remote_foreign_call("www.blah.com", "apache", "get_config");
As the example shows, the remote_foreign_call function returns
whatever is returned by the function on the remote server.
- remote_foreign_check(server, module)
(Versions 0.82 and above)
- Checks if a module exists and is supported on a remote Webmin server.
If yes, return 1 - otherwise, returns 0. If in doubt, you should call
this before calling remote_foreign_call to access functions in
other modules on another server.
- remote_eval(server, module, code)
(Versions 0.82 and above)
- Executes some perl code on a remote Webmin server in the context of
the given module. This can be very useful if you want to do something
that is not possible by calling a function with
remote_foreign_call. However, you must first call
remote_foreign_require with the same server and module before
using this function.
- remote_finished()
(Versions 0.82 and above)
- This function should be called by any CGI that makes use of any of the
other remote_ functions once it has finshed calling them, in
order to clean up connections to the remote servers. It is not strictly
necessary though as the connections will timeout after 10 seconds of
inactivity. Also, when using fast RPC this never needs to be called
as remote sessions will exit as soon as your CGI finishes.
- remote_foreign_config(server, module)
(Versions 0.90 and above)
- This function is similar to foreign_config, but is for fetching
module configurations from remote servers instead. Unlike
foreign_config it returns a hash reference rather than a hash.
- remote_write(server, localfile, [remotefile])
(Versions 0.90 and above)
- If when making remote function calls you need to transfer a large amount
of data to a remote server, this function should be used instead of
passing it in a scalar through remote_foreign_call. The
localfile parameter is a file on the server the function is
called on, and the remotefile parameter the name of a file
on the remote server to which the contents of localfile will
be copied. If remotefile is omitted, a random temporary filename
will be chosen instead and returned from the function.
- remote_read(server, localfile, remotefile)
(Versions 0.90 and above)
- This is the opposite of remote_write, in that it copies data
from a file on a remote webmin server into a local file.
- other_groups(user)
(Versions 0.82 and above)
- Returns a list of secondary groups to which some Unix user belongs.
- date_chooser_button(dayfield, monthfield, yearfield, [formno])
(Versions 0.83 and above)
- Returns HTML for a button that when clicked allows the user to select
a date. The dayfield parameter must be the name of a text input
into which the day will be placed, monthfield the name of
select input for the month, and yearfield the name of a text
input for the year. The formno if given is the number of the
form on the current page that contains the inputs.
- seed_random()
(Versions 0.85 and above)
- Seeds the Perl random number generator so that calls to rand
will return truly random results. Uses /dev/urandom if available,
or the current time and process ID otherwise.
- disk_usage_kb(directory)
(Versions 0.86 and above)
- Returns the number of kilobytes used by the given directory and all the
files in it.
- help_search_link(terms, [section]+)
(Versions 0.86 and above)
- Returns HTML for a link to the System Documentation module for
searching for the given terms. The section parameters after the terms
determine what documentation is searched, and each can be one of
- man - Manual pages
- doc - Package documentation
- kernel - Kernel documentation
- howto - HOWTO documents
- kde - KDE documentation
- perl - Perl module documentation
- help - Webmin help
- google - The Google search engine
The return value from this function can be passed as the 7th parameter
to the header function on the main page of your module, creating
a link to additional info in man pages or README files. For example :
&header("The Foo Module", undef, undef, 1, 1, undef,
&help_search_link("foo", "man", "doc", "google"));
- make_http_connection(host, port, ssl, method, page)
(Versions 0.90 and above)
- A general function for making an HTTP connection, possibly using
SSL. The function will attempt to connect to the given host
and port (in SSL mode if the ssl flag is set), through
a proxy server if you have one configured in Webmin. It will then make
an HTTP request using the given method and page,
and return a session handle reference if no errors are encountered.
If any error does occur in the connection, a scalar error string will be
returned.
The returned session handle should be used with the
read_http_connection and write_http_connection functions
to send any additional headers and to read back the response headers
and body. When done, the close_http_connection function should
be called with the session handle.
- read_http_connection(handle, [amount])
(Versions 0.90 and above)
- Reads either a single line from the given session handle, or the specified
number of bytes if the amount parameter is supplied.
- write_http_connection(handle, data, ..)
(Versions 0.90 and above)
- Writes the given data strings to the HTTP session handle.
- close_http_connection(handle)
(Versions 0.90 and above)
- Closes an HTTP session handle created by make_http_connection.
- clean_environment()
(Versions 0.91 and above)
- Deleted from the global environment %ENV all entries set by the Webmin
webserver, such as REMOTE_USER and anything starting with
HTTP_. This should be called before your CGI script starts
a server process such as Apache or Squid, so it doesn't get confused by
environment variables normally only visible to CGI programs.
- reset_environment()
(Versions 0.91 and above)
- Returns the environment to the state it had before the last call to
clean_environment.
- get_theme_info(theme)
(Versions 0.92 and above)
- Like get_module_info, but returns the details of a theme from
it's theme.info file.
- remote_error_setup(function)
(Versions 0.93 and above)
- Normally, when one of the remote_* functions encounters an
error (such as the remote Webmin server being down), it will call
the standard error function which will cause your CGI program
to exit. However, if you use this function to register an alternate
error handler, your error handler will be called instead, and the
remote function will return.
- switch_to_remote_user()
(Versions 0.93 and above)
- This function should only be called by code in Usermin modules, and
will switch the UID and GID of the current process to those of the Unix
user whose login matches the current Usermin login. If your Usermin
module can run with normal user permissions (and most can), you should
call this function after init_config in your module's library.
In addition to switching the UID, this function also sets the global
variable @remote_user_info to the details of the Unix user,
as returned by the getpwnam Perl function.
- create_user_config_dirs()
(Versions 0.93 and above)
- In Usermin, modules cannot store persistent configuration data
in their configuration directory $module_config_directory because it is only writable by root. If you code wants to store settings on
a per-user basis, it should call this function which will set the
global variable $user_module_config_directory to
~currentuser/.usermin/modulename and ensure that the directory exists.
The files defaultuconfig in the module's directory,
uconfig in the module configuration directory under
/etc/webmin and config in the user's module configuration
directory will be read in that order into the global hash
%userconfig. See the Usermin section of this documentation for
more details.
- filter_javascript()
(Versions 0.93 and above)
- Given the HTML for an entire webpage, this function attempts to strip out
or disable all Javascript and returns the result. If your module displays
HTML from an untrusted source (such as an email message or file on the
server), it should call this function on the HTML in order to remove the
potential security risk of malicious Javascript, which could capture the
session key for the current Webmin login.
- read_file_cached(filename, \hash)
(Versions 0.950 and above)
- Like the standard read_file function documented above, but keeps
a cache of files read in order to avoid reading them multiple times.
Mostly for internal use at the moment.
- get_all_module_infos()
(Versions 0.950 and above)
- Returns a list of hash references, each containing the details of one
installed module in the same format as returned by the standard
get_module_info function. In order to avoid having to read one
file from each module, this function caches the module details in the
file /etc/webmin/module.infos.cache, which can be read much
faster.
- resolve_links(file)
(Versions 0.950 and above)
- Given a filename that may contain symbolic links somewhere in it's path,
returns the actual real filename that it refers to. Unlike the Perl
readlink function, this also resolves symbolic links in
directories along the path as well.
- same_file(file1, file2)
(Versions 0.950 and above)
- Returns 1 if two filenames refer to the same actual file, by comparing
inode numbers.
- flush_webmin_caches()
(Versions 0.980 and above)
- Clears all the in-memory and on-disk caches used by web-lib.pl. This
function is really for internal use only.
Javascript Functions
The functions listed in this section are defined in the library
javascript-lib.pl, which is included with Webmin versions
0.950 and above. These functions were generously contributed by
John Smith
<john.smith@mscsoftware.com>.
You can see examples of these functions in action by downloading
and installing the javascript-lib.pl
samples webmin module, which shows what each function does.
Table of Contents
- jroll_over
- This gives you simple mouse over functions on graphics and includea a link.
- Parameters
- &jroll_over("url", "name", "border", "imgoff", "imgon");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jroll_over("http://www.mscsoftware.com", "mscbutton", "0", "images/msc_off.gif", "images/msc_on.gif");
|
- jimg_preload
- Preloads any number of given images.
- Parameters
- &jimg_preload("image", "image", "image", "etc");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jimg_preload("image/1.gifi", "imgage/u.gif", "images2/button.jpg", "images2/logo.png");
|
- jimg_update
- Updates any image on your page that has a name associated with it.
- Parameters
- &jimg_update("name", "image");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jimg_update("mscimage", "images/new_logo.jpg");
|
- janim
- Builds an Animation with any given list of images.
- Parameters
- &janim("name", "speed", "image", "image", "image", "etc")
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &janim("mscanim1", "1250", "images/1.gif", "images/slide.png", "images/logofin.jpg")
|
- janim_start
- Starts the animation you built with janim.
- Parameters
- &janim_start("name");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &janim_start("mscanim1");
|
- janim_stop
- Stops the animation you built with janim.
- Parameters
- &janim_stop("name");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &janim_stop("mscanim1");
|
- jalert
- Launches an alert dialog box with a custom message.
- Parameters
- &jalert("message");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jalert("Your alert message!");
|
- jwindow
- Opens a window with a given URL.
- Parameters
- &jwindow("url", "name", "width", "height");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jwindow("http://www.msclinux.com", "msclinux", "800", "600");
|
- jwindow_xy
- Repostitions a named windows position on the users screen.
- Parameters
- &jwindow_xy("name", "x", "y");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jwindow_xy("msclinux", "250", "120");
|
- jterminal
- Creates an empty plain text window for writing data to.
- Parameters
- &jterminal("name", "width", "height");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jterminal("mscterm", "100", "300");
|
- jwrite
- Write data to a created window or terminal.
- Parameters
- &jwrite("name", "data");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jwrite("mscterm", "Download MSC.Linux from http://www.msclinux.com");
|
- jtext
- Simple text rollovers between two colors.
- Parameters
- &jtext("text", "offcolor", "oncolor");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &jtext("MSC.Linux Rules!", "red", "#F1F1F1");
|
- jtalkback
- Builds a JavaScript for a pop-up talkback/bug report window.
- Parameters
- &jtalkback();
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &header($text{'index_title'}, "", undef, 1, 1);
- &jtalkback();
|
- jerror
- Launches the jtalkback window upon execution.
- Parameters
- &jerror("title", "email", "width", "height", "errmsg", "url", "erroredonline");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &header($text{'index_title'}, "", undef, 1, 1);
- &jtalkback();
- @somedata = `cat msclinux.log` or &jerror("MSC.Linux Bug Report", \
- "john.smoth\@some.email.com", "400", "300", $!, $0, __LINE__);
|
- jtalkback_link
- Creates a button or text link to launch the jtalkback window.
- Parameters
- &jtalkback_link("title", "email", "width", "height", "text", "type");
- Code Example
- #!/usr/bin/perl
- require '../javascript-lib.pl';
- &header($text{'index_title'}, "", undef, 1, 1);
- &jtalkback();
- &jtalkback_link("Bug Report Window", "totheadmin\@help.desk.com", 400, 300, "Text Link", 0);
- &jtalkback_link("Bug Report Window", "totheadmin\@help.desk.com", 400, 300, "Button", 1);
|
Module Configuration
Almost all modules have a set of configuration parameters, available
to module CGI programs in the %config array. When Webmin is
installed, a config file appropriate for the chosen operating system
is copied from the module directory to the Webmin configuration
directory for that module, typically something like
/etc/webmin/foobar/config.
The associative array %gconfig contains global configuration
options, typically from the file /etc/webmin/config. Some useful
global configuration options are :
- os_type
- The operating system type selected in setup.sh, such as
solaris or redhat-linux.
- os_version
- The operating system version selected in setup.sh, such as
2.5 or 5.1
- path
- The Unix path for this operating system, as a : separated list of
directories.
Many modules deal with the configuration of some service that is
mostly the same on different operating systems. Apache for example
works exactly the same under Solaris and Redhat Linux - the only difference
is the standard location of the Apache config files. In the Webmin Apache
module the Apache config file directory is itself a configurable parameter
that is initially set based on the operating system chosen.
Configuration parameters can also be used for options that the
user may want to occasionally change. For example, the BIND module
has a parameter that controls for format of new DNS zone serial numbers.
When the 4th parameter of the header() function is set, a link
will be generated to a CGI program that allows the user to edit the
configuration of the current module. This program reads the file
config.info in the module directory to determine the
possible values for each config parameter. A typical config.info
file might look like :
foobar_path=Path to foobar config file,0
display_mode=Index page display mode,1,0-Long,1-Medium,2-Short
password_file=Foobar server users file,3,None
file_user=Config files are owned by user,5
Each line is in the format
config_name=description,type[,values]
The meanings of the parts of each line are :
- config_name
The name of a parameter in the module configuration that this line
will apply to.
- description
A description of this parameter for the user.
- type
A number that determines how this parameter can be chosen. Possible values
are
- 0 - Free text. Any value can be entered by the user
- 1 - One of many. The user can choose one of several options.
For this type, the values part of the line is a
comma-separated list of value-display pairs.
The value part of each pair is what gets stored in the
config file, while the display part is what is shown to
the user.
- 2 - Many of many. The user can choose zero of more of several
options. Available options are specified in the same way as type 2.
- 3 - Optional free text. The user can either select the default
option, or enter some value. The values part of the line
is the description of the default option (typically something
like 'None' or 'Default mode')
- 4 - One of many. The same as type 1, but uses a menu instead of
a row of radio buttons
- 5 - Unix user. Displays a list of users from the host Webmin
is running on.
- 6 - Unix group. Displays a list of groups from the host Webmin
is running on.
- 7 - Directory. Like the free text input, but with a directory
chooser next to it.
- 8 - File. Like the free text input, but with a file chooser next
to it.
- 9 - Multiline free text. The first value after the type is
the width of the input, and the second the height.
Not every config parameter needs an entry in config.info - only those
that the user may want to edit.
When a module is installed (either as part of a Webmin distribution or
separately) a config file appropriate to the OS being used is copied from
the module directory to the configuration directory (usually under
/etc/webmin). To decide which base config file to use, Webmin
uses the OS name and version chosen when setup.sh was run to
look for the following files
config-osname-osversion
config-osname
config
Where osname is something like redhat-linux or solaris,
and osversion is something like 2.6 or 5.0.
A typical module might have the following config files
config-redhat-linux
config-redhat-linux-5.0
config-slackware-linux
config-debian-linux
config-solaris
Webmin treats each of the Linux distributions as a different OS,
as each has different locations for things like the Apache config file,
crontab files and bootup scripts. The OS version number for Linux should
be the distribution version (such as 4.1 or 5.0) rather than the kernel
version.
Look and Feel
All Webmin modules should have the same general colour scheme, look and feel
as defined by the following rules:
Design Goals
A typical Webmin module is written to configure some Unix service, such
as Apache, Squid or NFS exports. Most Unix servers are configured by
editing some text file, which may have a complex format. Any Webmin module
that modifies some configuration file must be able to parse all
possible options in such a config file - even if not all options are
presented to the user.
No module should ever corrupt a service config file or remove options that
it does not understand. Modules should be able to parse any valid configuration
without requiring special comments or a special format. If your module cannot
deal with some option in a config file, it should be left alone.
Webmin modules should be designed to be easy for novices to use, but still
allow the user to do almost everything that could be done by editing the
config file directly.
Online Help
Webmin versions 0.63 and above now have support for context-sensitive help.
The hlink function outputs HTML for a link to a CGI program that
processes a given help page. Help pages are stored in the help
subdirectory under the module directory, and are named simple page.html.
So a call to hlink like
print &hlink("Enter username:", "name"),
"<input name=username size=20><p>\n";
would output a link to display the help page help/name.html.
Per-Module ACLs
Webmin versions 0.72 and above support a standard method for restricting
which features of a module a user can access. For example, the Apache module
allows a Webmin user to be restricted to managing selected virtual servers,
and the BIND module allows user to be limited to editing records only in
certain domains.
Module ACL options are set in the Webmin Users module by clicking on
the name of a module next to a user's name. The options available are generated
by code from the module itself (except for the Can edit module
configuration? option, which is always present). When the user clicks
on Update the form parameters are also parsed by code from the module
being configured, before being saved in the Webmin config directory.
A module wanting ACL options must contain a file called acl_security.pl
in its directory. This file must contain two perl functions :
- acl_security_form(acl)
- This function takes a reference to a hash containing the current ACL
options for this user, and must output HTML for form inputs to edit
those ACL options. Because the HTML will be inside a 4-column table,
you must generate the appropriate <tr> and <td> tags around
your input elements.
- acl_security_save(acl, inputs)
- This function must fill in the given hash reference with values from the
form created by acl_security_form. Form inputs are available
in the global hash %in as generated by ReadParse, or
from the second parameter to the function.
Because these functions are called in the context of your module, the
acl_security.pl file can require the common functions
file used by other CGI programs in your module. This gives you access
to all the standard Webmin functions, and allows you to provide more
meaningful inputs. For example, when setting ACL options for the Apache
module a list of virtual servers from the Apache config is displayed for
the user to select from.
An example acl_security.pl might look like :
do 'foo-lib.pl';
sub acl_security_form
{
print "<tr> <td><b>Can edit users?</b></td>\n";
printf "<td><input type=radio name=edit value=1 %s> Yes\n",
$_[0]->{'edit'} ? 'checked' : '';
printf "<input type=radio name=edit value=0 %s> No</td> </tr>\n",
$_[0]->{'edit'} ? '' : 'checked';
}
sub acl_security_save
{
$_[0]->{'edit'} = $in{'edit'};
}
If a user has not yet had any ACL options set for a module, a default
set of options will be used. These are read from the file defaultacl
in the module directory, which must contain name=value pairs
one per line. These options should allow the user to do anything, so that
the admin or master Webmin user is not restricted by default.
To actually enforced the chosen ACL options for each user, your module programs
must use the get_module_acl function to get the ACL for the current
users, and then verify that each action is allowed. When called with no
parameters this function will return a hash containing the options set for
the current user in the current module, which is almost always what you want.
For example :
#!/usr/local/bin/perl
require 'foo-lib.pl';
%access = &get_module_acl();
$access{'create'} ||
&error("You are not allowed to create new foo users");
When designing a module that some users will have limited access to, remember
the user can enter any URL, not just those that you link to.
For example, just doing ACL checking in the program that displays a form
is not enough - the program that processing the form should do all the same
checks as well. Similarly, CGI parameters should never be trusted, especially
hidden parameters.
User Update Notification
Since version 0.72 it has been possible to have the Users and Groups
module notify your module when a Unix user is added, updated or deleted.
This can be useful if your module deals with additional information that is
associated with users. For example, the Disk Quotas module sets
default quotas when new users are created, and the Samba Windows File
Sharing module keeps the Samba password file in sync with the Unix user
list.
To have your module notified when a user is added, updated or deleted you
must create a perl script called useradmin_update.pl in your
module directory. This file must contain three perl functions :
- useradmin_create_user(user)
- This function is called when a new Unix user is created. The parameter
is a hash containing the details of the new user, described in more detail
below.
- useradmin_modify_user(user)
- This function is called when an existing Unix user is modified in any
way. The parameter is a hash containing the new details of the user.
- useradmin_delete_user(user)
- This function is called when a Unix user is deleted. Like the other
functions, the hash containing the user's details.
The hash reference passed to each of the three functions has the following
keys :
user |
The login name of the new or modified user |
uid |
The Unix UID of the user |
gid |
The Unix GID for the user's primary group |
pass |
The user's password, encrypted with the crypt() function |
plainpass |
The user's password in plain text. This is only available when the
passmode key is equal to 3 |
passmode |
This number depends on the choice made for the Password field
in the Create User or Edit User form.
- No password is set for this user, typically meaning that no
password is required to login
- This user is not allowed to login at all
- Only the encrypted password for this user is available
- A new or initial plain-text password is available in the
plainpass key.
- The user's password is unchanged. Only possible when
useradmin_modify_user is called.
|
real |
The user's real name |
home |
The user's home directory |
shell |
The user's login shell |
If the system has shadow passwords enabled, other keys may also be available -
but it is not a good idea to rely on them.
When your functions are called, they will be in the context of your module.
This means that your useradmin_update.pl script can require
the file of common functions used by other CGI programs. The functions can
perform any action you like in order to update other config files or whatever,
but should not generate any output on STDOUT, or take too long to execute.
A partial example useradmin_update.pl might look like :
do 'foo-lib.pl';
sub useradmin_create_user
{
local $lref = &read_file_lines($users_file);
push(@$lref, "$_[0]->{'user'}:$_[0]->{'pass'}");
&flush_file_lines();
}
Internationalisation
Webmin versions 0.75 and above provide module writers with functions
for generating different text and messages depending on the language
selected by the user. Each module that wishes to use this feature should
have a subdirectory called lang which contains a translation file
for each language supported. Each line of a translation file defines
a message in that language in the format :
message_code=Message in this language
The default language for Webmin is english (code en), so every module
should have at least a file called lang/en. If any other language
is missing a message, the english one will be used instead. Check the file
lang_list.txt for all the languages currently supported and their
codes. To change the current language, go into the Webmin Configuration
module and click on the Language icon.
When your module calls the init_config function, all the messages
from the appropriate translation file will be read into the hash %text.
Thus instead of generating hard-coded text like this :
print "Click here to start the server :<p>\n";
Your module should use the %text hash like this :
print $text{'startmsg'},"<p>\n";
Messages from the appropriate file in the top-level lang directory
are also included in %text. Several useful messages such as
save, delete and create are thus available to
every module.
In some cases, you may want to include some variable text in a message.
Because the position of the variable may differ depending on the language
used, message strings can include placemarkers like $1,
$2 or $3. The function text should be used
to replace these placemarkers with actual values like so :
print &text('servercount', $count),"<p>\n";
Your module's module.info file can also support multiple languages
by adding a line like desc_XX=module description for each language,
where XX is the language code. You can also have a separate
config.info file for each language, called config.info.XX
where XX is the language code, and separate help files for each
language, named like intro.XX.html. In all cases, if there is no
translation for the user's chosen language then the default (english)
will be used instead.
Adding New Languages
New translations of the existing core Webmin modules are always welcome. If
you want to translate Webmin into a new language or update one of the
existing translations, follow these steps :
- Get the latest development
version so that you can see the latest translations that have been
done by other people.
- In the file lang_list.txt in the Webmin root directory, add a new
line for your language like :
lang=sw,titles=1,charset=iso-6666-6 Swahili
The lang= part defines the short code for the language, and should follow
the ISO standard where possible. The titles= part controls whether Webmin
should use letter images for displaying page titles in the language,
and should be set to 1 if your language uses european characters.
The optional charset= part sets the character set that is sent to the
web browser when using the language, so that is can automatically select
the right font to use.
- Switch to your new language in the Webmin Configuration module under
the Language icon.
- In the directory lang under the Webmin root and in each of the
lang subdirectories under the module directories, create a new
file called sw (or whatever the short code for your language is)
that is a translation of the en file in the same directory.
- In each of the module.info files under the module directories,
add a new desc_sw= line that is a translation of the desc= line.
- In each of the module directories, create a new file called
config.info.sw which is a translation of config.info
(if it exists).
- In the help subdirectory under each of the module directories
(where they exist), translate all of the something.html
files into something.sw.html.
A table of currently translated languages is available
so that you can see how much has been done for each language and module so
far. There is also a list of other translators that
you might want to contact before doing your own translation work.
You don't have to finish translating the entire of Webmin for your
translation to be useful. Many people just do a few modules at a time, or
skip the help pages initially.
When your translation has made some progress, send me a .tar.gz file of
all the translated files at jcameron@webmin.com so that I can include it in the
main Webmin distribution. The best way to tar up everything is with the
command :
tar czf /tmp/translation.tar.gz */lang/sw lang/sw */module.info */config.info.sw */help/*.sw.html
Translators may also find the follow programs usedful :
Module Packaging
The Webmin Configuration module allows the user to add a new module to their
existing setup. Modules must be packaged as an uncompressed Unix TAR file
containing one or more modules. Each module in the TAR file must have all its
files in one subdirectory - for example, a module TAR file might look like :
drwxrwxr-x 3001/10 0 Aug 12 21:53 1998 dfsadmin/
drwxrwxr-x 3001/10 0 Nov 7 01:10 1997 dfsadmin/images/
-rw-rw-r-- 3001/10 245 Aug 1 23:41 1998 dfsadmin/images/icon.gif
-rw-rw-r-- 3001/10 1438 Aug 1 23:41 1998 dfsadmin/images/dfsadmin.gif
-rw-rw-r-- 3001/10 1541 Aug 1 23:41 1998 dfsadmin/images/create_share.gif
-rw-rw-r-- 3001/10 1265 Aug 1 23:41 1998 dfsadmin/images/edit_share.gif
drwxrwxr-x 3001/10 0 May 16 18:32 1997 dfsadmin/test/
-rw-r--r-- 3001/10 493 May 16 18:32 1997 dfsadmin/test/dfstab
-rw-r--r-- 3001/10 483 May 16 18:15 1997 dfsadmin/test/dfstab.bak
-rw-rw-r-- 3001/10 2774 Jul 29 22:22 1998 dfsadmin/dfs-lib.pl
-rwxr-xr-x 3001/10 1582 Mar 31 15:45 1998 dfsadmin/index.cgi.bak
-rw-rw-r-- 3001/10 49 Aug 12 21:53 1998 dfsadmin/module.info
-rwxr-xr-x 3001/10 1596 Mar 31 15:45 1998 dfsadmin/index.cgi
-rw-rw-r-- 3001/10 2775 Jul 29 22:22 1998 dfsadmin/dfs-lib.pl.bak
-rw-rw-r-- 3001/10 199 Mar 5 19:30 1998 dfsadmin/help.html
-rw-rw-r-- 3001/10 175 Mar 5 19:30 1998 dfsadmin/config.info
-rw-r--r-- 3001/10 140 Mar 5 19:30 1998 dfsadmin/config-solaris
-rwxr-xr-x 3001/10 142 Mar 5 19:30 1998 dfsadmin/delete_share.cgi
-rwxr-xr-x 3001/10 4842 Mar 5 19:30 1998 dfsadmin/edit_share.cgi
-rwxr-xr-x 3001/10 657 Jun 8 15:02 1998 dfsadmin/restart_sharing.cgi.bak
-rwxr-xr-x 3001/10 3000 Mar 5 19:30 1998 dfsadmin/save_share.cgi
-rw-rw-r-- 3001/10 57 Aug 12 21:53 1998 dfsadmin/module.info.bak
-rwxr-xr-x 3001/10 573 Jun 8 15:02 1998 dfsadmin/restart_sharing.cgi
The standard extension for Webmin modules is .wbm, but any filename
can be used.
Webmin modules can also be packaged as RPMs, which are suitable for installing
on servers on which the RPM version of Webmin itself is already installed.
I have created a script called makemodulerpm.pl
that can package up an module directory into an RPM by creating the spec
file automatically.
File Locking
Webmin version 0.81 introduced several new common functions for locking files
to prevent multiple programs from writing to them at the same time. Module
programmers should make use of these functions in order to prevent the
corruption or overwriting of configuration files in cases where two users
are using the same module at the same time.
Locking is done by the function lock_file, which takes the name of
a file as a parameter and obtains and exclusive lock on that file by creating
a file with the same name but with .lock appended. Similarly, the
function unlock_file removes the lock on the file given as a parameter.
Because the .lock file stores the PID of the process that locked
the file, any locks a CGI program holds will be automatically released when
it exits. However, it is recommended that locks be properly released by calling
unlock_file or unlock_all_files before exiting.
The following code shows how the locking functions might be used :
&lock_file("/etc/something.conf");
open(CONF, ">>/etc/something.conf");
print CONF "some new directive\n";
close(CONF);
&unlock_file("/etc/something.conf");
Locking should be done as soon as possible in the CGI program, ideally before
reading the file to be changed and definately before writing to it. Files can
and should be locked during creation and deletion as well, as should
directories and symbolic links before creation or removal. While this is
not really necessary to prevent file corruption, it does make the logging of
file changes performed by the program more complete, as explained below.
Action Logging
Also in Webmin 0.81 is support for detailed logging by CGI programs of
the actions performed by users for later viewing in the Webmin Actions Log
module. While previous versions wrote a HTTP logfile to
/var/webmin/miniserv.log, this did not contain the information
required to work out exactly what each Webmin user had been doing. To improve
on this, Webmin now logs detailed information to the file
/var/webmin/webmin.log and optionally to files in the directory
/var/webmin/diffs. Note that nothing will be recorded in this file
if logging is not enabled in the Webmin Configuration module.
The function webmin_log should be called by CGI programs
after they have successfully completed all processing and file updates.
The parameters taken by the function are :
- action - The action the program has performed. Usually
something like 'save' or 'delete'.
- type - The type of thing effected by the program. Often
something like 'user' or 'group', though can be left blank if
not appropriate.
- object - The name of the thing effected, such as 'jcameron'
or 'root' or 'www.foobar.com'.
- parameters - A reference to a hash containing additional
information that the program wants to log. Often just passing
\%in is useful.
All of these parameters can contain any information you want, as they are
merely logged to the detail logfile and not interpreted by webmin_log
in any way.
For example, a module might call the function like this :
&lock_file("/etc/foo.users");
open(USERS, ">>/etc/foo.users");
print USERS "$in{'username'} $in{'password'}\n";
close(USERS);
&unlock_file("/etc/foo.users");
&webmin_log("create", "user", $in{'username'}, \%in);
Because the raw logfiles are not easy to understand, Webmin also provides
support for converting detailed action logs into human-readable format.
The Webmin Actions Log module makes use of a Perl function in the file
log_parser.pl in each module subdirectory to convert logs records
from that module into a readable message.
The file must contain the function parse_webmin_log, which is
called once for each log record for this module. It will be called with
the following parameters :
- user - The Webmin user who run the program that generated
this log record.
- script - The filename of the CGI script that generated
this log, without the directory.
- action - Whatever was passed as the action
parameter to webmin_log to create this log record.
- type - Whatever was passed as the type
parameter to webmin_log.
- object - Whatever was passed as the object
parameter to webmin_log.
- parameters - A reference to a hash the same as the one
passed to webmin_log.
- long - If non-zero, this indicates that the function is
being called to create the description for the Action
Details page, and thus can return a longer message than
normal. You can ignore this if you like.
The function should return a text string based on the parameters passed to
it that converts them into a readable description for the user. For example,
your log_parser.pl file might look like :
require 'foo-lib.pl';
sub parse_webmin_log
{
local ($user, $script, $action, $type, $object, $params, $long) = @_;
if ($action eq 'create') {
return &text('log_create', $user);
}
elsif ($action eq 'delete') {
return &text('log_delete', $user);
}
}
Because the log_parser.pl file is read and executed in a similar way
to how the acl_security.pl file is handled by the Webmin Users
module, it can require the module's own library of functions just
like any module CGI program would. This means that the &text
function and %text hash are available for accessing the module's
translated text strings, as in the example above.
Webmin can also be configured to log exactly what file changes have been
made by each CGI program before calling webmin_log. Under
Logging in Webmin Configuration there is an option marked
Log changes made to files by each action which when enabled will
cause the webmin_log function to use the diff command to
find changes made to any file locked by each program.
When logging of file changes is enabled, the Action Details page
in the actions log module will show the diffs for all files updates, creations
and deletions by the chosen action. If locking of directories and symbolic
links is done as well, it will show their creation and modification as
well.
As well as having their file changes logged, programs can also use the
common functions system_logged, kill_logged and
rename_logged which take the same parameters as the Perl
system, kill and rename functions, but also
record the event for viewing on the Action Details page. There is also
a backquote_logged function which works similar to the Perl backquote
operator (it takes a command an executes it, returning the output), but also
logs the command. If these functions are used they must be called before
webmin_log for the logging to be actually recorded, as in this
example :
if ($pid) {
&kill_logged('TERM', $pid);
}
else {
&system_logged("/etc/init.d/foo stop");
}
&webmin_log("stop");
Pre and Post Install Scripts
Webmin versions 0.990 and above allow modules to contain perl scripts
that will be run after a module is installed and before it is uninstalled.
If your module contains a file called postinstall.pl, the perl function
module_install in this file will be called after the install
of your module is complete. Because it is executed in the module's directory,
it can make use of the common functions library, like so :
require 'yourmodule-lib.pl';
sub module_install
{
system("cp $module_root_directory/somefile $config_directory/somefile")
if (!-r "$config_directory/somefile");
}
The function will be called when a module is installed from the
Webmin Configuration or Cluster Webmin Servers modules. However, it is not
called if the install-module.pl script is used.
Similarly, if your module contains a file called uninstall.pl, the
perl function module_uninstall in that file will be called just
before the module is deleted. This can happen when it is deleted
using the Webmin Users or Cluster Webmin Servers modules, or when the entire
of Webmin is uninstalled. The uninstall function should clean up any
configuration that will no longer work when the module is uninstalled, such
as cron jobs that reference scripts in the module.
Creating Themes
Webmin versions 0.83 and above support themes, which are sets of alternate user
interfaces, graphics and colour schemes. A user can choose which theme he
wants by going into Webmin Configuration and clicking on Webmin Themes. Multiple
themes can be installed, but only one can be active at any one time - or if no
theme is active, the default colours and layout are used.
Like a module, a theme is a directory under the Webmin root directory that
contains certain files. The most important is the theme.info file,
which has the same format as the module.info file - name=value entries, one per line. Required names and their values are:
- desc
- A description for this theme, such as My Webmin Theme.
This is the text that will appear in the theme selection menu.
A theme can also contain a config file, also in name=value format. The values defined in this file control the behaviour
of the standard header and footer functions.
Supported names and their values are:
- cs_page
- A six-character hex string in RRGGBB format for the background
colour of Webmin pages.
- cs_link
- A six-character hex string in RRGGBB format for the colour of
visited and unvisiting links on Webmin pages.
- cs_text
- A six-character hex string in RRGGBB format for the colour of
normal text.
- bgimage
- A relative URL (like images/background.gif) for a
background image to be displayed on all pages.
- noindex
- If set to 1, the HTML generated by the header function
will not include a Webmin Index link. Useful if another
frame is used for the main index.
- brand
- HTML for an image or text to be displayed in the top-right corder
of the main index page.
- brand_url
- A URL to which the brand image is linked. These two options
are usually combined to create a company icon that links to its
homepage in customised versions of Webmin.
- headhtml
(Versions 0.86 and above)
- HTML that will be included inside the <head> section of
each Webmin page.
- headinclude
(Versions 0.86 and above)
- The name of a file in your theme directory whose contents will be
included inside the <head> section of each page.
- inbody
(Versions 0.86 and above)
- Text that will be included inside the <body> tag itself.
- prebody
(Versions 0.86 and above)
- HTML that will be included at the top of the <body> section
of each page. The following substitutions will be done in the HTML :
- %HOSTNAME% will be replaced with the system's hostname.
- %VERSION% will be replaced with the webmin version.
- %USER% will be replaced with the current user's login.
- %OS% will be replaced with the OS name and version.
- texttitles
(Versions 0.86 and above)
- If set to 1, the titles on all pages will be displayed as HTML
text rather than using letter images.
- postbody
(Versions 0.86 and above)
- HTML that will be included at the bottom of the <body>
section on each page. The same substitutions as prebody
are done.
- tb
(Versions 0.86 and above)
- Text that will be included inside the <tr> tag in table
header rows.
- cb
(Versions 0.86 and above)
- Text that will be included inside the <tr> tag in table
rows below the header.
- functions
(Versions 0.92 and above)
- The name of a file in your theme's directory that contains
perl functions for overriding the default header,
footer and error functions. See below for
more details.
- noicons
- If set to 1, the standard generate_icon and
icons_table functions will display only a name instead
of an icon. This can be useful if your theme is designed for
text-only or low bandwidth use.
In addition to changing the default colours, a theme can be used to
selectively override any icon or CGI program used by Webmin. When a theme
is chosen, its directory becomes an 'overlay' root directory for the Webmin
webserver. Thus, if your theme subdirectory contains a file called
images/newlogo.gif, it will replace the logo on the main menu
when it is displayed, because the webserver will look in the theme directory
first before looking for images/newlogo.gif under the top-level
directory.
In this way any of the module icons can be overridden, as can the images
used to make up the titles at the top of pages. For example, if your
theme directory contained a file called useradmin/images/icon.gif, it
would be used as the icon for the Users and Groups module on the main menu.
Because this 'replacement' does not actually change the real images, the user
can switch between themes or back to the default theme easily.
CGI programs can also be overriden as well, in exactly the same way. This
can be used to do things like changing the way the main menu is displayed,
by putting a custom index.cgi script in your theme directory. However,
this ability should be used carefully as changes to the real CGIs may break
your custom script if its behaviour is different to the one it replaces.
Also, note that when a theme CGI is executed, it will be in the real directory
and not the theme subdirectory. For example, this means that a custom top-level
index.cgi script would have to require ./web-lib.pl instead
of ../web-lib.pl, just as the real index.cgi does.
In Webmin versions 0.92 and above, a theme can override some of the common
HTML-generating functions by adding a line like functions=theme.pl
to the config file and creating a theme.pl script
in the theme's directory containing one or more of the following functions :
- theme_header
This function will be called instead of the standard header
function, with all the same parameters. It must handle all those
parameters properly, and output whatever HTML you want to use for
the page titles and so on.
- theme_footer
Called instead of the standard footer function, with the
same parameters. If your theme_header function opens an HTML
table for layout purposes, this function must close it so that the HTML
is properly complete.
- theme_error
Called instead of the standard error function, with the same
parameters.
These functions give you a lot of power to create themes that significantly
change the Webmin layout. However, for them to work properly they must
handle all the parameters that they are passed in exactly the same way that
the standard functions do.
The final part of creating a theme is packaging it. Just like module, themes
are packaged as a tar file of the theme directory, usually with a .wbt
extension. They can then be installed through the Webmin Themes page.
Creating Usermin Modules
Usermin has a very similar architecture to Webmin, and so its modules
have an almost identical design to Webmin modules. The main difference is that
Usermin is designed to be used by any Unix user on a server to perform tasks
that they could perform from the command line. Any third-party Usermin modules
should be written with this in mind.
By default, module CGI programs are run as root, just like in
Webmin. This is necessary because some tasks (like changing passwords)
can only be done as root. However, most Usermin modules do not
need superuser privileges and so should call the standard
switch_to_remote_user function just after calling init_config
, in order to lower privileges to those of the logged-in user.
Usermin module can have global configuration variables that are initially
set from the config or config-ostype file in the
module directory, and are available in %config. However, these
variables are never editable by the user - they can only be set in the
Usermin Configuration module of Webmin.
Per-user configurable options are supported though, using a different
mechanism. When the standard create_user_config_dirs function
is called, the global hash %userconfig will be filled with values
from the following sources, with later sources overriding earlier ones :
- The defaultuconfig file in the module directory
This should contain the default options for this module for all users,
to be used if no other settings are made by the user or sysadmin.
- The file /etc/webmin/modulename/defaultuconfig
This contains defaults for the module on this system, as set by the
sysadmin using the second part of the 'Usermin Module Configuration'
feature in the 'Usermin Configuration' Webmin module.
- The file ~username/.usermin/modulename/config
This contains options chosen by users themselves.
The editors for the system-wide and per-user configuration variables are
defined by the uconfig.info file in the module directory. This file
has the exact same format as the config.info file used for Webmin
and Usermin global configuration, explained elsewhere in this document.
If you create your own Usermin module, it should be packaged in exactly
the same way as a Webmin module (as a .tar or .tar.gz file). However, the
module.info file must contain the line usermin=1 so that
it cannot be installed into Webmin where it would not work properly.
Webmin APIs for Other Programming Languages
Even though most Webmin modules are written in Perl, it is possible to
use other languages to write CGI programs that run under the Webmin
webserver. In order to make this easier, other people have started porting
the web-lib.pl API to other languages, like Python and PHP.
A Python implementation of
the Webmin API is available, developed by Peter Åstrand. Currently this
is still under development.
A PHP replacement for web-lib.pl is also available,
developed by Nicolas Faurant. I'm not sure what the devlopment status of
this API is at the moment.
API Changes
- Version 0.990
- Added support for pre and post install module scripts.
- Added the noicons theme config option.
- Version 0.980
- Added the flush_webmin_caches function.
- Version 0.970
- The remote_read and remote_write functions have
been sped up to use direct TCP transfers when communicating with
Webmin 0.970 or above servers.
- The http_download function now has a new status code 5 that
it can pass to the callback function when doing a redirect.
- Version 0.960
- Added the read_file_cached, get_all_module_infos
resolve_links and same_file functions.
- Foreign calls and requires are now faster, due to the elimination
of unnecessary chdir calls. This should have no effect
on module code that calls these functions however.
- The foreign_call function does not have to be used.
Instead, you can just use the normal Perl syntax for calling
functions in other modules, like &module::function(args)
instead of &foreign_call("module", "function", args).
- All useradmin_update.pl, log_parser.pl and
acl_security.pl scripts that want to use functions from
their module's library must require it with the statement :
do 'foo-lib.pl';
This is a side-effect of the speedup in the foreign_call
function.
- The code that displays the webmin main menu and categories now caches
all the module.info files, so that it does not have to
read them all so often. However, this means that module developers
who edit their own module.info file may not see the change
take effect until they flush the cache by deleting
/etc/webmin/module.infos.cache.
- Version 0.93
- Added the remote_error_setup function.
- Added the progress_callback function, and an additional
parameter to http_download to make use of it.
- Added the Usermin-specific switch_to_remote_user and
create_user_config_dirs functions.
- Added the filter_javascript function.
- Version 0.92
- Added support for theme functions to override header,
footer and error.
- The footer function can now create multiple return links.
- Added the get_theme_info function.
- Version 0.91
- Added the clean_environment and reset_environment
functions.
- Added the kill_byname_logged function.
- Version 0.90
- Added the remote_foreign_config, remote_write
and remote_read functions.
- Added the make_http_connection, read_http_connection,
write_http_connection and close_http_connection
functions.
- Version 0.86
- Added the disk_usage_kb and help_search_link
functions.
- Added support for several new options in theme config files.
- Version 0.85
- Added the seed_random function.
- Version 0.83
- Added the date_chooser_button function.
- Version 0.82
- Added the remote_ series of functions for calling code on
other Webmin servers.
- Added the other_groups function.
- Version 0.81
- Added locking functions lock_file, unlock_file and
unlock_all_files as described in the File Locking
section.
- Added action logging functions webmin_log,
system_logged, backquote_logged, kill_logged
and rename_logged as described in the Action Logging
section.
- Version 0.77
- The module.info file can now contain a category line.
See above for more details.
- Version 0.75
- The header function can now generate a header image
itself if the 2nd parameter is empty.
- Added support for internationalisation, in particular the text
function and the %text hash. See above for more details.
- Added the encode_base64 function.
- Version 0.74
- The header function now accepts an additional parameter
for adding extra HTML to the <head> section of the page.
- Added link to a font used for creating Webmin headers.
- Version 0.73
- The init_config function no longer needs the module name to
be passed as a parameter, in order to support the cloning of modules.
Modules should no longer have their name hard-coded anywhere in
CGI programs or perl scipts - instead, the $module_name
variable should be used.
- Version 0.72
- Added the get_module_acl and save_module_acl
functions for use with the per-module ACL feature. See above for
more details.
- Changed the way the Users and Groups module notifies other
modules when users are added, updated and deleted. The API for
notification is now documented above.
- Version 0.70
- Module library files should now include web-lib.pl with
the statement do '../web-lib.pl'; instead of
require '../web-lib.pl';. This is required to make foreign
function calls to your module possible.
- It is now possible to call functions from other modules' libraries,
using the foreign_require and foreign_call
functions. See the documentation above for more details.
- The function get_system_hostname has been added, to
return the hostname of the system Webmin is running on. The
hostname function in Sys::Hostname was failing
on some Linux systems.
- Added the function get_webmin_version.
- ACL checking is now automatic. The old acl_check function
now does nothing, and so no longer needs to be called.
- Version 0.63
- Added the hlink function, which returns HTML for a pop-up
window for some module help page.
- Added the user_chooser_button and group_chooser_button
functions, for more scalable selection of users and groups.
|