From wiliGear wiki
A new generation WILI-S device (starting FW version 3.54) web management is based on the skins. Skins influence not only on device appearance but also on device functionality. This means that when device acts as an access point, it has completely different web interface from device running as wireless client, although they both are using the same operating system. When user starts device configuration, he shall choose one of configuration skins available. Web interface will be changed according to selection and user may proceed with further device configuration. If later user decides to configure the same device in completely different role, he simply selects another role skin and reconfigures device using new skin.
There are two types of skins:
- build-in - the skins of this type are undeletable so even after the device reset to factory defaults the build-in skins will remain.
- custom - the skins of this type are fully manageable - they can be uploaded and deleted from the system by the administrator.
Skin is the package (.tgz format) that contains device configuration scripts. The minimal skin package must include:
- version.txt file with meta information about the skin. Refer to the section Version.txt File Format for details.
- index.html file. It is the entry point for skin. Usually it redirects the user to the request dispatcher.
Follow the steps to create a skin package:
1. Change directory to skin development directory:
2. Create gziped tar:
tar -czf output_directory/skin_name.tgz *
3. Test the package:
tar -xOzf output_directory/skin_name.tgz version.txt - | grep -E 'version|title'
4. Output must be two lines:
Creating Custom Skins
Rebranding is a modification of the skin in a way, which changes the GUI appearance of the device. Usually it includes the logo images. Familiarity with the CSS (Cascading Style Sheets) mechanism will make rebranding of skin an easier task. All you have to do is replace images in image/ directory with the images you prefer and/or modify the skin stylesheets (main.css, menu.css, etc.). If you're willing to change the layout of items, you should take a look at the view/page.tmpl and view/unauthorized.tmpl HTML source code. It's heavily based on div HTML item grouping, so quite a lot of layout modifications are possible with modifications to main.css only. Additionally view processors view/page.tmpl and view/unauthorized.tmpl may need to be modified - this certainly requires solid HTML knowledge. After you applied all the modifications, repackage the skin as described in section Skin package.
|Do not forget to change version information in version.txt file. Refer to the section Version.txt File Format for details.|
Modifying Existing WILI-CORE Skin Functionality
The most useful PHP3 library files in lib directory are:
- authorize.inc - handles user authentication and authorization
- cfg.inc - contains WILI-S configuration file management routines.
- menu.class.inc - menu item container definition
- skin.inc - utilities for skin management
- status.inc - utilities to query various aspects of the device state
- system.inc - utilities for firmware file management and device maintenance
- ui_messages.inc - message and error reporting on WEB UI in a unified way
Feel free to add your own libraries here.
The structure and workflow of the request dispatcher is described in section WILI-Core Skin Architecture. After you've applied all the modifications, repackage the skin as described in section Skin package.
|Do not forget to change version information in version.txt file. Refer to the section Version.txt File Format for details.|
Here are some tips and suggestions for common modifications:
Adding New Pages
This is achieved by adding model script to ctrl/your_page.php and creating page view in view/your_page.tmpl. Model script may be absent, however the template in view directory is required. Usually, you would use global PHP variables to transfer data between data model script and page view. It is suggested to use global PHP array variable $GLOBALS, e.g. to transfer some string in hello page you would do something like that in ctrl/hello.php:
<? $GLOBALS['hello']['message'] = 'Hello, World!'; ?>
And then placing this variable somewhere in view/hello.tmpl:
<? echo $GLOBALS['hello']['message']; ?>
Your new hello page will be accessible via http://your.device.ip/page.cgi?page=hello
Adding pages with several steps
When pages accept the interaction with the user (e.g. asking for confirmation or require several steps to complete), it is recommended to store the initial page in global variable $src_page - see the code of maint-reboot for an example (ctrl/maint-reboot.php and view/maint-reboot.tmpl). This way, you would maintain selected menu item and will have a possibility for user to return to the original page at any time (obviously, by placing page flow controls in the view).
Introducing new menu items (or removing extra items)
Take a look at ctrl/menu.php for menu item structure - it is a hierarchical structure of Menu objects. The code is quite straightforward - create a Menu object with page name, page title and relative URL to access it, then add it to the place you want it to be.
Changing menu item layout
See view/menu.tmpl for current implementation. If you want to change the layout, you will definitely need to rewrite/modify this code. Basically, it's just a simple traversal of hierarchical tree structure of Menu objects.
Displaying errors and messages
To display errors, which occurred during data model building, or provide information messages to the user, use add_error or add_message functions from lib/ui_messages.inc.
Writing a Skin from Scratch
You're mostly on your own here. Skins may be done in a numerous different ways - choose your own! We would suggest to study the source code of the default WILI-S skin which is described in section WILI-Core Skin Architecture.
Version.txt File Format
The Version.txt file is a text file consisting of <key>=<value> assignments, one assignment per line. Key is case sensitive. The symbol # is used as comment. Two keys are required in the version.txt file:
- title – short name of the skin.
- version – skin version number.
The suggested keys:
- author – author of the skin.
- description – description of the skin.
WILI-Core Skin Architecture
WILI-Core is the built-in skin in all the basic WILIBOX firmware images.
The package of WILI-Core includes the library set which can be reused. All the development and customization works should correspond to the licence requirements. Licence text is included in every library source file.
Basic library files are:
- lib/cfg.inc (configuration file processing methods)
- lib/skin.inc (skin processing methods – saving, downloading, activation)
- lib/authorize.inc (administrator account authentication methods and access management)
- lib/common.inc (general skin methods)
- lib/status.inc (methods for statistics gathering and displaying)
- lib/system.inc (firmware management methods and system wide controls)
- lib/atheros.inc (methods dedicated to wireless interface management and monitoring)
PHP based control routines and scripts can be found in the ctrl/ directory.
WILI-Core Skin Explained
File/directory tree structure of WILI-CORE skin:
- ctrl/ - place for code, which prepares data model and controls web page behaviour;
- view/ - rendering (HTML) code, according to data model built, see *.tmpl files;
- images/ - images (product, vendor logos, decorations etc);
- lib/ - additional PHP functions to ease creation of data model scripts;
- version.txt - skin meta information;
- page.cgi - centralized request dispatcher, all web requests are dispatched through it;
- index.html - simple wrapper to redirect root directory requests to request dispatcher (page.cgi);
- *.css - CSS (Cascading Style Sheets) for controlling look-and-feel of the web pages;
The most attention shall be paid to centralized request dispatcher page.cgi. It's implementation is placed in ctrl/page.php
As the name of the request dispatcher suggests, the core of the single request is a single page. Requests to the skin engine include page parameter, which indicates what information user requests. Request dispatcher takes this page parameter, looks for a data model implementation for the requested page, loads it (if it is present), and then it loads an appropriate view for the data model. The view is then presented to the end user. This is the simplistic description of the page.cgi request dispatcher. Since this dispatcher serves embedded device management system, it also takes care of access control to the pages. The only administrative page, which is supposed to be accessible without authorization is login. In case you'd ever want to change that you're free to do this by modifying the source code of ctrl/page.php according to your needs.
Structural request dispatcher code overview:
- Load required libraries (for settings, authorization, configuration and message management).
- Check authorization status - all pages except login require authorization. If the authorized session does not exist, page variable is modified to have login value.
- Include ctrl/$page.php for data model building. Data model for given $page may be missing - views may actually exist without any data. There is a possibility for data model builder to pass over the data model building to another page - this can be achieved by overriding global variable $GLOBALS['main']['page']
- This can be done only once, i.e. original page may pass over data model building to a secondary page, but secondary page cannot pass data model building any further. Usage sample can be found in ctrl/logout.php script.
- Each page will probably want to have a separate page title - this can be specified in data model by overriding $GLOBALS[$page] variable.
- Current implementation is also capable of fetching the title for page from menu definitions (in ctrl/menu.php), but this is limited for authorized pages only - menus are not available for unauthorized access.
- Include the view processor - view/page.tmpl for authorized page access and view/unauthorized.tmpl for unauthorized pages. As it was already mentioned, the only unauthorized access page so far is login.
The dispatcher passes the workflow to the view processors. The main role of view processors is to provide a unified look and feel to all the requested pages. Basically, view processors is nothing more, but a view template, which includes data model view/$page.tmpl at the certain template location. Authorized view processor view/page.tmpl also includes menu view - view/menu.tmpl, so that all authorized pages will contain menu for page navigation. Unauthorized view processor difference from authorized one is minimal - it does not include menu.
- main.css - main Cascading Style Sheet, which defines the most important styles common to the most pages;
- menu.css - CSS for menu look and feel;
- $page.css - CSS for current view, used for overriding/extending main.css styles.
You can take a look at the skin source code at any moment if more questions arise. Basic methods are described in the next section.
Skin Libraries and Methods
function cfg_load ($filename=cfg_file)
Loads key=value configuration file into cfg array, where key is index in array and value is value in array by the that index.
Loads configuration file to simple text variable.
function cfg_get ($cfg, $key)
Returns value by key index from cfg array.
function cfg_set (&$cfg, $key, $value)
Changes value in refered cfg array by key index.
Returns cfg array.
function cfg_get_def ($cfg, $key, $dvalue)
Returns value by key index from cfg array if key index exists.
If key index in array not found then returns default value.
function cfg_save ($cfg, $file=cfg_file)
Saves cfg array into file.
Returns 0 on success. -1 on failure.
function cfg_str_save ($str, $file=cfg_file)
Saves cfg string into file.
Returns 0 on success. -1 on failure.
function cfg_list ($cfg)
Dump cfg array into stdout in key=value format.
function cfg_set_modified ($file=cfg_file)
Sets modified flag in cfg file.
function cfg_is_modified ($file=cfg_file)
If cfg file was modified returns 1, 0 if cfg file unchanged.
function cfg_set_inactive ($file=cfg_inactive_file)
Sets reboot-needed flag in inactive file.
function cfg_is_inactive ($file=cfg_inactive_file)
If reboot-needed file exists returns true, false if cfg is active.
function cfg_get_index ($cfg, $key_exp, $val, $def_idx)
Get key and key index by key expration and value.
Returns key and key index in array. array is key, array is index.
If key not found returns default key index in array.
$cfg = array("wireless.1.devname" => "prism0", "wireless.2.devname" => "ath0"); $idx = get_index($cfg, "wireless.(digit:+).devname", "ath0", 1); echo $idx; Result: 2
Read configuration of requested type: active, backup.
Discard current changes already saved to config file.
Apply current changes. Save, run sysconf –w.
Skin specific configuration apply.
Requesting purge and giving known skin keys, purges every unknown to skin configuration key and leaves only these, that are in $skin_keys array.
Then after saves skin version and applies configuration.
Activate given skin: extract, copy, save.
If there is defined and exists skin default config, then copy over current config file.
Returns true if skin default configuration is available.
Checks if there are defined skin actions after default configuration load include needed library and do execute that action.
function skin_getrecord_byfile($skins, $file)
Extracts one skin record by given file.
Get active skin title and version.
INTERNAL: does not verify if it really exists.
Get current skin name and version in one string.
Get active skin title and version.
function skin_search($dir = skins_persistent_dir, $status = skin_status_custom)
Collect available skin set.
Collects built-in, uploaded, stored in specified directory skins.
function skin_store($src_file, $filename = 0, $dir = skins_persistent_dir)
Save uploaded skin permanently to device flash.
Delete specified skin from flash.
Download skin - sends HTML headers and outputs archyve directly to browser.
function skin_redirect_root($uri = 'page.cgi?page=login')
Redirect browser to unique generated URL.
It is used on new skin activation to force refreshed pages, css and images.
Save current skin version to configuration.
function check_admin($skip_renew = false)
Check if user (administrator) is logged in – authenticated.
Get currently logged in user username.
function login_admin($username, $password)
Login administrator with given username/password.
function update_config($old_user, $new_user, $crypted_pass)
Update configuration with changed username/password.
function change_password($old_user, $new_user, $old_password, $new_password)
Function is suppossed to change only OWN password and username, do not change OTHER USER password, because session cookies are re-written.
Redirects to specified page on same host/directory.
|Do not use this method together with setcookie(). In that case one of them will not work: most probably header('Location: page') will not work.|
function output_attachment($file, $filename, $content_type = 'text/plain', $attach_inline = 'attachment')
Send HTML headers and output file as attachment.
May also output as inline if requested.
function output_inline($file, $filename, $content_type = 'text/plain')
Output file inline - calls output_attachment() method.
function cust_array_merge($arr1, $arr2)
Custom array_merge function, array_merge comes from php4, we use php3.
Takes all elements from both arrays and adds to new array.
Array keys are discarded!!! Not to discard array keys, use simple + operator.
Custom basename, which does not only basename() but also removes all WIndows like path with backslashes.
function option_list($values_arr, $preselected = , $disabled = )
Otputs HTML tags <option value='value'>description</option>.
Uses given array key-val, preselected item, also may be disabled control.
function auth_config2select($proto, $cipher)
Converts prototype and cipher values to one string, that is used in HTML <select>.
function auth_select2config($wir_mode, $selection, &$proto, &$cipher)
Converts back from one string selected in <select> to prototype and cipher.
Output current license as attachment. Called on license download request.
Save license to file.
function get_license_status(&$status, &$period)
Get current license status: valid/invalid, period.
function get_essid ($ifname)
Get given interface SSID.
function get_frequency ($ifname)
Get given interface frequency.
function get_channel ($ifname)
Get given interface channel.
function get_txpower ($ifname)
Get given interface TX power.
function get_rate ($ifname)
Get given interface rate.
function get_rates_arr ($ifname)
Get available rates for interface.
function get_rxrate ($ifparentname)
Content of /proc/sys/dev/" . $ifparentname . "/rx_rate.
function get_link_stats ($ifname)
function get_link_errors ($ifname)
function iwpriv_getint ($ifname, $cmd)
Eecute iwpriv with given parameters.
function iwpriv_getstring ($ifname, $cmd)
Execute iwpriv with given parameters.
function get_wmmlevel ($ifname)
Get WMM level.
function get_modelist ($ifname)
Get IEEE_MODE from iwconfig.
Because iwpriv return possible modes, but not current function get_ieeemode_iwconfig($ifname).
function get_ieeemode ($ifname)
get IEEE_MODE from executing iwpriv.
function get_ieeemode_str ($ifname)
Get human readable IEEE_MODE string.
function get_securityname ($ifname)
Get security: WPA/WEP.
function get_ipv4addr ($ifname)
function get_macaddr ($ifname)
Uptime in human readable format.
List all network interfaces.
function get_stats($ifname = '-a')
Get interface statistics.
If no parameter given, get all interfaces stats
Some more detailed interface statistics.
function get_routes($ifname = 0)
Get kernel routing table.
function get_arps($ifname = 0)
Get ARP table.
Get CPU Info.
Get Load Info.
Return current interface mode: Master/Managed.
function get_peer_data_rate($ifname, $mac_address)
Get current interface data rate to given MAC.
Return iwconfig output in array for given interface.
function get_peers($ifname = )
Show currently connected peers.
Get memory info.
Returns simply UP/DOWN.
Removes the dot from the string.
function get_wstats($ifname = 0)
Get wireless statistics.
Find any up wireless interface.
Run shell command: iwconfig 2>/dev/null | grep -B 1 Mode.
Return founded interface name, which has Mode set or false if no such interface found.
function get_radioinfo($ifname = 0)
Get radio information.
Get current firmware version.
function fw_validate ($file)
Validates firmware upgrade file, returns true (1) if firmware file is OK.
Launches firmware flash as a background process after some delay (delay_before_reboot - see it's value in settings.inc).
function fw_extract_version ()
Extracts firmware version information from firmware_file (see settings.inc).
Extracts device name from current (running) firmware version or Redboot config.
Starts device reboot in a background after delay_before_reboot (see settings.inc for delay value).
Resets device to factory defaults (as a background process) after delay_before_reboot (see settings.inc for delay value).
Using current (running) firmware version decide which ehternet interface names are used.
Xscale: ixp0, ixp1; otherwise: eth0, eth1.
Returns array. ret - WAN, ret – LAN.
Returns wireless information for interface.
Get radio list into array.
Get interface parent (if it is for example vssid'ed interface).
Returns TRUE if it is WILI-S 4.00 or above.
Returns TRUE if it is WILI-S 3.5x.