Webmin home page Feedback
Webmin

Webmin
  
Documentation
Documentation
  
Programming
Programming
  
Usermin
Usermin
  
Mirror Sites
Mirror$lSites
  
Other Stuff
Other$lStuff
   
Webmin Version: 0.990
Released: 1 Jul 2002
Download: tar.gz | RPM

 Webmin Modules 

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 :

  1. 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.

  2. &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.

  3. 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 :

    1. Server has been contacted
      The second parameter is 1 if the requested URL is a redirect, or 0 if a normal file.
    2. Download has started
      The second parameter is the size of the file being downloaded, if it is known.
    3. 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.
    4. Download complete
    5. 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 &lt;, &gt; and &amp; 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:
  • All pages should be viewable on any browser that supports images, tables and forms. Browser features such as frames, DHTML, Javascript or Java should not be used unless there is no other option. It should be possible to use Webmin from browsers such as Netscape 1.1 or Pocket IE.

  • All CGI programs that generate HTML output should call the header() function. The standard modules use 50-point helvetica text in black with a transparent background, created using The GIMP. Your modules should use the same font, size and style for consistency.

  • The header() function outputs HTML tags setting the background, text and link colours for the generated page based on configured colour scheme. The init_config() function sets the global variables $tb and $cb which should be used as the background colour for table headers and body rows respectively, as in this example :
    print "<table border width=100%>\n";
    print "<tr $tb> <td><b>Foo</b></td> <td><b>Bar</b></td> </tr>\n";
    print "<tr $cb> <td>some value</td> <td>another value</td> </tr>\n";
    ...
    
  • Try to avoid generating HTML forms that contain a large number of input fields. Some browsers (particularly netscape on Unix) slow down when rendering such pages.


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.
  1. No password is set for this user, typically meaning that no password is required to login
  2. This user is not allowed to login at all
  3. Only the encrypted password for this user is available
  4. A new or initial plain-text password is available in the plainpass key.
  5. 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.

 <-  Return to index