Creating Webmin Themes

This chapter explains how themes work and takes you through the process of creating your own theme for Webmin. It covers both basic features such as image replacement and advanced capabilities like writing an alternate header function.

Introduction to 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 for a Webmin user at any one time - or if no theme is active, the default colors 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. Right now the only required name and its value is :

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 color of Webmin pages.

cs_link A six-character hex string in RRGGBB format for the color of visited and unvisited 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 corner 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 customized versions of Webmin.

headhtml HTML that will be included inside the section of each Webmin page.

headinclude The name of a file in your theme directory whose contents will be included inside the section of each page.

inbody Text that will be included inside the tag itself.

prebody HTML that will be included at the top of the 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 If set to 1, the titles on all pages will be displayed as HTML text rather than using letter images.

postbody HTML that will be included at the bottom of the section on each page. The same substitutions as prebody are done.

tb Text that will be included inside the tag in table header rows.

cb Text that will be included inside the tag in table rows below the header.

functions The name of a file in your theme's directory that contains Perl functions for overriding the default header, footer and error functions. See the "Theme functions" section 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.

Many of these options will not work automatically if your theme uses the functions option to create its own replacement for the header function. Normally they are checked for and implemented by the standard header function, so if you define your own it will need to check the %tconfig global hash and interpret the values that it contains in the same way, if you still want them to be configurable in the theme's config file.

Just like modules, themes can also be packaged as RPMs, which are suitable for installing on servers on which the RPM version of Webmin itself is already installed. You can download a script called makemodulerpm.pl from http://www.webmin.com/makemodulerpm.pl that can package up a theme directory into an RPM by creating the spec file automatically.

Overriding images and programs

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 overridden 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 CGI 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. 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.

If your theme does replace an existing script, be sure to read it carefully so that your replacement implements all of the same functionality. Some of the things to keep in mind when replacing the top-level index.cgi program are :

  1. The function get_available_module_infos can be used to get a list of modules available to the current Webmin user, for use when generating any tables of icons.
  2. If $gconfig{'gotoone'} is set to 1 and the user has only one module, your index.cgi should re-direct the browser directly to that module instead of displaying a menu. Users can set this in the Index Page Options page of the Webmin Configuration module.
  3. If $gconfig{'nohostname'} is set, no hostname or operating system information should be displayed. This can also be set on the Index Page Options page.
  4. When the global variable $gconfig{'nofeedbackcc'} is set to 2, no feedback link should appear. This is configured on the User Interface page of the Webmin Configuration module.
  5. If your menu program normally categorizes modules, when then $gconfig{'notabs'} variable is set categorization should be turned off so that all modules appear on a single page. Again, this is set on the Index Page Options page.
  6. If your program arranges module icons in a table and the variable $gconfig{'nocols'} is set, it should be used as the number of columns to display.
  7. If $gconfig{'deftab'} is set and your program categorizes modules, it should be used to decide which category to open by default.
  8. The entries in $config_directory/webmin.catnames should be used to get user-defined categories and different names set for standard categories. This can be done on the Edit Categories page of the Webmin Configuration module.
  9. If your program displays a logout link, it should only appear if neither of the following environment variables are defined. They both indicate that a form of authentication has been used that makes logging out impossible or irrelevant. $ENV{'SSL_USER'} Indicates that the current user has logged in with SSL client authentication. $ENV{'LOCAL_USER'} Indicates that the user is connecting from localhost and that his Unix username matches his Webmin login.
  10. If the variable $main::session_id is set, Webmin is in session (or cookie) authentication mode. You should generate a link to /session_login.cgi?logout=1 labeled Logout or something similar. However, if that variable is not set then Webmin is using HTTP authentication. Instead your code should create a link to /switch_user.cgi labeled Switch User, as the normal logout link above will not work.

It is not mandatory to implement all of the suggestions above – however, it will make your theme behave more like those included as standard with Webmin.

