Skin API

From wiliGear wiki

Revision as of 09:11, 1 February 2008 by Bite (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search

Contents

Skin

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 Package

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:

 cd 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:

 version=skin_version
 title=skin_name


Creating Custom Skins

Skin creation usually involves rebranding and functionality modification. Rebranding may be used to give a different look and feel of the user interface - it requires the basic knowledge of the HTML, CSS and some JavaScript usually. The modification of skin functionality is more complex – it requires the knowledge of the PHP language as well as the device functionality, configuration methods, available system utilities, etc. The easiest way to create your own skin is to modify an existing skin, repackage it and upload the package back to the device.


Rebranding

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.


Image:saukt.jpg 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

Modifying the existing skin functionality will require deep knowledge of PHP3 scripting language. HTML, CSS and JavaScript are also subjects to be familiar with. Understanding of the device functionality itself is also preferred, although some device functionality wrapper functions may be found in lib subdirectory.

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.

Image:saukt.jpg 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

Skin Package

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;
  • *.js - JavaScript libraries for interactivity of the Web UI.

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.


In addition to data model view inclusion, all view processors include (via linking) HTML stylesheets and JavaScript libraries. Included CSS style sheets:

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


Included JavaScript libraries:

  • $page.js - page specific JavaScript library.


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

lib/cfg.inc

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.


function cfg_str_load($filename=cfg_file)

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[0] is key, array[1] is index.

If key not found returns default key index in array[1].

Example:

$cfg = array("wireless.1.devname" => "prism0", "wireless.2.devname" => "ath0");
$idx = get_index($cfg, "wireless.(digit:+).devname", "ath0", 1);
echo $idx[1];
Result: 2


function read_configuration($type='active')

Read configuration of requested type: active, backup.


function cfg_discard($filename=cfg_file)

Discard current changes already saved to config file.


function cfg_apply($filename=cfg_file)

Apply current changes. Save, run sysconf –w.


function skin_cfg_apply($filename=cfg_file,$skin_keys=skin_cfg_keys,$purge=false)

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.



lib/skin.inc

function skin_activate($file)

Activate given skin: extract, copy, save.


function skin_load_skin_default()

If there is defined and exists skin default config, then copy over current config file.


function skin_default_cfg_exists()

Returns true if skin default configuration is available.


function skin_detect_hardware()

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.


function skin_getactive_notchecked()

Get active skin title and version.

INTERNAL: does not verify if it really exists.


function skin_get_current()

Get current skin name and version in one string.


function skin_getactive()

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.


function skin_delete($filename)

Delete specified skin from flash.


function skin_output($filename)

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.


function skin_save_version2cfg($filename=cfg_file)

Save current skin version to configuration.


lib/authorize.inc

Image:info.jpg First skin implementation had authentication by cookie.

Later session support was added to WILI-S devices (WILI-S uses PHP3, which does not have sessions support, but we added sessions to PHP3 in our devices).

Now authentication goes using sessions. So some method descriptions may mention cookies, but sessions are used.


function check_admin($skip_renew = false)

Check if user (administrator) is logged in – authenticated.


function get_username()

Get currently logged in user username.


function login_admin($username, $password)

Login administrator with given username/password.


function logout_admin()

Logout administrator.


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.


function redirect($page)

Redirects to specified page on same host/directory.

Image:saukt.jpg 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.


lib/common.inc

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.


function cust_basename($filename)

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.

lib/licensing.inc

function output_license()

Output current license as attachment. Called on license download request.


function save_license($file)

Save license to file.


function get_license_status(&$status, &$period)

Get current license status: valid/invalid, period.


lib/status.inc

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)

Link statistics


function get_link_errors ($ifname)

Link errors.


function iwpriv_getint ($ifname, $cmd)

Eecute iwpriv with given parameters.

Rturn INT.


function iwpriv_getstring ($ifname, $cmd)

Execute iwpriv with given parameters.

Rturn STRING.


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)

Get IP.


function get_macaddr ($ifname)

Get MAC.


function get_uptime()

Uptime in human readable format.


function get_interfaces()

List all network interfaces.


function get_stats($ifname = '-a')

Get interface statistics.

If no parameter given, get all interfaces stats


function get_stats_individual($ifname)

Some more detailed interface statistics.


function get_routes($ifname = 0)

Get kernel routing table.


function get_arps($ifname = 0)

Get ARP table.


function get_cpuinfo()

Get CPU Info.


function get_load()

Get Load Info.


function get_iface_mode($ifname)

Return current interface mode: Master/Managed.


function get_peer_data_rate($ifname, $mac_address)

Get current interface data rate to given MAC.


function parse_iwconfig($ifname)

Return iwconfig output in array for given interface.


function get_peers($ifname = )

Show currently connected peers.


function get_meminfo()

Get memory info.


function get_status_str($intvalue)

Returns simply UP/DOWN.

0-initializing (DOWN);

1-scanning (UP);

2-authenticating (UP);

3-associating (UP);

4-running (UP).


function removedot($str)

Removes the dot from the string.


function get_wstats($ifname = 0)

Get wireless statistics.


function find_wireless_if()

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.


lib/system.inc

function fw_get_version()

Get current firmware version.


function fw_validate ($file)

Validates firmware upgrade file, returns true (1) if firmware file is OK.


function fw_flash()

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


function fw_get_devname()

Extracts device name from current (running) firmware version or Redboot config.


function device_reboot()

Starts device reboot in a background after delay_before_reboot (see settings.inc for delay value).


function device_resettodefaults()

Resets device to factory defaults (as a background process) after delay_before_reboot (see settings.inc for delay value).


function fw_get_ether_names()

Using current (running) firmware version decide which ehternet interface names are used.

Xscale: ixp0, ixp1; otherwise: eth0, eth1.

Returns array. ret[0] - WAN, ret[1] – LAN.


lib/atheros.inc

function get_wirelessinfo($ifname)

Returns wireless information for interface.


function get_countrycode()

Get countrycode.


function get_allradios()

Get radio list into array.


function get_if_parent($name)

Get interface parent (if it is for example vssid'ed interface).


function wilios_4xx()

Returns TRUE if it is WILI-S 4.00 or above.


function wilios_35x()

Returns TRUE if it is WILI-S 3.5x.

Personal tools