Theme functions

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 :

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 most complex is the theme_header function, due to the large number of parameters that it takes and the other global variables that it can make use of. When writing it, consider the following :

  1. All parameters should be checked an interpreted in the same was the real header function.
  2. There is no need for your function to call PrintHeader? , as this will be done automatically before it is called. It can just go ahead and start producing HTML.
  3. HTML produced should be valid and complete. That means starting with , followed by a section containing the and then the start of the <body> section. </li> <li> If the variable $gconfig{'sysinfo'} is set to 0, information about the current user, hostname, operating system and version of Webmin should be displayed in the browser's status bar. This can be done by producing HTML like : <script> defaultStatus = "fred logged into Webmin 1.060 on www.example.com"; </script> </li> <li> If $gconfig{'sysinfo'} is set to 1, this information should be appended to the page title in the <title> HTML tag instead. If $gconfig{'sysinfo'} is set to 2, the information should be displayed in the page itself somewhere just below the title. If set to 3, the host and login details should not appear anywhere. </li> <li> In all cases the function get_webmin_version can be used to get the version of Webmin, and get_system_hostname the current hostname. </li> <li> The <body> tag that your code produces may contain bgcolor=, link= and text= parameters containing the values from the global variables $gconfig{'cs_page'}, $gconfig{'cs_link'} and $gconfig{'cs_text'}, if they are set. This ensures that color preferences set by the user on the User Interface page of the Webmin Configuration module are used. However, feel free to ignore them if your theme only looks good with a certain color scheme. </li> <li> If every page includes a <strong>Logout</strong> or <strong>Switch User</strong> link, it should not appear if any of the following environment variables are set : $ENV{'SSL_USER'} The current user has logged in with SSL client authentication. $ENV{'LOCAL_USER'} The user is connecting from localhost and that his Unix username matches his Webmin login. $ENV{'ANONYMOUS_USER'} This page is being accessed without any authentication at all. </li> <li> If the variable $ENV{'HTTP_WEBMIN_SERVERS'} is set, your page heading should include a link to the URL in that variable labeled <strong>Webmin Servers</strong>. This is set when connecting via a tunnel in the Webmin Servers Index module, and the URL refers to that module on the originating system. This gives user an easy way to return to the list of servers. </li> <li> If your theme generates titles made up of letter images, plain text should be used instead if $gconfig{'texttitles'} is set to 1. This is controlled by a setting on the User Interface page of the Webmin Configuration module. </li> <li> Unless your heading is very similar to the default, the theme_footer function should be defined as well. It must produce closing HTML that matches that produced by theme_header, followed by </body> and </html> tags. Be sure to interpret and display the multiple 'return' links that can be supplied to the footer function as well. </li> <li> Some themes normally puts all page content into a table by outputting an un-closed <table> tag in the header function. If the global variable $theme_no_table is set, this should be turned off as it indicates that the CGI program will be slowly producing some progressive output. Many browsers will not display a table's content until it has been completely output. Similarly, your theme_footer function should not produce a closing </table> tag when $theme_no_table is set. </li> <li> The special CGI program session_login.cgi that display Webmin's login form will call theme_header as well. However, at this point the browser has not logged into Webmin and so will not be able to access any images that your header refers to. For this reason, when called with the first two parameters set to undef (as it will be in this case), your function should not produce any <img> tags. Or they should always refer to the special /unauthenticated URL path, to which access is always allowed even to clients that have not logged in. </li></ol> <p /> <p /> Reading the header function in web-lib.pl and the theme_header function is mscstyle3/theme.pl should give you a good idea of how the various parameters and global variables should be handled. <a name="TopicEnd"></a> <p /> <br /> <p /> <div class=TopicAction> <a href='/twiki/bin/edit/Webmin/CreatingWebminThemes?t=1216985884' rel='nofollow' title='Edit this topic text' accesskey='e'><b><span class='twikiAccessKey'>E</span>dit</b></a> | <a href="/twiki/bin/attach/Webmin/CreatingWebminThemes" accesskey="A" title="Attach an image or document to this topic" rel='nofollow'><span class='twikiAccessKey'>A</span>ttach</a> | Backlinks: <a href="/twiki/bin/oops/Webmin/CreatingWebminThemes?template=backlinksweb" title='Search the Webmin Web for topics that link to here' accesskey="b">We<span class='twikiAccessKey'>b</span></a>, <a href="/twiki/bin/oops/Webmin/CreatingWebminThemes?template=backlinksallwebs" title="Search all webs for topics that link to here" accesskey="L">A<span class='twikiAccessKey'>l</span>l Webs</a> | <a href="/Webmin/CreatingWebminThemes?cover=print.quickmenu" title="Printable version of this topic" accesskey="P" rel='nofollow'><span class='twikiAccessKey'>P</span>rintable</a> | <a href="/twiki/bin/rdiff/Webmin/CreatingWebminThemes?type=history" title="View total topic history" accesskey="H" rel="nofollow"><span class='twikiAccessKey'>H</span>istory</a>: r1 | <a href="/twiki/bin/oops/Webmin/CreatingWebminThemes?template=oopsmore&param1=1&param2=1" title='Delete or rename this topic; set parent topic; view and compare revisions' accesskey="M" rel='nofollow'><span class='twikiAccessKey'>M</span>ore topic actions</a> </div> <div class="TWikiFooterNote"> <p /> </div> <p /> <div class="TWikiCopyright"><span class="twikiRight"> <a href="http://doxfer.com/"><img src="/twiki/pub/images/doxfer-80-27.png" alt="Doxfer is docs for...anything!" width="80" height="27" title="Doxfer is docs for...anything!" border="0" /></a></span>Copyright © by the contributing authors. All material on Doxfer is the property of the contributing authors. <br /> Ideas, requests, problems regarding Doxfer? <a href='mailto:doxa@doxfer.com?subject=Doxfer Feedback on Webmin.CreatingWebminThemes'>Send feedback</a> </div> </div> <p /> <a name="PageBottom"></a> <p /> <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-1493647-2"; urchinTracker(); </script> </body></html> <p /> <p /> <p /> <p /> <p /> <p /> <p /> <p />