<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.innovaphone.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Odawid</id>
	<title>innovaphone wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.innovaphone.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Odawid"/>
	<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Special:Contributions/Odawid"/>
	<updated>2026-05-08T01:17:41Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference10:Concept_Linux_Application_Platform&amp;diff=56547</id>
		<title>Reference10:Concept Linux Application Platform</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference10:Concept_Linux_Application_Platform&amp;diff=56547"/>
		<updated>2020-07-16T15:47:37Z</updated>

		<summary type="html">&lt;p&gt;Odawid: /* Manual Debian 8 (jessie) Upgrade */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
The innovaphone Linux Application Platform permits to install innovaphone or custom applications for certain purposes, like Reporting or a Fax Server.&amp;lt;br&amp;gt;&lt;br /&gt;
It also allows to backup/restore configuration files, uninstall applications or see and backup logs.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The Linux distribution Debian 7.1 (Wheezy) is used and linux kernel is 3.4.10 (IPxx10) and 3.2.0.4 (VM)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The architecture of the platform is armel.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
&lt;br /&gt;
There are three ways to use the innovaphone Linux Application Platform:&lt;br /&gt;
&lt;br /&gt;
===On an IPxx10 Gateway===&lt;br /&gt;
* An IP810, IP0010, IP3010 or IP6010 Gateway&lt;br /&gt;
* Firmware Version 10&lt;br /&gt;
* A compact flash card with UDMA support (minimum 8 GB)&lt;br /&gt;
** We recommend SanDisk Extreme with UDMA and 90 MB/s or above&lt;br /&gt;
&lt;br /&gt;
===On an IPx11 Gateway===&lt;br /&gt;
* An IP0011, IP311, IP411, IP811 or IP3011 Gateway&lt;br /&gt;
* Firmware Version 11r2&lt;br /&gt;
* An SSD mSATA&lt;br /&gt;
&lt;br /&gt;
===As a Virtual Machine===&lt;br /&gt;
* VMWare Player, VMWare Workstation, VMWare vSphere, Microsoft HyperV ([[Howto:Convert_a_V10_LinuxAP_to_VHDX_to_run_on_Hyper-V]])&lt;br /&gt;
&lt;br /&gt;
* Minimal Requirements for the Virtual Machine:&lt;br /&gt;
 1vCPU ( we run 800 MHZ CPU on our IPXX10 Gateways, so similar speed or higher it&#039;s enough, nevertheless depending on the operations/load you could need more CPU speed/vCPU)&lt;br /&gt;
 512 MB RAM&lt;br /&gt;
 8GB Disk&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
Download the latest Linux Application Platform from [https://download.innovaphone.com download.innovaphone.com ].&amp;lt;br&amp;gt;&lt;br /&gt;
You can download and install two different packages: The IPxx10/IPx11 package to run on the gateways or a VMware image for VMware&lt;br /&gt;
&lt;br /&gt;
===Default Credentials===&lt;br /&gt;
* Web/Webdav: &#039;&#039;&#039;admin&#039;&#039;&#039;/&#039;&#039;&#039;linux&#039;&#039;&#039;&lt;br /&gt;
* Root-Login (e.g. with Putty): &#039;&#039;&#039;root&#039;&#039;&#039;/&#039;&#039;&#039;iplinux&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Disk space calculation===&lt;br /&gt;
See [[Reference10:Concept_Reporting#Calculation_of_required_disk_space]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&lt;br /&gt;
It is strongly recommended that you try to precalculate the needed disk space and that you choose a suiting disk size.&lt;br /&gt;
&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Disk space usage after first time installation===&lt;br /&gt;
&lt;br /&gt;
====IPxx10/IPx11 Gateways====&lt;br /&gt;
&lt;br /&gt;
* /dev/sda1: 32 MB (fat32 partition with two kernels, which are started by the IPxx10 or IPx11)&lt;br /&gt;
* /dev/sda2: 524 MB (ext2 initial installation partition)&lt;br /&gt;
* /dev/sda3: 120 MB (swap partition)&lt;br /&gt;
* /dev/sda4: 620 MB / xx GB depending of the size of the used CF card (ext4 partition, which is actually booted)&lt;br /&gt;
&lt;br /&gt;
 All in all about 1.3 GB are already in use after the initial installation.&lt;br /&gt;
&lt;br /&gt;
====VMWare====&lt;br /&gt;
&lt;br /&gt;
* /dev/sda1: 674 MB (ext2 initial installation partition)&lt;br /&gt;
* /dev/sda2: 120 MB (swap partition)&lt;br /&gt;
* /dev/sda3: 767 MB / xx GB depending of your pre installation configuration (ext3 partition, which is actually booted) &lt;br /&gt;
&lt;br /&gt;
 All in all about 1.6 GB are already in use after the initial installation.&lt;br /&gt;
&lt;br /&gt;
===Linux Application Platform (IPxx10 or IPx11 Gateways)===&lt;br /&gt;
&lt;br /&gt;
It is recommended to use CF-Cards with sizes of 8GB or more and the card &#039;&#039;&#039;must&#039;&#039;&#039; support UDMA!&amp;lt;br&amp;gt;&lt;br /&gt;
* Enable Linux under Linux General. &lt;br /&gt;
  [[image:IPxx10_Linux_-_enable.png]]&lt;br /&gt;
* Be sure that &amp;quot;Autostart Linux&amp;quot; is disabled until the installation process is finished.&lt;br /&gt;
* You need to enable Proxy-ARP on ETH0 or ETH1 [[ Reference:Configuration/ETH/IP|here ]], so your gateway and the linux appliance will share the same physical interface. Simply go to &#039;&#039;&#039;IP4 &amp;gt; ETH0 (if used) &amp;gt; IP&#039;&#039;&#039; and check &#039;&#039;&#039;Proxy ARP&#039;&#039;&#039;&lt;br /&gt;
* Decompress the downloaded package. You should have an image file like &amp;lt;code&amp;gt;linux_ipxx10_armel.img&amp;lt;/code&amp;gt; now. This works for both &#039;&#039;&#039;IPxx10&#039;&#039;&#039; and &#039;&#039;&#039;IPx11&#039;&#039;&#039; hardware!&lt;br /&gt;
* Upload the decompressed file over the gateways web interface under [[ Reference10:General/Compact-Flash/Image ]] (IPxx10) or [[ Reference12:General/SSD/Image ]] (IPx11). Unmount the CF card/SSD if necessary. Select &amp;quot;Part 1&amp;quot; before starting the upload!&lt;br /&gt;
  [[image:IPxx10_Linux_-_upload_image.jpg]]&lt;br /&gt;
* Reset the box (which also activates the config change of step 1).&lt;br /&gt;
* Configure IP under [[ Reference10:Linux/IP ]]: select either &amp;quot;Disabled&amp;quot; to assign a static IP or ETH0/ETH1 to receive an IP-Address from DHCP-Server behind ETH0 or ETH1.&lt;br /&gt;
* Configure the kernel file, which you find under [[ Reference10:General/Compact-Flash/General#Browse_CF_Content ]] on [[ Reference10:Linux/General ]] &#039;&#039;&#039;Linux kernel file&#039;&#039;&#039;&lt;br /&gt;
** IPxx10 hardware: &amp;lt;code&amp;gt;Image-6010-3.4.10&amp;lt;/code&amp;gt;&lt;br /&gt;
** IPx11 hardware: &amp;lt;code&amp;gt;Image-IPx11-4.4.0&amp;lt;/code&amp;gt;&lt;br /&gt;
* Configure &amp;lt;code&amp;gt;root=/dev/sda2&amp;lt;/code&amp;gt; under [[ Reference10:Linux/General ]] &#039;&#039;&#039;Kernel command line&#039;&#039;&#039;.&lt;br /&gt;
* If you want, configure the autostart flag.&lt;br /&gt;
* Submit your changes.&lt;br /&gt;
* Click the [[ Reference10:Linux/General ]] &#039;&#039;&#039;Start&#039;&#039;&#039;-Link. The page refreshes until Linux gets an IP and then tries to get a link to the Linux Web Server, which can take some time for the first time installation (~ 5 minutes to 2 hours, for a IP411 ~15 minutes).&lt;br /&gt;
[[Image:device_conf.jpg]]&lt;br /&gt;
* Open the Linux Web Server to see the installation progress (which might take several minutes too). The default credentials are &#039;&#039;&#039;admin&#039;&#039;&#039;/&#039;&#039;&#039;linux&#039;&#039;&#039; for both platforms.&lt;br /&gt;
[[Image:installation.jpg]]&lt;br /&gt;
* The output of the installation log is stored on the Linux AP under &amp;lt;code&amp;gt;/var/log/init_install.log&amp;lt;/code&amp;gt;. In case you have no access to the web server but a console or SSH access, you can check the installation progress in this log file. E.g. login to the console with root/iplinux and run follwong command: &amp;lt;code&amp;gt;more /var/log/init_install.log&amp;lt;/code&amp;gt;. In case you have an SSH connection to the Linux AP, you can download this file using [http://winscp.net WinSCP] tool.&lt;br /&gt;
* Enter the innovaphone device IP address (optional port allowed) and admin credentials when the installation has finished. Now wait until the page refrehses. The web server credentials are now the innovaphone device admin credentials, e.g. &#039;&#039;&#039;admin&#039;&#039;&#039;/&#039;&#039;&#039;ip6010&#039;&#039;&#039;.&lt;br /&gt;
** If the device couldn&#039;t be reconfigured, you will get an error message &#039;&#039;&#039;Command line at the PBX could not be changed...&#039;&#039;&#039; In this case, you have to open [[ Reference10:Linux/General ]] on your device, click stop and enter &amp;lt;code&amp;gt;root=/dev/sda4&amp;lt;/code&amp;gt; under &#039;&#039;&#039;Kernel command line&#039;&#039;&#039;. Then start again. Your Linux webserver credentials will be &#039;&#039;&#039;admin&#039;&#039;&#039;/&#039;&#039;&#039;linux&#039;&#039;&#039; in this case.&lt;br /&gt;
* Linux install has finished.&lt;br /&gt;
* You will see now &amp;lt;code&amp;gt;root=/dev/sda4&amp;lt;/code&amp;gt; under [[ Reference10:Linux/General ]] since Linux is running in on the fourth partition. You shouldn&#039;t change that unless you want to install Linux again.&lt;br /&gt;
&lt;br /&gt;
===Linux Application Platform (VMWare)===&lt;br /&gt;
&lt;br /&gt;
* Decompress the downloaded archive. You should have two files: &#039;&#039;&#039;IP-Debian.vmx&#039;&#039;&#039; and &#039;&#039;&#039;IP-Debian.vmdk&#039;&#039;&#039;.&lt;br /&gt;
* We can open using Vmware Player/Workstation, if you wish to run on Vsphere 4.x or later please convert it by the same method it&#039;s done with the IPVA (see [[Reference10:Concept_Innovaphone_Virtual_Appliance#VMware_vSphere | Using VMware vSphere]])&lt;br /&gt;
* Now you have two possibilities (example for VMWare Player, VMWare Workstation should be similar):&lt;br /&gt;
** If you want to assign more than 8 GB virtual flash:&lt;br /&gt;
*** Do &#039;&#039;&#039;not&#039;&#039;&#039; directly start/doubleclick the vmx file!&lt;br /&gt;
*** Start the VMware Player and Open the vmx file with &#039;&#039;&#039;Open a Virtual Machine&#039;&#039;&#039;.&lt;br /&gt;
*** Open &#039;&#039;&#039;Edit virtual machine settings&#039;&#039;&#039;.&lt;br /&gt;
*** Select the hard disk and &#039;&#039;&#039;Expand&#039;&#039;&#039; it under &#039;&#039;&#039;Utilities&#039;&#039;&#039; to the wished size.&lt;br /&gt;
*** Apply the change and klick &#039;&#039;&#039;Play virtual machine&#039;&#039;&#039;.&lt;br /&gt;
** If 8 GB are enough, simply double click the vmx file and Linux will start.&lt;br /&gt;
* The first time, a script will automatically configure a new partition, the web server etc., which will take some time. The waiting time depends on the CPU of the computer running the vmware player. In some cases the waiting time can be up to 30 minutes, in most cases the installation finishes in about 2-5 minutes.&lt;br /&gt;
* In the meantime, fetch your IP from the VMWare Player screen or login as root and get your IP address with the command &#039;&#039;&#039;ifconfig&#039;&#039;&#039;.&lt;br /&gt;
* Login to the web server to see the installation progress (it may take some minutes until the web server is up).&lt;br /&gt;
* Linux will restart automatically after the first time installation has finished.&lt;br /&gt;
* Linux install has finished.&lt;br /&gt;
&lt;br /&gt;
===Hotfix Installation===&lt;br /&gt;
If you have already installed the latest version of the Linux Application Platform, simply download the Linux...HotfixIncremental for your platform (VM or IPxx10/IPx11) or if you have missed some hotfixes, download the Linux...HotfixCumulative archive, which contains all hotfixes since hotfix1.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Upload this hotfix archive [[Reference10:Concept_Linux_Application_Platform#Upload.2FUpdate|here]].&lt;br /&gt;
&lt;br /&gt;
====Refreshing issue on installation====&lt;br /&gt;
You might get a PHP error when the browser is refreshing during the installation. Just refresh (F5) the page and you&#039;ll get the installation progress again.&lt;br /&gt;
&lt;br /&gt;
=== Upgrade from a previous major Release ===&lt;br /&gt;
For instructions how to upgrade from a previous major release (such as V9 to V10), see &#039;&#039;Upgrading Linux Application Platform&#039;&#039; in [[Howto:Firmware_Upgrade_V9_V10|Firmware Upgrade V9 V10]].&lt;br /&gt;
&lt;br /&gt;
===Static IP===&lt;br /&gt;
The Linux itself &#039;&#039;&#039;must&#039;&#039;&#039; be running in DHCP client mode on an IPxx10/IPxx11 gateway to run properly. If you want to assign a static IP address, do it like this:&lt;br /&gt;
&lt;br /&gt;
* On an IPxx10/IPxx11: assign a static IP under [[Reference10:Linux/IP]], this will do an internal DHCP response to the Linux that&#039;s running as DHCP client mode.&lt;br /&gt;
* On a VMWare: assign a static IP in your local DHCP server for your MAC address defined in the *.vmx file or configure a static IP address under [[ #Configure_IP | Configure IP ]].&lt;br /&gt;
&lt;br /&gt;
===IPxx10/IPxx11 Transit network for Linux===&lt;br /&gt;
When running Linux on an innovaphone device IPxx10/IPxx11 there is no dedicated network interface for the Linux machine. Instead we have a special transit network between the Linux and the device. The Linux will always operate as DHCP Client mode.&lt;br /&gt;
&lt;br /&gt;
Any ARP request done by the Linux machine will always get the same ARP result that will be the internal &amp;quot;NIC&amp;quot; inside the device, so all packets are always sent to the same IPxx10/IPxx11 device that works as a router. When the packet sent by the Linux machine arrives the innovaphone device, it will follow the IP routing table of the device itself.&lt;br /&gt;
&lt;br /&gt;
In case we have a single network (voice) we will have no problem since the default gateway is just one. However, if we wish to split into two networks (voice and data) and the Linux machine should have a different default gateway, this has no effect since IP routing is based on the innovaphone device IP routing table, because we can&#039;t have two default gateways at the same time.&lt;br /&gt;
&lt;br /&gt;
==Administration==&lt;br /&gt;
&lt;br /&gt;
===General===&lt;br /&gt;
&lt;br /&gt;
====Configure IP====&lt;br /&gt;
&lt;br /&gt;
The IP configuration on the Linux Application Platform is &#039;&#039;&#039;only&#039;&#039;&#039; available on a &#039;&#039;&#039;VM&#039;&#039;&#039;! A static IP for a Linux Application Platform for an IPxx10/IPxx11 can be configured on your gateway under Linux/IP.&lt;br /&gt;
&lt;br /&gt;
* Mode: either DHCP Client or Static&lt;br /&gt;
* [IP Address]: the desired static IP address&lt;br /&gt;
* [Subnet Mask]&lt;br /&gt;
* [Gateway]&lt;br /&gt;
* [DNS Server]&lt;br /&gt;
* [Alternate DNS Server]&lt;br /&gt;
&lt;br /&gt;
The optional parameters in [] can be only configured, if &#039;&#039;&#039;Static&#039;&#039;&#039; is selected as mode.&lt;br /&gt;
&lt;br /&gt;
====Change the root credentials====&lt;br /&gt;
&lt;br /&gt;
Here you can change the credentials of the Linux root user.&amp;lt;br&amp;gt;&lt;br /&gt;
Default password: &#039;&#039;&#039;iplinux&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Configure Authenticated URLs====&lt;br /&gt;
&lt;br /&gt;
Configure credentials for authenticated URLs. These credentials will be used in automatic backups.&amp;lt;br&amp;gt;&lt;br /&gt;
You can add/remove Urls with the &#039;&#039;&#039;+&#039;&#039;&#039; and &#039;&#039;&#039;-&#039;&#039;&#039; at the right side of the list.&lt;br /&gt;
&lt;br /&gt;
* URL: the URL, e.g. https://172.16.123.123/backup&lt;br /&gt;
* User: the user for this URL&lt;br /&gt;
* Password: the password for this URL&lt;br /&gt;
&lt;br /&gt;
====Configure NTP server====&lt;br /&gt;
&lt;br /&gt;
Configures a NTP server.&lt;br /&gt;
&lt;br /&gt;
* NTP Server: the IP of the NTP Server&lt;br /&gt;
&lt;br /&gt;
====Change Timezone====&lt;br /&gt;
&lt;br /&gt;
Default is Europe/Berlin but you can change that to a valid timezone (an error is given if timezone not present).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Change postgresql admin password====&lt;br /&gt;
&lt;br /&gt;
If innovaphone Reporting is installed, you can configure another password for the postgres admin user.&amp;lt;br&amp;gt;&lt;br /&gt;
Default password: &#039;&#039;&#039;postgres&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Web Server===&lt;br /&gt;
&lt;br /&gt;
We use lighttpd version 1.4.32. The linux web server user is &#039;&#039;&#039;www-data&#039;&#039;&#039; and group user also &#039;&#039;&#039;www-data&#039;&#039;&#039;. Root directory for the web-server is &#039;&#039;&#039;/var/www/innovaphone&#039;&#039;&#039;. This information is mainly relevant if you plan to develope custom applications and integrate them into linux application platform.&lt;br /&gt;
&lt;br /&gt;
Default users and password for the different levels on the Linux application plattform (see figure below):&lt;br /&gt;
[[image:Linux_Application_hierarki.PNG]]&lt;br /&gt;
&lt;br /&gt;
====Change web server properties and public access to the web/webdav====&lt;br /&gt;
* Force HTTPS: enables redirection for HTTP to HTTPS&lt;br /&gt;
* Public Web Paths: these paths are not password protected, e.g. &#039;/ap&#039;&lt;br /&gt;
* Public Webdav Paths: these webdav paths are not password protected, e.g. &#039;/backup&#039;&lt;br /&gt;
** These paths are by default readonly. You can set the &#039;Write&#039; flag to make the path also writable. This flag will be anyway ignored if credentials are provided.&amp;lt;br&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&amp;lt;IPadr&amp;gt;&#039;&#039;&amp;lt;code&amp;gt;/webdav/&amp;lt;/code&amp;gt; is the root directory for webdav files. If you want to access a directory/file without credentials you have to add this directory to the Public Webdav Paths.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;code&amp;gt;/webdav/background/&amp;lt;/code&amp;gt; Here you have the background pictures for your Phones.&amp;lt;br&amp;gt;&lt;br /&gt;
Public Webdav Paths: &amp;lt;code&amp;gt;/background&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/background/a&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Now you have a public access to the folder background. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enter a single &#039;&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;&#039; for a public root directory. All sub directories and files will be also public then.&amp;lt;br&amp;gt;&lt;br /&gt;
* If you enter e.g. &#039;&amp;lt;code&amp;gt;/update/&amp;lt;/code&amp;gt;&#039;, the directory &#039;update&#039; and all sub directories/files will be public.&amp;lt;br&amp;gt;&lt;br /&gt;
* If you enter e.g. &#039;&amp;lt;code&amp;gt;/update&amp;lt;/code&amp;gt;&#039;, only the directory &#039;update&#039; and its files will be public.&lt;br /&gt;
&lt;br /&gt;
Important: Linux file names are case sensitive (so &amp;lt;code&amp;gt;/Update&amp;lt;/code&amp;gt; is not equal &amp;lt;code&amp;gt;/update&amp;lt;/code&amp;gt;)!.&lt;br /&gt;
&lt;br /&gt;
====Change the Linux web server credentials====&lt;br /&gt;
&lt;br /&gt;
Here you can change the credentials for Web Server access.&lt;br /&gt;
&lt;br /&gt;
If running VMWare, default password is &#039;&#039;&#039;linux&#039;&#039;&#039;. If running IPXX10, password is the one entered at the end of first installation (admin password of the device where linux is running)&lt;br /&gt;
&lt;br /&gt;
====Change the Linux webdav access credentials====&lt;br /&gt;
&lt;br /&gt;
Here you can change the credentials for webdav access.&lt;br /&gt;
&lt;br /&gt;
If running VMWare, default password is &#039;&#039;&#039;linux&#039;&#039;&#039;. If running IPXX10, password is the one entered at the end of first installation (admin password of the device where linux is running)&lt;br /&gt;
&lt;br /&gt;
====Change application access credentials====&lt;br /&gt;
&lt;br /&gt;
If you have installed an application, which has the lighttpd-auth property set in its configuration file, you can configure a separate user/password for the applications web site.&amp;lt;br&amp;gt;&lt;br /&gt;
If you want to disable the separate authentication, leave the &#039;&#039;&#039;user&#039;&#039;&#039; field empty and enter the currently configured password. The authentication will be the same as the root web server authentication afterwards.&amp;lt;br&amp;gt;&lt;br /&gt;
One can just login on the application web site with this access.&lt;br /&gt;
&lt;br /&gt;
A configured access overrides a configured public web path to &#039;/apps/application-name&#039;!&lt;br /&gt;
&lt;br /&gt;
====Configure mutual TLS====&lt;br /&gt;
&lt;br /&gt;
If you need mutual TLS for innovaphone devices with a certificate signed by innovaphone, you can activate mutual TLS for a configurable &#039;&#039;&#039;port&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Currently we&#039;re just supporting client certificates signed by innovaphone&#039;s &#039;&#039;innovaphone Device Certification Authority&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The physical mutual TLS path is &#039;&#039;&#039;/var/www/innovaphone/mtls&#039;&#039;&#039;. Here you can put your script files, e.g. mtls.php.&amp;lt;br&amp;gt;&lt;br /&gt;
You then call this script file by &#039;&#039;&#039;https://linux-ip:mtls-port/mtls.php&#039;&#039;&#039;, as this path is the document root for the configured port.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How to upload the script:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using a webdav client (like NetDrive) upload the script to the webdav folder.&lt;br /&gt;
Afterwards connect with Putty to the linux.&lt;br /&gt;
&lt;br /&gt;
The uploaded file is under /var/www/innovaphone/webdav and we must move it to /var/www/innovaphone/mtls&lt;br /&gt;
&lt;br /&gt;
===Certificates===&lt;br /&gt;
&lt;br /&gt;
The current server certificate installed on the web server is shown here. A self signed certificate, innovaphone-linux, is installed by default. It is recommended to change it with your own certificate.&lt;br /&gt;
&lt;br /&gt;
It is also possible to trust or reject other certificates.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Currently the LAP doesn&#039;t support the upload of a password protected certificate. As a workaround it is possible to convert the certificate with OpenSSL (on windows or Linux) to PEM format without password and upload this one.&lt;br /&gt;
&lt;br /&gt;
With the following openssl command, the password protected certificate can be changed into an unprotected certificate. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;openssl pkcs12 -in&amp;lt;/code&amp;gt; &#039;&#039;CertificateWithPasswort&#039;&#039; &amp;lt;code&amp;gt;-out&amp;lt;/code&amp;gt; &#039;&#039;CertificateWithoutPasswort&#039;&#039;.pem &amp;lt;code&amp;gt;-nodes&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The unprotected certificate should be deleted directly after upload for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to create a private, unsigned certificate you can do this with the following commands on the Linux AP CLI.&lt;br /&gt;
It is best to go in a folder which can be reached via http later as &amp;lt;code&amp;gt;/var/www/innovaphone/webdav/...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enter the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days xxxx (insert number)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;code&amp;gt;-nodes&amp;lt;/code&amp;gt; if you don&#039;t want to protect your private key with a passphrase.&lt;br /&gt;
&lt;br /&gt;
You now will be asked for certificate information.&lt;br /&gt;
&lt;br /&gt;
To merge the certificate and key you can enter the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cat cert.pem &amp;gt;&amp;gt; key.pem&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The file key.pem can now be uploaded via the web interface of the Linux AP.&lt;br /&gt;
&lt;br /&gt;
===Backup===&lt;br /&gt;
&lt;br /&gt;
The web server can be configured to poll a Command File URL (on a web server).&amp;lt;br&amp;gt;&lt;br /&gt;
The backup process is similar to [[Reference10:Services/Update]].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An alarm server can be also configured to receive alarms during an automatic backup: [[ #Alarm_Server | Alarm Server under Diagnostics ]].&lt;br /&gt;
&lt;br /&gt;
At the bottom you will see a list of the current automatic backup serials from the Command File URL and the log of the last automatic backups.&lt;br /&gt;
&lt;br /&gt;
[[Image:backup_restore.jpg]]&lt;br /&gt;
&lt;br /&gt;
====Command File====&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 saveinnovaphonecfgs http://172.16.123.123/webdav/backup/cfgs-#i-#b10.tar.gz&lt;br /&gt;
&lt;br /&gt;
The available default commands are:&lt;br /&gt;
&lt;br /&gt;
=====saveinnovaphonecfgs=====&lt;br /&gt;
&lt;br /&gt;
Saves all neccessary configuration files (no application specific files) as a tar gz archive (so you should use .tar.gz as ending).&lt;br /&gt;
&lt;br /&gt;
=====saveinnovaphonelogs=====&lt;br /&gt;
&lt;br /&gt;
Saves all available (also application related) log files as a tar gz archive (so you should use .tar.gz as ending).&lt;br /&gt;
&lt;br /&gt;
=====saveinnovaphone-applicationnamelogs=====&lt;br /&gt;
&lt;br /&gt;
Saves log files as a tar gz archive (so you should use .tar.gz as ending) for applicationname (reporting, exchange or faxserver)&lt;br /&gt;
&#039;&#039;&#039;saveinnovaphone-reportinglogs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====saveinnovaphone-applicationnamecfgs=====&lt;br /&gt;
&lt;br /&gt;
Saves all neccessary configuration files as a tar gz archive (so you should use .tar.gz as ending) for applicationname (reporting, exchange or faxserver)&lt;br /&gt;
&#039;&#039;&#039;saveinnovaphone-reportingcfgs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====saveinnovaphone-applicationnamedb=====&lt;br /&gt;
&lt;br /&gt;
Saves ddbb if existing as a tar gz archive (so you should use .tar.gz as ending) for applicationname (reporting, exchange or faxserver)&lt;br /&gt;
&#039;&#039;&#039;saveinnovaphone-reportingdb&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====times=====&lt;br /&gt;
Executes the following command(s) only, if the specified time matches and only once per hour (independent of poll timeout value).&amp;lt;br&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# both commands always executed&lt;br /&gt;
saveinnovaphonelogs http://xxx.xxx.xxx.xxx.xxx/webdav/backup/linux-logs-#i-#m-#b10.tar.gz&lt;br /&gt;
saveinnovaphonecfgs http://xxx.xxx.xxx.xxx.xxx/webdav/backup/linux-cfg-#i-#m-#b10.tar.gz&lt;br /&gt;
# commands only from monday till saturday at 10am and 11am executed. &lt;br /&gt;
times day:1,2,3,4,5 hour:10,11 &lt;br /&gt;
saveinnovaphone-reportingcfgs http://xxx.xxx.xxx.xxx.xxx/webdav/backup/linux-innovaphone-reporting-cfgs-#i-#d-#b10.tar.gz&lt;br /&gt;
saveinnovaphone-reportinglogs http://xxx.xxx.xxx.xxx.xxx/webdav/backup/linux-innovaphone-reporting-logs-#i-#d-#b10.tar.gz&lt;br /&gt;
# commands only Saturdays and Sundays at 00am executed. &lt;br /&gt;
times day:6,7 hour:00 &lt;br /&gt;
saveinnovaphone-reportingcfgs http://xxx.xxx.xxx.xxx.xxx/webdav/backup/linux-innovaphone-reporting-cfgs-#i-#d-#b10.tar.gz&lt;br /&gt;
saveinnovaphone-reportinglogs http://xxx.xxx.xxx.xxx.xxx/webdav/backup/linux-innovaphone-reporting-logs-#i-#d-#b10.tar.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* day goes from 1 (Monday) to 7 (Sunday).&amp;lt;br&amp;gt;&lt;br /&gt;
* hour goes from 00 to 23.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can specify multiple times commands to override the last one.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Backup file name macros=====&lt;br /&gt;
&lt;br /&gt;
You can use some macros for the backup filename:&lt;br /&gt;
&lt;br /&gt;
* #i - will be replaced with the current IP address&lt;br /&gt;
* #m - will be replaced with the current MAC address&lt;br /&gt;
* #d - will be replaced with date/time in format Ymd-His (20110231-111010)&lt;br /&gt;
* #bxx - will be replaced with the current backup index, whilst xx is the maximum index&lt;br /&gt;
&lt;br /&gt;
====Save configuration files/data====&lt;br /&gt;
&lt;br /&gt;
Open this link to see all available files/data/logs to download them manually.&lt;br /&gt;
&lt;br /&gt;
 Password files for web server authentication won&#039;t be saved!&lt;br /&gt;
&lt;br /&gt;
====Restore configuration files/data====&lt;br /&gt;
&lt;br /&gt;
Open this link to restore all available files/data.&lt;br /&gt;
&lt;br /&gt;
 Password files for web server authentication won&#039;t be restored!&lt;br /&gt;
&lt;br /&gt;
===Relay Hosts===&lt;br /&gt;
&lt;br /&gt;
The Application Platform contains a mail client which speaks SMTP. &lt;br /&gt;
The SMTP daemon (postfix) looks up by default the DNS MX record of the recipient email address.&amp;lt;br&amp;gt;&lt;br /&gt;
Relay SMTP hosts can also be configured to deliver the mails. Each relay host is related to a &#039;&#039;&#039;sender&#039;&#039;&#039; mail address or a &#039;&#039;&#039;sender&#039;&#039;&#039; mail domain. TLS is used if the host supports it.&amp;lt;br&amp;gt;&lt;br /&gt;
Examples of the server entry:&lt;br /&gt;
; mydomain.com: MX record to the domain&lt;br /&gt;
; smtphost: host name with MX record lookup&lt;br /&gt;
; [gateway.example.com]: host name with DNS lookup&lt;br /&gt;
; [an.ip.add.ress]: IP address without DNS lookup&lt;br /&gt;
The form [hostname] turns off MX lookups. See also [http://www.postfix.org/postconf.5.html#relayhost the postfix documentation].&amp;lt;br&amp;gt;&lt;br /&gt;
If anonymous SMTP is to be used, user and password must be left empty.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:relay_hosts.jpg]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Important to use &amp;quot;[]&amp;quot; like in the picture.&lt;br /&gt;
&lt;br /&gt;
Currently innovaphone Reporting and innovaphone Faxserver are using these relay hosts, if entered.&lt;br /&gt;
&lt;br /&gt;
===Database===&lt;br /&gt;
&lt;br /&gt;
The innovaphone database is created to store e.g. relay hosts. &lt;br /&gt;
PostgreSQL is also available for other applications and any of them could create its own database. &lt;br /&gt;
&lt;br /&gt;
====Password====&lt;br /&gt;
&lt;br /&gt;
The database user is &#039;&#039;&#039;innovaphone&#039;&#039;&#039; with default password &#039;&#039;&#039;innovaphone&#039;&#039;&#039;. &lt;br /&gt;
This password may be changed here.&lt;br /&gt;
&lt;br /&gt;
====Remote Access====&lt;br /&gt;
&lt;br /&gt;
There are tools (PgAdmin III) that allow to connect to application databases remotely. &lt;br /&gt;
It is first needed to configure the IP you are connecting from here. (Only Single-IP entry it&#039;s allowed, no submask or wildcard for multiple IPs)&lt;br /&gt;
&lt;br /&gt;
For the PgAdmin III it is imporant to use innovaphone as Service-DB (Wartungs-DB). Default login credentials - User: innovaphone - Password: innovaphone&lt;br /&gt;
&lt;br /&gt;
===Announcements===&lt;br /&gt;
&lt;br /&gt;
You can upload a 16bit,8khz,mono wave file, which will be converted to G711U/G711A/G723/G729 .&amp;lt;br&amp;gt;&lt;br /&gt;
The converted files will be stored inside the webdav/announcements folder, e.g. http://172.16.111.111/webdav/announcements/test.g7xx&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
If you check the &#039;&#039;&#039;Return files as ZIP file&#039;&#039;&#039; flag, you will get a ZIP file, which contains the converted files. These files are not stored locally then! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For the new Codec G722, OPUS-NB and OPUS-WB you have to use the online converter available on my.innovaphone portal (login necessary first): https://my.innovaphone.com/support.php or on our website https://www.innovaphone.com/en/support/convert.html. No Conversion of new codecs is possible with Linux AP !&lt;br /&gt;
&lt;br /&gt;
==Applications==&lt;br /&gt;
&lt;br /&gt;
===List===&lt;br /&gt;
&lt;br /&gt;
A list of all currently installed applications.&amp;lt;br&amp;gt;&lt;br /&gt;
If an application has an own web interface, you can reach it by using the application name link.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Uninstall====&lt;br /&gt;
Use the uninstall link in the list to uninstall an application.&lt;br /&gt;
&lt;br /&gt;
===Upload/Update===&lt;br /&gt;
&lt;br /&gt;
Here all new applications, application updates and application platform updates are installed.&amp;lt;br&amp;gt;&lt;br /&gt;
After uploading the file, the installation will start automatically and the installation process will be shown. The page refreshes until the installation has finished.&lt;br /&gt;
&lt;br /&gt;
==Diagnostics==&lt;br /&gt;
&lt;br /&gt;
===Logs===&lt;br /&gt;
&lt;br /&gt;
Here you can view, download or clear the available log files from the application platform or from installed applications.&amp;lt;br&amp;gt;&lt;br /&gt;
You can also download all log files at once (this archiv also contains older versions from the log files).&lt;br /&gt;
&lt;br /&gt;
===RPCAP===&lt;br /&gt;
&lt;br /&gt;
Enable/disable RPCAP for use with Wireshark.&amp;lt;br&amp;gt;&lt;br /&gt;
A link will be displayed, which you can use within Wireshark.&lt;br /&gt;
&lt;br /&gt;
===Alarm Server===&lt;br /&gt;
&lt;br /&gt;
Configure an innovaphone device as alarm server:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ip&#039;&#039;&#039;: IP address of the innovaphone device&lt;br /&gt;
* [&#039;&#039;&#039;port&#039;&#039;&#039;]&lt;br /&gt;
* [&#039;&#039;&#039;user&#039;&#039;&#039;]: user for authentication to the alarm server &lt;br /&gt;
* [&#039;&#039;&#039;password&#039;&#039;&#039;]&lt;br /&gt;
* [&#039;&#039;&#039;https&#039;&#039;&#039;]: use https to send the alarm&lt;br /&gt;
&lt;br /&gt;
Options in &#039;&#039;&#039;[]&#039;&#039;&#039; are optional.&lt;br /&gt;
&lt;br /&gt;
 Alarms from installed applications or the application platform itself will be sent to this configured server.&lt;br /&gt;
&lt;br /&gt;
===Status===&lt;br /&gt;
&lt;br /&gt;
View the disk usage.&lt;br /&gt;
&lt;br /&gt;
===Reset===&lt;br /&gt;
====IPxx10====&lt;br /&gt;
&lt;br /&gt;
Shutdown the application platform. You&#039;ll have to restart it over the IPxx10 gateway.&lt;br /&gt;
&lt;br /&gt;
====VMWare====&lt;br /&gt;
&lt;br /&gt;
Shutdown the application platform or reboot it.&lt;br /&gt;
&lt;br /&gt;
===Status PHP script===&lt;br /&gt;
http://LinuxAP/status.php returns an XML file containing the output from the following linux commands:&amp;lt;br&amp;gt;&lt;br /&gt;
* df -H&lt;br /&gt;
* free -h&lt;br /&gt;
* uptime&lt;br /&gt;
* ps -wwweo pid,lstart,time,etime,pcpu,pmem,rsz,vsz,args&lt;br /&gt;
* ss -A inet -ap&lt;br /&gt;
* top -b -n 1&lt;br /&gt;
&lt;br /&gt;
==Use as Log or Alarm Server==&lt;br /&gt;
&lt;br /&gt;
You can use the application platform as a server for innovaphone logs.&amp;lt;br&amp;gt;&lt;br /&gt;
Configure Local-AP(-s)/Remote-AP(-s) on [[Reference10:Services/Logging]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The following scripts are used to retrieve the logs/alarms:&lt;br /&gt;
* logs: /ap/log.fcgi&lt;br /&gt;
* alarms: /ap/alarm.fcgi&lt;br /&gt;
&lt;br /&gt;
So you can make the path &#039;&#039;&#039;/ap&#039;&#039;&#039; public on the &#039;&#039;Linux Web Server&#039;&#039; or you configure an authenticated URL for these files/this path on your &#039;&#039;innovaphone gateway&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 If you configure an authenticated URL, don&#039;t forget to configure port 80 or port 443 for secure transport (Remote-AP-S) like&lt;br /&gt;
 https://111.111.111.111:443/ap or http://111.111.111.111:80/ap&lt;br /&gt;
&lt;br /&gt;
The log and alarm files will be saved unter http://LAP/webdav/log or /alarm. The files are rotated after 1 MB size and four times, so you&#039;ll have max 5 files.&lt;br /&gt;
&lt;br /&gt;
==Use as File/VM-Server==&lt;br /&gt;
&lt;br /&gt;
You can use the application platform as file server, e.g. for udpate scripts, voicemail etc.&amp;lt;br&amp;gt;&lt;br /&gt;
You can access the server with a webdav client via &#039;&#039;&#039;http(s)://Linux-IP/webdav&#039;&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Public access to certain paths etc. can be configured under the [[Reference10:Concept_Linux_Application_Platform#Web_Server | web server configuration]].&lt;br /&gt;
&lt;br /&gt;
Keep in mind that the Linux Filesystem(ext3) is case sensetive. The PBX will always search for lowercase letters. If you name your file ‘greetings.G711A’ it won’t be found. You have to name the file ‘greetings.g711a’.&lt;br /&gt;
&lt;br /&gt;
==Enable further Tracing==&lt;br /&gt;
There are different trace options, which can be enabled by calling a certain php script:&amp;lt;br&amp;gt;&lt;br /&gt;
 https://LINUX-IP/trace.php?level=127&lt;br /&gt;
&lt;br /&gt;
The level is calculated by the addition of one or multiple of the following trace options:&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
 || &#039;&#039;&#039;Option&#039;&#039;&#039; || &#039;&#039;&#039;To add&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_STD || 1&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_DB || 2&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_TIME || 4&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_CALL_FLOW_TOTAL || 8&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_CALL_FLOW || 16&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_PARSE_CFG || 32&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_LDAP || 64&lt;br /&gt;
|-&lt;br /&gt;
 || TRACE_XML || 128&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So currently all trace options are enabled with the level &#039;&#039;&#039;255&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Default trace level are &amp;quot;0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
===Creating own applications===&lt;br /&gt;
See [[Reference10:Concept Linux Application]]&lt;br /&gt;
&lt;br /&gt;
===Tools===&lt;br /&gt;
&lt;br /&gt;
====WinSCP====&lt;br /&gt;
&lt;br /&gt;
[https://winscp.net WinSCP] is a usefull webdav client, which can be used to access webdav of the innovaphone application platform.&lt;br /&gt;
&lt;br /&gt;
====Putty====&lt;br /&gt;
&lt;br /&gt;
[http://www.putty.org/ Putty] is SSH client to connect to the linux application platform.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Configuring a new Kernel===&lt;br /&gt;
If you have installed a hotfix with a new kernel, you will see a warning message on your application platform. Something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code type=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
You&#039;re not running the latest kernel Image-6010-3.4.10!&lt;br /&gt;
Take a look at our wiki to see, what you have to do now!&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To change to the new kernel, you have to reconfigure something on your device, where the CF card is plugged in.&lt;br /&gt;
* First shutdown your Linux (see [[ Reference10:Concept_Linux_Application_Platform#IPxx10 ]])&lt;br /&gt;
* Stop Linux under [[ Reference10:Linux/General ]]&lt;br /&gt;
* Configure the latest kernel file (currently &amp;lt;code&amp;gt;Image-6010-3.4.10&amp;lt;/code&amp;gt;) under [[ Reference10:Linux/General ]] &#039;&#039;&#039;Linux kernel file&#039;&#039;&#039;&lt;br /&gt;
* Start Linux under [[ Reference10:Linux/General ]]&lt;br /&gt;
&lt;br /&gt;
===Alarms of the Application Platform===&lt;br /&gt;
If you have configured an [[ #Alarm_Server | Alarm Server]], you will receive certain alarms.&amp;lt;br&amp;gt;&lt;br /&gt;
Currently, the following alarms exist:&lt;br /&gt;
&lt;br /&gt;
* Disk Usage &amp;gt;= 90%&lt;br /&gt;
* read-only mounted partition&lt;br /&gt;
* bad blocks on CF cards&lt;br /&gt;
* Alarms for the innovaphone Reporting Application, if installed&lt;br /&gt;
* Alarms for the innovaphone Exchange Calendar Connector Application, if installed&lt;br /&gt;
* Alarms for the innovaphone Faxserver Application, if installed&lt;br /&gt;
&lt;br /&gt;
===Initially installed packages===&lt;br /&gt;
&lt;br /&gt;
The following packages are already installed without any application:&lt;br /&gt;
&lt;br /&gt;
* adduser&lt;br /&gt;
* apt&lt;br /&gt;
* apt-utils&lt;br /&gt;
* aptitude&lt;br /&gt;
* aptitude-common&lt;br /&gt;
* base-files&lt;br /&gt;
* base-passwd&lt;br /&gt;
* bash&lt;br /&gt;
* binutils&lt;br /&gt;
* bsdmainutils&lt;br /&gt;
* bsdutils&lt;br /&gt;
* bzip2&lt;br /&gt;
* ca-certificates&lt;br /&gt;
* comerr-dev&lt;br /&gt;
* coreutils&lt;br /&gt;
* cpio&lt;br /&gt;
* cpp&lt;br /&gt;
* cpp-4.7&lt;br /&gt;
* cpp-4.6&lt;br /&gt;
* cron&lt;br /&gt;
* curl&lt;br /&gt;
* dash&lt;br /&gt;
* db-util&lt;br /&gt;
* db5.1-util&lt;br /&gt;
* debconf&lt;br /&gt;
* debconf-i18n&lt;br /&gt;
* debian-archive-keyring&lt;br /&gt;
* debianutils&lt;br /&gt;
* diffutils&lt;br /&gt;
* dmidecode&lt;br /&gt;
* dmsetup&lt;br /&gt;
* dos2unix&lt;br /&gt;
* dovecot-common&lt;br /&gt;
* dovecot-core&lt;br /&gt;
* dovecot-pgsql&lt;br /&gt;
* dovecot-pop3d&lt;br /&gt;
* dovecot-sieve&lt;br /&gt;
* dpkg&lt;br /&gt;
* e2fslibs&lt;br /&gt;
* e2fsprogs&lt;br /&gt;
* file&lt;br /&gt;
* findutils&lt;br /&gt;
* gamin&lt;br /&gt;
* gcc&lt;br /&gt;
* gcc-4.7&lt;br /&gt;
* gcc-4.6&lt;br /&gt;
* gcc-4.6-base&lt;br /&gt;
* gcc-4.7-base&lt;br /&gt;
* gettext-base&lt;br /&gt;
* gnupg&lt;br /&gt;
* gpgv&lt;br /&gt;
* grep&lt;br /&gt;
* groff-base&lt;br /&gt;
* grub-common&lt;br /&gt;
* grub-legacy&lt;br /&gt;
* gzip&lt;br /&gt;
* hdparm&lt;br /&gt;
* hostname&lt;br /&gt;
* ifupdown&lt;br /&gt;
* info&lt;br /&gt;
* initramfs-tools&lt;br /&gt;
* initscripts&lt;br /&gt;
* insserv&lt;br /&gt;
* install-info&lt;br /&gt;
* iproute&lt;br /&gt;
* iptables&lt;br /&gt;
* iputils-ping&lt;br /&gt;
* isc-dhcp-client&lt;br /&gt;
* isc-dhcp-common&lt;br /&gt;
* klibc-utils&lt;br /&gt;
* kmod&lt;br /&gt;
* krb5-multidev&lt;br /&gt;
* libacl1&lt;br /&gt;
* libapt-inst1.5&lt;br /&gt;
* libapt-pkg4.12&lt;br /&gt;
* libasprintf0c2&lt;br /&gt;
* libattr1&lt;br /&gt;
* libblkid1&lt;br /&gt;
* libboost-iostreams1.49.0&lt;br /&gt;
* libbsd0&lt;br /&gt;
* libbz2-1.0&lt;br /&gt;
* libbz2-dev&lt;br /&gt;
* libc-bin&lt;br /&gt;
* libc-client2007e&lt;br /&gt;
* libc-dev-bin&lt;br /&gt;
* libc6&lt;br /&gt;
* libc6-dev&lt;br /&gt;
* libcap2&lt;br /&gt;
* libclass-isa-perl&lt;br /&gt;
* libcomerr2&lt;br /&gt;
* libcurl3&lt;br /&gt;
* libcurl4-openssl-dev&lt;br /&gt;
* libcwidget3&lt;br /&gt;
* libdb5.1&lt;br /&gt;
* libdevmapper1.02.1&lt;br /&gt;
* libedit2&lt;br /&gt;
* libept1.4.12&lt;br /&gt;
* libexpat1&lt;br /&gt;
* libfcgi-dev&lt;br /&gt;
* libfcgi0ldbl&lt;br /&gt;
* libffi5&lt;br /&gt;
* libfreetype6&lt;br /&gt;
* libfuse2&lt;br /&gt;
* libgamin-dev&lt;br /&gt;
* libgamin0&lt;br /&gt;
* libgcc1&lt;br /&gt;
* libgcrypt11&lt;br /&gt;
* libgcrypt11-dev&lt;br /&gt;
* libgdbm-dev&lt;br /&gt;
* libgdbm3&lt;br /&gt;
* libglib2.0-0&lt;br /&gt;
* libgmp10&lt;br /&gt;
* libgnutls-dev&lt;br /&gt;
* libgnutls-openssl27&lt;br /&gt;
* libgnutls26&lt;br /&gt;
* libgnutlsxx27&lt;br /&gt;
* libgomp1&lt;br /&gt;
* libgpg-error-dev&lt;br /&gt;
* libgpg-error0&lt;br /&gt;
* libgpgme11&lt;br /&gt;
* libgpm2&lt;br /&gt;
* libgssapi-krb5-2&lt;br /&gt;
* libgssrpc4&lt;br /&gt;
* libidn11&lt;br /&gt;
* libidn11-dev&lt;br /&gt;
* libitm1&lt;br /&gt;
* libk5crypto3&lt;br /&gt;
* libkadm5clnt-mit8&lt;br /&gt;
* libkadm5srv-mit8&lt;br /&gt;
* libkdb5-6&lt;br /&gt;
* libkeyutils1&lt;br /&gt;
* libklibc&lt;br /&gt;
* libkmod2&lt;br /&gt;
* libkrb5-3&lt;br /&gt;
* libkrb5-dev&lt;br /&gt;
* libkrb5support0&lt;br /&gt;
* libldap-2.4-2&lt;br /&gt;
* libldap2-dev&lt;br /&gt;
* liblocale-gettext-perl&lt;br /&gt;
* liblzma5&lt;br /&gt;
* libmagic1&lt;br /&gt;
* libmemcache-dev&lt;br /&gt;
* libmemcache0&lt;br /&gt;
* libmount1&lt;br /&gt;
* libmpc2&lt;br /&gt;
* libmpfr4&lt;br /&gt;
* libmysqlclient18&lt;br /&gt;
* libncurses5&lt;br /&gt;
* libncursesw5&lt;br /&gt;
* libnewt0.52&lt;br /&gt;
* libnfnetlink0&lt;br /&gt;
* libonig2&lt;br /&gt;
* libopts25&lt;br /&gt;
* libp11-kit-dev&lt;br /&gt;
* libp11-kit0&lt;br /&gt;
* libpam-modules&lt;br /&gt;
* libpam-modules-bin&lt;br /&gt;
* libpam-pgsql&lt;br /&gt;
* libpam-runtime&lt;br /&gt;
* libpam0g&lt;br /&gt;
* libpam0g-dev&lt;br /&gt;
* libparted0debian1&lt;br /&gt;
* libpcre3&lt;br /&gt;
* libpcre3-dev&lt;br /&gt;
* libpcrecpp0&lt;br /&gt;
* libpipeline1&lt;br /&gt;
* libpng12-0&lt;br /&gt;
* libpng12-dev&lt;br /&gt;
* libpopt0&lt;br /&gt;
* libpq-dev&lt;br /&gt;
* libpq5&lt;br /&gt;
* libprocps0&lt;br /&gt;
* libpth20&lt;br /&gt;
* libqdbm14&lt;br /&gt;
* libquadmath0&lt;br /&gt;
* libreadline6&lt;br /&gt;
* librtmp-dev&lt;br /&gt;
* librtmp0&lt;br /&gt;
* libsasl2-2&lt;br /&gt;
* libsasl2-modules&lt;br /&gt;
* libselinux1&lt;br /&gt;
* libsemanage-common&lt;br /&gt;
* libsemanage1&lt;br /&gt;
* libsepol1&lt;br /&gt;
* libsigc++-2.0-0c2a&lt;br /&gt;
* libslang2&lt;br /&gt;
* libsqlite3-0&lt;br /&gt;
* libsqlite3-dev&lt;br /&gt;
* libss2&lt;br /&gt;
* libssh2-1&lt;br /&gt;
* libssh2-1-dev&lt;br /&gt;
* libssl-dev&lt;br /&gt;
* libssl1.0.0&lt;br /&gt;
* libstdc++6&lt;br /&gt;
* libtasn1-3&lt;br /&gt;
* libtasn1-3-dev&lt;br /&gt;
* libtext-charwidth-perl&lt;br /&gt;
* libtext-iconv-perl&lt;br /&gt;
* libtext-wrapi18n-perl&lt;br /&gt;
* libtinfo5&lt;br /&gt;
* libtokyocabinet9&lt;br /&gt;
* libudev0&lt;br /&gt;
* libusb-0.1-4&lt;br /&gt;
* libustr-1.0-1&lt;br /&gt;
* libuuid-perl&lt;br /&gt;
* libuuid1&lt;br /&gt;
* libwrap0&lt;br /&gt;
* libxapian22&lt;br /&gt;
* libxml2&lt;br /&gt;
* libxml2-dev&lt;br /&gt;
* libxml2-utils&lt;br /&gt;
* linux-base&lt;br /&gt;
* linux-image-3.2.0-4-686-pae&lt;br /&gt;
* linux-libc-dev&lt;br /&gt;
* locales&lt;br /&gt;
* login&lt;br /&gt;
* logrotate&lt;br /&gt;
* lsb-base&lt;br /&gt;
* lsb-release&lt;br /&gt;
* make&lt;br /&gt;
* makedev&lt;br /&gt;
* man-db&lt;br /&gt;
* manpages&lt;br /&gt;
* manpages-dev&lt;br /&gt;
* mawk&lt;br /&gt;
* mime-support&lt;br /&gt;
* mlock&lt;br /&gt;
* module-init-tools&lt;br /&gt;
* mount&lt;br /&gt;
* multiarch-support&lt;br /&gt;
* mysql-common&lt;br /&gt;
* nano&lt;br /&gt;
* ncurses-base&lt;br /&gt;
* ncurses-bin&lt;br /&gt;
* net-tools&lt;br /&gt;
* netbase&lt;br /&gt;
* netcat-traditional&lt;br /&gt;
* ntp&lt;br /&gt;
* ntpdate&lt;br /&gt;
* openssh-client&lt;br /&gt;
* openssh-server&lt;br /&gt;
* openssl&lt;br /&gt;
* parted&lt;br /&gt;
* passwd&lt;br /&gt;
* patch&lt;br /&gt;
* perl-base&lt;br /&gt;
* php-pear&lt;br /&gt;
* php-xml-parser&lt;br /&gt;
* php-xml-serializer&lt;br /&gt;
* php5-cgi&lt;br /&gt;
* php5-cli&lt;br /&gt;
* php5-common&lt;br /&gt;
* php5-curl&lt;br /&gt;
* php5-imap&lt;br /&gt;
* php5-pgsql&lt;br /&gt;
* php5-xcache&lt;br /&gt;
* pkg-config&lt;br /&gt;
* postfix&lt;br /&gt;
* postfix-pcre&lt;br /&gt;
* postfix-pgsql&lt;br /&gt;
* postgresql-9.1&lt;br /&gt;
* postgresql-client-9.1&lt;br /&gt;
* postgresql-client-common&lt;br /&gt;
* postgresql-common&lt;br /&gt;
* procps&lt;br /&gt;
* psmisc&lt;br /&gt;
* python&lt;br /&gt;
* python-minimal&lt;br /&gt;
* python2.7&lt;br /&gt;
* python2.7-minimal&lt;br /&gt;
* rdate&lt;br /&gt;
* readline-common&lt;br /&gt;
* rsyslog&lt;br /&gt;
* sasl2-bin&lt;br /&gt;
* sed&lt;br /&gt;
* sensible-utils&lt;br /&gt;
* shared-mime-info&lt;br /&gt;
* ssh&lt;br /&gt;
* ssl-cert&lt;br /&gt;
* sudo&lt;br /&gt;
* sysv-rc&lt;br /&gt;
* sysvinit&lt;br /&gt;
* sysvinit-utils&lt;br /&gt;
* tar&lt;br /&gt;
* tasksel&lt;br /&gt;
* tasksel-data&lt;br /&gt;
* traceroute&lt;br /&gt;
* tzdata&lt;br /&gt;
* ucf&lt;br /&gt;
* udev&lt;br /&gt;
* util-linux&lt;br /&gt;
* uuid-dev&lt;br /&gt;
* vim&lt;br /&gt;
* vim-common&lt;br /&gt;
* vim-runtime&lt;br /&gt;
* vim-tiny&lt;br /&gt;
* wget&lt;br /&gt;
* whiptail&lt;br /&gt;
* xz-utils&lt;br /&gt;
* zlib1g&lt;br /&gt;
* zlib1g-dev&lt;br /&gt;
* lighttpd-mod-webdav&lt;br /&gt;
* lighttpd&lt;br /&gt;
&lt;br /&gt;
==Known Issues==&lt;br /&gt;
=== Do not update Debian Packages ===&lt;br /&gt;
The Linux application platform comes with the tested set of required Debian packages.  &#039;&#039;It is not recommended to do a manual update of those packages&#039;&#039; (or the kernel itself).  We have seen situations where updated packages had been changed in a non-downward compatible fashion - resulting in the applications running on the Linux application platform not working properly an more!&lt;br /&gt;
&lt;br /&gt;
===Separate authentication for innovaphone applications===&lt;br /&gt;
If you configured a separate authentication, it depends on the used browser, whether you have to re-authenticate on switching between the root web and the innovaphone application web access or not.&lt;br /&gt;
&lt;br /&gt;
===Refreshing issue on hotfix installation===&lt;br /&gt;
[[ Reference10:Concept_Linux_Application_Platform#Refreshing_issue_on_installation | See here. ]]&lt;br /&gt;
&lt;br /&gt;
===Kernel Update in VM Platform===&lt;br /&gt;
The installation of a new kernel fails and this process leaves the system unstable, not being able to install any more debian packages. Hotfix installations will probably fail.&lt;br /&gt;
&lt;br /&gt;
===Outdated packages? Debian Upgrade?===&lt;br /&gt;
From time to time we will deliver upgraded debian packages with a new hotfix. As we have to insure compatibility with our applications, we won&#039;t perform an upgrade for each hotfix!&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Please do &#039;&#039;&#039;not&#039;&#039;&#039; perform an update/upgrade yourself, as this will break future hotfix/application releases. Sometimes we deliver debian packages in our hotfixes and dependencies might be broken if you update/upgrade yourself.&lt;br /&gt;
&lt;br /&gt;
====I want to do it anyway!!!====&lt;br /&gt;
Ok, save your application/ap configuration and data files and install our latest &#039;&#039;&#039;FULL&#039;&#039;&#039; release without any hotfix. Restore the configuration/data files and perform your update/upgrade. Now you can be happy, if everything still works fine...&amp;lt;br&amp;gt;&lt;br /&gt;
Perform these steps for each new hotfix release, as you might not be able to apply a new hotfix.&lt;br /&gt;
&lt;br /&gt;
====Manual Debian 8 (jessie) Upgrade====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Make a backup first and innovaphone won&#039;t be able to support manually upgraded installations&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
If you want an update to Debian 8 (jessie), you can do this via the command line interface (CLI).&lt;br /&gt;
But there are a few steps necessary.&lt;br /&gt;
&lt;br /&gt;
Install or update all innovaphone applications (Reporting, Faxserver, Exchange Calendar Connector) that should be run on the Linux Application Platform.&lt;br /&gt;
&lt;br /&gt;
;Important&lt;br /&gt;
;*Subsequently, no Innovaphone applications may be installed or uninstalled!&lt;br /&gt;
;*Future Innovaphone Service Releases can not be installed after this step.&lt;br /&gt;
&lt;br /&gt;
[[ #Hotfix_Installation | Update ]] the Linux Application Platform and all applications to the latest version (at least Service Release 53).&lt;br /&gt;
&lt;br /&gt;
Make a [[ #Backup | Backup ]] of the Linux Application Platform and all applications.&lt;br /&gt;
&lt;br /&gt;
Make sure, your Linux Application Platform has internet access.&lt;br /&gt;
&lt;br /&gt;
* Login with a terminal client like Putty.&lt;br /&gt;
&lt;br /&gt;
* Enter the Debian 8 (jessie) sources in the sources.list to perform the update. &amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;code&amp;gt;echo &amp;quot;deb http://ftp.de.debian.org/debian jessie main&amp;quot; &amp;gt;&amp;gt; /etc/apt/sources.list&lt;br /&gt;
 echo &amp;quot;deb http://security.debian.org jessie/updates main&amp;quot; &amp;gt;&amp;gt; /etc/apt/sources.list&amp;lt;/code&amp;gt;&lt;br /&gt;
* Perform the update.&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;code&amp;gt;apt-get update&lt;br /&gt;
 apt-get dist-upgrade&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following questions answer as follows.&lt;br /&gt;
 &amp;lt;code&amp;gt;Configuration file &#039;/etc/sysctl.conf&#039;: N =&amp;gt; keep the current version &amp;lt;br&amp;gt;&lt;br /&gt;
 Configuration file &#039;/etc/vim/vimrc&#039;: N =&amp;gt; keep the current version&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the Linux Application Platform.&lt;br /&gt;
 &amp;lt;code&amp;gt;reboot&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Remove the paket php5-xcache, as the new PHP comes with an own opcode cache which creates conflicts. &amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;code&amp;gt;apt-get remove php5-xcache&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Disable php zend extension, which is now incompatible and restart the webserver.&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;code&amp;gt;sed -i &#039;s/zend_extension/;zend_extension/g&#039; /etc/php5/cgi/php.ini&lt;br /&gt;
 /etc/init.d/lighttpd restart&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Change /bin/sh shell. &amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;code&amp;gt;ln -sf /bin/bash /bin/sh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Apply unoconv patch which comes with latest service release.&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;code&amp;gt;cp /usr/bin/unoconv /var/www/innovaphone/apps/innovaphone-faxserver&lt;br /&gt;
 cd /var/www/innovaphone/apps/innovaphone-faxserver&lt;br /&gt;
 patch &amp;lt; /var/www/innovaphone/apps/innovaphone-faxserver/unoconv.patch&lt;br /&gt;
 chown innovaphone-faxserver:www-data unoconv&lt;br /&gt;
 /etc/init.d/innovaphone-faxserver restart&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Important, you cannot upgrade the Linux Application Platform to Debian 9 (stretch).&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
If you have installed one of our upgrade hotfixes and you had installed packages, which weren&#039;t included in innovaphone applications, the upgrade of some packages might have failed. You will see a warning message on your application platform. Something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code type=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
The following packages couldn&#039;t be upgraded due to missing dependencies: php5-cgi php5-cli&lt;br /&gt;
Take a look at our wiki to see, what you have to do now!&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you have to perfom some actions yourself:&lt;br /&gt;
* make sure, your Linux Application Platform has internet access&lt;br /&gt;
* login with a terminal client like Putty&lt;br /&gt;
* start &#039;apt-get update&#039;&lt;br /&gt;
* start &#039;apt-get install php5-cgi php5-cli&#039; (list the packages of the warning message)&lt;br /&gt;
* delete the file /var/www/innovaphone/log/missing_packages.log to clear the warning message:&lt;br /&gt;
** rm /var/www/innovaphone/log/missing_packages.log&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Your installation should be now up to date again.&amp;lt;b/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Database Performance Issues ===&lt;br /&gt;
When you run many applications on your LAP (for example, Reporting or Fax for many PBXs), you may run into database performance issues.  In this case, you will see messages like&lt;br /&gt;
&lt;br /&gt;
 LOG:  checkpoints are occurring too frequently (29 seconds apart)&lt;br /&gt;
 HINT:  Consider increasing the configuration parameter &amp;quot;checkpoint_segments&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
in the postgresql log file.  To fix this, you may carefully increase the setting of &amp;lt;code&amp;gt;checkpoint_segments&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;/etc/postgresql/9.1/main/postgresql.conf&amp;lt;/code&amp;gt;.  By default, this value is not set (commented out):&lt;br /&gt;
&lt;br /&gt;
 #checkpoint_segments = 3  # in logfile segments, min 1, 16MB each&lt;br /&gt;
&lt;br /&gt;
You can change this to 10&lt;br /&gt;
&lt;br /&gt;
 checkpoint_segments = 10  # in logfile segments, min 1, 16MB each&lt;br /&gt;
&lt;br /&gt;
(note the removed comment introducer at the beginning of the line).  Please note that this will take 112MB more disk space on the LAP, so be sure you have enough. &lt;br /&gt;
&lt;br /&gt;
For more details on postgresql tuning, see https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server.&lt;br /&gt;
&lt;br /&gt;
Note that you may need to re-apply this change when you have installed a LAP update.&lt;br /&gt;
&lt;br /&gt;
==How To==&lt;br /&gt;
===Reset webserver/webdav passwords===&lt;br /&gt;
In case you have lost your webserver or webdav password, but you still have the root credentials, you can login with SSH and execute the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code type=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;admin:Linux Web Server:c33c4d3f554367d5d1c3c9bf36803024&amp;quot; &amp;gt; /home/lighttpd/lighttpd_htdigest.user&lt;br /&gt;
echo &amp;quot;admin:Linux Webdav:7182e328a0531dd2d44d225f36da6b87&amp;quot; &amp;gt; /home/lighttpd/webdav_htdigest.user&lt;br /&gt;
/etc/init.d/lighttpd restart&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards you can access your webserver/webdav with &#039;&#039;&#039;admin&#039;&#039;&#039;/&#039;&#039;&#039;linux&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 The same can be done for application specific passwords, e.g. Reporting. &lt;br /&gt;
 In this case, use the file &#039;&#039;&#039;/home/lighttpd/innovaphone-reporting-htdigest.user&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Convert the Linux AP to VMware vSphere ===&lt;br /&gt;
If you are using a VMware vSphere 4.x or later you need to use the VM Ware Standalone Converter to convert the Linux Application Platform.&lt;br /&gt;
You&#039;ll find a step by step guide [https://kb.swivelsecure.com/wiki/index.php/VMWare_Converter_How_to_Guide here]&lt;br /&gt;
&lt;br /&gt;
==TroubleShooting==&lt;br /&gt;
&lt;br /&gt;
===Installation process failed===&lt;br /&gt;
&lt;br /&gt;
When the installation process stuck either because it doesn&#039;t get IP or services are not refresh/finished there is some additional information we could get from the Compact Flash that could help us understanding what is failing and if necessary open a support ticket and include this information in the ticket to innovaphone.&lt;br /&gt;
&lt;br /&gt;
*  Stop the linux and check General-&amp;gt;Compact Flash &amp;quot;Browse files&amp;quot;. All files in there might be helpfull (all but the kernel, of course).&lt;br /&gt;
*  Start the linux and check if you can connect to the configured/expected IP address via Putty after ~1 minute.&lt;br /&gt;
&lt;br /&gt;
Note: The file /var/log/init_install.log might help us to get a clue of the failure.&lt;br /&gt;
&lt;br /&gt;
===Howto save and restore Linux AP data/database if the webgui is not available===&lt;br /&gt;
&lt;br /&gt;
If the linux ap webgui is not reachable a common reason is that the harddisc is full.&lt;br /&gt;
If a full hd is the case, maybe your first thought is to increase the harddisc.&lt;br /&gt;
It could be a solution but there are some traps to increase the partition in linux which can be ended in complete data loss&lt;br /&gt;
&lt;br /&gt;
The fastest way to get linux ap working with a new harddsik size is to install a new one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How can you save the data without get access over the webgui?&#039;&#039;&#039;&lt;br /&gt;
If you can reach linux via putty it could be possible :)&lt;br /&gt;
&lt;br /&gt;
Here are some possibilities how to do that over the shell:&lt;br /&gt;
&#039;&#039;&#039;(But keep in the back of you head that you are working as root and therefore typing errors can lead to undesirable behaviours!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Delete at first all the logfiles. Sometimes a few MByte are enough to get all the stopped services running again and you could reach liunx over the webgui.&lt;br /&gt;
i.e. the reporting logfiles are under &amp;quot;&#039;&#039;/var/www/innovaphone/apps/innovaphone-reporting/log&#039;&#039;&amp;quot;, the fax server logfiles are under &lt;br /&gt;
&amp;quot;&#039;&#039;/var/www/innovaphone/apps/innovaphone-faxserver/log&#039;&#039;&amp;quot;&lt;br /&gt;
-&amp;gt; &#039;&#039;&#039;Don&#039;t delete the &#039;log&#039; directory itself!&#039;&#039;&#039; Delete only the content:&lt;br /&gt;
&lt;br /&gt;
   root@vmware-debian: cd /var/www/innovaphone/apps/innovaphone-reporting/log/&lt;br /&gt;
   root@vmware-debian: rm *&lt;br /&gt;
&lt;br /&gt;
Is the linux ap after a restart running and over http reachable, download all the config and databases and restore them on the new linux ap (2.2).&lt;br /&gt;
&lt;br /&gt;
[[image:save.png]]&lt;br /&gt;
&lt;br /&gt;
2. In case the reason for the unreachable webgui was not a full harddisk you can save the config/database (only reporting and exchange connector at the moment) &lt;br /&gt;
over the shell.&lt;br /&gt;
&lt;br /&gt;
  root@vmware-debian:/# cd /home/postgres/&lt;br /&gt;
  &#039;&#039;for reporting type:&#039;&#039;&lt;br /&gt;
  root@vmware-debian:/# sudo -u postgres /usr/bin/pg_dump --encoding=utf8 --schema=public -Fc -U postgres innovaphone-reporting | gzip -fc6 &amp;gt; innovaphone-reporting-db.gz&lt;br /&gt;
&lt;br /&gt;
  root@vmware-debian:/# cd /home/postgres/&lt;br /&gt;
  &#039;&#039;for exchange connector type:&#039;&#039;&lt;br /&gt;
  root@vmware-debian:/# sudo -u postgres /usr/bin/pg_dump --encoding=utf8 --schema=public -Fc -U postgres innovaphone-exchange | gzip -fc6 &amp;gt; innovaphone-exchange-db.gz&lt;br /&gt;
&lt;br /&gt;
2.1 Access linux with winscp &#039;&#039;&#039;(protocol: scp / user: root)&#039;&#039;&#039; and download the .gz (don&#039;t unzip)&lt;br /&gt;
&lt;br /&gt;
[[image:reporting.png]]&lt;br /&gt;
&lt;br /&gt;
(BTW: you can &#039;&#039;&#039;download&#039;&#039;&#039; with &#039;&#039;&#039;scp&#039;&#039;&#039; also the complete webdav files. But for the &#039;&#039;&#039;upload&#039;&#039;&#039; use as user &#039;admin&#039; and as protocol &amp;quot;&#039;&#039;&#039;webdav&#039;&#039;&#039;&amp;quot;. &lt;br /&gt;
Otherwise the owner is still root and this ends in authorization problems)&lt;br /&gt;
&lt;br /&gt;
[[image:webdav.png]]&lt;br /&gt;
&lt;br /&gt;
2.2. on the new linux ap upload this .gz&lt;br /&gt;
&lt;br /&gt;
[[image:restore.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
3. The steps mentioned above should be only the last try to get the data and could work or not.&lt;br /&gt;
To be always on the save site use a standby Linux (for reporting), save configs (update server) and delete (automatic) old cdr&#039;s to avoid a full hd.&lt;br /&gt;
&lt;br /&gt;
=== How to recover from a broken File System ===&lt;br /&gt;
Sometimes you may find messages in the &#039;&#039;kern.log&#039;&#039; log file (in &#039;&#039;var/log&#039;&#039;) like&lt;br /&gt;
&lt;br /&gt;
 Aug 15 10:45:31 ip6010-debian kernel: EXT4-fs (sda4): initial error at 1500329378: ext4_journal_start_sb:328&lt;br /&gt;
 Aug 15 10:45:31 ip6010-debian kernel: EXT4-fs (sda4): last error at 1500329378: ext4_journal_start_sb:328&lt;br /&gt;
&lt;br /&gt;
This indicates a file system failure on the Linux Installation.&lt;br /&gt;
&lt;br /&gt;
When the Linux file system is broken, you can try to repair it using some command line Linux tools.&lt;br /&gt;
&lt;br /&gt;
* Open the WebGUI of the gateway running your LAP and proceed to &#039;&#039;Linux/General&#039;&#039;&lt;br /&gt;
** terminate Linux (&#039;&#039;Status/Stop&#039;&#039;)&lt;br /&gt;
** modify the &#039;&#039;Kernel command line&#039;&#039; from &#039;&#039;root=/dev/sda4&#039;&#039; to &amp;lt;code&amp;gt;root=/dev/sda2&amp;lt;/code&amp;gt;&lt;br /&gt;
** start Linux again&lt;br /&gt;
:: This will run Linux on another (hopefully sane) partition.&lt;br /&gt;
&lt;br /&gt;
* use [https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html putty] to log in to the LAP&#039;s command line&lt;br /&gt;
** on the command prompt, use &amp;lt;code&amp;gt;e2fsck -p -f /dev/sda4&amp;lt;/code&amp;gt;&lt;br /&gt;
:: this should fix any issue on the file system&lt;br /&gt;
&lt;br /&gt;
* go back to the WebGUI of the gateway running your LAP and proceed to &#039;&#039;Linux/General&#039;&#039;&lt;br /&gt;
** terminate Linux (&#039;&#039;Status/Stop&#039;&#039;)&lt;br /&gt;
** modify the &#039;&#039;Kernel command line&#039;&#039; from &#039;&#039;root=/dev/sda2&#039;&#039; to &amp;lt;code&amp;gt;root=/dev/sda4&amp;lt;/code&amp;gt;&lt;br /&gt;
** start Linux again&lt;br /&gt;
:: This will run Linux on the original partition.&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t fix your issue, you need to replace the SSD with a new one, re-install the LAP and any applications and restore your backups. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;internal&amp;gt;&lt;br /&gt;
Internal: How to recover from a disk-is-full Condition: [http://wiki-intern.innovaphone.com/index.php?title=Reporting#Vergr.C3.B6.C3.9Fern_der_Partition_.28VM.29]&lt;br /&gt;
&amp;lt;/internal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
* [[Howto:Convert a V10 LinuxAP to VHDX to run on Hyper-V]]&lt;br /&gt;
* [[Howto:Extend V10 LinuxAP HDD Size (VM)]]&lt;br /&gt;
* [[Howto:Tested_mSata_modules]]&lt;br /&gt;
* [[Howto:MSATA Placement]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Concept|Linux Application Platform]]&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:IQM_Statistical_CSV_Data_for_Agent_and_Queue&amp;diff=53397</id>
		<title>Howto:IQM Statistical CSV Data for Agent and Queue</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:IQM_Statistical_CSV_Data_for_Agent_and_Queue&amp;diff=53397"/>
		<updated>2019-08-27T08:04:59Z</updated>

		<summary type="html">&lt;p&gt;Odawid: /* More information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In previous releases (before build 80160) the iQM server did a data logging using Excel sheets. While this method has the great advantage that the output is a ready to use Excel Chart including formulas, front pages and different sheets there are also some limitations. For example it is very difficult support all kind of OS and all kind of Excel and Office Versions on the iQM Server while the real typically is done on “normal” PC´s where Excel is installed.&lt;br /&gt;
&lt;br /&gt;
Therefore the Data logging is done writing data in a CSV format. This format can be natively loaded from Excel. The difference is that there are no single sheets for days, but all data are of a month in one single Excel Sheet. Also Formulas or filter if required can be added, but there are not included in the source file.&lt;br /&gt;
&lt;br /&gt;
==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
iQM Build 80160 or higher&lt;br /&gt;
&lt;br /&gt;
Excel is not required on the iQM Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Keywords: iQM,queue monitor,monitor,queue,PBX-Queue,call center,contact center,waiting queue,agent,wrap-up,wrap up,wrapup,innovaphone queue monitor,queuemonitor,queue-monitor,queue_monitor,Queue Monitor--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==More information==&lt;br /&gt;
QM provide two type of statistical data, data regarding individual Agents and data regarding the general status of the WQ. The usage is different: while individual Agent data are used to evaluate the operating of the single Agents, the WQ data are used for resource planning. See more details and explanation in the following chapters.&lt;br /&gt;
Statistical data are transmitted via Email to the supervisor automatically (daily or monthly). The can also be requested manually pressing the relative button on the iQM server:&lt;br /&gt;
&lt;br /&gt;
[[image:IQM214.png‎]]&lt;br /&gt;
&lt;br /&gt;
If requested on demand the actual data of today of cause will be just from midnight until the moment of the request. During transmission the relative buttons will shown:&lt;br /&gt;
&lt;br /&gt;
[[image:IQM215.png‎]]&lt;br /&gt;
&lt;br /&gt;
Please note that MS has timeouts in all applications and therefore it could take some time until you will find the statistic in your mailbox.&lt;br /&gt;
Note: if in the setup a valid IP-Adress is indicated in the e-mail server (iQM does no control if not) iQM performs a ping check before processing the email. If like in the example the Ping result is negative warning message is displayed, each 20 seconds are done further checks.&lt;br /&gt;
 &lt;br /&gt;
[[image:IQM209.png‎]]&lt;br /&gt;
&lt;br /&gt;
The e-mails are buffered (max. 6), also in case of other email error a relative warning message is displayed (and stored in the log file).&lt;br /&gt;
Statistical data can also be transmitted automatically each day at midnight and at the end of the month.&lt;br /&gt;
Please note that a IQM Server tracks always data form “his” primary WQ while the data of the second WQ and processed by the second iQM Server.&lt;br /&gt;
&lt;br /&gt;
==Files==&lt;br /&gt;
Each time a file is send, regardless if automatically or requested by a user, a copy of the original file is stored in a directory created automatically by the iQM server. The directory named “CSV” is a sub-directory where the log files are in.&lt;br /&gt;
&lt;br /&gt;
Example: if Your logfile path is “c:\asdf\“ the CSV data are stored in “c:\asdf\CSV”&lt;br /&gt;
&lt;br /&gt;
Please note that a copy of files is done even if no email address is indicated. &lt;br /&gt;
&lt;br /&gt;
Therefore also a logging without email is possible, just working with files. &lt;br /&gt;
&lt;br /&gt;
As usual it is recommended to work only with the file in the CSV subdirectory and not with the original files in the log directory.&lt;br /&gt;
&lt;br /&gt;
The files stored in the CSV subdirectory and received via email can be opened with any software, in the following examples we open with Excel for further processing.&lt;br /&gt;
&lt;br /&gt;
Please note that the csv files in the logging directory should not be opened and they have a write protection switched on while the files in the CSV subdirectory and the one attached to the emails have no write protection.&lt;br /&gt;
&lt;br /&gt;
Once opened the file could be processed, modified, stored and renamed as you like, see later chapters.&lt;br /&gt;
&lt;br /&gt;
===File Names===&lt;br /&gt;
&lt;br /&gt;
The filename of automatic generated files (typically at the beginning of the month) is the following: &lt;br /&gt;
&lt;br /&gt;
The CSV filename has the format “iQM_SS_L_YYYY_MM_DD_HHMMSS.csv” where:&lt;br /&gt;
&lt;br /&gt;
SS = source (“AG” for agent and “WQ” for Waiting queue”)&lt;br /&gt;
&lt;br /&gt;
L = Labe of the iQM sever&lt;br /&gt;
&lt;br /&gt;
YYYY =  Year&lt;br /&gt;
&lt;br /&gt;
MM = month&lt;br /&gt;
&lt;br /&gt;
DD = Day &lt;br /&gt;
&lt;br /&gt;
HHMMSS = hour, minute, second&lt;br /&gt;
&lt;br /&gt;
If a file is send automatically by email the file name of the attached file is “iQM_SS_ll_YYYY_MM.csv”, so no day and timestamp is in the filename.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
“iQM_AG_MyFinanceGroup_2016_04_18_152709.csv” filename of the file stored in the CSV subdirectory at time 15:27:09. &lt;br /&gt;
&lt;br /&gt;
“iQM_AG_MyFinanceGroup_2016_04.csv”  automatic created file attached to the email&lt;br /&gt;
&lt;br /&gt;
“iQM_AG__2016_04_000009.csv” filename of the file stored in the CSV subdirectory. Note that there is no label in this example and the 00:00:09 indicated that this file was stored automatically at midnight at the end of the month.&lt;br /&gt;
&lt;br /&gt;
===e-mail format===&lt;br /&gt;
&lt;br /&gt;
The email shows in the object field the type and source of the Statistic in the format iQM-Report, “AG” for the Agent Statistics and “WQ” for the Waiting queue Statistic. On top the name of the iQM server is in the object, usefully if more iQM are operating.&lt;br /&gt;
&lt;br /&gt;
Example of email Subject:&lt;br /&gt;
&lt;br /&gt;
“iQM-Report Statistic WQ MyFinanceGroup” data of the Waiting Queue of the iQM Server “MyFinanceGroup”&lt;br /&gt;
&lt;br /&gt;
iQM-Report Statistic AG MyFinanceGroup” data of the Agent of the iQM Server “MyFinanceGroup”&lt;br /&gt;
&lt;br /&gt;
The e-mail body shows the source path of the attached file and name of the attached file.&lt;br /&gt;
&lt;br /&gt;
Example for email body:&lt;br /&gt;
&lt;br /&gt;
C:\asdf\iQM_AG_Myxlabel_2016_04.csv&lt;br /&gt;
Automatic generated report - Do NOT answer!&lt;br /&gt;
&lt;br /&gt;
The CSV Data Files are attached in the mail.&lt;br /&gt;
&lt;br /&gt;
===Manual data dump===&lt;br /&gt;
&lt;br /&gt;
If a statistic File is dumped (requested) manually the data are partial. If for example Agent data are requested in day 6.12 at 14:00, data will be complete for the days 1-6, but data of the day 6 are just logged from 00:00 to 14:00. Similar happens to the queue data: if a request is done at 12:35 the quarterly hour from 12:30 to 12:45 will contain partial data.&lt;br /&gt;
&lt;br /&gt;
Note: In agent data, where for each day a line for each agent is stored, a manual dump cause double lines in the day where the system starts up the very first time. On further days this will not happen.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
“iQM_AG_MyFinanceGroup_2016_04_18_152709.csv” indicate that the request was done day 18, hour 15:27:09&lt;br /&gt;
&lt;br /&gt;
In the Queue Table the minute of the snapshot is indicated:&lt;br /&gt;
&lt;br /&gt;
[[image:iQMcsv01.png‎]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the example the data dump was done at 15:33 and therefore line 4 contains partial data.&lt;br /&gt;
&lt;br /&gt;
==Excel Import==&lt;br /&gt;
&lt;br /&gt;
The CSV Data can be imported in Excel, the CSV character is semi column (“;”). &lt;br /&gt;
&lt;br /&gt;
===Agent Data===&lt;br /&gt;
&lt;br /&gt;
The headline (localized, in all examples in English) indicates the following columns:&lt;br /&gt;
&lt;br /&gt;
[[image:IQM_N_14.png‎]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A: Day of month&lt;br /&gt;
&lt;br /&gt;
B: Month&lt;br /&gt;
&lt;br /&gt;
C: Name of Agent. Numbers in a line regards this single agent: a call is counted as such if the phone of the agent rings, not if a call is in the queue. &lt;br /&gt;
&lt;br /&gt;
D: Number of incoming calls. If in the setup of the iQM server is flagged “log only calls from WQ” just incoming calls form the Waiting Queue are counted: if not checked all calls (even if not from the Waiting Queue) are counted.&lt;br /&gt;
&lt;br /&gt;
E: Number of outgoing calls&lt;br /&gt;
&lt;br /&gt;
F: Time in seconds of the phone in ringing status. You can calculate the average time of answer for this agent divide this value with the number of calls in (F/D). If in the setup of the iQM server is flagged “log only calls from WQ” just incoming calls form the Waiting Queue are counted: if not checked all calls (even if not from the Waiting Queue) are counted.&lt;br /&gt;
&lt;br /&gt;
G: Number of abandoned calls = calls not answered while the agent phone rings. This means that the phone has to ring and the agent did not answer. If a caller gives up during the queuing in the Waiting queue (ando no Phone is ringing) this is not counted. Note that the abandoned calls counter in the iQM Server (that count abandoned calls in any situation) cannot be compared with this counter.&lt;br /&gt;
&lt;br /&gt;
H: Conversation time in seconds for incoming calls.If in the setup of the iQM server is flagged “log only calls from WQ” just incoming calls form the Waiting Queue are counted: if not checked all calls (even if not from the Waiting Queue) are counted.&lt;br /&gt;
&lt;br /&gt;
I: Conversation time in seconds of outgoing calls. Outgoing calls are all calls done in a active mode (so even internal active calls)&lt;br /&gt;
&lt;br /&gt;
J: Wrap up Time in seconds. Shows how long a Agent was in the wrap up status.&lt;br /&gt;
&lt;br /&gt;
K: Time in seconds being in Group, shows how long a Agent was logged in the group. &lt;br /&gt;
&lt;br /&gt;
L: Number of threshold overflow. Each time the phone rings longer than the seconds indicated in the iQM Setup “Ring TH” (the agent phone is ringing longer than) this counter is increased.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Description Example (assuming that in the setup “only calls from Waiting Queue” is flagged).&lt;br /&gt;
&lt;br /&gt;
The Phone of Agent Valentina (line 3) in day 19 October (the year is indicated in the filename) rings 14 times for calls coming from the WQ, 4 times longer than 10 Seconds before answering the call. 3 calls where not answered unless the phone rings, the total time of phone ringing was 72 seconds, the conversation time for the incoming calls 154 seconds. The Agent was 70 seconds in wrap up and logged in the group 11884 seconds.  Valentina did 1 outgoing call speaking 36 seconds. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please note that the format of the counters is generally well done, for example the value “month” is in two digit format (in the example “04”): but the view in Excel depends on the setup of your Excel sheet.&lt;br /&gt;
&lt;br /&gt;
====Loggin rules====&lt;br /&gt;
&lt;br /&gt;
The following rules regard the iQM statistics for second’s calls. A “second call” is a call done from agent while the first call is on hold. A typical situation is a consultation with another extension. &lt;br /&gt;
&lt;br /&gt;
Please note that an outgoing call is a call from the agent to a destination, regardless if the called number is, from the PBX point of view, an extension or an external destination. &lt;br /&gt;
&lt;br /&gt;
Observe also that the iQM is not a reporting and the following described rules can cause different counter status if compared. While a reporting is simple tracing each call as an independent event the iQM statistics follow a callcenter logic. If the independent call counting is requested simple use the reporting tool.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.	incoming call&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
When the incoming call comes in the queue statistic incoming call counter is increased, if the agent answers the agent incoming call counter; a timestamp for call duration is saved.&lt;br /&gt;
&lt;br /&gt;
If the agent put this first call on hold and is doing an outgoing call the agent client will show the second number while a timestamp for the second call is saved.&lt;br /&gt;
The agent talks with the second destination and transfers the call. In the Queue Statistic the call transfer counter is increased. In the agent statistic the outgoing call counter is not increased, the entire call duration is booked on the incoming call duration timer. &lt;br /&gt;
&lt;br /&gt;
The same behaviour is given if the call is transferred without consultation (the agent just transfer the call without waiting that the far destination answers the call).&lt;br /&gt;
The wrap up will trigger when the call is transferred.&lt;br /&gt;
&lt;br /&gt;
If the agent transfers the call to the Waiting Queue the call duration will continue to count on that agent until the call is answered. Please note that the client will show the pending call. If group wrap up is on the agent will not be logged in the group until the call is answered or the agent picks up the phone, then wrap up will trigger. If queue wrap up in switched on wrap up will trigger, after the wrap up the call is offered again to the agent.&lt;br /&gt;
&lt;br /&gt;
A second option is that the agent releases the second call and speaks again with the first original incoming call. The outgoing call counter is increased when the agent releases the second call and the outgoing call duration is increased using the timestamp of the second call. Please note that the client will show the second number until the call is terminated. Wrap up will trigger at the end of the call.&lt;br /&gt;
&lt;br /&gt;
A third option is that the agent toggles between the two calls and release the first (the incoming) call.&lt;br /&gt;
&lt;br /&gt;
The wrap up will just trigger when the second call is released. The outgoing call counter is not increased; the entire call duration is assigned to the incoming call.&lt;br /&gt;
If the first incoming caller releases while the agent is in conversation with the second outgoing call the entire call is considered as incoming, the total time amount is booked on the incoming call and the outgoing call counter is not increased.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.	Outgoing call&#039;&#039;&#039;&lt;br /&gt;
All operation described before are possible also doing as first call an outgoing call, then put that call on hold and do a second outgoing call. Outgoing calls without involvement of the waiting queue will not cause any wrap up.&lt;br /&gt;
&lt;br /&gt;
In case of an Call transfer there is just one call add in the statistic, the entire call duration is add  to the outgoing call duration.&lt;br /&gt;
&lt;br /&gt;
If the second call is released the outgoing counter is increased, so when the agent released two outgoing calls are counted. The entire call duration is added.&lt;br /&gt;
&lt;br /&gt;
If the agent toggles between the calls the display on the client will not follow but showing always the second call. If the agent releases the first call the counter of outgoing call will not be increased while the entire call duration is added to the outgoing call duration timer.&lt;br /&gt;
&lt;br /&gt;
If the first called user releases while the agent is in conversation with the second outgoing call the entire call is considered as one single outgoing call, the total time amount is booked on the outgoing time counter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3.	Short Calls&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In the iQM Setup it is possible to set a minimum duration time in seconds. Calls shorter that the seconds defines are not logged in the missed call list of the agent. Calls also not are considered as valid calls for the statistic. Please note that short calls are not counted in the statistics if:&lt;br /&gt;
&lt;br /&gt;
-	The ringing time is shorter the the threshold and the agent will not answer.&lt;br /&gt;
&lt;br /&gt;
-	The ringing time is shorter that e threshold, the agent answer the call but the conversation time is shorter than the threshold.  This is valid independently if the caller or the agent releases the call.&lt;br /&gt;
&lt;br /&gt;
Please note that the reporting tool will not track very short calls (&amp;lt;=1 second) while a threshold in the iQM could cause that the reporting reports the call while the iQM will not.&lt;br /&gt;
&lt;br /&gt;
Please note also that the counter of the waiting queue are not affected by this filter option, therefore the queue counter will count all calls, even the short one. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Formulas====&lt;br /&gt;
&lt;br /&gt;
Being native Excel sheets any type of formulas (for example sums) can be added and also Filter can be applied with a few klick (marking all and adding “Filter”).&lt;br /&gt;
&lt;br /&gt;
In the Excel format there are some columns not available automatically in the CSV logging, but it is easy to add a column with the relative formulas. &lt;br /&gt;
&lt;br /&gt;
Here some example for additional formulas:&lt;br /&gt;
&lt;br /&gt;
Time in Minutes = time in Seconds / 60&lt;br /&gt;
&lt;br /&gt;
Average Time to Answer = F: Time to answer in seconds / D: Number of incoming calls&lt;br /&gt;
&lt;br /&gt;
Average duration of incoming calls = H: Conversation time in seconds of incoming calls / D: Number of incoming calls&lt;br /&gt;
&lt;br /&gt;
Average duration of outgoing calls = I: Conversation time in seconds of outgoing calls / E: Number of outgoing calls&lt;br /&gt;
&lt;br /&gt;
Average duration of calls = (H: Conversation time in seconds of incoming calls + I: Conversation time in seconds of outgoing calls) / ( D: Number of incoming calls + E: Number of outgoing calls)&lt;br /&gt;
&lt;br /&gt;
===Queue Data===&lt;br /&gt;
&lt;br /&gt;
Queue Data are data regarding the waiting Queue and the group of agents, not single agents.For example there is no difference for a call being queued or ringing on a phone.&lt;br /&gt;
&lt;br /&gt;
Queue data are stored in 15 Minutes intervals. Therefore each hour has 4 entries: 00, 15, 30 and 45. Please note that always the past quarter is indicated. For example in “10:00” are data from 09:45 to 10:00, in “10:15” are in data from “10:00” to “10:15”.&lt;br /&gt;
&lt;br /&gt;
If a queue report is requested manually an odd timestamp will appear (for example “10:04”) indicating the snapshot time for the current quarter.&lt;br /&gt;
&lt;br /&gt;
The headline (localized, in the example in English) indicates the following columns:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:IQM_N_15.png‎]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A: Day of month&lt;br /&gt;
&lt;br /&gt;
B: Month&lt;br /&gt;
&lt;br /&gt;
C: Hour &lt;br /&gt;
&lt;br /&gt;
D: Minute &lt;br /&gt;
&lt;br /&gt;
E: Number of incoming calls on the Waiting Queue&lt;br /&gt;
&lt;br /&gt;
F: Number of abandoned calls (in any situation)&lt;br /&gt;
&lt;br /&gt;
G: Percentage of served calls (calls answered)&lt;br /&gt;
&lt;br /&gt;
H: Percentage of abandoned calls (calls not answered)&lt;br /&gt;
&lt;br /&gt;
I: Waiting time in seconds = total waiting time of calls in the waiting queue &lt;br /&gt;
&lt;br /&gt;
J: Number of agents logged in the group (Agent Group)&lt;br /&gt;
&lt;br /&gt;
K: Number of transferred calls: If an Agent does not terminate the call but is doing a call transfer this counter is incremented.&lt;br /&gt;
&lt;br /&gt;
L: Peak call duration in seconds = longest waiting time &lt;br /&gt;
&lt;br /&gt;
M: Average Waiting time of calls in seconds (I/E)&lt;br /&gt;
&lt;br /&gt;
N: Number of threshold overflow. Each time a calls waits longer than the seconds indicated in the iQM Setup “Waiting TH” this counter is increased.&lt;br /&gt;
&lt;br /&gt;
O: Number of active calls done from the agents (Build 80178)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the time frame from 16:30 to 16:45 the 19 October (the year is indicated in the filename) 10 calls came in to the Waiting Queue, 2 calls where not served (abandoned), so 80% of the calls are served while 20% not. The total waiting time of those 10 calls was 167 seconds, at 16:30 there where 2 Agents logged into the group. 1 call was transferred to other destinations while 9 calls served from the Agent. The Peak Waiting time in this period was 36 seconds, the average waiting time 17 seconds. One time a call waits longer than 30 seconds. The Agents did 2 outgoing calls in this time frame.&lt;br /&gt;
&lt;br /&gt;
Please note that all columns refer to the waiting queue except column O: this column shows the number of outgoing calls of the agents during the quarter hour timeframe. This value is interesting to evaluate the activity of the call enter during the timeframe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Known Problems===&lt;br /&gt;
Some customer wants additional columns (for example adding two cells or doing other type of mathematical calculation), hiding columns, modify header, using filter and similar. In Excel all that is very simple and can be done in an automatic mode with one click. This Wiki is not a Excel tutorial, anyway some hint you can find here:&lt;br /&gt;
&lt;br /&gt;
[[ Howto:IQM_Server#Data_processing | Howto:IQM_Server#Data_processing]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == Related Articles == --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
&lt;br /&gt;
[[Howto:IQM_Statistical_Excel_Data_for_Agent_and_Queue]]&lt;br /&gt;
&lt;br /&gt;
[[Howto:Queue_Monitor_-_Overview]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:PHP_based_Update_Server_V2&amp;diff=50428</id>
		<title>Howto:PHP based Update Server V2</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:PHP_based_Update_Server_V2&amp;diff=50428"/>
		<updated>2018-08-14T11:41:54Z</updated>

		<summary type="html">&lt;p&gt;Odawid: /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* all innovaphone devices&lt;br /&gt;
* web server running PHP 5 (e.g. Linux Application Platform)&lt;br /&gt;
&lt;br /&gt;
All Versions. &lt;br /&gt;
&lt;br /&gt;
By default, the [[Reference10:Concept_Update_Server | Update Manager]] mechanism reads a file that corresponds to the device type (e.g. &amp;lt;code&amp;gt;update-ip222.htm&amp;lt;/code&amp;gt;).  While this makes sense (update scripts may vary by device type), it is sometimes tedious, as you have to edit a huge amount of files which typically are (at least partly) identical.&lt;br /&gt;
&lt;br /&gt;
Here is a PHP script that can be used as an &#039;&#039;Update Server&#039;&#039; that allows you to simplify the handling of update scripts. It also includes a mechanism that makes sure that all devices always have the same firmware installed as a given &#039;&#039;master device&#039;&#039; has.   Finally, it implements a straight forward configuration backup scheme.&lt;br /&gt;
&lt;br /&gt;
This article describes version 2 of this update server (build 2006 and up). The previous version is described in [[Howto:PHP_based_Update_Server]]. The enhancements are&lt;br /&gt;
* Status user interface showing all known devices&lt;br /&gt;
* Ability to roll out custom device certificates&lt;br /&gt;
* Ability to provide configuration files to MTLS-authenticated devices only (e.g. in order to keep certain configuration settings secure)&lt;br /&gt;
* Hide configuration files from public read access&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
The update server script requires a web server with working PHP 5.3 or higher platform.  It has been tested with Apache and ligHTTPD (on a [[Reference10:Concept Linux Application Platform | Linux Application Platform]]).   On IIS, neither the certificate roll-out nor the MTLS authentication or configuration backup works with IIS.&lt;br /&gt;
&lt;br /&gt;
The platform running the PHP scripts must have a valid time setting!&lt;br /&gt;
&lt;br /&gt;
=== Features ===&lt;br /&gt;
The update server can&lt;br /&gt;
* update all your devices with boot code and firmware that corresponds to the versions running on a reference device of your choice&lt;br /&gt;
* save backups of your devices configuration. Backups are saved only if the configuration changed since the last backup&lt;br /&gt;
* invoke your own update scripts depending on &lt;br /&gt;
** various phases (e.g. you can have &#039;&#039;staging&#039;&#039; scripts which are only executed once and normal scripts which are executed in normal operation later on)&lt;br /&gt;
** devices classes (e.g. you can have different scripts for phones and gateways)&lt;br /&gt;
** environments (e.g. you can have scripts for your internal devices and others for devices in home offices)&lt;br /&gt;
** the device serial number&lt;br /&gt;
* roll out customer specific device certificates&lt;br /&gt;
* roll out update scripts to devices only that have identified themselves with a valid device certificate (MTLS)&lt;br /&gt;
* maintain a list of devices in your installation along with some vital information about each individual device&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== On the Linux Application Platform ====&lt;br /&gt;
Here is how you would install it on the [[Reference10:Concept_Linux_Application_Platform|LAP]].  Some of the steps may not be necessary if you don&#039;t want to use all features.&lt;br /&gt;
&lt;br /&gt;
On the &#039;&#039;Linux Application Platform&#039;&#039;, you would &lt;br /&gt;
* open the LAP&#039;s file system using a SFTP client such as e.g. [https://winscp.net/eng/index.php WinSCP] (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;root/iplinux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]). Note that you must use SFTP rather than WebDAV, as WebDAV will not give access to the executable web server files&lt;br /&gt;
* create a new root directory underneath &amp;lt;code&amp;gt;/var/www/innovaphone/mtls&amp;lt;/code&amp;gt;, e.g. &amp;lt;code&amp;gt;/var/www/innovaphone/mtls/update&amp;lt;/code&amp;gt;&lt;br /&gt;
* download the complete file package of scripts and files here: http://download.innovaphone.com/ice/wiki-src/ &lt;br /&gt;
* copy all files and directories in to this new directory&lt;br /&gt;
* change owner and group of all files and directories to &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, change mode to 0600 for all files and 0700 for all directories (see [[#Migrating_from_build_2000_an_newer | below]] for how to do this with WinSCP)&lt;br /&gt;
&lt;br /&gt;
* log in to the LAP&#039;s admin UI (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;admin/linux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]) and open its &#039;&#039;Administration/Web Server/Change web server properties and public access to the web/webdav&#039;&#039; configuration UI. Add the following paths to &#039;&#039;Public Web Paths&#039;&#039; (assuming your base directory is called &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;):&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/web&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/fw/&amp;lt;/code&amp;gt; (note the trailing slash!)&lt;br /&gt;
: make sure that no other sub-directories of &#039;&#039;update&#039;&#039; are listed&lt;br /&gt;
: make sure you have no trailing &#039;/&#039; in any of these paths (except &#039;&#039;fw/&#039;)&lt;br /&gt;
: this will make sure the update server&#039;s admin user interface is not accessible to the public&lt;br /&gt;
&lt;br /&gt;
At this point, you should be able to access the update server&#039;s admin user interface, e.g. &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php&amp;lt;/code&amp;gt;.  However, the only thing you see is a login page.  Please note that your browser should ask you for a password for this page (unless you already entered it before).  Cookies must be enabled for the login page to work properly. &lt;br /&gt;
&lt;br /&gt;
===== If you want to provide HTTPS Acess to the Update Server =====&lt;br /&gt;
For HTTPS access to the update server, you may want to install your own server certificate under &#039;&#039;Administration/Certificates/Current server certificate&#039;&#039;.  However, this is not strictly required (you will experience some warning messages when using your browser to access the update server, however, calling devices will work just fine). &lt;br /&gt;
&lt;br /&gt;
===== If you want to setup MTLS-restricted Delivery of Update Scripts =====&lt;br /&gt;
If you think you have sensitive information in your update scripts, you should make sure to deliver such scripts to your own verified devices only.  This can be done by authenticating calling devices with &#039;&#039;mutual TLS&#039;&#039; (MTLS).  In this case, the calling device must use HTTPS to retrieve the update script and present a trusted client certificate that identifies itself as the calling device (that is, has the device serial as the certificate&#039;s &#039;&#039;common name&#039;&#039; (CN)). &lt;br /&gt;
&lt;br /&gt;
For this feature, you need to &#039;&#039;Configure mutual TLS&#039;&#039; in the LAP&#039;s &#039;&#039;Administration/Web Server&#039;&#039; panel.  Simply tick the &#039;&#039;Active&#039;&#039; check-mark and select an appropriate &#039;&#039;MTLS Port&#039;&#039;.  The port must not conflict with any other TCP port used on the LAP, so neither 80 nor 443 is a good choice.  444 is a good choice.  Although it [http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&amp;amp;page=8 is assigned to the snpp protocol] by IANA, it is not used by the LAP (and probably rarely used anyway).&lt;br /&gt;
&lt;br /&gt;
If MTLS is already activated on your LAP, simply take note of the currently configured &#039;&#039;MTLS Port&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Please note that MTLS access is &#039;&#039;not possible&#039;&#039; through a &#039;&#039;reverse proxy&#039;&#039; (RP).  This is because the RP always will terminate the incoming TLS connection and establish its own to the target.  Therefore, the client certificate presented to the target server is the RP&#039;s certificate, not the original clients certificate.  In our context - where MTLS is used to verify the identity of the original caller - clients must not access the update server through an RP.&lt;br /&gt;
&lt;br /&gt;
You can either expose your update server directly to the internet (and carefully think through the security implications) or create specific TCP port forwarding towards the update server in your NAT-router/firewall.  In this case, we recommend to use non-standard HTTP and HTTPS ports on the NAT router (cause this will already keep most of the HTTP port scanners out there in the internet from functioning).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Also, you will need the public key of all the CAs you will trust.  These must be configured in to the web server so it can trust the certificates your devices will present to it.  See [[#Enforcing_Trust]] for details.&lt;br /&gt;
&lt;br /&gt;
==== On an Apache Server running on the Windows Operating System ====&lt;br /&gt;
The update server will run on Apache too.  However, as we did not test this setup thoroughly, we recommend to use the LAP&#039;s LigHTTPD instead.  &lt;br /&gt;
&lt;br /&gt;
* For hints on using MTLS on an Apache Web Server, see [[Reference10:Concept_Provisioning#Enforcing_mutual_TLS_on_Apache | Enforcing mutual TLS on Apache]]&lt;br /&gt;
* For hints on getting the &#039;&#039;innovaphone device certificate authority&#039;&#039; public keys (which you may or may not need), see [[Reference10:Concept_Provisioning#How_to_get_inno-dev-ca-certificate.crt | How to get inno-dev-ca-certificate.crt ]]&lt;br /&gt;
&lt;br /&gt;
==== On Microsoft&#039;s IIS ====&lt;br /&gt;
We do not recommend to use IIS as &lt;br /&gt;
* it does not support PUT easily&lt;br /&gt;
* it is not compatible with the innovaphone device&#039;s MTLS implementation&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
If you intend to deliver your update scripts with MTLS (that is, with HTTPS and mutual certificate check)&lt;br /&gt;
* you will need to have the full name of your &#039;&#039;certificate Authority&#039;&#039; (CA) as it is noted as &#039;&#039;Common Name&#039;&#039; (CN) in your CA&#039;s certificate&lt;br /&gt;
* also, you will need a PEM version of your CA&#039;s public key (a &#039;&#039;PEM version&#039;&#039; of a certificate is a text file that begins with a line like &amp;lt;code&amp;gt;-----BEGIN CERTIFICATE-----&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Also, you need to know the &#039;&#039;MTLS Port&#039;&#039; configured in your LAP (see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts| If you want to setup MTLS-restricted Delivery of Update Scripts ]] above).&lt;br /&gt;
&lt;br /&gt;
All tweakable parameters are set in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  You may want to use an XML-capable editor such as notepad++, netbeans or Visual-Studio for editing.  if your editor supports it, you benefit from the &#039;&#039;document type description&#039;&#039; (DTD) provided in &amp;lt;code&amp;gt;full-config.dtd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;false&amp;quot; debugcerts=&amp;quot;false&amp;quot; debugscript=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The attributes of the &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; tag control some aspects of debugging.  For now, simply set all 3 to &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt;.  Do not forget to revert them back to &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt; when everything runs smoothly, large log files will result if not. &lt;br /&gt;
&lt;br /&gt;
==== Securing Access ====&lt;br /&gt;
To control access to the update server&#039;s data, you should set a login.  This can be done in the &#039;&#039;master&#039;&#039; tag by specifying both &#039;&#039;user&#039;&#039; and &#039;&#039;password&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;master ...  user=&amp;quot;myadmin&amp;quot; password=&amp;quot;mysecret&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Default username and password are admin/password.&lt;br /&gt;
&lt;br /&gt;
==== Delivering Firmware and Boot Code ====&lt;br /&gt;
At this point, you can simulate a device by requesting an update script using an URL like &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php?type=IP232&amp;amp;sn=00-90-33-00-00-00&amp;amp;hwid=IP232-00-00-00&amp;amp;ip=1.2.3.4&amp;lt;/code&amp;gt; in your browser (please note that this URL should not ask you for a password).  Most likely, your browser will wait a little while and then say something like:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # failed to use cached data (cache not current), retrieving info online&lt;br /&gt;
 # cannot get PBX info: cannot access http://yourmasterdevice.youdomain.tld/CMD0/box_info.xml, reading cache&lt;br /&gt;
 # cannot get cached PBX info: cannot access cache/master-info.xml - exit&lt;br /&gt;
&lt;br /&gt;
This is because you did not yet specify the &#039;&#039;master device&#039;&#039; which always runs the reference firmware.  &lt;br /&gt;
&lt;br /&gt;
The idea here is that you have one innovaphone device in your system where the firmware is always manually updated. All other devices shall follow this reference firmware.  The update server will deliver the firmware that runs on the master device to calling devices.  For this to work, you need to set the &#039;&#039;info&#039;&#039; attribute of the [[#master|&#039;&#039;master&#039;&#039;]] tag and leave everything else &#039;&#039;as is&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Remember that you do all your local configuration changes in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As &#039;&#039;master&#039;&#039; is a first level tag, you can add it directly underneath the opening &#039;&#039;&amp;lt;config&amp;gt;&#039;&#039; tag.  The only thing we need to define right now is the path to read the firmware information from your master device.  Let&#039;s say your reference device has the IP address &amp;lt;code&amp;gt;172.16.0.10&amp;lt;/code&amp;gt;, you end up with &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;true&amp;quot; debugcerts=&amp;quot;true&amp;quot; debugscript=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;  user=&amp;quot;myadmin&amp;quot; password=&amp;quot;mysecret&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
(you could use a DNS name instead of the IP address of course). &lt;br /&gt;
The &#039;&#039;info&#039;&#039; URL is used by the update server itself only, it is never used by devices requesting an update script.&lt;br /&gt;
&lt;br /&gt;
When you refresh the page that simulates a device requesting an update script, the output should now change to something like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # failed to use cached data (cache not current), retrieving info online&lt;br /&gt;
 # current firmware (unknown) does not match required firmware (130178)&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
This is to say that your master device runs firmware 130178 and the calling device does not (actually, as the calling client is simulated by your browser, it does not transmit its current firmware to the update server so it is &#039;&#039;(unknown)&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
In order to actually update the clients with firmware and boot code, the files must be made available to the calling client somehow.  This is done by specifying an URL in the [[Reference10:Concept_Update_Server#Prot_command | prot ]] and [[Reference10:Concept_Update_Server#Boot_command | boot ]] commands sent to the calling device:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # current firmware (unknown) does not match required firmware (130178)&lt;br /&gt;
 mod cmd UP0 prot http://update.yourcompany.com/mtls/update/fw/130178/ ser 130178&lt;br /&gt;
 # current boot code (unknown) does not match required boot code (130112)&lt;br /&gt;
 mod cmd UP0 boot http://update.yourcompany.com/mtls/update/fw/130112/ ser 130112&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
By default, the URL generated points to a sub-directory of your update server called &#039;&#039;fw&#039;&#039;: &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/fw/130178/&amp;lt;/code&amp;gt;.  Note that this default URL expects sub-directories underneath the &#039;&#039;fw&#039;&#039; directory which correspond to the firmware and boot code build number.  The file structure thus would be like&lt;br /&gt;
&lt;br /&gt;
 /var/www/innovaphone/mtls/update/fw&lt;br /&gt;
                                    /130178&lt;br /&gt;
                                           /ip232.bin&lt;br /&gt;
                                    /130112&lt;br /&gt;
                                           /boot232.bin&lt;br /&gt;
&lt;br /&gt;
Note that the URL ends with a slash (&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;).  This instructs the calling device to append the appropriate file name itself when retrieving the file (see [[Reference10:Concept_Update_Server#Prot_command | the prot command ]] for details). &lt;br /&gt;
&lt;br /&gt;
However, you can also specify any other URL by setting the &#039;&#039;url&#039;&#039; attribute in the &#039;&#039;fwstorage&#039;&#039; tag of your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. In this attribute, certain meta words will be replaced (see [[#fwstorage | the &#039;&#039;fwstorage&#039;&#039; tag ]] for details).  The default setting for example is &amp;lt;code&amp;gt;fw/{build}/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can disable firmware and boot code updates altogether by setting the &#039;&#039;info&#039;&#039; attribute in the &#039;&#039;master&#039;&#039; tag to an empty value.&lt;br /&gt;
&lt;br /&gt;
==== Your own Update Script Files ====&lt;br /&gt;
The update server will deliver update scripts to calling devices which are synthesized from a number of &#039;&#039;update script snippets&#039;&#039; which you define yourself.  The idea is that many devices share parts of their configuration while other parts are different.  This depends on&lt;br /&gt;
* the device &#039;&#039;class&#039;&#039; (e.g. a phone or a gateway)&lt;br /&gt;
: the device class is automatically derived from its model.  In fact, a single device may be in multiple classes. For example, an IP232 is in these classes: &#039;&#039;phone, pre_opus_phone, phone_newui&#039;&#039; which basically says that its a phone and has no OPUS codec yet but a &amp;quot;new&amp;quot; user interface (as opposed to the old one found e.g. on an IP110). A number of useful classes are pre-defined, but you can add your own in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
* the device&#039;s environment (e.g. &#039;&#039;home-office&#039;&#039;, &#039;&#039;branch-office&#039;&#039;)&lt;br /&gt;
:  These reflect that fact that devices may need different configuration if they are in different locations (or environments).  The update server does not know about a device&#039;s environment, which is why you need to configure it in to the devices update URL if you need this.  By default, there is a single environment defined called &#039;&#039;default&#039;&#039;, but of course, you can add your own&lt;br /&gt;
* phase&lt;br /&gt;
: configuring devices may need multiple phases to go through.  If more than one phase is defined, the device will go through all phases sequentially, which is why a &#039;&#039;phase&#039;&#039; has a numerical &#039;&#039;seq&#039;&#039; attribute.  Phases are went through in order of this attribute. When the device has reached the last phase, it will stay there.  By default, there is only one phase called &#039;&#039;update&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can define update script snippets for any combination of device, environment and phase.  You do so simply by placing appropriate files in to the &#039;&#039;scripts&#039;&#039; directory on your update server.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a closer look at the web page we used to simulate a device calling for an update script before (&amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php?type=IP232&amp;amp;sn=00-90-33-00-00-00&amp;amp;hwid=IP232-00-00-00&amp;amp;ip=1.2.3.4&amp;lt;/code&amp;gt;).  It will show you all the possible files it would deliver to the device:&lt;br /&gt;
&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 # scripts/update-all-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-all-default.txt does not exist&lt;br /&gt;
 # scripts/update-phone-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-phone-default.txt does not exist&lt;br /&gt;
 # scripts/update-pre_opus_phone-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/update-phone_newui-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
&lt;br /&gt;
The update script snippet files need to have proper names to define when they should be delivered.  As you can see, they all start with &amp;lt;code&amp;gt;update-&amp;lt;/code&amp;gt; which means that they apply to devices which are in the &#039;&#039;update&#039;&#039; phase.  As by default there is only a single phase defined, all possible file names start with &amp;lt;code&amp;gt;update-&amp;lt;/code&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
The next part here is either &amp;lt;code&amp;gt;phone-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pre_opus_phone-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;phone_newui-&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;all-&amp;lt;/code&amp;gt;.  This is because the calling IP232 is in three classes, so all respective snippets will be delivered to it.  &#039;&#039;all&#039;&#039; however is a wild-card.  That is, such files will be delivered to all devices, no matter what class they are in.  You may wonder why there was no &#039;&#039;all&#039;&#039; for the phase.  This is because there is only a single phase defined.  If there would be more, the &#039;&#039;all&#039;&#039;-variation of the phase-part  of the file name would be appear.&lt;br /&gt;
&lt;br /&gt;
The third part finally is either &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;00_90_33_00_00_00&amp;lt;/code&amp;gt; in our case. &#039;&#039;default&#039;&#039; is the name of the only &#039;&#039;environment&#039;&#039; that is defined by default.  &#039;&#039;00_90_33_00_00_00&#039;&#039; is the device&#039;s serial number which is treated as an implicitly defined environment name. This allows you to deliver certain snippets to a single device only.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s create an update script snippet that is delivered to all phones in the default environment when they are in the update phase.  The file name (which looks like &#039;&#039;phase&#039;&#039;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&#039;&#039;class&#039;&#039;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&#039;&#039;environment&#039;&#039;&amp;lt;code&amp;gt;.txt&amp;lt;/code&amp;gt;) has to be &amp;lt;code&amp;gt;update-phone-default.txt&amp;lt;/code&amp;gt; therefore.  Just for an exercise, let us set the device name (as shown in the browser&#039;s title bar) to &#039;&#039;This is a Phone!&#039;&#039;.&lt;br /&gt;
The command to do so is &amp;lt;code&amp;gt;config add CMD0 /name This+is+a+Phone%21&amp;lt;/code&amp;gt;, so your file may look like this&lt;br /&gt;
&lt;br /&gt;
 # set the device name&lt;br /&gt;
 config add CMD0 /name This+is+a+Phone%21&lt;br /&gt;
&lt;br /&gt;
(btw: did you observe that config line arguments need to be url-encoded?).  Now create the file and upload it in to the &#039;&#039;scripts&#039;&#039; directory of you update server.  When you now refresh the page which simulates the device calling for an update script, you will see something like this:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # newest script (scripts/update-phone-default.txt) 11s old&lt;br /&gt;
 # files being updated (scripts/update-phone-default.txt 11s old, waiting for at least 90s to expire)&lt;br /&gt;
&lt;br /&gt;
When you update multiple script snippets, it is often undesirable that a device retrieves an inconsistent state of the scripts you are working on (e.g. if you already have saved one but not yet the other).  To avoid this, the update server will look at the files modification dates and if one of those that needs to be delivered to the device is younger than 90 seconds, it will not send any of them at all.  &lt;br /&gt;
&lt;br /&gt;
So when you wait for the 90 seconds to pass and refresh the page again, you will see something like this:&lt;br /&gt;
&lt;br /&gt;
 # firmware build info cache is current&lt;br /&gt;
 # phase: update, nextphase: , environment: default, type: IP232, classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone-default.txt 4.1 mins&lt;br /&gt;
 ...&lt;br /&gt;
 #     scripts/update-phone-default.txt&lt;br /&gt;
 # { begin script &#039;scripts/update-phone-default.txt&#039; &lt;br /&gt;
 # set the device name&lt;br /&gt;
 config add CMD0 /name This+is+a+Phone%21&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # end script &#039;scripts/update-phone-default.txt&#039; }&lt;br /&gt;
 &lt;br /&gt;
 # trigger reset if required&lt;br /&gt;
 config write&lt;br /&gt;
 config activate&lt;br /&gt;
 iresetn&lt;br /&gt;
&lt;br /&gt;
As you can see, your snippet has been delivered by the update script.  However, the update server has also added some trailing commands which write back the config to the devices flash memory (&amp;lt;code&amp;gt;config write&amp;lt;/code&amp;gt;), activate it (&amp;lt;code&amp;gt;config activate&amp;lt;/code&amp;gt;) and trigger a reset if needed (&amp;lt;code&amp;gt;iresetn&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If there are multiple snippets available for a calling device, all of them are concatenated in the sequence shown in the header of the returned script (where the possible file names are listed)&lt;br /&gt;
&lt;br /&gt;
==== Device Status ====&lt;br /&gt;
When you have a lot of devices which are served by the update server, you may want to have a list of these devices along with some useful information regarding each devices.  &lt;br /&gt;
&lt;br /&gt;
You can enable this by defining the &#039;&#039;status&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  So open the file and add the tag right next to the &#039;&#039;master&#039;&#039; tag you added before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config&amp;gt;&lt;br /&gt;
    &amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;status&lt;br /&gt;
        dir=&amp;quot;status&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you have done so, please refresh the page that simulates your calling device and then open &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php?mode=status&amp;lt;/code&amp;gt;.  You will now see a device list (well, a list with a single device, the one you simulated using your browser).   The list will show some information regarding the devices that requested an update script lately.   For more options, see [[#status]].&lt;br /&gt;
&lt;br /&gt;
==== Device Backup ====&lt;br /&gt;
It is generally useful to have recent backups of all of your device configurations.  The update server supports that if you enable it by defining the &#039;&#039;backup&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. Simply put it right next to the &#039;&#039;master&#039;&#039; or &#039;&#039;status&#039;&#039; tag you added before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;backup&lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have done so and then refresh the page that simulates your calling device, you will now see &lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
 &lt;br /&gt;
 mod cmd UP0 scfg http://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m&lt;br /&gt;
&lt;br /&gt;
instead of &lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
 &lt;br /&gt;
 # Backups not enabled in config&lt;br /&gt;
&lt;br /&gt;
When a client requests an update script the next time, this will initiate a configuration backup which is stored underneath the &#039;&#039;backup&#039;&#039; directory.  For each device, a sub-directory is created and all backup files are stored therein.  By default, the last 10 differing configuration backups are kept.&lt;br /&gt;
&lt;br /&gt;
==== Controlling the Time-frames when Snippets are delivered ====&lt;br /&gt;
The update client built-in to innovaphone devices allows to restrict updates to certain time frames (e.g. only during the night). This can be controlled using the [[Reference10:Concept_Update_Server#Times_command | times ]] command.&lt;br /&gt;
&lt;br /&gt;
You can configure the update server to use the time commands by setting the &#039;&#039;allow&#039;&#039; and &#039;&#039;initial&#039;&#039; attributes in the &#039;&#039;times&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        allow=&amp;quot;22,23,0,1,2,3,4&amp;quot; &lt;br /&gt;
        initial=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If either the &#039;&#039;allow&#039;&#039; or &#039;&#039;initial&#039;&#039; attribute is present, the update script will contain a line like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # Restricted times&lt;br /&gt;
 mod cmd UP1 times  /allow 22,23,0,1,2,3,4 /initial 1&lt;br /&gt;
&lt;br /&gt;
In the example above, all update script activity will occur only between 10pm and 5am (local device time).   For more details, see [[Reference10:Concept_Update_Server#Times_command | Concept Update Server]]&lt;br /&gt;
&lt;br /&gt;
==== Using and Enforcing HTTPS ====&lt;br /&gt;
Your devices can either use HTTP or HTTPS to access the update server.  In normal operation, the update server will generate URLs (e.g. the URLs used to retrieve firmware or to backup configurations) for the same protocol.  &lt;br /&gt;
&lt;br /&gt;
However, you can enforce use of HTTPS by setting the &#039;&#039;forcehttps&#039;&#039; attribute in the [[Howto:PHP_based_Update_Server_V2#times | &#039;&#039;times&#039;&#039; ]] tag to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. If so, a device calling in with HTTP will be re-configured to use HTTPS:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # using HTTP and &#039;forcehttps&#039; is set -&amp;gt; need to switch to HTTPS&lt;br /&gt;
 &lt;br /&gt;
 # changed state query args: polling, phase&lt;br /&gt;
 # new url=https://update.yourcompany.com/mtls/update/update.php?polling=5&amp;amp;phase=&amp;amp;type=#t&amp;amp;sn=#m&amp;amp;hwid=#h&amp;amp;ip=#i&lt;br /&gt;
 ...&lt;br /&gt;
(note that if you are using a non-standard port for HTTPS, you must define it using the &#039;&#039;httpsport&#039;&#039; attribute).&lt;br /&gt;
&lt;br /&gt;
==== Delivering Custom Certificates ====&lt;br /&gt;
innovaphone devices come with pre-defined, trustworthy device certificates. However, all &#039;&#039;soft&#039;&#039; devices (such as the softwarephone, myPBX for Android/iOS or the IPVA) do not.  Also, in many scenarios customers run their own &#039;&#039;public key infrastructure&#039;&#039; (PKI) and request their own certificates to be used instead of the pre-defined. This is why there is a need to roll-out custom certificates to devices. &lt;br /&gt;
&lt;br /&gt;
The update server supports this task to an extend.  It can&lt;br /&gt;
* check if a calling device has a proper certificate&lt;br /&gt;
* instruct a calling device without proper certificate to create a &#039;&#039;certificate signing request&#039;&#039; (CSR)&lt;br /&gt;
* download the CSR to the update server for easy access by the administrator&lt;br /&gt;
* upload a signed CSR to the device&lt;br /&gt;
* upload the public key(s) of the CA in to the device&#039;s trust list&lt;br /&gt;
&lt;br /&gt;
In order to roll-out custom certificates with the update server, the administrator needs to&lt;br /&gt;
* run his own PKI (a.k.a. &#039;&#039;certificate authority&#039;&#039; (CA))&lt;br /&gt;
* monitor CSRs that appear in the update server&#039;s device list&lt;br /&gt;
* approve the request by manually submitting it to his own CA&lt;br /&gt;
* upload the signed CSR to the update server&lt;br /&gt;
&lt;br /&gt;
Also, all devices must run &#039;&#039;V12r1 SR8&#039;&#039; or newer before the new certificate can be uploaded.  Devices with older firmware will be updated automatically (see [[#Delivering_Firmware_and_Boot_Code]] above). However, the new firmware must be &#039;&#039;V12r1 SR8&#039;&#039; or later. &lt;br /&gt;
&lt;br /&gt;
To learn how you can create proper device certificates with your own windows CA, see [[Howto:Creating custom Certificates using a Windows Certificate Authority]].&lt;br /&gt;
&lt;br /&gt;
By default, custom certificates are turned off and you will see a note like&lt;br /&gt;
&lt;br /&gt;
 # certificates: either certificate handling or state tracking not enabled - not doing any certificate checking&lt;br /&gt;
&lt;br /&gt;
in the delivered update script.&lt;br /&gt;
&lt;br /&gt;
Custom certificates are turned on by adding a &#039;&#039;customcerts&#039;&#039; tag to your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
	dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The the page that simulates your calling device will now include a line saying:&lt;br /&gt;
&lt;br /&gt;
 # certificates: we dont know anything about the current certificate state - not doing any certificate checking &lt;br /&gt;
&lt;br /&gt;
In order to decide if or if not a calling device has a valid certificate, the device needs to send its current public key to the update server.  This is done by enabling &#039;&#039;queries&#039;&#039; in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  &#039;&#039;Queries&#039;&#039; is a means to have the device submit certain information to the update server.  In the update server&#039;s default configuration, two queries are defined but not enabled:&lt;br /&gt;
&lt;br /&gt;
* the query &#039;&#039;certificates&#039;&#039; sends the current certificate state &lt;br /&gt;
* the query &#039;&#039;admin&#039;&#039; sends the current device name (as set in &#039;&#039;General/Admin&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
To enable a query, you must specify the class a calling device must be in in order to execute the query.  This is done by adding an &#039;&#039;applies&#039;&#039; tag for the respective query in your configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;queries&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;admin&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
    &amp;lt;/queries&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically says that both queries should be executed by devices of just any class.  Unless you enable queries, your update script will include lines such as:&lt;br /&gt;
&lt;br /&gt;
 # no queries defined for any of callers classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
&lt;br /&gt;
Once you have enabled them, you will see something like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # query &#039;certificates&#039;&lt;br /&gt;
 mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=query&amp;amp;sn=#m&amp;amp;id=certificates ser nop /always mod%20cmd%20X509%20xml-info&lt;br /&gt;
 # query &#039;admin&#039;&lt;br /&gt;
 mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=query&amp;amp;sn=#m&amp;amp;id=admin ser nop /always mod%20cmd%20CMD0%20xml-info&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
You can display the data sent by a query in the device status display.  To do so, you need to define one or more &#039;&#039;show&#039;&#039; tags as part of the respective &#039;&#039;query&#039;&#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;!-- show device certificate CNs and Issuer CNs in status page --&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Subject&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@subject_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Issuer&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@issuer_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two steps however are still missing: &lt;br /&gt;
&lt;br /&gt;
* a) you need to tell the update server the names of all the CAs you consider trustworthy.  This is done by listing their names in the &#039;&#039;CAname&#039;&#039; attribute of the &#039;&#039;customcerts&#039;&#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
        dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
        CAname=&amp;quot;innovaphone Device Certification Authority,innovaphone Device Certification Authority 2,innovaphone-INNO-DC-W2K8-Zertifizierungsserver&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
: The example shown defines that you will accept both of innovaphone&#039;s device certificate authorities and also your own CA called &#039;&#039;innovaphone-INNO-DC-W2K8-Zertifizierungsserver&#039;&#039;.  Devices with device certificates issued by one of these CAs will be left untouched.  For all other devices (for example, any &#039;&#039;myPBX for Android/iOS&#039;&#039; device that has a self-signed certificate), the generation of a custom certificate will be initiated.&lt;br /&gt;
&lt;br /&gt;
* And b) you need to provide the public key of your CA (so it can be uploaded to the calling device&#039;s trust list).  You need to place the DER (not PEM) encoded public key in to a file called &amp;lt;code&amp;gt;certs/CAkey-01.cer&amp;lt;/code&amp;gt; on your update server (if you want to upload the whole certificate chain, put all of the public keys in the chain in to separate additional files called &amp;lt;code&amp;gt;certs/CAkey-02.cer&amp;lt;/code&amp;gt; and so forth.&lt;br /&gt;
&lt;br /&gt;
For more details on how to approve certificate signing requests, see [[#Approving Certificate Signing Requests]] below.&lt;br /&gt;
&lt;br /&gt;
==== Enforcing Trust ====&lt;br /&gt;
Update script snippets may include sensitive information which you do not want to disclose to the public.  Even though you can force the use of HTTPS (see above), this still does not keep your data secure.  After all, an attacker could simply request an update script from your update server using HTTPS.  To secure your data, you need to make sure that snippets are only sent to devices which identify themselves using a trusted certificate with a correct &#039;&#039;common name&#039;&#039; (CN).  This is done using &#039;&#039;mutual transport layer security&#039;&#039; (MTLS).  Therefore, you need to configure MTLS in the LAP (see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts | If you want to setup MTLS-restricted Delivery of Update Scripts]] above). &lt;br /&gt;
&lt;br /&gt;
You can enable this by setting &#039;&#039;forcetrust&#039;&#039; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &#039;&#039;httpsport&#039;&#039; to the port configured as &#039;&#039;MTLS Port&#039;&#039; in your web server.  This is done in the &#039;&#039;times&#039;&#039; tag of your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        ...&lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot;&lt;br /&gt;
        httpsport=&amp;quot;444&amp;quot;&lt;br /&gt;
        forcetrust=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Please note that &#039;&#039;forcetrust&#039;&#039; does nothing unless &#039;&#039;forcehttps&#039;&#039; is also set!&lt;br /&gt;
&lt;br /&gt;
If so, the update server will deliver update script snippets only to clients which identify themselves with a proper certificate.    For this to work, you will need to add the public key of your certificate authority to your web server&#039;s list of trusted certificates.  &lt;br /&gt;
&lt;br /&gt;
When using the &#039;&#039;Linux Application Platform&#039;&#039; (LAP), you need to add the PEM-encoded public key of your certificate authority to the &#039;&#039;innovaphone-ca.pem&#039;&#039; file in &amp;lt;code&amp;gt;/home/root/ssl_cert&amp;lt;/code&amp;gt;.  When you have installed the LAP, this file will contain the PEM-encoded public keys of the 2 innovaphone device certificate authorities.  You can simply add the public key of your CA to the end of this file:&lt;br /&gt;
&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...inno-ca public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...inno-ca2 public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...your-ca public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
&lt;br /&gt;
You will need to restart the LigHTTPD then (most easily done by restarting the entire LAP (&#039;&#039;Diagnose/Reset&#039;&#039;) or by issuing the command &amp;lt;code&amp;gt;/etc/rc2.d/S02lighttpd restart&amp;lt;/code&amp;gt; from the linux root command prompt). Finally, you must set the &#039;&#039;forcetrust&#039;&#039; attribute. &lt;br /&gt;
(Note that the &#039;&#039;innovaphone-ca.pem&#039;&#039; file may be overwritten when a new LAP version is installed.  It is thus a good idea to keep a copy and check it after an upgrade).&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;forcetrust&#039;&#039; is effective and the calling device does not use HTTPS, it will be reconfigured to do so:&lt;br /&gt;
&lt;br /&gt;
 # using HTTP and &#039;forcehttps&#039; is set -&amp;gt; need to switch to HTTPS&lt;br /&gt;
 ...&lt;br /&gt;
 # new url=https://update.yourcompany.com:444/update/update.php?polling=5&amp;amp;phase=&amp;amp;type=#t&amp;amp;sn=#m&amp;amp;hwid=#h&amp;amp;ip=#i&amp;amp;env=default&lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS but sends no certificate, you will see a message like&lt;br /&gt;
&lt;br /&gt;
 # cannot verify CN with HTTPS: SSL_CLIENT_S_DN_CN not present - fix web server configuration or use MTLS-enabled port!&lt;br /&gt;
&lt;br /&gt;
This is probably because it is using a non-MTLS enabled port for HTTPS (e.g. the standard port 443) although MTLS is configured for a different port. &lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS and sends a certificate but the CN does not match the serial number of the device, you will see a message such as&lt;br /&gt;
&lt;br /&gt;
 # Device claims to be &#039;IP232-30-00-af&#039; but identifies as &#039;CKL-CELSIUS-W10.innovaphone.sifi&#039; by TLS&lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS and sends a certificate but the certificate is not trusted because its issuer is not listed in &#039;&#039;innovaphone-ca.pem&#039;&#039; (see above), the connection will be refused &lt;br /&gt;
&lt;br /&gt;
In all such cases, no snippet will be delivered.  If the certificate is good, you will see a message like &lt;br /&gt;
&lt;br /&gt;
 # good certificate(CN=&#039;IP232-30-00-af&#039;)&lt;br /&gt;
&lt;br /&gt;
followed by the appropriate snippets.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple Phases ====&lt;br /&gt;
When you configure multiple phases, all phases up to the final phase are stepped through and when all associated update script snippets for all phases are done, the device will ultimately stay in the final phase.  This can be used e.g. to implement update script snippets which are executed once only when the device is initialized.  Settings made in all but the last phase can later be overridden by the user or an administrator.  The settings done in the update script settings for the final phase however are re-executed whenever one of your update script files for this phase changes.&lt;br /&gt;
The process of deploying some initial settings is often called &#039;&#039;staging&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To enable staging, you therefore create a new phase that comes before the default phase (which is &#039;&#039;update&#039;&#039;).  Phases are sorted numerical by an attribute called &#039;&#039;seq&#039;&#039;.  As the default phase &#039;&#039;update&#039;&#039; is defined with &#039;&#039;seq=200&#039;&#039;, your new staging phase must be defined with a lower seq value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
	    &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you define such a phase, there will be new possible update script snippet file names: &lt;br /&gt;
&lt;br /&gt;
 # phase: staging, nextphase: update, environment: default, type: IP232, classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 # scripts/all-all-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-all-default.txt does not exist&lt;br /&gt;
 # scripts/all-phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-phone-default.txt does not exist&lt;br /&gt;
 # scripts/all-pre_opus_phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/all-phone_newui-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-phone_newui-default.txt does not exist&lt;br /&gt;
 # scripts/staging-all-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-all-default.txt does not exist&lt;br /&gt;
 # scripts/staging-phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-phone-default.txt does not exist&lt;br /&gt;
 # scripts/staging-pre_opus_phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/staging-phone_newui-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-phone_newui-default.txt does not exist&lt;br /&gt;
&lt;br /&gt;
First of all, there are new names for this particular phase.  Furthermore, as we now have multiple phases, the new wild-card name &#039;&#039;all&#039;&#039; is possible.  &lt;br /&gt;
&lt;br /&gt;
An example for a staging script snippet might be a file called &amp;lt;code&amp;gt;staging-all-all.txt&amp;lt;/code&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
 # change admin password&lt;br /&gt;
 config add CMD0 /user admin,my-admin-password&lt;br /&gt;
 config activate&lt;br /&gt;
 config rem CMD0 /user&lt;br /&gt;
&lt;br /&gt;
This will set the admin password to &amp;lt;code&amp;gt;my-admin-password&amp;lt;/code&amp;gt; during staging (it should be obvious that such staging should only be done in combination with [[#Enforcing_Trust|Enforcing Trust]], see above).&lt;br /&gt;
&lt;br /&gt;
=== A complete &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt; Sample ===&lt;br /&gt;
Here is a complete sample of a configuration file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;status&lt;br /&gt;
	    dir=&amp;quot;status&amp;quot;&lt;br /&gt;
	    missing=&amp;quot;1000&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;backup&lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        allow=&amp;quot;22,23,0,1,2,3,4&amp;quot; &lt;br /&gt;
        initial=&amp;quot;1&amp;quot;&lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot;&lt;br /&gt;
	httpsport=&amp;quot;444&amp;quot;&lt;br /&gt;
        forcetrust=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
        dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
	CAname=&amp;quot;innovaphone Device Certification Authority,innovaphone Device Certification Authority 2&amp;quot;&lt;br /&gt;
        CSRsan-dns-1=&amp;quot;{name}.company.com&amp;quot;&lt;br /&gt;
        CSRsan-dns-2=&amp;quot;{hwid}.company.com&amp;quot;&lt;br /&gt;
        CSRsan-dns-3=&amp;quot;{rdns}&amp;quot;&lt;br /&gt;
        CSRsan-ip-1=&amp;quot;{realip}&amp;quot;&lt;br /&gt;
	/&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
	    &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
    &amp;lt;environments&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&amp;quot;intranet&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;sifi&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;berlin&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;verona&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;homeoffice&#039;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;mobile&#039;/&amp;gt;&lt;br /&gt;
   &amp;lt;/environments&lt;br /&gt;
    &amp;lt;queries&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;admin&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Subject&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@subject_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Issuer&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@issuer_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
    &amp;lt;/queries&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operation ===&lt;br /&gt;
&lt;br /&gt;
==== Configuring and Debugging a real Device ====&lt;br /&gt;
To configure your device for use with the update server, you simply set &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php&amp;lt;/code&amp;gt; as &#039;&#039;Command File URL&#039;&#039; in &#039;&#039;Services/Update&#039;&#039; (you can optionally add a &amp;lt;code&amp;gt;?env=envname1,envname2&amp;lt;/code&amp;gt; query argument if you want to set one or more specific environments for your device).  The update server will re-configure the device later on so that it uses all the required query arguments.&lt;br /&gt;
&lt;br /&gt;
Generally, there are the following methods to set the &#039;&#039;Command File URL&#039;&#039;&lt;br /&gt;
* configure it manually using the admin GUI&lt;br /&gt;
* provide it to the device using DHCP (this will however not work for the softwarephone or &#039;&#039;myPBX for Android/iOS&#039;&#039;)&lt;br /&gt;
* use the innovaphone provisioning service (see [[Reference10:Concept_Provisioning|Reference10:Concept Provisioning]] for details)&lt;br /&gt;
&lt;br /&gt;
Once the &#039;&#039;Command File URL&#039;&#039; is set on the device, you can debug what the update client in the device does, using the normal trace mechanism.  For this, you will want to open the &#039;&#039;Debug&#039;&#039; page (&amp;lt;code&amp;gt;http://x.x.x.x/debug.xml&amp;lt;/code&amp;gt;) and set the &#039;&#039;Update/Polling&#039;&#039; and &#039;&#039;Update/Execution&#039;&#039; check-marks.  When  the update client queries the update server, you will see lines like &lt;br /&gt;
&lt;br /&gt;
 0:0826:465:5 - upd_poll: state IDLE -&amp;gt; RECV&lt;br /&gt;
 0:0826:465:7 - IP.0 -&amp;gt; UPD-POLL.0 : SOCKET_GET_LOCAL_ADDR_RESULT(172.16.100.201,255.255.0.0,0,&#039;&#039;,ANY)&lt;br /&gt;
 0:0826:466:0 - IP.0 -&amp;gt; UPD-POLL.0 : SOCKET_GET_LOCAL_ADDR_RESULT(172.16.100.201,255.255.0.0,0,&#039;&#039;,ANY)&lt;br /&gt;
 0:0826:695:0 - upd_poll: state=RECV sent()&lt;br /&gt;
 0:0826:752:0 - upd_poll: status 200 headercomplete=1 contentlength=0&lt;br /&gt;
 0:0826:754:0 - upd_poll: recv_data(2199)&lt;br /&gt;
 0:0826:754:1 - upd_poll: recv_data(0) EOF&lt;br /&gt;
 0:0826:754:1 - upd_poll: GET EOF - state=RECV http-status=200 length=2199&lt;br /&gt;
 0:0826:754:1 - upd_poll: do commands&lt;br /&gt;
 0:0826:754:1 - upd_poll: state RECV -&amp;gt; EXEC&lt;br /&gt;
&lt;br /&gt;
in the trace.  Commands included in the update script will look like&lt;br /&gt;
&lt;br /&gt;
 0:0826:754:5 - script::get_line: &amp;gt;line(mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m)&lt;br /&gt;
 0:0826:754:5 - upd_poll: pass &#039;mod cmd UP0 /sync scfg https://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m&#039;)&lt;br /&gt;
&lt;br /&gt;
Finally, you do not need to wait for the next time the device decides to contact the update server.  Instead, you can force this by sending an &amp;lt;code&amp;gt;http://&amp;lt;/code&amp;gt;&#039;&#039;your-device-ip&amp;lt;code&amp;gt;/!mod cmd UP1 poll&amp;lt;/code&amp;gt; to the device.&lt;br /&gt;
&lt;br /&gt;
==== The Device Status Update Page ====&lt;br /&gt;
If status tracking is enabled (see [[#Device_Status | Device Status]] above), the update server will keep a list of devices it knows of.  You can see this list by calling &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php?mode=status&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
By default, the list will not be updated unless you refresh the page.  However, if you set the &#039;&#039;refresh&#039;&#039; attribute in the &#039;&#039;status&#039;&#039; tag in your &#039;&#039;use-config.xml&#039;&#039; file tp &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;, all entries in this list will be refreshed every 60 seconds (however, the list itself will not be reloaded, so to see new devices, your need to refresh the entire page).  Devices that have not been seen for more than 7 days are shown in a different colour.  Devices that have not been seen for longer than 90 days will be silently removed from the list.&lt;br /&gt;
&lt;br /&gt;
===== Filtering =====&lt;br /&gt;
From build 2011, you can filter the devices shown using the &#039;&#039;device filter&#039;&#039; field in the &#039;&#039;Device&#039;&#039; column header.  The filter string is matched against ip-address, serial number, type, name, phase, class, environment, firmware and bootcode.  Also, you can filter by using the keywords &#039;&#039;present&#039;&#039; and &#039;&#039;missing&#039;&#039; (based on the &#039;&#039;missing&#039;&#039; attribute of the &#039;&#039;status&#039;&#039; tag in your configuration file). If one of these attributes match your filter expression, the device is shown.&lt;br /&gt;
&lt;br /&gt;
A filter expression must match a complete &#039;&#039;word&#039;&#039;.  For example, if you filter by &amp;lt;code&amp;gt;16&amp;lt;/code&amp;gt; this would match the ip-address &amp;lt;code&amp;gt;172.&amp;lt;/code&amp;gt;16&amp;lt;code&amp;gt;.0.20&amp;lt;/code&amp;gt; but it would not match &amp;lt;code&amp;gt;192.&amp;lt;/code&amp;gt;16&amp;lt;code&amp;gt;8.0.1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you specify multiple filter expressions (separated by white space), only devices which match all of the expressions will be shown.  For example, if you filter by &amp;lt;code&amp;gt;172.16. ip222&amp;lt;/code&amp;gt; this might match all IP222 in your 172.16.*.* network.  Filter expressions are case insensitive.&lt;br /&gt;
&lt;br /&gt;
==== Approving Certificate Signing Requests ====&lt;br /&gt;
When you use custom certificate roll-out, you will see a column &#039;&#039;Certificates&#039;&#039; in the device status list, showing the devices certificate status.  &lt;br /&gt;
&lt;br /&gt;
[[Image:PHP_based_Update_Server_V2_Device_Status.png]]&lt;br /&gt;
&lt;br /&gt;
If a CSR has been created on the device, this will be available for download in the &#039;&#039;Files&#039;&#039; section of the &#039;&#039;Info&#039;&#039; column.  You can submit the CSR to your CA and then upload the signed request (using the &#039;&#039;Upload&#039;&#039; button in the &#039;&#039;Files&#039;&#039; section of the &#039;&#039;Info&#039;&#039; column).  The signed request will eventually be uploaded to the device then.  On  the device itself, the CSR is shown in &#039;&#039;General/Certificates&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:PHP_based_Update_Server_V2_CSR.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Certificate Errors ====&lt;br /&gt;
When a signed certificate request uploaded to the device can not be installed on the device, you will see a message like &amp;lt;code&amp;gt;Certificate upload error - certificate handling stopped&amp;lt;/code&amp;gt; in the &#039;&#039;Certificates&#039;&#039; columns for the device.  In this case, any further processing will be stopped.  Most likely, the reason is that you uploaded the wrong file as signed certificate request (either not a signed certificate at all or a signed request for another device).&lt;br /&gt;
&lt;br /&gt;
In this case&lt;br /&gt;
* remove any certificate request from the device&lt;br /&gt;
* remove the &amp;lt;code&amp;gt;X509/REQUESTERROR&amp;lt;/code&amp;gt; from the device configuration (i.e. &amp;lt;code&amp;gt;vars del X509/REQUESTERROR&amp;lt;/code&amp;gt;)&lt;br /&gt;
: these 2 steps can be easily done by resetting the device to factory defaults and then set the &#039;&#039;Update URL&#039;&#039; again&lt;br /&gt;
* remove any stored files for the device on the update server (shown in the &#039;&#039;Certificates&#039;&#039; column)&lt;br /&gt;
&lt;br /&gt;
The normal process will start all over again then.&lt;br /&gt;
&lt;br /&gt;
=== Migrating old PHP Update Server Installations ===&lt;br /&gt;
==== Migrating from build 2000 an newer ====&lt;br /&gt;
* Copy all files and folders, &#039;&#039;&#039;except&#039;&#039;&#039; the &#039;&#039;scripts&#039;&#039; and &#039;&#039;config&#039;&#039; folder, from the source to your destination&lt;br /&gt;
* make sure all files and directories have correct owner (&#039;&#039;www-data&#039;&#039;), group (&#039;&#039;www-data&#039;&#039;) and mode (&#039;&#039;read&#039;&#039;/&#039;&#039;write&#039;&#039; plus &#039;&#039;execute&#039;&#039; for directories)&lt;br /&gt;
: for example, in WinSCP you can use the &#039;&#039;Properties (F9)&#039;&#039; dialogue on the installations root folder:&lt;br /&gt;
: [[Image:PHP based Update Server V2-WinSCP-Properties.png]]&lt;br /&gt;
* open the &#039;&#039;StatusPage&#039;&#039; and make sure you refresh all cached files in your browser (depending on your browser, this may happen with Ctrl-R or Ctrl-F5)&lt;br /&gt;
&lt;br /&gt;
==== Migrating from build 1011 and older ====&lt;br /&gt;
To upgrade from the [http://download.innovaphone.com/ice/wiki-src/index.php?urloffset=php-update-server%2F&amp;amp;name=php-update-server+%28all+available+builds%29&amp;amp;reverselevel=0&amp;amp;maxbuilds=999&amp;amp;root=c%3A%2Finetpub%2Fwwwroot%2Fdownload%2Fice%2Fdownload%2Fp%2Fwiki-src%2Fphp-update-server%2F1010+%28PHP+based+Update+Server+final%29%2F.. old version (builds up to 1011)] of the PHP based update server (as described in [[Howto:PHP based Update Server]]), do the following&lt;br /&gt;
&lt;br /&gt;
* diff your &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; to the one originally shipped (you can download it at [http://download.innovaphone.com/ice/download/p/wiki-src/php-update-server/1011%20(PHP%20based%20Update%20Server%20final)/php-update-server-1011.zip download.innovaphone.com/ice/wiki-src])&lt;br /&gt;
: take note of all the changes you made to it&lt;br /&gt;
* install the new version of the update server to a different URL&lt;br /&gt;
* configure it according to your needs by modifying &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  Do not modify the new &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt;!&lt;br /&gt;
** apply all modifications you did to your old &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; to your new &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
** if you have used a custom setting for fwstorage/@url, you need to change it a bit.  Change for example &amp;lt;code&amp;gt;url=&amp;quot;http://myfwserver.mycompany.com&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;http://myfwserver.mycompany.com/{build}/&amp;lt;/code&amp;gt; (note the trailing slash!)&lt;br /&gt;
* copy all your update script snippet files from the old server (these are all the .txt files in the old server&#039;s root directory) to the &amp;lt;code&amp;gt;scripts&amp;lt;/code&amp;gt; directory of your new server&lt;br /&gt;
* copy the complete &amp;lt;code&amp;gt;fw&amp;lt;/code&amp;gt; tree from the old server to the &amp;lt;code&amp;gt;fw&amp;lt;/code&amp;gt; directory of your new server&lt;br /&gt;
* thoroughly test your new installation with some test devices&lt;br /&gt;
* when satisfied, edit &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; and change the code as described in the comment inside the file&lt;br /&gt;
* copy &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; from the new installation to the old installation&lt;br /&gt;
* on one of the devices which are currently served by the old update server, change the &#039;&#039;Command File URL&#039;&#039; so that it points to &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt;.  Do not change anything else in the URL. So if it currently is set to e.g. &lt;br /&gt;
: &amp;lt;code&amp;gt;https://172.16.0.90/update/update.php?type=#t&amp;amp;env=sifi&amp;amp;polling=0&amp;amp;phase=update&amp;lt;/code&amp;gt;, change it to&lt;br /&gt;
: &amp;lt;code&amp;gt;https://172.16.0.90/update/update-migrate.php?type=#t&amp;amp;env=sifi&amp;amp;polling=0&amp;amp;phase=update&amp;lt;/code&amp;gt;&lt;br /&gt;
* verify that this device properly switches to your new installation&lt;br /&gt;
** the &#039;&#039;Command File URL&#039;&#039; is changed so that it points to the new installation&lt;br /&gt;
** the device shows up in the device status page of your new server&lt;br /&gt;
&lt;br /&gt;
* rename &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;update-old.php&amp;lt;/code&amp;gt; in your old update server&lt;br /&gt;
* rename &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt; in your old update server&lt;br /&gt;
* verify that all of your devices start showing up in the new server&#039;s status page&lt;br /&gt;
&lt;br /&gt;
=== Complete Parameter Reference ===&lt;br /&gt;
Note: attributes are marked with an &#039;&#039;at&#039;&#039; (&amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;) prefix.  So &#039;&#039;master/@info&#039;&#039; refers to the &#039;&#039;info&#039;&#039; attribute in the &#039;&#039;master&#039;&#039; tag.&lt;br /&gt;
&lt;br /&gt;
The following tags and attributes are available in the &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt; file, their default values are configured in &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; (which you should not modify):&lt;br /&gt;
&lt;br /&gt;
==== master ====&lt;br /&gt;
Defines the reference device where the firmware and boot code information is taken from.&lt;br /&gt;
; master/@info : the URL to the device info data.  Set it to an URL like &amp;lt;code&amp;gt;http://&amp;lt;/code&amp;gt;&#039;&#039;your-reference-device&#039;&#039;&amp;lt;code&amp;gt;/CMD0/box_info.xml&amp;lt;/code&amp;gt;. Please note that this device must not have the &#039;&#039;Password protect all HTTP pages&#039;&#039; set in &#039;&#039;Services/HTTP/Server&#039;&#039;.  If you use the literal &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt;, the master device will not be queried&lt;br /&gt;
; master/@expire : the firmware info cache lifetime.  The firmware information is cached in a file (to make sure this information is present even if the reference device is off-line).  The cache will not be refreshed before the &#039;&#039;expire&#039;&#039; time (in seconds) is expired&lt;br /&gt;
; master/@cache : the cache file name.  The web server must be able to write this file (see [[#Installation | &#039;&#039;Installation&#039;&#039; ]] above)&lt;br /&gt;
; master/@user : if non-empty, this is the user name required to access the update server&#039;s web ui&lt;br /&gt;
; master/@password : the password&lt;br /&gt;
&lt;br /&gt;
From build 2009, you can control the firmware and bootcode version to use on update:&lt;br /&gt;
; master/@firmware : if set, it may be one of &lt;br /&gt;
:: &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; (default if not set) : the firmware version is derived from the master device&lt;br /&gt;
:: &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt; : the firmware update is generally disabled&lt;br /&gt;
:: &#039;&#039;build-number&#039;&#039; : the firmware is set to a certain &#039;&#039;build-number&#039;&#039; regardless of the firmware running on the master device&lt;br /&gt;
; master/@bootcode: if set, it may be one of &lt;br /&gt;
:: &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; (default if not set) : the bootcode version is derived from the master device&lt;br /&gt;
:: &amp;lt;code&amp;gt;firmware&amp;lt;/code&amp;gt; : the bootcode version is set to the firmware version. This may be useful if the master device has no bootcode (e.g. the ipva)&lt;br /&gt;
:: &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt; : the bootcode update is generally disabled&lt;br /&gt;
:: &#039;&#039;build-number&#039;&#039; : the bootcode is set to a certain &#039;&#039;build-number&#039;&#039; regardless of the bootcode running on the master device&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;master &lt;br /&gt;
        info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;&lt;br /&gt;
        expire=&amp;quot;3600&amp;quot;&lt;br /&gt;
        cache=&amp;quot;cache/master-info.xml&amp;quot;&lt;br /&gt;
        user=&amp;quot;myadmin&amp;quot;&lt;br /&gt;
        password=&amp;quot;mysecret&amp;quot;&lt;br /&gt;
        firmware=&amp;quot;4711&amp;quot;&lt;br /&gt;
        bootcode=&amp;quot;firmware&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== master/applies ====&lt;br /&gt;
Available from build 2009.&lt;br /&gt;
&lt;br /&gt;
Boot code and firmware updates are only executed by devices which match all of the given &amp;lt;applies&amp;gt; conditions. A condition is met if the device belongs to the class that is given as tag content.  If the &#039;&#039;env&#039;&#039; attribute is set, the tag content is interpreted as an &#039;&#039;environment&#039;&#039; name which has to match.&lt;br /&gt;
&lt;br /&gt;
; master/applies/@env : if this attribute exists, the tag content is compared with the environments the device is in.  Otherwise, it is compared with the classes it is in &lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;master &lt;br /&gt;
    info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;&lt;br /&gt;
    expire=&amp;quot;3600&amp;quot;&lt;br /&gt;
    cache=&amp;quot;cache/master-info.xml&amp;quot;&lt;br /&gt;
    user=&amp;quot;myadmin&amp;quot;&lt;br /&gt;
    password=&amp;quot;mysecret&amp;quot;&lt;br /&gt;
    firmware=&amp;quot;4711&amp;quot;&lt;br /&gt;
    bootcode=&amp;quot;firmware&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- applied to phones in berlin only --&amp;gt;&lt;br /&gt;
    &amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
    &amp;lt;applies env=&amp;quot;&amp;quot;&amp;gt;berlin&amp;lt;/applies&amp;gt;&lt;br /&gt;
&amp;lt;/master&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== fwstorage ====&lt;br /&gt;
Defines from where the device will retrieve the firmware files for updates.&lt;br /&gt;
; fwstorage/@url :  defines the URL to retrieve the files from.  In this URL, the following meta words will be replaced as follows:&lt;br /&gt;
:* &amp;lt;code&amp;gt;{build}&amp;lt;/code&amp;gt; - the requested firmware or boot-code &lt;br /&gt;
:* &amp;lt;code&amp;gt;{model}&amp;lt;/code&amp;gt; - the devices type (e.g. &amp;lt;code&amp;gt;IP232&amp;lt;/code&amp;gt;).  This is derived from the &#039;&#039;type&#039;&#039; query argument used in the update URL which is set to the value &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; which in turn is expanded to the [[Reference10:Concept_Update_Server#Scfg_command|&#039;&#039;device type&#039;&#039;]] of the device requesting the update script&lt;br /&gt;
:* &amp;lt;code&amp;gt;{filetype}&amp;lt;/code&amp;gt; - the type of the required file, either &amp;lt;code&amp;gt;boot&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;prot&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code&amp;gt;{filename}&amp;lt;/code&amp;gt; - (from build 2014) the boot code or firmware filename for the device in lower case.  Required if you use the LAP as firmware storage and firmware files are falsely requested in uppercase letters (as URLs on the LAP are case sensitive and if the files are requested with upper case names, the original files with lowercase name are not found).  This also allows you to use alternate firmware file names (such as e.g. &amp;lt;code&amp;gt;ip110-sip.bin&amp;lt;/code&amp;gt;).  See the &#039;&#039;filenames&#039;&#039; tag&lt;br /&gt;
Note that if the &#039;&#039;url&#039;&#039; ends with a slash (&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;), the calling device will automatically [[Reference10:Concept_Update_Server#Prot_command|append the name of the requested file]]. In this case, the file system the URL points to must therefore contain sub-directories for each firmware build which contain the corresponding firmware builds (e.g, &#039;&#039;fw/12345/ip232.bin&#039;&#039;).  If &#039;&#039;url&#039;&#039; is not an URL (as is the case for the default value &amp;lt;code&amp;gt;fw/{build}/&amp;lt;/code&amp;gt;), it is treated as a sub-directory underneath the update server&#039;s root directory&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;fwstorage url=&amp;quot;fw/{build}/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Loading firmware files from innovaphone.com =====&lt;br /&gt;
You can also load firmware from the innovaphone.com web site.  To do so, set &#039;&#039;url&#039;&#039; like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;fwstorage url=&amp;quot;http://webbuild.innovaphone.com/{build}/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that &#039;&#039;this is a voluntary service, no guarantee of availability, no service level agreement&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== backup ====&lt;br /&gt;
Defines where backup files are kept.&lt;br /&gt;
; backup/@dir :  the directory underneath the script directory where backups are stored&lt;br /&gt;
; backup/@nbackups :  the number of different backup files kept&lt;br /&gt;
; backup/@scfg :  the target URL for the scfg command.  If this is not an url, it is interpreted relative to the script directory URL. You can add more options for the &#039;&#039;scfg&#039;&#039; command, like in &amp;lt;code&amp;gt;scfg=&amp;quot;update.php?mode=backup&amp;amp;amp;hwid=#h&amp;amp;amp;sn=#m ser hourly /force 1&amp;quot;&amp;lt;/code&amp;gt; (this example will make sure backups are attempted only once per hour, so as to reduce load on the server).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;backup &lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
        nbackups=&amp;quot;10&amp;quot;&lt;br /&gt;
        scfg=&amp;quot;update.php?mode=backup&amp;amp;amp;hwid=#h&amp;amp;amp;sn=#m&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== status ====&lt;br /&gt;
Defines details regarding the state kept for a device requesting an update script.&lt;br /&gt;
; status/@dir : the directory the status files are kept in (e.g. &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;).  Used as the name for a sub-directory underneath your install directory on your web server. You must make sure that files in this directory cannot be read by anyone without proper authentication, as such files may contain sensitive information.&lt;br /&gt;
; status/@expire : if set and not empty, devices which have not requested an update script will be removed from the inventory after &#039;&#039;n&#039;&#039; seconds.  For example, &#039;&#039;expire=&amp;quot;7776000&amp;quot;&#039;&#039; will forget about devices after 90 days with no contact&lt;br /&gt;
; status/@missing : devices are shown in a different colour (indicating that they are &#039;&#039;missing&#039;&#039;) after &#039;&#039;n&#039;&#039; seconds. For example, &#039;&#039;missing=&amp;quot;604800&amp;quot;&#039;&#039; will flag devices as missing after 7 days with no contact&lt;br /&gt;
; status/@refresh : if set and not empty and larger than zero, the admin user interface showing the known devices will refresh the status of all shown devices each &#039;&#039;n&#039;&#039; seconds&lt;br /&gt;
; status/@logkeep : number of seconds log messages for individual devices will be kept&lt;br /&gt;
; status/usehttpsdevlinks : if set to true, links to devices in the status page are created using the https:// scheme&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;status &lt;br /&gt;
        dir=&amp;quot;status&amp;quot; &lt;br /&gt;
        expire=&amp;quot;7776000&amp;quot; &lt;br /&gt;
        missing=&amp;quot;200&amp;quot; &lt;br /&gt;
        refresh=&amp;quot;10&amp;quot;&lt;br /&gt;
        logkeep=&amp;quot;90&amp;quot;&lt;br /&gt;
        usehttpsdevlinks=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== times ====&lt;br /&gt;
Defines details regarding the delivery of update scripts to requesting devices. &lt;br /&gt;
&lt;br /&gt;
; times/@dir : the directory the update scripts are stored in.  For security reasons, you may want to make sure that files in this directory cannot be read without proper authentication.&lt;br /&gt;
&lt;br /&gt;
These attributes define the arguments of the [[Reference10:Concept_Update_Server#Times_command | times command]].  If neither &#039;&#039;allow&#039;&#039; nor &#039;&#039;initial&#039;&#039; is set, no &#039;&#039;times&#039;&#039; command is used (that is, the update scripts will be processed at all times).&lt;br /&gt;
; times/@allow :  the hours to be used in the &#039;&#039;times&#039;&#039; command (as in &amp;lt;code&amp;gt;mod cmd UP1 times /allow &amp;lt;/code&amp;gt;&#039;&#039;hours&#039;&#039;)&lt;br /&gt;
; times/@initial :  the minutes to be used in the &#039;&#039;times&#039;&#039; command (as in &amp;lt;code&amp;gt;mod cmd UP1 times /initial &amp;lt;/code&amp;gt;&#039;&#039;minutes&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Delivered update scripts can include a [[Reference10:Concept_Update_Server#Check_command | check command ]] if the &#039;&#039;check&#039;&#039; attribute is set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.  . In this case, the devices will executed the scripts again only when you have edited/changed them.&lt;br /&gt;
; times/@check :  if set to true, update scripts will be executed once only (unless their contents change)&lt;br /&gt;
&lt;br /&gt;
When editing a number of update scripts, it is often not desirable if one changed script is already executed before another is changed too.   When the &#039;&#039;grace&#039;&#039; attribute is set to a positive value, no script at all is delivered to requesting devices unless &#039;&#039;n&#039;&#039; seconds have expired since the last edit.  For example, setting &#039;&#039;grace&#039;&#039; to 90 gives you one and a half minute to finish all your edits. &lt;br /&gt;
&lt;br /&gt;
; times/@grace :  defines the number of seconds that must expire before update script changes take effect&lt;br /&gt;
&lt;br /&gt;
The update server works in either &#039;&#039;fast&#039;&#039; or &#039;&#039;normal&#039;&#039; mode. In &#039;&#039;fast&#039;&#039; mode, update scripts have to be requested more frequently, for example to step through multiple staging phases faster. This is enforced by modifying the calling device&#039;s &#039;&#039;Interval&#039;&#039; setting in [[Reference11r1:Services/Update | &#039;&#039;Services/Update &#039;&#039;]] and setting it to 1 in &#039;&#039;fast&#039;&#039; mode.&lt;br /&gt;
&lt;br /&gt;
; times/@interval :  polling interval in minutes for normal operation (that is, when all staging s done)&lt;br /&gt;
; times/@polling :  when you are using multiple &#039;&#039;phases&#039;&#039; (e.g. &#039;&#039;staging&#039;&#039; and &#039;&#039;update&#039;&#039;), this defines the number of seconds to wait before the device reads the scripts for the next phase (see [[Reference10:Concept_Update_Server#Provision_command | provision command]]) (please do not modify the default value)&lt;br /&gt;
&lt;br /&gt;
In some installations it may be desired to deliver update scripts with HTTPS only or even only to calling devices which have identified themselves with a proper TLS certificate.  &lt;br /&gt;
&lt;br /&gt;
; times/@forcehttps : if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, update scripts will only be delivered if the device call in with HTTPS.  If the device is ready to receive an update script and still calls in with HTTP only, its &#039;&#039;Command File URL&#039;&#039; will be re-configured to use HTTPS automatically.&lt;br /&gt;
; times/@httpsport : if you use a non-standard port for HTTPS access to update scripts, it can be defined here&lt;br /&gt;
; times/@httpsurlmod : if your HTTPS URL differs from the HTTP URL, you can specifiy a &#039;&#039;modifier&#039;&#039;.  It has the form &amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&#039;&#039;pattern&#039;&#039;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&#039;&#039;replacement&#039;&#039;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt; where &#039;&#039;pattern&#039;&#039; is a [http://docs.php.net/manual/en/pcre.pattern.php PHP PCRE pattern]. For example, &amp;lt;code&amp;gt;!mtls/!!i&amp;lt;/code&amp;gt; will remove the string &amp;lt;code&amp;gt;mtls/&amp;lt;/code&amp;gt; from the URL used by the device to create the HTTPS URL to use. The delimiter (in this case &amp;quot;!&amp;quot;) can be changed according to your own wishes, the first character defines the delimiter. The &amp;quot;i&amp;quot; at the end ignores uppercase.&lt;br /&gt;
&lt;br /&gt;
Note: If you want to change the hostname of your URL, you have to add the Port 444 to your hostname. The code should then look like this: &amp;lt;code&amp;gt;!hostname1:444/mtls/!hostname2:444/!i&amp;lt;/code&amp;gt;.&lt;br /&gt;
; times/@forcetrust : if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, update scripts will only be delivered if the device call in with HTTPS and a valid and trusted client certificate that identifies itself as the devices it claims to be&lt;br /&gt;
; times/@forcestaging : before build 2009, the restrictions imposed by the times/@allow settings affected all update &#039;&#039;phases&#039;&#039;.  This however makes staging cumbersome, as you usually want to restrict normal configuration changes to off-working-hours.  Now you can set the &#039;&#039;forcestaging&#039;&#039; attribute to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.  If so, the restriction will be applied only to the last phase (that is, the &#039;&#039;staging&#039;&#039; phases will execute immediately). Also, the final phase will be executed once by staged devices. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        dir=&amp;quot;scripts&amp;quot; &lt;br /&gt;
        allow=&amp;quot;&amp;quot; &lt;br /&gt;
        initial=&amp;quot;&amp;quot; &lt;br /&gt;
        check=&amp;quot;true&amp;quot; &lt;br /&gt;
        polling=&amp;quot;5&amp;quot; &lt;br /&gt;
        interval=&amp;quot;15&amp;quot; &lt;br /&gt;
        grace=&amp;quot;90&amp;quot; &lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot; &lt;br /&gt;
        httpsport=&amp;quot;444&amp;quot; &lt;br /&gt;
        forcetrust=&amp;quot;false&amp;quot; &lt;br /&gt;
        httpsurlmod=&amp;quot;!mtls/!!i&amp;quot;&lt;br /&gt;
        forcestaging=&amp;quot;true&amp;quot;&lt;br /&gt;
/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== phases ==== &lt;br /&gt;
Defines the scripting phases.  In many installations, there are initializations which should be performed once only.  This is known as the &#039;&#039;staging&#039;&#039; phase.  Once this is done, the devices continue with the execution of the normal update scripts (this phase is known as &#039;&#039;update&#039;&#039; by default).  In the (unlikely) event that you want more or less phases, you can add/remove &#039;&#039;phase&#039;&#039; tags.&lt;br /&gt;
==== phases/phase ====&lt;br /&gt;
; phases/phase/@id :  the name for the phase&lt;br /&gt;
; phases/phase/@seq:  the sequential number for the phase. Phases are stepped-through in the numeric order defined by their &#039;&#039;seq&#039;&#039; atribute. &lt;br /&gt;
&lt;br /&gt;
By virtue if the &#039;&#039;seq&#039;&#039; attribute, you can insert phases in to the set of phases defined by default, which is&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
        &amp;lt;!-- sequence is important! --&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;update&amp;quot; seq=&amp;quot;200&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For example,&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;phase&amp;quot; seq=&amp;quot;150&amp;quot;&amp;gt;&amp;lt;/phase&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will insert a custom phase &#039;&#039;myphase&#039;&#039; as second phase.&lt;br /&gt;
&lt;br /&gt;
==== environments ====&lt;br /&gt;
Defines the distinguished environments.  Devices can have zero or more &#039;&#039;environments&#039;&#039; associated.  The environments a device is considered to be in must be passed as &amp;lt;code&amp;gt;?env=&amp;lt;/code&amp;gt;&#039;&#039;name1,name2,..&#039;&#039; URL query arg in the update url.  Update scripts for all environments listed will be applied. The default config file defines the environments &#039;&#039;intern&#039;&#039; and &#039;&#039;homeoffice&#039;&#039; but you can define your own if you like.&lt;br /&gt;
==== environments/environment ====&lt;br /&gt;
; environments/environment/@id :  the name for the environment&lt;br /&gt;
&lt;br /&gt;
==== environments/environment/implies ====&lt;br /&gt;
Each &#039;&#039;environment&#039;&#039; may have a number of sub-tags of type &#039;&#039;implies&#039;&#039;. It contains the &#039;&#039;id&#039;&#039; of another &#039;&#039;environment&#039;&#039;.   If a device is in an environment with an &#039;&#039;implies&#039;&#039; sub-tag, it is assumed that it is in the implied environment also. &lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;environments&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;hq&#039;&amp;gt;&lt;br /&gt;
            &amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
        &amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;intranet&#039;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;homeoffice&#039;/&amp;gt;&lt;br /&gt;
    &amp;lt;/environments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== classes ====&lt;br /&gt;
Defines the available device classes.  Devices of different classes (e.g. phones and gateways) can have different update scripts. The device class is derived from the &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; (device type) query arg of the update script URL (which is why you must configure it in the update URL).  By default, the classes &#039;&#039;phone&#039;&#039;, &#039;&#039;opus_phone&#039;&#039;, &#039;&#039;pre_opus_phone&#039;&#039;, &#039;&#039;phone_oldui&#039;&#039;, &#039;&#039;phone_newui&#039;&#039;, &#039;&#039;mobile&#039;&#039;, &#039;&#039;gw&#039;&#039;, &#039;&#039;fxogw&#039;&#039;, &#039;&#039;fxsgw&#039;&#039;, &#039;&#039;brigw&#039;&#039;, &#039;&#039;prigw&#039;&#039; are recognized (newer versions may include more and/or updated class definitions).   Also, any device is considered to be member of a class that has the device type as class-name.  For example, an IP112 is in a class called &#039;&#039;ip112&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A given device can be in multiple classes and will execute all update scripts available for these classes.&lt;br /&gt;
&lt;br /&gt;
==== classes/class ====&lt;br /&gt;
Each &#039;&#039;class&#039;&#039; has a number of sub-tags of type &#039;&#039;model&#039;&#039;. It contains the value replaced for the &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; query arg.  The models listed belong to the class.&lt;br /&gt;
; classes/class/@id :  the name of the class&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;classes&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;gw&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip0010&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip110&amp;lt;/model&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip232&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone_oldui&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip110&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone_newui&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip232&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
    &amp;lt;/classes&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== nobootdev ====&lt;br /&gt;
Device types listed here do not receive boot code updates.&lt;br /&gt;
===== nobootdev/model =====&lt;br /&gt;
Each model tag defines a device type that shall not receive boot code updates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;nobootdev&amp;gt; &lt;br /&gt;
        &amp;lt;model&amp;gt;ipva&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;ipvadec&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;swphone&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxa&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxi&amp;lt;/model&amp;gt;&lt;br /&gt;
    &amp;lt;/nobootdev&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== nofirmdev ====&lt;br /&gt;
Device types listed here do not receive firmware updates.&lt;br /&gt;
===== nobootdev/model =====&lt;br /&gt;
Each model tag defines a device type that shall not receive firmware updates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;nofirmdev&amp;gt; &lt;br /&gt;
        &amp;lt;model&amp;gt;swphone&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxi&amp;lt;/model&amp;gt;&lt;br /&gt;
    &amp;lt;/nofirmdev&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== filenames ====&lt;br /&gt;
Available from build 2014. Allows you to define alternate firmware and boocode names for use with the &amp;lt;code&amp;gt;{filename}&amp;lt;/code&amp;gt; replacement (see the &#039;&#039;fwstorage&#039;&#039; tag), if required.&lt;br /&gt;
&lt;br /&gt;
===== filenames/model =====&lt;br /&gt;
Each mode defines a set of alternative file names for a certain device type.&lt;br /&gt;
; filenames/model/@id : the (lowercase) device type identfier (e.g. &amp;lt;code&amp;gt;ip112&amp;lt;/code&amp;gt;). If this matches the device type of the calling device, the alternate file names are replaced&lt;br /&gt;
; filenames/model/@prot: the alternate firmware file name&lt;br /&gt;
; filenames/model/@boot: the alternate boot file name&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;filenames&amp;gt;&lt;br /&gt;
        &amp;lt;model id=&amp;quot;mypbxa&amp;quot; prot=&amp;quot;mypbx.apk&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/filenames&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
defines the firmware file name &amp;lt;code&amp;gt;mypbx.apk&amp;lt;/code&amp;gt; for the device type &amp;lt;code&amp;gt;mypbxa&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== stdargs ====&lt;br /&gt;
Better don&#039;t touch :-)&lt;br /&gt;
&lt;br /&gt;
==== customcerts ====&lt;br /&gt;
innovaphone hardware devices come with a device specific, trust-able &#039;&#039;device certificate&#039;&#039;.  However, in many situations it is desirable to roll-out customer-created &#039;&#039;custom  certificates&#039;&#039; to all devices.  The update server can do this.  This will replace the shipped devices certificates both on hardware devices (where all such certificates are derived from innovaphone&#039;s certificate authority) as well as on soft devices which run with a self.-signed certificate by default (such as the software-phone or &#039;&#039;myPBX for Android/iOS&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
; customcerts/@dir : the name of the directory underneath your installation directory which stores device certificates. you should make sure that this directory cannot be accessed without proper authentication&lt;br /&gt;
; customcerts/@CAkeys : a file name pattern (e.g. &amp;lt;code&amp;gt;CAkey*&amp;lt;/code&amp;gt;).  All files in &#039;&#039;customcerts/@dir&#039;&#039; which match the pattern must contain DER or PEM encoded public keys which form the &#039;&#039;certificate chain&#039;&#039; of your CA (usually it is only one and the public key of your CA). One key per file.  The files, when sorted by name, must contain the CA key itself in the last file (any intermediate certificates, if any, in the other files in correct order)&lt;br /&gt;
; customcerts/@CAtype : must be &amp;lt;code&amp;gt;manual&amp;lt;/code&amp;gt; currently&lt;br /&gt;
; customcerts/@CAname : a comma-separated list of CA names.  Devices presenting a certificate signed by one of these CAs will be considered as having a valid certificate.  Otherwise, they wil be instructed to create a &#039;&#039;certificate signing request&#039;&#039; (CSR) for subsequent submission to your CA&lt;br /&gt;
; customcerts/@CAnamesep : defines the name separator for &#039;&#039;customcerts/@CAname&#039;&#039;.  The default is &#039;&amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;&#039; and you must change it to a different value if one of your CAs includes a comma in its name&lt;br /&gt;
; customcerts/@renew : if set and not 0, certificates are replaced by new ones &#039;&#039;n&#039;&#039; days before they expire&lt;br /&gt;
; customcerts/@CAwildcard : normally, the update server will accept a certificate only if its CN matches the device&#039;s serial number.  However, sometimes, so-called &#039;&#039;wildcard certificates&#039;&#039; such as &amp;lt;code&amp;gt;*.innovaphone.com&amp;lt;/code&amp;gt; are used on a device (e.g. on a PBX or on a &#039;&#039;reverse proxy&#039;&#039;).  If set, the update server will also accept a certificate that contains a CN which equals the value of &#039;&#039;customcerts/@CAwildcard&#039;&#039;. Note that the CN must match literally.  For example, if &#039;&#039;&#039;&#039;customcerts/@CAwildcard&#039;&#039; is set to &amp;lt;code&amp;gt;*.innovaphone.com&amp;lt;/code&amp;gt; a CN like &amp;lt;code&amp;gt;host.innovaphone.com&amp;lt;/code&amp;gt; is not accepted&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the update server determines that a device calls in with an un-trusted or expired certificate, it will have it create a signing-request for a new certificate.  The requested certificate properties can be defined:&lt;br /&gt;
&lt;br /&gt;
; customcerts/@CSRkey : the key size, e.g. &amp;lt;code&amp;gt;2048-bit&amp;lt;/code&amp;gt;. Note that we do not recommend keys larger than 2048 bit (see [[Reference7:Certificate_management#Certificate_Key_Length_and_CPU_Usage]] for details)&lt;br /&gt;
; customcerts/@CSRsignature : the signature algorithm, e.g. &amp;lt;code&amp;gt;SH256&amp;lt;/code&amp;gt;&lt;br /&gt;
; customcerts/@CSRdn-cn : the CN (&#039;&#039;common name&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-ou : the OU (&#039;&#039;organizational unit&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-o : the O (&#039;&#039;organization&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-l : the L (&#039;&#039;locality&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-st : the ST (&#039;&#039;state or province&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-c : the C (&#039;&#039;country&#039;&#039;) part used for the DN (note: &#039;&#039;CSRdn&#039;&#039; for many CAs, must be a 2-letter ISO country code)&lt;br /&gt;
; customcerts/@CSRsan-dns-1 : the first of up to three DNS names &lt;br /&gt;
; customcerts/@CSRsan-ip-1 : the first of up to two IP addresses&lt;br /&gt;
&lt;br /&gt;
Within the set of CSR attributes, the following meta-words will be replaced:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;{realip}&amp;lt;/code&amp;gt; : the real IP address of the device as reported in the &amp;lt;code&amp;gt;ip=#i&amp;lt;/code&amp;gt; query argument&lt;br /&gt;
* &amp;lt;code&amp;gt;{ip}&amp;lt;/code&amp;gt; : the IP address of the device as seen by the update server&lt;br /&gt;
* &amp;lt;code&amp;gt;{proxy}&amp;lt;/code&amp;gt; : the IP address of the reverse proxy the device used to reach the update server&lt;br /&gt;
* &amp;lt;code&amp;gt;{sn}&amp;lt;/code&amp;gt; : the serial number of the device as reported in the &amp;lt;code&amp;gt;sn=#m&amp;lt;/code&amp;gt; query argument (e.g. &amp;lt;code&amp;gt;009033030df0&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;{hwid}&amp;lt;/code&amp;gt; : the hardware-id of the device as reported in the &amp;lt;code&amp;gt;sn=#m&amp;lt;/code&amp;gt; query argument (e.g. &amp;lt;code&amp;gt;IP1200-03-0d-f0&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;{name}&amp;lt;/code&amp;gt; : the &#039;&#039;Device Name&#039;&#039; (set in &#039;&#039;General/Admin&#039;&#039;) of the device&lt;br /&gt;
* &amp;lt;code&amp;gt;{rdns}&amp;lt;/code&amp;gt; : the DNS name found in a reverse DNS lookup for the real-ip address reported by the device (see &#039;&#039;{realip}&#039;&#039;) above&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;customcerts &lt;br /&gt;
        dir=&amp;quot;certs&amp;quot; &lt;br /&gt;
        CAkeys=&amp;quot;CAkey*&amp;quot; &lt;br /&gt;
        CAtype=&amp;quot;manual&amp;quot; &lt;br /&gt;
        CAname=&amp;quot;innovaphone-INNO-DC-W2K8-Zertifizierungsserver&amp;quot; &lt;br /&gt;
        CAnamesep=&amp;quot;,&amp;quot; &lt;br /&gt;
        CAwildcard=&amp;quot;*.innovaphone.com&amp;quot;&lt;br /&gt;
        CSRkey=&amp;quot;2048-bit&amp;quot; &lt;br /&gt;
        CSRsignature=&amp;quot;SH256&amp;quot; &lt;br /&gt;
        CSRdn-cn=&amp;quot;{hwid}&amp;quot; &lt;br /&gt;
        CSRdn-ou=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-o=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-l=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-st=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-c=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRsan-dns-1=&amp;quot;{name}.company.com&amp;quot; &lt;br /&gt;
        CSRsan-dns-2=&amp;quot;{hwid}.company.com&amp;quot; &lt;br /&gt;
        CSRsan-dns-3=&amp;quot;{rdns}&amp;quot; &lt;br /&gt;
        CSRsan-ip-1=&amp;quot;{realip}&amp;quot; &lt;br /&gt;
        CSRsan-ip-2=&amp;quot;&amp;quot; &lt;br /&gt;
        renew=&amp;quot;90&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries ====&lt;br /&gt;
If queries are defined and applicable for the calling device, it will be instructed to send certain information to the update server which will be stored in the device status file kept on the server.  Each piece of such information is defined usign a separate &#039;&#039;query&#039;&#039; tag.&lt;br /&gt;
&lt;br /&gt;
; queries/@scfg : defines to URL used by the device to send the information.  Normally not changed from the default&lt;br /&gt;
==== queries/query ====&lt;br /&gt;
Defines one piece of information to be submitted to the update server.&lt;br /&gt;
&lt;br /&gt;
; queries/query/@id : a unique name for the query&lt;br /&gt;
; queries/query/@title : a title for this piece of information shown in the device status&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;.&lt;br /&gt;
        &amp;lt;!-- retrieve and show some details from IP4/General/STUN page --&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;media&amp;quot; title=&amp;quot;Media&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd MEDIA xml-info&amp;lt;/cmd&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;NAT&amp;quot;&amp;gt;concat(/state/queries/media/info/nat/@result, &#039; (&#039;, /state/queries/media/info/nat/@public-addr, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Server&amp;quot;&amp;gt;concat(&#039;STUN: &#039;, /state/queries/media/info/@stun, &#039; TURN: &#039;, /state/queries/media/info/@turn, &#039; (&#039;, /state/queries/media/info/@turn-user, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;!-- show primary phone registration --&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;registration&amp;quot; title=&amp;quot;Registration&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd PHONE/USER phone-regs /cmd phone-regs&amp;lt;/cmd&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;State: User/Number&amp;quot;&amp;gt;concat(/state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@state, &#039;: &#039; , /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@h323, &#039;/&#039;, /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@e164)&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;PBX/ID&amp;quot;&amp;gt;concat(/state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@gk-addr, &#039;/&#039;, /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@gk-id)&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries/query/cmd ====&lt;br /&gt;
The content of this tag defines the command to be executed on the device which outputs the requested information. These are &#039;&#039;mod cmd&#039;&#039;s typically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
            &amp;lt;!-- get info for custom certificates --&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd X509 xml-info&amp;lt;/cmd&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Howto:Effect_arbitrary_Configuration_Changes_using_a_HTTP_Command_Line_Client_or_from_an_Update#Using_the_Mechanism_for_Device_Status_Queries ]] for details on how to find out whicgh commands to use.&lt;br /&gt;
&lt;br /&gt;
==== queries/query/applies ====&lt;br /&gt;
Defined queries are only executed by devices which belong to the class that is given as tag content.  If the &#039;&#039;env&#039;&#039; atribute is set, the tag content is interpreted as an &#039;&#039;environment&#039;&#039; name which has to match.&lt;br /&gt;
&lt;br /&gt;
; queries/query/applies/@env : if this attribute exists, the tag content is compared with the environments the device is in.  Otherwise, it is compared with the classes it is in (unfortunately, you can not combine bith)&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;!-- applied to phones only --&amp;gt;&lt;br /&gt;
&amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries/query/show====&lt;br /&gt;
If one or more  &#039;&#039;show&#039;&#039; tags are defined for the &#039;&#039;query&#039;&#039; tag, the data will be shown in the device status page.  The values shown are defined by the tag content which is an XPath expression selecting the data from the device state.  The XPath expression always begins with &amp;lt;code&amp;gt;/state/queries/&amp;lt;/code&amp;gt;&#039;&#039;query-id&#039;&#039; (as defined by the &#039;&#039;id&#039;&#039; attribute in the query tag).  &lt;br /&gt;
&lt;br /&gt;
; queries/query/show/@title : used as title when the values are displayed in the status page&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;show title=&amp;quot;NAT&amp;quot;&amp;gt;concat(/state/queries/media/info/nat/@result, &#039; (&#039;, /state/queries/media/info/nat/@public-addr, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
*[http://download.innovaphone.com/ice/wiki-src#php-update-server http://download.innovaphone.com/ice/wiki-src/] - download the complete file package of scripts and files described in this article&lt;br /&gt;
: you need to use build 2000 or higher.  Older versions are described in [[Howto:PHP_based_Update_Server]]&lt;br /&gt;
&lt;br /&gt;
== Hints for writing your update snippets ==&lt;br /&gt;
Writing update scripts is largely undocumented and sometimes tricky.  Here are some general guidelines.&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;config add/del&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Many setting are done using &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; commands.  So these are very useful in update scripts too.&lt;br /&gt;
&lt;br /&gt;
The straight forward method to find out which commands you need is as follows:&lt;br /&gt;
* get a device of the type in question and do factory reset&lt;br /&gt;
* save the configuration to a file&lt;br /&gt;
* do the desired settings using the normal web admin UI&lt;br /&gt;
* save the resulting configuration to another file&lt;br /&gt;
* compare the saved files&lt;br /&gt;
&lt;br /&gt;
Usually, you want to set only specific parts of the configuration line.  For example, assume you want to set the default coder to &#039;&#039;OPUS-WB&#039;&#039;. Your saved configuration line might look like&lt;br /&gt;
&lt;br /&gt;
 config change PHONE SIG /prot SH323 /gk-addr pbx.innovaphone.com /gk-id innovaphone.com /tones 0 /lcoder OPUS-WB,20, /coder OPUS-WB,20,k1&lt;br /&gt;
&lt;br /&gt;
To set only the coder settings, you would set the relevant options with the &amp;lt;code&amp;gt;config add&amp;lt;/code&amp;gt; command as follows:&lt;br /&gt;
&lt;br /&gt;
 config add PHONE SIG /lcoder OPUS-WB,20,&lt;br /&gt;
 config add PHONE SIG /coder OPUS-WB,20,k1&lt;br /&gt;
&lt;br /&gt;
You can also remove specific options, as in &lt;br /&gt;
&lt;br /&gt;
 config rem PHONE SIG /tones&lt;br /&gt;
&lt;br /&gt;
which would remove the &amp;lt;code&amp;gt;/tones 0&amp;lt;/code&amp;gt; from the configuration line for &amp;lt;code&amp;gt;PHONE SIG&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Note that the PHP update server will add the&lt;br /&gt;
&lt;br /&gt;
 config write&lt;br /&gt;
 config activate &lt;br /&gt;
 iresetn&lt;br /&gt;
&lt;br /&gt;
at the end of the delivered script automatically, so you do not need to do it yourself.  In fact, it is not recommended to have any reset command in your snippets.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; Lines with associated Passwords ====&lt;br /&gt;
Sometimes, there is a password associated with certain configurations.  Consider the STUN/TURN configuration: &lt;br /&gt;
&lt;br /&gt;
 config change MEDIA /stun stun.innovaphone.com /turn turn.innovaphone.com /turn-user innovaphone /turn-pwd 2 /nat-detect 61&lt;br /&gt;
&lt;br /&gt;
The TURN password, being sensitive, needs to be encrypted in your configuration.  This is why it is stored as a &#039;&#039;VAR&#039;&#039;, which provides encryption support (see below):&lt;br /&gt;
&lt;br /&gt;
 vars create MEDIA/TURN-PWD pc ....&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the relationship between an option and an associated VAR needs to be guessed.  You can be sure that the module name in the &amp;lt;code&amp;gt;config changey&amp;lt;/code&amp;gt; matches the modules name in the &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; command. However, the variable name mist be guessed. &lt;br /&gt;
&lt;br /&gt;
You can also set the password in your script using the &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt;&amp;lt;!-- , but this does make sense only in staging (that is pre-update-phase) scripts (see below for a discussion why). If you need to do it in a script snippet for the update phase, you should --&amp;gt;, however, you may also consider using a &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; (see below) such as e.g.&lt;br /&gt;
&lt;br /&gt;
 mod cmd MEDIA form /cmd form /del %2Fstun-slow /stun stun.innovaphone.com /turn turn.innovaphone.com /turn-user innovaphone /turn-pwd my-turn-pw /nat-detect 61&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Sometimes it makes sense to use &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; commands.  The syntax is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; vars create &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;name&amp;gt; &amp;lt;flags&amp;gt; &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&amp;lt;name&amp;gt;&#039;&#039; is a module name followed by a variable name, optionally followed by an index.  For example, a phone will store the currently selected main registration as &amp;lt;code&amp;gt;vars create PHONE/ACTIVE-USER p &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;index&amp;gt;&#039;&#039;.  So the module is &amp;lt;code&amp;gt;PHONE&amp;lt;/code&amp;gt; and the variable name is &amp;lt;code&amp;gt;ACTIVE-USER&amp;lt;/code&amp;gt;.  When the variable is multi-valued, an index is added to the name.  For example, the registration settings for all but the first registration are stored as indexed variable, as in &amp;lt;code&amp;gt;vars create PHONE/USER-REG/00001 p &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;settings&amp;gt;&#039;&#039;, where &amp;lt;code&amp;gt;00001&amp;lt;/code&amp;gt; is the index (registrations count from 0 in this case).&lt;br /&gt;
&lt;br /&gt;
There are a number of flags which can be combined, the most prominent used in update scripts are:&lt;br /&gt;
; p : permanent.  The var is stored in flash memory (you will almost always use this flag in update scripts)&lt;br /&gt;
; c : crypted.  The var value needs to be encrypted and the &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; given is crypted&lt;br /&gt;
; x : crypted, plain value.  The var needs to be encrypted but the &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is given as plain (that is, un-encrypted) text. This allows you to set an encrypted variable without encrypting the desired value&lt;br /&gt;
; b : binary. The var value is binary.  Its &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is given as a bin2hex string&lt;br /&gt;
&lt;br /&gt;
Please note that using &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; will &#039;&#039;always&#039;&#039; set the internal &#039;&#039;reset needed condition&#039;&#039; in the device (regardless which &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is set).  This means that a subsequent &amp;lt;code&amp;gt;resetn&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;iresetn&amp;lt;/code&amp;gt; will always trigger a reset.  So if you use it, make sure that you use the &#039;&#039;times/@check&#039;&#039; ([[#times | see above]]) to protect your script from re-executing the snippet (and thus rebooting the device) all the time. &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
When you use a &amp;lt;code&amp;gt;mod cmd UP1 check ...&amp;lt;/code&amp;gt; command in your script (see times/@check [[#times | above]]), this will create an endless loop if you use &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; followed by one of the &amp;lt;code&amp;gt;resetn&amp;lt;/code&amp;gt; commands in the code guarded by the &amp;lt;code&amp;gt;check&amp;lt;/code&amp;gt; command. This code will never be fully executed, as the &#039;&#039;reset needed&#039;&#039; condition will always be set and the reset will always happen.  You can use it in &#039;&#039;pre-update-phase&#039;&#039; scripts (that is, during the staging process) as this is not protected by a &amp;lt;code&amp;gt;check&amp;lt;/code&amp;gt; command.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
See [[Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update]] for a discussion of how to use &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; in update scripts.&lt;br /&gt;
&lt;br /&gt;
=== Writing your own Dynamic Scripting Code ===&lt;br /&gt;
NB: this feature is available from build 2020.&lt;br /&gt;
&lt;br /&gt;
By default, the update server delivers update scripts which are composed from a number of static files (so-called &#039;&#039;snippets&#039;&#039;).  Sometimes it makes sense however, to create such snippets dynamically (e.g. based on a database lookup).  Here is how to do this.&lt;br /&gt;
&lt;br /&gt;
Dynamic scripting is implemented by a user-supplied custom &amp;lt;code&amp;gt;class CustomUpdateSnippet&amp;lt;/code&amp;gt;.  The code for this class must be placed in to the file &amp;lt;code&amp;gt;config/scripting.class.php&amp;lt;/code&amp;gt;.  As a starter, sample class code is available in &amp;lt;code&amp;gt;config/sample.scripting.class.php&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * to provide your own runtime generated snippets, rename this file to &#039;scripting.class.php&#039; and &lt;br /&gt;
 * implement the member functions&lt;br /&gt;
 * $property will have one member called &lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
class CustomUpdateSnippet extends UpdateSnippet {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * snippet to deliver after standard text snippets&lt;br /&gt;
     * @return array of string&lt;br /&gt;
     */&lt;br /&gt;
    public function getPostSnippet() {&lt;br /&gt;
        return parent::getPostSnippet();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * snippet to deliver before standard text snippets&lt;br /&gt;
     * @return array of strings&lt;br /&gt;
     */&lt;br /&gt;
    public function getPreSnippet() {&lt;br /&gt;
        return parent::getPreSnippet();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /** &lt;br /&gt;
     * do we want to suppress the standard text snippets?&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function sendStandardSnippets() {&lt;br /&gt;
        return parent::sendStandardSnippets();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample code overrides of the classes member functions just call the base classes which do nothing at all. So if you just copy the sample code into &amp;lt;code&amp;gt;scripting.class.php&amp;lt;/code&amp;gt;, nothing will change.  However, if &amp;lt;code&amp;gt;getPreSnippet()&amp;lt;/code&amp;gt; returns an array of strings (the parent class function returns an empty array), each array member will be sent to the calling device &#039;&#039;before&#039;&#039; the standard snippets are sent.  Likewise, if &amp;lt;code&amp;gt;getPostSnippet()&amp;lt;/code&amp;gt; returns an array of strings (the parent class function returns an empty array), each array member will be sent to the calling device &#039;&#039;after&#039;&#039; the standard snippets are sent. If &amp;lt;code&amp;gt;sendStandardSnippets()&amp;lt;/code&amp;gt; returns false, the standard snippets will not be sent.&lt;br /&gt;
&lt;br /&gt;
To determine the dynamic snippets to send, the user-provided &amp;lt;code&amp;gt;class CustomUpdateSnippet&amp;lt;/code&amp;gt; has access to the members of its base &amp;lt;code&amp;gt;class UpdateSnippet&amp;lt;/code&amp;gt;, namely the &amp;lt;code&amp;gt;var $statexml&amp;lt;/code&amp;gt; member. This member contains a &amp;lt;code&amp;gt;SimpleXMLElement&amp;lt;/code&amp;gt; object with all state information available for the calling device.&lt;br /&gt;
&lt;br /&gt;
Here is a sample state found in &amp;lt;code&amp;gt;$statexml&amp;lt;/code&amp;gt; (as output by the &amp;lt;code&amp;gt;dump()&amp;lt;/code&amp;gt; member function): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;state seen=&amp;quot;1522065435&amp;quot; requested=&amp;quot;130774bootcode&amp;quot; phase=&amp;quot;update&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;device sn=&amp;quot;00-90-33-3e-0c-57&amp;quot; type=&amp;quot;IP112&amp;quot; classes=&amp;quot;phone, opus_phone, phone_newui, hstrace, ip112&amp;quot; ip=&amp;quot;127.0.0.1&amp;quot; rp=&amp;quot;false&amp;quot; phase=&amp;quot;update&amp;quot; environments=&amp;quot;sifi, 172net&amp;quot; certstat=&amp;quot;either certificate handling or state tracking not enabled - not doing any certificate checking&amp;quot; hwid=&amp;quot;IP222-46-5c-77&amp;quot; realip=&amp;quot;172.16.80.241&amp;quot; requestDownloaded=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;firmware requested=&amp;quot;130986&amp;quot; requested-at=&amp;quot;1522065435&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;bootcode requested-at=&amp;quot;1522065435&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;config filename=&amp;quot;scripts/all-all-all.txt&amp;quot; delivered=&amp;quot;1522065426&amp;quot; version=&amp;quot;1486559970&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/state&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The most interesting elements in this XML are probably the attributes of the &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;device&amp;lt;/code&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
== Optional Configurations on the Linux Application Platform ==&lt;br /&gt;
===Support for more Connections===&lt;br /&gt;
By default the LAP&#039;s web server lighttpd allows for 512 concurrent connections with 1024 open file descriptors.  When you serve a huge number of devices with the update server, then this might be too low.  You will see some devices not being able to contact the update server for a while.  This should not be a real issue as the devices will retry.  However, updating all devices may take long due to this.&lt;br /&gt;
&lt;br /&gt;
In the lighttpd log (in &amp;lt;code&amp;gt;/var/log/lighttpd&amp;lt;/code&amp;gt; on the LAP), you will see entries like this:&lt;br /&gt;
&lt;br /&gt;
 2017-10-16 13:45:18: (network_linux_sendfile.c.140) open failed:  Too many open files &lt;br /&gt;
 2017-10-16 13:45:18: (mod_fastcgi.c.3075) write failed: Too many open files 24 &lt;br /&gt;
 2017-10-16 13:45:18: (server.c.1434) [note] sockets disabled, out-of-fds &lt;br /&gt;
 2017-10-16 16:23:25: (response.c.634) file not found ... or so:  Too many open files /mtls/updatev2/web/innovaphone_logo_claim_fisch.png -&amp;gt;&lt;br /&gt;
 2017-10-16 17:57:45: (server.c.1432) [note] sockets disabled, connection limit reached &lt;br /&gt;
&lt;br /&gt;
If you experience such issues, proceed as follows:&lt;br /&gt;
&lt;br /&gt;
* connect to the LAP with SFTP (e.g. using WinSCP)&lt;br /&gt;
* change directory to &amp;lt;code&amp;gt;/etc/lighttpd&amp;lt;/code&amp;gt;&lt;br /&gt;
* edit &amp;lt;code&amp;gt;lighttpd.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
* search for the 2 lines which set &amp;lt;code&amp;gt;server.max-fds&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;server.max-connections&amp;lt;/code&amp;gt;&lt;br /&gt;
* replace the standard values.  We recommend to set the number of file descriptors to 4 times the number of requests when using the update server, e.g. &lt;br /&gt;
: old&lt;br /&gt;
:: server.max-fds             = 1024&lt;br /&gt;
:: server.max-connections     =  512&lt;br /&gt;
: new&lt;br /&gt;
:: server.max-fds             = 8000&lt;br /&gt;
:: server.max-connections     =  2000&lt;br /&gt;
* save the file&lt;br /&gt;
* restart linux (&#039;&#039;Diagnostics/Reset/Reboot&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Be sure to closely monitor the &#039;&#039;Diagnostics/Status&#039;&#039; page for a while after such configuration.  &lt;br /&gt;
&lt;br /&gt;
Also, when you update the LAP, you will have to re-do the changes (as always when you change something &#039;&#039;under the hood&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Debug files rotation based on logrotate ===&lt;br /&gt;
If you have to debug during operation and a lot of devices access the PHP Update Server V2, you have to keep track of the debug files or automatically limit them. For this you can use logrotate on the innovaphone Linux AP. With logrotate you can apply time-based or size-based rules when files are packed and when they are deleted.&lt;br /&gt;
* open the LAP&#039;s file system using a SFTP client such as e.g. [https://winscp.net/eng/index.php WinSCP] (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;root/iplinux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]). Note that you must use SFTP rather than WebDAV, as WebDAV will not give access to the executable web server files. &lt;br /&gt;
* Under the path &amp;lt;code&amp;gt;/etc/logrotate.d&amp;lt;/code&amp;gt; create a file e.g. &amp;lt;code&amp;gt;updateserver&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/etc/logrotate.d/updateserver&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this file now enter the following content and save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 /var/www/innovaphone/mtls/update/debug/*.txt {&lt;br /&gt;
 size 5M&lt;br /&gt;
 missingok&lt;br /&gt;
 rotate 2&lt;br /&gt;
 compress&lt;br /&gt;
 delaycompress&lt;br /&gt;
 notifempty&lt;br /&gt;
 create 644 www-data www-data&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will include all *.txt files from the debug directory of the PHP Update Server V2 in the logrotate process of the operating system.&lt;br /&gt;
&lt;br /&gt;
; size 5M : means every 5MB the file is rotated or zipped&lt;br /&gt;
; size 5k : means every 5kB the file is rotated or zipped&lt;br /&gt;
Alternatively, you can also rotate the file based on time&lt;br /&gt;
; daily : means that every day the file is rotated or zipped&lt;br /&gt;
; weekly : means that the file is rotated or zipped daily&lt;br /&gt;
&lt;br /&gt;
; missingok : if a debug file does not exist, it will be ignored&lt;br /&gt;
; rotate n : files are removed before the last ones are deleted.&lt;br /&gt;
; compress : compresses the old debug files&lt;br /&gt;
; delaycompress : compresses the debug data only after it has been moved once&lt;br /&gt;
; notifempty : empty log files are not rotated&lt;br /&gt;
; create 644 www-data www-data : creates a new, empty debug file with appropriate permissions&lt;br /&gt;
&lt;br /&gt;
== Update Server and Reverse Proxy ==&lt;br /&gt;
It is possible to implement access to the update server through a &#039;&#039;reverse proxy&#039;&#039; (RP).  However, you have to keep some issues in mind:&lt;br /&gt;
* &#039;&#039;Mutual Transport Layer Security&#039;&#039; (MTLS) is not possible&lt;br /&gt;
: MTLS requires a direct TLS connection between the two parties. An RP however would terminate the TLS connection and entertain two independent connections to the parties.  This breaks MTLS.  If you want to use MTLS and serve external clients, you must therefore provide a direct access to the update server (that is an external IP address either directly or through port forwarding)&lt;br /&gt;
: see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts]] for details&lt;br /&gt;
* When using the RP, you can choose to forward encrypted traffic (HTTPS) arriving from external to the update server using HTTP (unencrypted). The update server however eventually rewrites the update URL in the calling devices configuration.  In order to do this, it determines the type of the internal connection.  So if the connection from the RP to the update server is using HTTP, it would create a &#039;&#039;http://...&#039;&#039; URL.  Otherwise it would create an &#039;&#039;https://..&#039;&#039; URL (also, it would be using the same port). This way, if the RP forwards requests to the update server with HTTP, the synthesized new URL for the calling client would use HTTP too, even though the original request was sent with HTTPS.  This may or may not be what you want (as all of your clients would end up using non-encrypted traffic). Even worse, it might not work at all, if the RP does not accept HTTP for example.&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
* [[Reference10:Concept_Update_Server]]&lt;br /&gt;
* [[Reference12r1:DHCP_client]]&lt;br /&gt;
* [[Reference10:Concept_Linux_Application_Platform]]&lt;br /&gt;
* [[Reference10:Concept_Provisioning]]&lt;br /&gt;
* [[Howto:PHP_based_Update_Server]] (old version)&lt;br /&gt;
* [[Howto:Creating custom Certificates using a Windows Certificate Authority]]&lt;br /&gt;
* [[Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:PHP_based_Update_Server_V2&amp;diff=50427</id>
		<title>Howto:PHP based Update Server V2</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:PHP_based_Update_Server_V2&amp;diff=50427"/>
		<updated>2018-08-14T11:41:35Z</updated>

		<summary type="html">&lt;p&gt;Odawid: /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* all innovaphone devices&lt;br /&gt;
* web server running PHP 5 (e.g. Linux Application Platform)&lt;br /&gt;
&lt;br /&gt;
All Versions. &lt;br /&gt;
&lt;br /&gt;
By default, the [[Reference10:Concept_Update_Server | Update Manager]] mechanism reads a file that corresponds to the device type (e.g. &amp;lt;code&amp;gt;update-ip222.htm&amp;lt;/code&amp;gt;).  While this makes sense (update scripts may vary by device type), it is sometimes tedious, as you have to edit a huge amount of files which typically are (at least partly) identical.&lt;br /&gt;
&lt;br /&gt;
Here is a PHP script that can be used as an &#039;&#039;Update Server&#039;&#039; that allows you to simplify the handling of update scripts. It also includes a mechanism that makes sure that all devices always have the same firmware installed as a given &#039;&#039;master device&#039;&#039; has.   Finally, it implements a straight forward configuration backup scheme.&lt;br /&gt;
&lt;br /&gt;
This article describes version 2 of this update server (build 2006 and up). The previous version is described in [[Howto:PHP_based_Update_Server]]. The enhancements are&lt;br /&gt;
* Status user interface showing all known devices&lt;br /&gt;
* Ability to roll out custom device certificates&lt;br /&gt;
* Ability to provide configuration files to MTLS-authenticated devices only (e.g. in order to keep certain configuration settings secure)&lt;br /&gt;
* Hide configuration files from public read access&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
The update server script requires a web server with working PHP 5.3 or higher platform.  It has been tested with Apache and ligHTTPD (on a [[Reference10:Concept Linux Application Platform | Linux Application Platform]]).   On IIS, neither the certificate roll-out nor the MTLS authentication or configuration backup works with IIS.&lt;br /&gt;
&lt;br /&gt;
The platform running the PHP scripts must have a valid time setting!&lt;br /&gt;
&lt;br /&gt;
=== Features ===&lt;br /&gt;
The update server can&lt;br /&gt;
* update all your devices with boot code and firmware that corresponds to the versions running on a reference device of your choice&lt;br /&gt;
* save backups of your devices configuration. Backups are saved only if the configuration changed since the last backup&lt;br /&gt;
* invoke your own update scripts depending on &lt;br /&gt;
** various phases (e.g. you can have &#039;&#039;staging&#039;&#039; scripts which are only executed once and normal scripts which are executed in normal operation later on)&lt;br /&gt;
** devices classes (e.g. you can have different scripts for phones and gateways)&lt;br /&gt;
** environments (e.g. you can have scripts for your internal devices and others for devices in home offices)&lt;br /&gt;
** the device serial number&lt;br /&gt;
* roll out customer specific device certificates&lt;br /&gt;
* roll out update scripts to devices only that have identified themselves with a valid device certificate (MTLS)&lt;br /&gt;
* maintain a list of devices in your installation along with some vital information about each individual device&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== On the Linux Application Platform ====&lt;br /&gt;
Here is how you would install it on the [[Reference10:Concept_Linux_Application_Platform|LAP]].  Some of the steps may not be necessary if you don&#039;t want to use all features.&lt;br /&gt;
&lt;br /&gt;
On the &#039;&#039;Linux Application Platform&#039;&#039;, you would &lt;br /&gt;
* open the LAP&#039;s file system using a SFTP client such as e.g. [https://winscp.net/eng/index.php WinSCP] (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;root/iplinux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]). Note that you must use SFTP rather than WebDAV, as WebDAV will not give access to the executable web server files&lt;br /&gt;
* create a new root directory underneath &amp;lt;code&amp;gt;/var/www/innovaphone/mtls&amp;lt;/code&amp;gt;, e.g. &amp;lt;code&amp;gt;/var/www/innovaphone/mtls/update&amp;lt;/code&amp;gt;&lt;br /&gt;
* download the complete file package of scripts and files here: http://download.innovaphone.com/ice/wiki-src/ &lt;br /&gt;
* copy all files and directories in to this new directory&lt;br /&gt;
* change owner and group of all files and directories to &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, change mode to 0600 for all files and 0700 for all directories (see [[#Migrating_from_build_2000_an_newer | below]] for how to do this with WinSCP)&lt;br /&gt;
&lt;br /&gt;
* log in to the LAP&#039;s admin UI (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;admin/linux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]) and open its &#039;&#039;Administration/Web Server/Change web server properties and public access to the web/webdav&#039;&#039; configuration UI. Add the following paths to &#039;&#039;Public Web Paths&#039;&#039; (assuming your base directory is called &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;):&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/web&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;/mtls/update/fw/&amp;lt;/code&amp;gt; (note the trailing slash!)&lt;br /&gt;
: make sure that no other sub-directories of &#039;&#039;update&#039;&#039; are listed&lt;br /&gt;
: make sure you have no trailing &#039;/&#039; in any of these paths (except &#039;&#039;fw/&#039;)&lt;br /&gt;
: this will make sure the update server&#039;s admin user interface is not accessible to the public&lt;br /&gt;
&lt;br /&gt;
At this point, you should be able to access the update server&#039;s admin user interface, e.g. &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php&amp;lt;/code&amp;gt;.  However, the only thing you see is a login page.  Please note that your browser should ask you for a password for this page (unless you already entered it before).  Cookies must be enabled for the login page to work properly. &lt;br /&gt;
&lt;br /&gt;
===== If you want to provide HTTPS Acess to the Update Server =====&lt;br /&gt;
For HTTPS access to the update server, you may want to install your own server certificate under &#039;&#039;Administration/Certificates/Current server certificate&#039;&#039;.  However, this is not strictly required (you will experience some warning messages when using your browser to access the update server, however, calling devices will work just fine). &lt;br /&gt;
&lt;br /&gt;
===== If you want to setup MTLS-restricted Delivery of Update Scripts =====&lt;br /&gt;
If you think you have sensitive information in your update scripts, you should make sure to deliver such scripts to your own verified devices only.  This can be done by authenticating calling devices with &#039;&#039;mutual TLS&#039;&#039; (MTLS).  In this case, the calling device must use HTTPS to retrieve the update script and present a trusted client certificate that identifies itself as the calling device (that is, has the device serial as the certificate&#039;s &#039;&#039;common name&#039;&#039; (CN)). &lt;br /&gt;
&lt;br /&gt;
For this feature, you need to &#039;&#039;Configure mutual TLS&#039;&#039; in the LAP&#039;s &#039;&#039;Administration/Web Server&#039;&#039; panel.  Simply tick the &#039;&#039;Active&#039;&#039; check-mark and select an appropriate &#039;&#039;MTLS Port&#039;&#039;.  The port must not conflict with any other TCP port used on the LAP, so neither 80 nor 443 is a good choice.  444 is a good choice.  Although it [http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&amp;amp;page=8 is assigned to the snpp protocol] by IANA, it is not used by the LAP (and probably rarely used anyway).&lt;br /&gt;
&lt;br /&gt;
If MTLS is already activated on your LAP, simply take note of the currently configured &#039;&#039;MTLS Port&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Please note that MTLS access is &#039;&#039;not possible&#039;&#039; through a &#039;&#039;reverse proxy&#039;&#039; (RP).  This is because the RP always will terminate the incoming TLS connection and establish its own to the target.  Therefore, the client certificate presented to the target server is the RP&#039;s certificate, not the original clients certificate.  In our context - where MTLS is used to verify the identity of the original caller - clients must not access the update server through an RP.&lt;br /&gt;
&lt;br /&gt;
You can either expose your update server directly to the internet (and carefully think through the security implications) or create specific TCP port forwarding towards the update server in your NAT-router/firewall.  In this case, we recommend to use non-standard HTTP and HTTPS ports on the NAT router (cause this will already keep most of the HTTP port scanners out there in the internet from functioning).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Also, you will need the public key of all the CAs you will trust.  These must be configured in to the web server so it can trust the certificates your devices will present to it.  See [[#Enforcing_Trust]] for details.&lt;br /&gt;
&lt;br /&gt;
==== On an Apache Server running on the Windows Operating System ====&lt;br /&gt;
The update server will run on Apache too.  However, as we did not test this setup thoroughly, we recommend to use the LAP&#039;s LigHTTPD instead.  &lt;br /&gt;
&lt;br /&gt;
* For hints on using MTLS on an Apache Web Server, see [[Reference10:Concept_Provisioning#Enforcing_mutual_TLS_on_Apache | Enforcing mutual TLS on Apache]]&lt;br /&gt;
* For hints on getting the &#039;&#039;innovaphone device certificate authority&#039;&#039; public keys (which you may or may not need), see [[Reference10:Concept_Provisioning#How_to_get_inno-dev-ca-certificate.crt | How to get inno-dev-ca-certificate.crt ]]&lt;br /&gt;
&lt;br /&gt;
==== On Microsoft&#039;s IIS ====&lt;br /&gt;
We do not recommend to use IIS as &lt;br /&gt;
* it does not support PUT easily&lt;br /&gt;
* it is not compatible with the innovaphone device&#039;s MTLS implementation&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
If you intend to deliver your update scripts with MTLS (that is, with HTTPS und mutual certificate check)&lt;br /&gt;
* you will need to have the full name of your &#039;&#039;certificate Authority&#039;&#039; (CA) as it is noted as &#039;&#039;Common Name&#039;&#039; (CN) in your CA&#039;s certificate&lt;br /&gt;
* also, you will need a PEM version of your CA&#039;s public key (a &#039;&#039;PEM version&#039;&#039; of a certificate is a text file that begins with a line like &amp;lt;code&amp;gt;-----BEGIN CERTIFICATE-----&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Also, you need to know the &#039;&#039;MTLS Port&#039;&#039; configured in your LAP (see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts| If you want to setup MTLS-restricted Delivery of Update Scripts ]] above).&lt;br /&gt;
&lt;br /&gt;
All tweakable parameters are set in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  You may want to use an XML-capable editor such as notepad++, netbeans or Visual-Studio for editing.  if your editor supports it, you benefit from the &#039;&#039;document type description&#039;&#039; (DTD) provided in &amp;lt;code&amp;gt;full-config.dtd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;false&amp;quot; debugcerts=&amp;quot;false&amp;quot; debugscript=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The attributes of the &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; tag control some aspects of debugging.  For now, simply set all 3 to &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt;.  Do not forget to revert them back to &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt; when everything runs smoothly, large log files will result if not. &lt;br /&gt;
&lt;br /&gt;
==== Securing Access ====&lt;br /&gt;
To control access to the update server&#039;s data, you should set a login.  This can be done in the &#039;&#039;master&#039;&#039; tag by specifying both &#039;&#039;user&#039;&#039; and &#039;&#039;password&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;master ...  user=&amp;quot;myadmin&amp;quot; password=&amp;quot;mysecret&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Default username and password are admin/password.&lt;br /&gt;
&lt;br /&gt;
==== Delivering Firmware and Boot Code ====&lt;br /&gt;
At this point, you can simulate a device by requesting an update script using an URL like &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php?type=IP232&amp;amp;sn=00-90-33-00-00-00&amp;amp;hwid=IP232-00-00-00&amp;amp;ip=1.2.3.4&amp;lt;/code&amp;gt; in your browser (please note that this URL should not ask you for a password).  Most likely, your browser will wait a little while and then say something like:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # failed to use cached data (cache not current), retrieving info online&lt;br /&gt;
 # cannot get PBX info: cannot access http://yourmasterdevice.youdomain.tld/CMD0/box_info.xml, reading cache&lt;br /&gt;
 # cannot get cached PBX info: cannot access cache/master-info.xml - exit&lt;br /&gt;
&lt;br /&gt;
This is because you did not yet specify the &#039;&#039;master device&#039;&#039; which always runs the reference firmware.  &lt;br /&gt;
&lt;br /&gt;
The idea here is that you have one innovaphone device in your system where the firmware is always manually updated. All other devices shall follow this reference firmware.  The update server will deliver the firmware that runs on the master device to calling devices.  For this to work, you need to set the &#039;&#039;info&#039;&#039; attribute of the [[#master|&#039;&#039;master&#039;&#039;]] tag and leave everything else &#039;&#039;as is&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Remember that you do all your local configuration changes in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As &#039;&#039;master&#039;&#039; is a first level tag, you can add it directly underneath the opening &#039;&#039;&amp;lt;config&amp;gt;&#039;&#039; tag.  The only thing we need to define right now is the path to read the firmware information from your master device.  Let&#039;s say your reference device has the IP address &amp;lt;code&amp;gt;172.16.0.10&amp;lt;/code&amp;gt;, you end up with &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;true&amp;quot; debugcerts=&amp;quot;true&amp;quot; debugscript=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;  user=&amp;quot;myadmin&amp;quot; password=&amp;quot;mysecret&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
(you could use a DNS name instead of the IP address of course). &lt;br /&gt;
The &#039;&#039;info&#039;&#039; URL is used by the update server itself only, it is never used by devices requesting an update script.&lt;br /&gt;
&lt;br /&gt;
When you refresh the page that simulates a device requesting an update script, the output should now change to something like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # failed to use cached data (cache not current), retrieving info online&lt;br /&gt;
 # current firmware (unknown) does not match required firmware (130178)&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
This is to say that your master device runs firmware 130178 and the calling device does not (actually, as the calling client is simulated by your browser, it does not transmit its current firmware to the update server so it is &#039;&#039;(unknown)&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
In order to actually update the clients with firmware and boot code, the files must be made available to the calling client somehow.  This is done by specifying an URL in the [[Reference10:Concept_Update_Server#Prot_command | prot ]] and [[Reference10:Concept_Update_Server#Boot_command | boot ]] commands sent to the calling device:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # current firmware (unknown) does not match required firmware (130178)&lt;br /&gt;
 mod cmd UP0 prot http://update.yourcompany.com/mtls/update/fw/130178/ ser 130178&lt;br /&gt;
 # current boot code (unknown) does not match required boot code (130112)&lt;br /&gt;
 mod cmd UP0 boot http://update.yourcompany.com/mtls/update/fw/130112/ ser 130112&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
By default, the URL generated points to a sub-directory of your update server called &#039;&#039;fw&#039;&#039;: &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/fw/130178/&amp;lt;/code&amp;gt;.  Note that this default URL expects sub-directories underneath the &#039;&#039;fw&#039;&#039; directory which correspond to the firmware and boot code build number.  The file structure thus would be like&lt;br /&gt;
&lt;br /&gt;
 /var/www/innovaphone/mtls/update/fw&lt;br /&gt;
                                    /130178&lt;br /&gt;
                                           /ip232.bin&lt;br /&gt;
                                    /130112&lt;br /&gt;
                                           /boot232.bin&lt;br /&gt;
&lt;br /&gt;
Note that the URL ends with a slash (&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;).  This instructs the calling device to append the appropriate file name itself when retrieving the file (see [[Reference10:Concept_Update_Server#Prot_command | the prot command ]] for details). &lt;br /&gt;
&lt;br /&gt;
However, you can also specify any other URL by setting the &#039;&#039;url&#039;&#039; attribute in the &#039;&#039;fwstorage&#039;&#039; tag of your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. In this attribute, certain meta words will be replaced (see [[#fwstorage | the &#039;&#039;fwstorage&#039;&#039; tag ]] for details).  The default setting for example is &amp;lt;code&amp;gt;fw/{build}/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can disable firmware and boot code updates altogether by setting the &#039;&#039;info&#039;&#039; attribute in the &#039;&#039;master&#039;&#039; tag to an empty value.&lt;br /&gt;
&lt;br /&gt;
==== Your own Update Script Files ====&lt;br /&gt;
The update server will deliver update scripts to calling devices which are synthesized from a number of &#039;&#039;update script snippets&#039;&#039; which you define yourself.  The idea is that many devices share parts of their configuration while other parts are different.  This depends on&lt;br /&gt;
* the device &#039;&#039;class&#039;&#039; (e.g. a phone or a gateway)&lt;br /&gt;
: the device class is automatically derived from its model.  In fact, a single device may be in multiple classes. For example, an IP232 is in these classes: &#039;&#039;phone, pre_opus_phone, phone_newui&#039;&#039; which basically says that its a phone and has no OPUS codec yet but a &amp;quot;new&amp;quot; user interface (as opposed to the old one found e.g. on an IP110). A number of useful classes are pre-defined, but you can add your own in &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
* the device&#039;s environment (e.g. &#039;&#039;home-office&#039;&#039;, &#039;&#039;branch-office&#039;&#039;)&lt;br /&gt;
:  These reflect that fact that devices may need different configuration if they are in different locations (or environments).  The update server does not know about a device&#039;s environment, which is why you need to configure it in to the devices update URL if you need this.  By default, there is a single environment defined called &#039;&#039;default&#039;&#039;, but of course, you can add your own&lt;br /&gt;
* phase&lt;br /&gt;
: configuring devices may need multiple phases to go through.  If more than one phase is defined, the device will go through all phases sequentially, which is why a &#039;&#039;phase&#039;&#039; has a numerical &#039;&#039;seq&#039;&#039; attribute.  Phases are went through in order of this attribute. When the device has reached the last phase, it will stay there.  By default, there is only one phase called &#039;&#039;update&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can define update script snippets for any combination of device, environment and phase.  You do so simply by placing appropriate files in to the &#039;&#039;scripts&#039;&#039; directory on your update server.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a closer look at the web page we used to simulate a device calling for an update script before (&amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php?type=IP232&amp;amp;sn=00-90-33-00-00-00&amp;amp;hwid=IP232-00-00-00&amp;amp;ip=1.2.3.4&amp;lt;/code&amp;gt;).  It will show you all the possible files it would deliver to the device:&lt;br /&gt;
&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 # scripts/update-all-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-all-default.txt does not exist&lt;br /&gt;
 # scripts/update-phone-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-phone-default.txt does not exist&lt;br /&gt;
 # scripts/update-pre_opus_phone-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/update-phone_newui-00_90_33_00_00_00.txt does not exist&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
&lt;br /&gt;
The update script snippet files need to have proper names to define when they should be delivered.  As you can see, they all start with &amp;lt;code&amp;gt;update-&amp;lt;/code&amp;gt; which means that they apply to devices which are in the &#039;&#039;update&#039;&#039; phase.  As by default there is only a single phase defined, all possible file names start with &amp;lt;code&amp;gt;update-&amp;lt;/code&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
The next part here is either &amp;lt;code&amp;gt;phone-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pre_opus_phone-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;phone_newui-&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;all-&amp;lt;/code&amp;gt;.  This is because the calling IP232 is in three classes, so all respective snippets will be delivered to it.  &#039;&#039;all&#039;&#039; however is a wild-card.  That is, such files will be delivered to all devices, no matter what class they are in.  You may wonder why there was no &#039;&#039;all&#039;&#039; for the phase.  This is because there is only a single phase defined.  If there would be more, the &#039;&#039;all&#039;&#039;-variation of the phase-part  of the file name would be appear.&lt;br /&gt;
&lt;br /&gt;
The third part finally is either &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;00_90_33_00_00_00&amp;lt;/code&amp;gt; in our case. &#039;&#039;default&#039;&#039; is the name of the only &#039;&#039;environment&#039;&#039; that is defined by default.  &#039;&#039;00_90_33_00_00_00&#039;&#039; is the device&#039;s serial number which is treated as an implicitly defined environment name. This allows you to deliver certain snippets to a single device only.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s create an update script snippet that is delivered to all phones in the default environment when they are in the update phase.  The file name (which looks like &#039;&#039;phase&#039;&#039;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&#039;&#039;class&#039;&#039;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&#039;&#039;environment&#039;&#039;&amp;lt;code&amp;gt;.txt&amp;lt;/code&amp;gt;) has to be &amp;lt;code&amp;gt;update-phone-default.txt&amp;lt;/code&amp;gt; therefore.  Just for an exercise, let us set the device name (as shown in the browser&#039;s title bar) to &#039;&#039;This is a Phone!&#039;&#039;.&lt;br /&gt;
The command to do so is &amp;lt;code&amp;gt;config add CMD0 /name This+is+a+Phone%21&amp;lt;/code&amp;gt;, so your file may look like this&lt;br /&gt;
&lt;br /&gt;
 # set the device name&lt;br /&gt;
 config add CMD0 /name This+is+a+Phone%21&lt;br /&gt;
&lt;br /&gt;
(btw: did you observe that config line arguments need to be url-encoded?).  Now create the file and upload it in to the &#039;&#039;scripts&#039;&#039; directory of you update server.  When you now refresh the page which simulates the device calling for an update script, you will see something like this:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # newest script (scripts/update-phone-default.txt) 11s old&lt;br /&gt;
 # files being updated (scripts/update-phone-default.txt 11s old, waiting for at least 90s to expire)&lt;br /&gt;
&lt;br /&gt;
When you update multiple script snippets, it is often undesirable that a device retrieves an inconsistent state of the scripts you are working on (e.g. if you already have saved one but not yet the other).  To avoid this, the update server will look at the files modification dates and if one of those that needs to be delivered to the device is younger than 90 seconds, it will not send any of them at all.  &lt;br /&gt;
&lt;br /&gt;
So when you wait for the 90 seconds to pass and refresh the page again, you will see something like this:&lt;br /&gt;
&lt;br /&gt;
 # firmware build info cache is current&lt;br /&gt;
 # phase: update, nextphase: , environment: default, type: IP232, classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone-default.txt 4.1 mins&lt;br /&gt;
 ...&lt;br /&gt;
 #     scripts/update-phone-default.txt&lt;br /&gt;
 # { begin script &#039;scripts/update-phone-default.txt&#039; &lt;br /&gt;
 # set the device name&lt;br /&gt;
 config add CMD0 /name This+is+a+Phone%21&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # end script &#039;scripts/update-phone-default.txt&#039; }&lt;br /&gt;
 &lt;br /&gt;
 # trigger reset if required&lt;br /&gt;
 config write&lt;br /&gt;
 config activate&lt;br /&gt;
 iresetn&lt;br /&gt;
&lt;br /&gt;
As you can see, your snippet has been delivered by the update script.  However, the update server has also added some trailing commands which write back the config to the devices flash memory (&amp;lt;code&amp;gt;config write&amp;lt;/code&amp;gt;), activate it (&amp;lt;code&amp;gt;config activate&amp;lt;/code&amp;gt;) and trigger a reset if needed (&amp;lt;code&amp;gt;iresetn&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If there are multiple snippets available for a calling device, all of them are concatenated in the sequence shown in the header of the returned script (where the possible file names are listed)&lt;br /&gt;
&lt;br /&gt;
==== Device Status ====&lt;br /&gt;
When you have a lot of devices which are served by the update server, you may want to have a list of these devices along with some useful information regarding each devices.  &lt;br /&gt;
&lt;br /&gt;
You can enable this by defining the &#039;&#039;status&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  So open the file and add the tag right next to the &#039;&#039;master&#039;&#039; tag you added before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config&amp;gt;&lt;br /&gt;
    &amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;status&lt;br /&gt;
        dir=&amp;quot;status&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you have done so, please refresh the page that simulates your calling device and then open &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php?mode=status&amp;lt;/code&amp;gt;.  You will now see a device list (well, a list with a single device, the one you simulated using your browser).   The list will show some information regarding the devices that requested an update script lately.   For more options, see [[#status]].&lt;br /&gt;
&lt;br /&gt;
==== Device Backup ====&lt;br /&gt;
It is generally useful to have recent backups of all of your device configurations.  The update server supports that if you enable it by defining the &#039;&#039;backup&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. Simply put it right next to the &#039;&#039;master&#039;&#039; or &#039;&#039;status&#039;&#039; tag you added before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;backup&lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have done so and then refresh the page that simulates your calling device, you will now see &lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
 &lt;br /&gt;
 mod cmd UP0 scfg http://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m&lt;br /&gt;
&lt;br /&gt;
instead of &lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # scripts/update-phone_newui-default.txt does not exist&lt;br /&gt;
 &lt;br /&gt;
 # Backups not enabled in config&lt;br /&gt;
&lt;br /&gt;
When a client requests an update script the next time, this will initiate a configuration backup which is stored underneath the &#039;&#039;backup&#039;&#039; directory.  For each device, a sub-directory is created and all backup files are stored therein.  By default, the last 10 differing configuration backups are kept.&lt;br /&gt;
&lt;br /&gt;
==== Controlling the Time-frames when Snippets are delivered ====&lt;br /&gt;
The update client built-in to innovaphone devices allows to restrict updates to certain time frames (e.g. only during the night). This can be controlled using the [[Reference10:Concept_Update_Server#Times_command | times ]] command.&lt;br /&gt;
&lt;br /&gt;
You can configure the update server to use the time commands by setting the &#039;&#039;allow&#039;&#039; and &#039;&#039;initial&#039;&#039; attributes in the &#039;&#039;times&#039;&#039; tag in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        allow=&amp;quot;22,23,0,1,2,3,4&amp;quot; &lt;br /&gt;
        initial=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If either the &#039;&#039;allow&#039;&#039; or &#039;&#039;initial&#039;&#039; attribute is present, the update script will contain a line like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # Restricted times&lt;br /&gt;
 mod cmd UP1 times  /allow 22,23,0,1,2,3,4 /initial 1&lt;br /&gt;
&lt;br /&gt;
In the example above, all update script activity will occur only between 10pm and 5am (local device time).   For more details, see [[Reference10:Concept_Update_Server#Times_command | Concept Update Server]]&lt;br /&gt;
&lt;br /&gt;
==== Using and Enforcing HTTPS ====&lt;br /&gt;
Your devices can either use HTTP or HTTPS to access the update server.  In normal operation, the update server will generate URLs (e.g. the URLs used to retrieve firmware or to backup configurations) for the same protocol.  &lt;br /&gt;
&lt;br /&gt;
However, you can enforce use of HTTPS by setting the &#039;&#039;forcehttps&#039;&#039; attribute in the [[Howto:PHP_based_Update_Server_V2#times | &#039;&#039;times&#039;&#039; ]] tag to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. If so, a device calling in with HTTP will be re-configured to use HTTPS:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # using HTTP and &#039;forcehttps&#039; is set -&amp;gt; need to switch to HTTPS&lt;br /&gt;
 &lt;br /&gt;
 # changed state query args: polling, phase&lt;br /&gt;
 # new url=https://update.yourcompany.com/mtls/update/update.php?polling=5&amp;amp;phase=&amp;amp;type=#t&amp;amp;sn=#m&amp;amp;hwid=#h&amp;amp;ip=#i&lt;br /&gt;
 ...&lt;br /&gt;
(note that if you are using a non-standard port for HTTPS, you must define it using the &#039;&#039;httpsport&#039;&#039; attribute).&lt;br /&gt;
&lt;br /&gt;
==== Delivering Custom Certificates ====&lt;br /&gt;
innovaphone devices come with pre-defined, trustworthy device certificates. However, all &#039;&#039;soft&#039;&#039; devices (such as the softwarephone, myPBX for Android/iOS or the IPVA) do not.  Also, in many scenarios customers run their own &#039;&#039;public key infrastructure&#039;&#039; (PKI) and request their own certificates to be used instead of the pre-defined. This is why there is a need to roll-out custom certificates to devices. &lt;br /&gt;
&lt;br /&gt;
The update server supports this task to an extend.  It can&lt;br /&gt;
* check if a calling device has a proper certificate&lt;br /&gt;
* instruct a calling device without proper certificate to create a &#039;&#039;certificate signing request&#039;&#039; (CSR)&lt;br /&gt;
* download the CSR to the update server for easy access by the administrator&lt;br /&gt;
* upload a signed CSR to the device&lt;br /&gt;
* upload the public key(s) of the CA in to the device&#039;s trust list&lt;br /&gt;
&lt;br /&gt;
In order to roll-out custom certificates with the update server, the administrator needs to&lt;br /&gt;
* run his own PKI (a.k.a. &#039;&#039;certificate authority&#039;&#039; (CA))&lt;br /&gt;
* monitor CSRs that appear in the update server&#039;s device list&lt;br /&gt;
* approve the request by manually submitting it to his own CA&lt;br /&gt;
* upload the signed CSR to the update server&lt;br /&gt;
&lt;br /&gt;
Also, all devices must run &#039;&#039;V12r1 SR8&#039;&#039; or newer before the new certificate can be uploaded.  Devices with older firmware will be updated automatically (see [[#Delivering_Firmware_and_Boot_Code]] above). However, the new firmware must be &#039;&#039;V12r1 SR8&#039;&#039; or later. &lt;br /&gt;
&lt;br /&gt;
To learn how you can create proper device certificates with your own windows CA, see [[Howto:Creating custom Certificates using a Windows Certificate Authority]].&lt;br /&gt;
&lt;br /&gt;
By default, custom certificates are turned off and you will see a note like&lt;br /&gt;
&lt;br /&gt;
 # certificates: either certificate handling or state tracking not enabled - not doing any certificate checking&lt;br /&gt;
&lt;br /&gt;
in the delivered update script.&lt;br /&gt;
&lt;br /&gt;
Custom certificates are turned on by adding a &#039;&#039;customcerts&#039;&#039; tag to your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
	dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The the page that simulates your calling device will now include a line saying:&lt;br /&gt;
&lt;br /&gt;
 # certificates: we dont know anything about the current certificate state - not doing any certificate checking &lt;br /&gt;
&lt;br /&gt;
In order to decide if or if not a calling device has a valid certificate, the device needs to send its current public key to the update server.  This is done by enabling &#039;&#039;queries&#039;&#039; in your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  &#039;&#039;Queries&#039;&#039; is a means to have the device submit certain information to the update server.  In the update server&#039;s default configuration, two queries are defined but not enabled:&lt;br /&gt;
&lt;br /&gt;
* the query &#039;&#039;certificates&#039;&#039; sends the current certificate state &lt;br /&gt;
* the query &#039;&#039;admin&#039;&#039; sends the current device name (as set in &#039;&#039;General/Admin&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
To enable a query, you must specify the class a calling device must be in in order to execute the query.  This is done by adding an &#039;&#039;applies&#039;&#039; tag for the respective query in your configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;queries&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;admin&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
    &amp;lt;/queries&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically says that both queries should be executed by devices of just any class.  Unless you enable queries, your update script will include lines such as:&lt;br /&gt;
&lt;br /&gt;
 # no queries defined for any of callers classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
&lt;br /&gt;
Once you have enabled them, you will see something like&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
 # query &#039;certificates&#039;&lt;br /&gt;
 mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=query&amp;amp;sn=#m&amp;amp;id=certificates ser nop /always mod%20cmd%20X509%20xml-info&lt;br /&gt;
 # query &#039;admin&#039;&lt;br /&gt;
 mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=query&amp;amp;sn=#m&amp;amp;id=admin ser nop /always mod%20cmd%20CMD0%20xml-info&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
You can display the data sent by a query in the device status display.  To do so, you need to define one or more &#039;&#039;show&#039;&#039; tags as part of the respective &#039;&#039;query&#039;&#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;!-- show device certificate CNs and Issuer CNs in status page --&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Subject&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@subject_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Issuer&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@issuer_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two steps however are still missing: &lt;br /&gt;
&lt;br /&gt;
* a) you need to tell the update server the names of all the CAs you consider trustworthy.  This is done by listing their names in the &#039;&#039;CAname&#039;&#039; attribute of the &#039;&#039;customcerts&#039;&#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
        dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
        CAname=&amp;quot;innovaphone Device Certification Authority,innovaphone Device Certification Authority 2,innovaphone-INNO-DC-W2K8-Zertifizierungsserver&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
: The example shown defines that you will accept both of innovaphone&#039;s device certificate authorities and also your own CA called &#039;&#039;innovaphone-INNO-DC-W2K8-Zertifizierungsserver&#039;&#039;.  Devices with device certificates issued by one of these CAs will be left untouched.  For all other devices (for example, any &#039;&#039;myPBX for Android/iOS&#039;&#039; device that has a self-signed certificate), the generation of a custom certificate will be initiated.&lt;br /&gt;
&lt;br /&gt;
* And b) you need to provide the public key of your CA (so it can be uploaded to the calling device&#039;s trust list).  You need to place the DER (not PEM) encoded public key in to a file called &amp;lt;code&amp;gt;certs/CAkey-01.cer&amp;lt;/code&amp;gt; on your update server (if you want to upload the whole certificate chain, put all of the public keys in the chain in to separate additional files called &amp;lt;code&amp;gt;certs/CAkey-02.cer&amp;lt;/code&amp;gt; and so forth.&lt;br /&gt;
&lt;br /&gt;
For more details on how to approve certificate signing requests, see [[#Approving Certificate Signing Requests]] below.&lt;br /&gt;
&lt;br /&gt;
==== Enforcing Trust ====&lt;br /&gt;
Update script snippets may include sensitive information which you do not want to disclose to the public.  Even though you can force the use of HTTPS (see above), this still does not keep your data secure.  After all, an attacker could simply request an update script from your update server using HTTPS.  To secure your data, you need to make sure that snippets are only sent to devices which identify themselves using a trusted certificate with a correct &#039;&#039;common name&#039;&#039; (CN).  This is done using &#039;&#039;mutual transport layer security&#039;&#039; (MTLS).  Therefore, you need to configure MTLS in the LAP (see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts | If you want to setup MTLS-restricted Delivery of Update Scripts]] above). &lt;br /&gt;
&lt;br /&gt;
You can enable this by setting &#039;&#039;forcetrust&#039;&#039; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &#039;&#039;httpsport&#039;&#039; to the port configured as &#039;&#039;MTLS Port&#039;&#039; in your web server.  This is done in the &#039;&#039;times&#039;&#039; tag of your &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        ...&lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot;&lt;br /&gt;
        httpsport=&amp;quot;444&amp;quot;&lt;br /&gt;
        forcetrust=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Please note that &#039;&#039;forcetrust&#039;&#039; does nothing unless &#039;&#039;forcehttps&#039;&#039; is also set!&lt;br /&gt;
&lt;br /&gt;
If so, the update server will deliver update script snippets only to clients which identify themselves with a proper certificate.    For this to work, you will need to add the public key of your certificate authority to your web server&#039;s list of trusted certificates.  &lt;br /&gt;
&lt;br /&gt;
When using the &#039;&#039;Linux Application Platform&#039;&#039; (LAP), you need to add the PEM-encoded public key of your certificate authority to the &#039;&#039;innovaphone-ca.pem&#039;&#039; file in &amp;lt;code&amp;gt;/home/root/ssl_cert&amp;lt;/code&amp;gt;.  When you have installed the LAP, this file will contain the PEM-encoded public keys of the 2 innovaphone device certificate authorities.  You can simply add the public key of your CA to the end of this file:&lt;br /&gt;
&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...inno-ca public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...inno-ca2 public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
 -----BEGIN CERTIFICATE-----&lt;br /&gt;
 ...your-ca public key...&lt;br /&gt;
 -----END CERTIFICATE-----&lt;br /&gt;
&lt;br /&gt;
You will need to restart the LigHTTPD then (most easily done by restarting the entire LAP (&#039;&#039;Diagnose/Reset&#039;&#039;) or by issuing the command &amp;lt;code&amp;gt;/etc/rc2.d/S02lighttpd restart&amp;lt;/code&amp;gt; from the linux root command prompt). Finally, you must set the &#039;&#039;forcetrust&#039;&#039; attribute. &lt;br /&gt;
(Note that the &#039;&#039;innovaphone-ca.pem&#039;&#039; file may be overwritten when a new LAP version is installed.  It is thus a good idea to keep a copy and check it after an upgrade).&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;forcetrust&#039;&#039; is effective and the calling device does not use HTTPS, it will be reconfigured to do so:&lt;br /&gt;
&lt;br /&gt;
 # using HTTP and &#039;forcehttps&#039; is set -&amp;gt; need to switch to HTTPS&lt;br /&gt;
 ...&lt;br /&gt;
 # new url=https://update.yourcompany.com:444/update/update.php?polling=5&amp;amp;phase=&amp;amp;type=#t&amp;amp;sn=#m&amp;amp;hwid=#h&amp;amp;ip=#i&amp;amp;env=default&lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS but sends no certificate, you will see a message like&lt;br /&gt;
&lt;br /&gt;
 # cannot verify CN with HTTPS: SSL_CLIENT_S_DN_CN not present - fix web server configuration or use MTLS-enabled port!&lt;br /&gt;
&lt;br /&gt;
This is probably because it is using a non-MTLS enabled port for HTTPS (e.g. the standard port 443) although MTLS is configured for a different port. &lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS and sends a certificate but the CN does not match the serial number of the device, you will see a message such as&lt;br /&gt;
&lt;br /&gt;
 # Device claims to be &#039;IP232-30-00-af&#039; but identifies as &#039;CKL-CELSIUS-W10.innovaphone.sifi&#039; by TLS&lt;br /&gt;
&lt;br /&gt;
If the calling device uses HTTPS and sends a certificate but the certificate is not trusted because its issuer is not listed in &#039;&#039;innovaphone-ca.pem&#039;&#039; (see above), the connection will be refused &lt;br /&gt;
&lt;br /&gt;
In all such cases, no snippet will be delivered.  If the certificate is good, you will see a message like &lt;br /&gt;
&lt;br /&gt;
 # good certificate(CN=&#039;IP232-30-00-af&#039;)&lt;br /&gt;
&lt;br /&gt;
followed by the appropriate snippets.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple Phases ====&lt;br /&gt;
When you configure multiple phases, all phases up to the final phase are stepped through and when all associated update script snippets for all phases are done, the device will ultimately stay in the final phase.  This can be used e.g. to implement update script snippets which are executed once only when the device is initialized.  Settings made in all but the last phase can later be overridden by the user or an administrator.  The settings done in the update script settings for the final phase however are re-executed whenever one of your update script files for this phase changes.&lt;br /&gt;
The process of deploying some initial settings is often called &#039;&#039;staging&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To enable staging, you therefore create a new phase that comes before the default phase (which is &#039;&#039;update&#039;&#039;).  Phases are sorted numerical by an attribute called &#039;&#039;seq&#039;&#039;.  As the default phase &#039;&#039;update&#039;&#039; is defined with &#039;&#039;seq=200&#039;&#039;, your new staging phase must be defined with a lower seq value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
	    &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you define such a phase, there will be new possible update script snippet file names: &lt;br /&gt;
&lt;br /&gt;
 # phase: staging, nextphase: update, environment: default, type: IP232, classes: phone+pre_opus_phone+phone_newui&lt;br /&gt;
 # possible files (from scripts):&lt;br /&gt;
 # scripts/all-all-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-all-default.txt does not exist&lt;br /&gt;
 # scripts/all-phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-phone-default.txt does not exist&lt;br /&gt;
 # scripts/all-pre_opus_phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/all-phone_newui-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/all-phone_newui-default.txt does not exist&lt;br /&gt;
 # scripts/staging-all-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-all-default.txt does not exist&lt;br /&gt;
 # scripts/staging-phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-phone-default.txt does not exist&lt;br /&gt;
 # scripts/staging-pre_opus_phone-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-pre_opus_phone-default.txt does not exist&lt;br /&gt;
 # scripts/staging-phone_newui-00_90_33_30_00_af.txt does not exist&lt;br /&gt;
 # scripts/staging-phone_newui-default.txt does not exist&lt;br /&gt;
&lt;br /&gt;
First of all, there are new names for this particular phase.  Furthermore, as we now have multiple phases, the new wild-card name &#039;&#039;all&#039;&#039; is possible.  &lt;br /&gt;
&lt;br /&gt;
An example for a staging script snippet might be a file called &amp;lt;code&amp;gt;staging-all-all.txt&amp;lt;/code&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
 # change admin password&lt;br /&gt;
 config add CMD0 /user admin,my-admin-password&lt;br /&gt;
 config activate&lt;br /&gt;
 config rem CMD0 /user&lt;br /&gt;
&lt;br /&gt;
This will set the admin password to &amp;lt;code&amp;gt;my-admin-password&amp;lt;/code&amp;gt; during staging (it should be obvious that such staging should only be done in combination with [[#Enforcing_Trust|Enforcing Trust]], see above).&lt;br /&gt;
&lt;br /&gt;
=== A complete &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt; Sample ===&lt;br /&gt;
Here is a complete sample of a configuration file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE config SYSTEM &amp;quot;full-config.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- add your local configuration here --&amp;gt;&lt;br /&gt;
&amp;lt;config debugmerge=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;master info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;status&lt;br /&gt;
	    dir=&amp;quot;status&amp;quot;&lt;br /&gt;
	    missing=&amp;quot;1000&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;backup&lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        allow=&amp;quot;22,23,0,1,2,3,4&amp;quot; &lt;br /&gt;
        initial=&amp;quot;1&amp;quot;&lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot;&lt;br /&gt;
	httpsport=&amp;quot;444&amp;quot;&lt;br /&gt;
        forcetrust=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;customcerts&lt;br /&gt;
        dir=&amp;quot;certs&amp;quot;&lt;br /&gt;
	CAname=&amp;quot;innovaphone Device Certification Authority,innovaphone Device Certification Authority 2&amp;quot;&lt;br /&gt;
        CSRsan-dns-1=&amp;quot;{name}.company.com&amp;quot;&lt;br /&gt;
        CSRsan-dns-2=&amp;quot;{hwid}.company.com&amp;quot;&lt;br /&gt;
        CSRsan-dns-3=&amp;quot;{rdns}&amp;quot;&lt;br /&gt;
        CSRsan-ip-1=&amp;quot;{realip}&amp;quot;&lt;br /&gt;
	/&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
	    &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
    &amp;lt;environments&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&amp;quot;intranet&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;sifi&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;berlin&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;verona&#039;&amp;gt;&lt;br /&gt;
		&amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
	&amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;homeoffice&#039;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;mobile&#039;/&amp;gt;&lt;br /&gt;
   &amp;lt;/environments&lt;br /&gt;
    &amp;lt;queries&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;admin&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;certificates&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Subject&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@subject_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Issuer&amp;quot;&amp;gt;/state/queries/certificates/info/servercert/certificate/@issuer_cn&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
    &amp;lt;/queries&amp;gt;&lt;br /&gt;
&amp;lt;/config&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operation ===&lt;br /&gt;
&lt;br /&gt;
==== Configuring and Debugging a real Device ====&lt;br /&gt;
To configure your device for use with the update server, you simply set &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/update.php&amp;lt;/code&amp;gt; as &#039;&#039;Command File URL&#039;&#039; in &#039;&#039;Services/Update&#039;&#039; (you can optionally add a &amp;lt;code&amp;gt;?env=envname1,envname2&amp;lt;/code&amp;gt; query argument if you want to set one or more specific environments for your device).  The update server will re-configure the device later on so that it uses all the required query arguments.&lt;br /&gt;
&lt;br /&gt;
Generally, there are the following methods to set the &#039;&#039;Command File URL&#039;&#039;&lt;br /&gt;
* configure it manually using the admin GUI&lt;br /&gt;
* provide it to the device using DHCP (this will however not work for the softwarephone or &#039;&#039;myPBX for Android/iOS&#039;&#039;)&lt;br /&gt;
* use the innovaphone provisioning service (see [[Reference10:Concept_Provisioning|Reference10:Concept Provisioning]] for details)&lt;br /&gt;
&lt;br /&gt;
Once the &#039;&#039;Command File URL&#039;&#039; is set on the device, you can debug what the update client in the device does, using the normal trace mechanism.  For this, you will want to open the &#039;&#039;Debug&#039;&#039; page (&amp;lt;code&amp;gt;http://x.x.x.x/debug.xml&amp;lt;/code&amp;gt;) and set the &#039;&#039;Update/Polling&#039;&#039; and &#039;&#039;Update/Execution&#039;&#039; check-marks.  When  the update client queries the update server, you will see lines like &lt;br /&gt;
&lt;br /&gt;
 0:0826:465:5 - upd_poll: state IDLE -&amp;gt; RECV&lt;br /&gt;
 0:0826:465:7 - IP.0 -&amp;gt; UPD-POLL.0 : SOCKET_GET_LOCAL_ADDR_RESULT(172.16.100.201,255.255.0.0,0,&#039;&#039;,ANY)&lt;br /&gt;
 0:0826:466:0 - IP.0 -&amp;gt; UPD-POLL.0 : SOCKET_GET_LOCAL_ADDR_RESULT(172.16.100.201,255.255.0.0,0,&#039;&#039;,ANY)&lt;br /&gt;
 0:0826:695:0 - upd_poll: state=RECV sent()&lt;br /&gt;
 0:0826:752:0 - upd_poll: status 200 headercomplete=1 contentlength=0&lt;br /&gt;
 0:0826:754:0 - upd_poll: recv_data(2199)&lt;br /&gt;
 0:0826:754:1 - upd_poll: recv_data(0) EOF&lt;br /&gt;
 0:0826:754:1 - upd_poll: GET EOF - state=RECV http-status=200 length=2199&lt;br /&gt;
 0:0826:754:1 - upd_poll: do commands&lt;br /&gt;
 0:0826:754:1 - upd_poll: state RECV -&amp;gt; EXEC&lt;br /&gt;
&lt;br /&gt;
in the trace.  Commands included in the update script will look like&lt;br /&gt;
&lt;br /&gt;
 0:0826:754:5 - script::get_line: &amp;gt;line(mod cmd UP0 scfg https://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m)&lt;br /&gt;
 0:0826:754:5 - upd_poll: pass &#039;mod cmd UP0 /sync scfg https://update.yourcompany.com/mtls/update/update.php?mode=backup&amp;amp;hwid=#h&amp;amp;sn=#m&#039;)&lt;br /&gt;
&lt;br /&gt;
Finally, you do not need to wait for the next time the device decides to contact the update server.  Instead, you can force this by sending an &amp;lt;code&amp;gt;http://&amp;lt;/code&amp;gt;&#039;&#039;your-device-ip&amp;lt;code&amp;gt;/!mod cmd UP1 poll&amp;lt;/code&amp;gt; to the device.&lt;br /&gt;
&lt;br /&gt;
==== The Device Status Update Page ====&lt;br /&gt;
If status tracking is enabled (see [[#Device_Status | Device Status]] above), the update server will keep a list of devices it knows of.  You can see this list by calling &amp;lt;code&amp;gt;http://update.yourcompany.com/mtls/update/admin/admin.php?mode=status&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
By default, the list will not be updated unless you refresh the page.  However, if you set the &#039;&#039;refresh&#039;&#039; attribute in the &#039;&#039;status&#039;&#039; tag in your &#039;&#039;use-config.xml&#039;&#039; file tp &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;, all entries in this list will be refreshed every 60 seconds (however, the list itself will not be reloaded, so to see new devices, your need to refresh the entire page).  Devices that have not been seen for more than 7 days are shown in a different colour.  Devices that have not been seen for longer than 90 days will be silently removed from the list.&lt;br /&gt;
&lt;br /&gt;
===== Filtering =====&lt;br /&gt;
From build 2011, you can filter the devices shown using the &#039;&#039;device filter&#039;&#039; field in the &#039;&#039;Device&#039;&#039; column header.  The filter string is matched against ip-address, serial number, type, name, phase, class, environment, firmware and bootcode.  Also, you can filter by using the keywords &#039;&#039;present&#039;&#039; and &#039;&#039;missing&#039;&#039; (based on the &#039;&#039;missing&#039;&#039; attribute of the &#039;&#039;status&#039;&#039; tag in your configuration file). If one of these attributes match your filter expression, the device is shown.&lt;br /&gt;
&lt;br /&gt;
A filter expression must match a complete &#039;&#039;word&#039;&#039;.  For example, if you filter by &amp;lt;code&amp;gt;16&amp;lt;/code&amp;gt; this would match the ip-address &amp;lt;code&amp;gt;172.&amp;lt;/code&amp;gt;16&amp;lt;code&amp;gt;.0.20&amp;lt;/code&amp;gt; but it would not match &amp;lt;code&amp;gt;192.&amp;lt;/code&amp;gt;16&amp;lt;code&amp;gt;8.0.1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you specify multiple filter expressions (separated by white space), only devices which match all of the expressions will be shown.  For example, if you filter by &amp;lt;code&amp;gt;172.16. ip222&amp;lt;/code&amp;gt; this might match all IP222 in your 172.16.*.* network.  Filter expressions are case insensitive.&lt;br /&gt;
&lt;br /&gt;
==== Approving Certificate Signing Requests ====&lt;br /&gt;
When you use custom certificate roll-out, you will see a column &#039;&#039;Certificates&#039;&#039; in the device status list, showing the devices certificate status.  &lt;br /&gt;
&lt;br /&gt;
[[Image:PHP_based_Update_Server_V2_Device_Status.png]]&lt;br /&gt;
&lt;br /&gt;
If a CSR has been created on the device, this will be available for download in the &#039;&#039;Files&#039;&#039; section of the &#039;&#039;Info&#039;&#039; column.  You can submit the CSR to your CA and then upload the signed request (using the &#039;&#039;Upload&#039;&#039; button in the &#039;&#039;Files&#039;&#039; section of the &#039;&#039;Info&#039;&#039; column).  The signed request will eventually be uploaded to the device then.  On  the device itself, the CSR is shown in &#039;&#039;General/Certificates&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:PHP_based_Update_Server_V2_CSR.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Certificate Errors ====&lt;br /&gt;
When a signed certificate request uploaded to the device can not be installed on the device, you will see a message like &amp;lt;code&amp;gt;Certificate upload error - certificate handling stopped&amp;lt;/code&amp;gt; in the &#039;&#039;Certificates&#039;&#039; columns for the device.  In this case, any further processing will be stopped.  Most likely, the reason is that you uploaded the wrong file as signed certificate request (either not a signed certificate at all or a signed request for another device).&lt;br /&gt;
&lt;br /&gt;
In this case&lt;br /&gt;
* remove any certificate request from the device&lt;br /&gt;
* remove the &amp;lt;code&amp;gt;X509/REQUESTERROR&amp;lt;/code&amp;gt; from the device configuration (i.e. &amp;lt;code&amp;gt;vars del X509/REQUESTERROR&amp;lt;/code&amp;gt;)&lt;br /&gt;
: these 2 steps can be easily done by resetting the device to factory defaults and then set the &#039;&#039;Update URL&#039;&#039; again&lt;br /&gt;
* remove any stored files for the device on the update server (shown in the &#039;&#039;Certificates&#039;&#039; column)&lt;br /&gt;
&lt;br /&gt;
The normal process will start all over again then.&lt;br /&gt;
&lt;br /&gt;
=== Migrating old PHP Update Server Installations ===&lt;br /&gt;
==== Migrating from build 2000 an newer ====&lt;br /&gt;
* Copy all files and folders, &#039;&#039;&#039;except&#039;&#039;&#039; the &#039;&#039;scripts&#039;&#039; and &#039;&#039;config&#039;&#039; folder, from the source to your destination&lt;br /&gt;
* make sure all files and directories have correct owner (&#039;&#039;www-data&#039;&#039;), group (&#039;&#039;www-data&#039;&#039;) and mode (&#039;&#039;read&#039;&#039;/&#039;&#039;write&#039;&#039; plus &#039;&#039;execute&#039;&#039; for directories)&lt;br /&gt;
: for example, in WinSCP you can use the &#039;&#039;Properties (F9)&#039;&#039; dialogue on the installations root folder:&lt;br /&gt;
: [[Image:PHP based Update Server V2-WinSCP-Properties.png]]&lt;br /&gt;
* open the &#039;&#039;StatusPage&#039;&#039; and make sure you refresh all cached files in your browser (depending on your browser, this may happen with Ctrl-R or Ctrl-F5)&lt;br /&gt;
&lt;br /&gt;
==== Migrating from build 1011 and older ====&lt;br /&gt;
To upgrade from the [http://download.innovaphone.com/ice/wiki-src/index.php?urloffset=php-update-server%2F&amp;amp;name=php-update-server+%28all+available+builds%29&amp;amp;reverselevel=0&amp;amp;maxbuilds=999&amp;amp;root=c%3A%2Finetpub%2Fwwwroot%2Fdownload%2Fice%2Fdownload%2Fp%2Fwiki-src%2Fphp-update-server%2F1010+%28PHP+based+Update+Server+final%29%2F.. old version (builds up to 1011)] of the PHP based update server (as described in [[Howto:PHP based Update Server]]), do the following&lt;br /&gt;
&lt;br /&gt;
* diff your &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; to the one originally shipped (you can download it at [http://download.innovaphone.com/ice/download/p/wiki-src/php-update-server/1011%20(PHP%20based%20Update%20Server%20final)/php-update-server-1011.zip download.innovaphone.com/ice/wiki-src])&lt;br /&gt;
: take note of all the changes you made to it&lt;br /&gt;
* install the new version of the update server to a different URL&lt;br /&gt;
* configure it according to your needs by modifying &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;.  Do not modify the new &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt;!&lt;br /&gt;
** apply all modifications you did to your old &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; to your new &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
** if you have used a custom setting for fwstorage/@url, you need to change it a bit.  Change for example &amp;lt;code&amp;gt;url=&amp;quot;http://myfwserver.mycompany.com&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;http://myfwserver.mycompany.com/{build}/&amp;lt;/code&amp;gt; (note the trailing slash!)&lt;br /&gt;
* copy all your update script snippet files from the old server (these are all the .txt files in the old server&#039;s root directory) to the &amp;lt;code&amp;gt;scripts&amp;lt;/code&amp;gt; directory of your new server&lt;br /&gt;
* copy the complete &amp;lt;code&amp;gt;fw&amp;lt;/code&amp;gt; tree from the old server to the &amp;lt;code&amp;gt;fw&amp;lt;/code&amp;gt; directory of your new server&lt;br /&gt;
* thoroughly test your new installation with some test devices&lt;br /&gt;
* when satisfied, edit &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; and change the code as described in the comment inside the file&lt;br /&gt;
* copy &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; from the new installation to the old installation&lt;br /&gt;
* on one of the devices which are currently served by the old update server, change the &#039;&#039;Command File URL&#039;&#039; so that it points to &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt;.  Do not change anything else in the URL. So if it currently is set to e.g. &lt;br /&gt;
: &amp;lt;code&amp;gt;https://172.16.0.90/update/update.php?type=#t&amp;amp;env=sifi&amp;amp;polling=0&amp;amp;phase=update&amp;lt;/code&amp;gt;, change it to&lt;br /&gt;
: &amp;lt;code&amp;gt;https://172.16.0.90/update/update-migrate.php?type=#t&amp;amp;env=sifi&amp;amp;polling=0&amp;amp;phase=update&amp;lt;/code&amp;gt;&lt;br /&gt;
* verify that this device properly switches to your new installation&lt;br /&gt;
** the &#039;&#039;Command File URL&#039;&#039; is changed so that it points to the new installation&lt;br /&gt;
** the device shows up in the device status page of your new server&lt;br /&gt;
&lt;br /&gt;
* rename &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;update-old.php&amp;lt;/code&amp;gt; in your old update server&lt;br /&gt;
* rename &amp;lt;code&amp;gt;update-migrate.php&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;update.php&amp;lt;/code&amp;gt; in your old update server&lt;br /&gt;
* verify that all of your devices start showing up in the new server&#039;s status page&lt;br /&gt;
&lt;br /&gt;
=== Complete Parameter Reference ===&lt;br /&gt;
Note: attributes are marked with an &#039;&#039;at&#039;&#039; (&amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;) prefix.  So &#039;&#039;master/@info&#039;&#039; refers to the &#039;&#039;info&#039;&#039; attribute in the &#039;&#039;master&#039;&#039; tag.&lt;br /&gt;
&lt;br /&gt;
The following tags and attributes are available in the &amp;lt;code&amp;gt;user-config.xml&amp;lt;/code&amp;gt; file, their default values are configured in &amp;lt;code&amp;gt;config.xml&amp;lt;/code&amp;gt; (which you should not modify):&lt;br /&gt;
&lt;br /&gt;
==== master ====&lt;br /&gt;
Defines the reference device where the firmware and boot code information is taken from.&lt;br /&gt;
; master/@info : the URL to the device info data.  Set it to an URL like &amp;lt;code&amp;gt;http://&amp;lt;/code&amp;gt;&#039;&#039;your-reference-device&#039;&#039;&amp;lt;code&amp;gt;/CMD0/box_info.xml&amp;lt;/code&amp;gt;. Please note that this device must not have the &#039;&#039;Password protect all HTTP pages&#039;&#039; set in &#039;&#039;Services/HTTP/Server&#039;&#039;.  If you use the literal &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt;, the master device will not be queried&lt;br /&gt;
; master/@expire : the firmware info cache lifetime.  The firmware information is cached in a file (to make sure this information is present even if the reference device is off-line).  The cache will not be refreshed before the &#039;&#039;expire&#039;&#039; time (in seconds) is expired&lt;br /&gt;
; master/@cache : the cache file name.  The web server must be able to write this file (see [[#Installation | &#039;&#039;Installation&#039;&#039; ]] above)&lt;br /&gt;
; master/@user : if non-empty, this is the user name required to access the update server&#039;s web ui&lt;br /&gt;
; master/@password : the password&lt;br /&gt;
&lt;br /&gt;
From build 2009, you can control the firmware and bootcode version to use on update:&lt;br /&gt;
; master/@firmware : if set, it may be one of &lt;br /&gt;
:: &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; (default if not set) : the firmware version is derived from the master device&lt;br /&gt;
:: &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt; : the firmware update is generally disabled&lt;br /&gt;
:: &#039;&#039;build-number&#039;&#039; : the firmware is set to a certain &#039;&#039;build-number&#039;&#039; regardless of the firmware running on the master device&lt;br /&gt;
; master/@bootcode: if set, it may be one of &lt;br /&gt;
:: &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; (default if not set) : the bootcode version is derived from the master device&lt;br /&gt;
:: &amp;lt;code&amp;gt;firmware&amp;lt;/code&amp;gt; : the bootcode version is set to the firmware version. This may be useful if the master device has no bootcode (e.g. the ipva)&lt;br /&gt;
:: &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt; : the bootcode update is generally disabled&lt;br /&gt;
:: &#039;&#039;build-number&#039;&#039; : the bootcode is set to a certain &#039;&#039;build-number&#039;&#039; regardless of the bootcode running on the master device&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;master &lt;br /&gt;
        info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;&lt;br /&gt;
        expire=&amp;quot;3600&amp;quot;&lt;br /&gt;
        cache=&amp;quot;cache/master-info.xml&amp;quot;&lt;br /&gt;
        user=&amp;quot;myadmin&amp;quot;&lt;br /&gt;
        password=&amp;quot;mysecret&amp;quot;&lt;br /&gt;
        firmware=&amp;quot;4711&amp;quot;&lt;br /&gt;
        bootcode=&amp;quot;firmware&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== master/applies ====&lt;br /&gt;
Available from build 2009.&lt;br /&gt;
&lt;br /&gt;
Boot code and firmware updates are only executed by devices which match all of the given &amp;lt;applies&amp;gt; conditions. A condition is met if the device belongs to the class that is given as tag content.  If the &#039;&#039;env&#039;&#039; attribute is set, the tag content is interpreted as an &#039;&#039;environment&#039;&#039; name which has to match.&lt;br /&gt;
&lt;br /&gt;
; master/applies/@env : if this attribute exists, the tag content is compared with the environments the device is in.  Otherwise, it is compared with the classes it is in &lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;master &lt;br /&gt;
    info=&amp;quot;http://172.16.0.10/CMD0/box_info.xml&amp;quot;&lt;br /&gt;
    expire=&amp;quot;3600&amp;quot;&lt;br /&gt;
    cache=&amp;quot;cache/master-info.xml&amp;quot;&lt;br /&gt;
    user=&amp;quot;myadmin&amp;quot;&lt;br /&gt;
    password=&amp;quot;mysecret&amp;quot;&lt;br /&gt;
    firmware=&amp;quot;4711&amp;quot;&lt;br /&gt;
    bootcode=&amp;quot;firmware&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- applied to phones in berlin only --&amp;gt;&lt;br /&gt;
    &amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
    &amp;lt;applies env=&amp;quot;&amp;quot;&amp;gt;berlin&amp;lt;/applies&amp;gt;&lt;br /&gt;
&amp;lt;/master&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== fwstorage ====&lt;br /&gt;
Defines from where the device will retrieve the firmware files for updates.&lt;br /&gt;
; fwstorage/@url :  defines the URL to retrieve the files from.  In this URL, the following meta words will be replaced as follows:&lt;br /&gt;
:* &amp;lt;code&amp;gt;{build}&amp;lt;/code&amp;gt; - the requested firmware or boot-code &lt;br /&gt;
:* &amp;lt;code&amp;gt;{model}&amp;lt;/code&amp;gt; - the devices type (e.g. &amp;lt;code&amp;gt;IP232&amp;lt;/code&amp;gt;).  This is derived from the &#039;&#039;type&#039;&#039; query argument used in the update URL which is set to the value &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; which in turn is expanded to the [[Reference10:Concept_Update_Server#Scfg_command|&#039;&#039;device type&#039;&#039;]] of the device requesting the update script&lt;br /&gt;
:* &amp;lt;code&amp;gt;{filetype}&amp;lt;/code&amp;gt; - the type of the required file, either &amp;lt;code&amp;gt;boot&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;prot&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code&amp;gt;{filename}&amp;lt;/code&amp;gt; - (from build 2014) the boot code or firmware filename for the device in lower case.  Required if you use the LAP as firmware storage and firmware files are falsely requested in uppercase letters (as URLs on the LAP are case sensitive and if the files are requested with upper case names, the original files with lowercase name are not found).  This also allows you to use alternate firmware file names (such as e.g. &amp;lt;code&amp;gt;ip110-sip.bin&amp;lt;/code&amp;gt;).  See the &#039;&#039;filenames&#039;&#039; tag&lt;br /&gt;
Note that if the &#039;&#039;url&#039;&#039; ends with a slash (&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;), the calling device will automatically [[Reference10:Concept_Update_Server#Prot_command|append the name of the requested file]]. In this case, the file system the URL points to must therefore contain sub-directories for each firmware build which contain the corresponding firmware builds (e.g, &#039;&#039;fw/12345/ip232.bin&#039;&#039;).  If &#039;&#039;url&#039;&#039; is not an URL (as is the case for the default value &amp;lt;code&amp;gt;fw/{build}/&amp;lt;/code&amp;gt;), it is treated as a sub-directory underneath the update server&#039;s root directory&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;fwstorage url=&amp;quot;fw/{build}/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Loading firmware files from innovaphone.com =====&lt;br /&gt;
You can also load firmware from the innovaphone.com web site.  To do so, set &#039;&#039;url&#039;&#039; like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;fwstorage url=&amp;quot;http://webbuild.innovaphone.com/{build}/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that &#039;&#039;this is a voluntary service, no guarantee of availability, no service level agreement&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== backup ====&lt;br /&gt;
Defines where backup files are kept.&lt;br /&gt;
; backup/@dir :  the directory underneath the script directory where backups are stored&lt;br /&gt;
; backup/@nbackups :  the number of different backup files kept&lt;br /&gt;
; backup/@scfg :  the target URL for the scfg command.  If this is not an url, it is interpreted relative to the script directory URL. You can add more options for the &#039;&#039;scfg&#039;&#039; command, like in &amp;lt;code&amp;gt;scfg=&amp;quot;update.php?mode=backup&amp;amp;amp;hwid=#h&amp;amp;amp;sn=#m ser hourly /force 1&amp;quot;&amp;lt;/code&amp;gt; (this example will make sure backups are attempted only once per hour, so as to reduce load on the server).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;backup &lt;br /&gt;
        dir=&amp;quot;backup&amp;quot;&lt;br /&gt;
        nbackups=&amp;quot;10&amp;quot;&lt;br /&gt;
        scfg=&amp;quot;update.php?mode=backup&amp;amp;amp;hwid=#h&amp;amp;amp;sn=#m&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== status ====&lt;br /&gt;
Defines details regarding the state kept for a device requesting an update script.&lt;br /&gt;
; status/@dir : the directory the status files are kept in (e.g. &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;).  Used as the name for a sub-directory underneath your install directory on your web server. You must make sure that files in this directory cannot be read by anyone without proper authentication, as such files may contain sensitive information.&lt;br /&gt;
; status/@expire : if set and not empty, devices which have not requested an update script will be removed from the inventory after &#039;&#039;n&#039;&#039; seconds.  For example, &#039;&#039;expire=&amp;quot;7776000&amp;quot;&#039;&#039; will forget about devices after 90 days with no contact&lt;br /&gt;
; status/@missing : devices are shown in a different colour (indicating that they are &#039;&#039;missing&#039;&#039;) after &#039;&#039;n&#039;&#039; seconds. For example, &#039;&#039;missing=&amp;quot;604800&amp;quot;&#039;&#039; will flag devices as missing after 7 days with no contact&lt;br /&gt;
; status/@refresh : if set and not empty and larger than zero, the admin user interface showing the known devices will refresh the status of all shown devices each &#039;&#039;n&#039;&#039; seconds&lt;br /&gt;
; status/@logkeep : number of seconds log messages for individual devices will be kept&lt;br /&gt;
; status/usehttpsdevlinks : if set to true, links to devices in the status page are created using the https:// scheme&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;status &lt;br /&gt;
        dir=&amp;quot;status&amp;quot; &lt;br /&gt;
        expire=&amp;quot;7776000&amp;quot; &lt;br /&gt;
        missing=&amp;quot;200&amp;quot; &lt;br /&gt;
        refresh=&amp;quot;10&amp;quot;&lt;br /&gt;
        logkeep=&amp;quot;90&amp;quot;&lt;br /&gt;
        usehttpsdevlinks=&amp;quot;true&amp;quot;&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== times ====&lt;br /&gt;
Defines details regarding the delivery of update scripts to requesting devices. &lt;br /&gt;
&lt;br /&gt;
; times/@dir : the directory the update scripts are stored in.  For security reasons, you may want to make sure that files in this directory cannot be read without proper authentication.&lt;br /&gt;
&lt;br /&gt;
These attributes define the arguments of the [[Reference10:Concept_Update_Server#Times_command | times command]].  If neither &#039;&#039;allow&#039;&#039; nor &#039;&#039;initial&#039;&#039; is set, no &#039;&#039;times&#039;&#039; command is used (that is, the update scripts will be processed at all times).&lt;br /&gt;
; times/@allow :  the hours to be used in the &#039;&#039;times&#039;&#039; command (as in &amp;lt;code&amp;gt;mod cmd UP1 times /allow &amp;lt;/code&amp;gt;&#039;&#039;hours&#039;&#039;)&lt;br /&gt;
; times/@initial :  the minutes to be used in the &#039;&#039;times&#039;&#039; command (as in &amp;lt;code&amp;gt;mod cmd UP1 times /initial &amp;lt;/code&amp;gt;&#039;&#039;minutes&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Delivered update scripts can include a [[Reference10:Concept_Update_Server#Check_command | check command ]] if the &#039;&#039;check&#039;&#039; attribute is set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.  . In this case, the devices will executed the scripts again only when you have edited/changed them.&lt;br /&gt;
; times/@check :  if set to true, update scripts will be executed once only (unless their contents change)&lt;br /&gt;
&lt;br /&gt;
When editing a number of update scripts, it is often not desirable if one changed script is already executed before another is changed too.   When the &#039;&#039;grace&#039;&#039; attribute is set to a positive value, no script at all is delivered to requesting devices unless &#039;&#039;n&#039;&#039; seconds have expired since the last edit.  For example, setting &#039;&#039;grace&#039;&#039; to 90 gives you one and a half minute to finish all your edits. &lt;br /&gt;
&lt;br /&gt;
; times/@grace :  defines the number of seconds that must expire before update script changes take effect&lt;br /&gt;
&lt;br /&gt;
The update server works in either &#039;&#039;fast&#039;&#039; or &#039;&#039;normal&#039;&#039; mode. In &#039;&#039;fast&#039;&#039; mode, update scripts have to be requested more frequently, for example to step through multiple staging phases faster. This is enforced by modifying the calling device&#039;s &#039;&#039;Interval&#039;&#039; setting in [[Reference11r1:Services/Update | &#039;&#039;Services/Update &#039;&#039;]] and setting it to 1 in &#039;&#039;fast&#039;&#039; mode.&lt;br /&gt;
&lt;br /&gt;
; times/@interval :  polling interval in minutes for normal operation (that is, when all staging s done)&lt;br /&gt;
; times/@polling :  when you are using multiple &#039;&#039;phases&#039;&#039; (e.g. &#039;&#039;staging&#039;&#039; and &#039;&#039;update&#039;&#039;), this defines the number of seconds to wait before the device reads the scripts for the next phase (see [[Reference10:Concept_Update_Server#Provision_command | provision command]]) (please do not modify the default value)&lt;br /&gt;
&lt;br /&gt;
In some installations it may be desired to deliver update scripts with HTTPS only or even only to calling devices which have identified themselves with a proper TLS certificate.  &lt;br /&gt;
&lt;br /&gt;
; times/@forcehttps : if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, update scripts will only be delivered if the device call in with HTTPS.  If the device is ready to receive an update script and still calls in with HTTP only, its &#039;&#039;Command File URL&#039;&#039; will be re-configured to use HTTPS automatically.&lt;br /&gt;
; times/@httpsport : if you use a non-standard port for HTTPS access to update scripts, it can be defined here&lt;br /&gt;
; times/@httpsurlmod : if your HTTPS URL differs from the HTTP URL, you can specifiy a &#039;&#039;modifier&#039;&#039;.  It has the form &amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&#039;&#039;pattern&#039;&#039;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&#039;&#039;replacement&#039;&#039;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt; where &#039;&#039;pattern&#039;&#039; is a [http://docs.php.net/manual/en/pcre.pattern.php PHP PCRE pattern]. For example, &amp;lt;code&amp;gt;!mtls/!!i&amp;lt;/code&amp;gt; will remove the string &amp;lt;code&amp;gt;mtls/&amp;lt;/code&amp;gt; from the URL used by the device to create the HTTPS URL to use. The delimiter (in this case &amp;quot;!&amp;quot;) can be changed according to your own wishes, the first character defines the delimiter. The &amp;quot;i&amp;quot; at the end ignores uppercase.&lt;br /&gt;
&lt;br /&gt;
Note: If you want to change the hostname of your URL, you have to add the Port 444 to your hostname. The code should then look like this: &amp;lt;code&amp;gt;!hostname1:444/mtls/!hostname2:444/!i&amp;lt;/code&amp;gt;.&lt;br /&gt;
; times/@forcetrust : if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, update scripts will only be delivered if the device call in with HTTPS and a valid and trusted client certificate that identifies itself as the devices it claims to be&lt;br /&gt;
; times/@forcestaging : before build 2009, the restrictions imposed by the times/@allow settings affected all update &#039;&#039;phases&#039;&#039;.  This however makes staging cumbersome, as you usually want to restrict normal configuration changes to off-working-hours.  Now you can set the &#039;&#039;forcestaging&#039;&#039; attribute to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.  If so, the restriction will be applied only to the last phase (that is, the &#039;&#039;staging&#039;&#039; phases will execute immediately). Also, the final phase will be executed once by staged devices. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;times &lt;br /&gt;
        dir=&amp;quot;scripts&amp;quot; &lt;br /&gt;
        allow=&amp;quot;&amp;quot; &lt;br /&gt;
        initial=&amp;quot;&amp;quot; &lt;br /&gt;
        check=&amp;quot;true&amp;quot; &lt;br /&gt;
        polling=&amp;quot;5&amp;quot; &lt;br /&gt;
        interval=&amp;quot;15&amp;quot; &lt;br /&gt;
        grace=&amp;quot;90&amp;quot; &lt;br /&gt;
        forcehttps=&amp;quot;true&amp;quot; &lt;br /&gt;
        httpsport=&amp;quot;444&amp;quot; &lt;br /&gt;
        forcetrust=&amp;quot;false&amp;quot; &lt;br /&gt;
        httpsurlmod=&amp;quot;!mtls/!!i&amp;quot;&lt;br /&gt;
        forcestaging=&amp;quot;true&amp;quot;&lt;br /&gt;
/&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== phases ==== &lt;br /&gt;
Defines the scripting phases.  In many installations, there are initializations which should be performed once only.  This is known as the &#039;&#039;staging&#039;&#039; phase.  Once this is done, the devices continue with the execution of the normal update scripts (this phase is known as &#039;&#039;update&#039;&#039; by default).  In the (unlikely) event that you want more or less phases, you can add/remove &#039;&#039;phase&#039;&#039; tags.&lt;br /&gt;
==== phases/phase ====&lt;br /&gt;
; phases/phase/@id :  the name for the phase&lt;br /&gt;
; phases/phase/@seq:  the sequential number for the phase. Phases are stepped-through in the numeric order defined by their &#039;&#039;seq&#039;&#039; atribute. &lt;br /&gt;
&lt;br /&gt;
By virtue if the &#039;&#039;seq&#039;&#039; attribute, you can insert phases in to the set of phases defined by default, which is&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
        &amp;lt;!-- sequence is important! --&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;staging&amp;quot; seq=&amp;quot;100&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;update&amp;quot; seq=&amp;quot;200&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For example,&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;phases&amp;gt;&lt;br /&gt;
        &amp;lt;phase id=&amp;quot;phase&amp;quot; seq=&amp;quot;150&amp;quot;&amp;gt;&amp;lt;/phase&amp;gt;&lt;br /&gt;
    &amp;lt;/phases&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will insert a custom phase &#039;&#039;myphase&#039;&#039; as second phase.&lt;br /&gt;
&lt;br /&gt;
==== environments ====&lt;br /&gt;
Defines the distinguished environments.  Devices can have zero or more &#039;&#039;environments&#039;&#039; associated.  The environments a device is considered to be in must be passed as &amp;lt;code&amp;gt;?env=&amp;lt;/code&amp;gt;&#039;&#039;name1,name2,..&#039;&#039; URL query arg in the update url.  Update scripts for all environments listed will be applied. The default config file defines the environments &#039;&#039;intern&#039;&#039; and &#039;&#039;homeoffice&#039;&#039; but you can define your own if you like.&lt;br /&gt;
==== environments/environment ====&lt;br /&gt;
; environments/environment/@id :  the name for the environment&lt;br /&gt;
&lt;br /&gt;
==== environments/environment/implies ====&lt;br /&gt;
Each &#039;&#039;environment&#039;&#039; may have a number of sub-tags of type &#039;&#039;implies&#039;&#039;. It contains the &#039;&#039;id&#039;&#039; of another &#039;&#039;environment&#039;&#039;.   If a device is in an environment with an &#039;&#039;implies&#039;&#039; sub-tag, it is assumed that it is in the implied environment also. &lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;environments&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;hq&#039;&amp;gt;&lt;br /&gt;
            &amp;lt;implies&amp;gt;intranet&amp;lt;/implies&amp;gt;&lt;br /&gt;
        &amp;lt;/environment&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;intranet&#039;/&amp;gt;&lt;br /&gt;
        &amp;lt;environment id=&#039;homeoffice&#039;/&amp;gt;&lt;br /&gt;
    &amp;lt;/environments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== classes ====&lt;br /&gt;
Defines the available device classes.  Devices of different classes (e.g. phones and gateways) can have different update scripts. The device class is derived from the &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; (device type) query arg of the update script URL (which is why you must configure it in the update URL).  By default, the classes &#039;&#039;phone&#039;&#039;, &#039;&#039;opus_phone&#039;&#039;, &#039;&#039;pre_opus_phone&#039;&#039;, &#039;&#039;phone_oldui&#039;&#039;, &#039;&#039;phone_newui&#039;&#039;, &#039;&#039;mobile&#039;&#039;, &#039;&#039;gw&#039;&#039;, &#039;&#039;fxogw&#039;&#039;, &#039;&#039;fxsgw&#039;&#039;, &#039;&#039;brigw&#039;&#039;, &#039;&#039;prigw&#039;&#039; are recognized (newer versions may include more and/or updated class definitions).   Also, any device is considered to be member of a class that has the device type as class-name.  For example, an IP112 is in a class called &#039;&#039;ip112&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A given device can be in multiple classes and will execute all update scripts available for these classes.&lt;br /&gt;
&lt;br /&gt;
==== classes/class ====&lt;br /&gt;
Each &#039;&#039;class&#039;&#039; has a number of sub-tags of type &#039;&#039;model&#039;&#039;. It contains the value replaced for the &amp;lt;code&amp;gt;#t&amp;lt;/code&amp;gt; query arg.  The models listed belong to the class.&lt;br /&gt;
; classes/class/@id :  the name of the class&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;classes&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;gw&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip0010&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip110&amp;lt;/model&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip232&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone_oldui&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip110&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
        &amp;lt;class id=&amp;quot;phone_newui&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;model&amp;gt;ip232&amp;lt;/model&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
        &amp;lt;/class&amp;gt;&lt;br /&gt;
    &amp;lt;/classes&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== nobootdev ====&lt;br /&gt;
Device types listed here do not receive boot code updates.&lt;br /&gt;
===== nobootdev/model =====&lt;br /&gt;
Each model tag defines a device type that shall not receive boot code updates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;nobootdev&amp;gt; &lt;br /&gt;
        &amp;lt;model&amp;gt;ipva&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;ipvadec&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;swphone&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxa&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxi&amp;lt;/model&amp;gt;&lt;br /&gt;
    &amp;lt;/nobootdev&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== nofirmdev ====&lt;br /&gt;
Device types listed here do not receive firmware updates.&lt;br /&gt;
===== nobootdev/model =====&lt;br /&gt;
Each model tag defines a device type that shall not receive firmware updates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;nofirmdev&amp;gt; &lt;br /&gt;
        &amp;lt;model&amp;gt;swphone&amp;lt;/model&amp;gt;&lt;br /&gt;
        &amp;lt;model&amp;gt;mypbxi&amp;lt;/model&amp;gt;&lt;br /&gt;
    &amp;lt;/nofirmdev&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== filenames ====&lt;br /&gt;
Available from build 2014. Allows you to define alternate firmware and boocode names for use with the &amp;lt;code&amp;gt;{filename}&amp;lt;/code&amp;gt; replacement (see the &#039;&#039;fwstorage&#039;&#039; tag), if required.&lt;br /&gt;
&lt;br /&gt;
===== filenames/model =====&lt;br /&gt;
Each mode defines a set of alternative file names for a certain device type.&lt;br /&gt;
; filenames/model/@id : the (lowercase) device type identfier (e.g. &amp;lt;code&amp;gt;ip112&amp;lt;/code&amp;gt;). If this matches the device type of the calling device, the alternate file names are replaced&lt;br /&gt;
; filenames/model/@prot: the alternate firmware file name&lt;br /&gt;
; filenames/model/@boot: the alternate boot file name&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;filenames&amp;gt;&lt;br /&gt;
        &amp;lt;model id=&amp;quot;mypbxa&amp;quot; prot=&amp;quot;mypbx.apk&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/filenames&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
defines the firmware file name &amp;lt;code&amp;gt;mypbx.apk&amp;lt;/code&amp;gt; for the device type &amp;lt;code&amp;gt;mypbxa&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== stdargs ====&lt;br /&gt;
Better don&#039;t touch :-)&lt;br /&gt;
&lt;br /&gt;
==== customcerts ====&lt;br /&gt;
innovaphone hardware devices come with a device specific, trust-able &#039;&#039;device certificate&#039;&#039;.  However, in many situations it is desirable to roll-out customer-created &#039;&#039;custom  certificates&#039;&#039; to all devices.  The update server can do this.  This will replace the shipped devices certificates both on hardware devices (where all such certificates are derived from innovaphone&#039;s certificate authority) as well as on soft devices which run with a self.-signed certificate by default (such as the software-phone or &#039;&#039;myPBX for Android/iOS&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
; customcerts/@dir : the name of the directory underneath your installation directory which stores device certificates. you should make sure that this directory cannot be accessed without proper authentication&lt;br /&gt;
; customcerts/@CAkeys : a file name pattern (e.g. &amp;lt;code&amp;gt;CAkey*&amp;lt;/code&amp;gt;).  All files in &#039;&#039;customcerts/@dir&#039;&#039; which match the pattern must contain DER or PEM encoded public keys which form the &#039;&#039;certificate chain&#039;&#039; of your CA (usually it is only one and the public key of your CA). One key per file.  The files, when sorted by name, must contain the CA key itself in the last file (any intermediate certificates, if any, in the other files in correct order)&lt;br /&gt;
; customcerts/@CAtype : must be &amp;lt;code&amp;gt;manual&amp;lt;/code&amp;gt; currently&lt;br /&gt;
; customcerts/@CAname : a comma-separated list of CA names.  Devices presenting a certificate signed by one of these CAs will be considered as having a valid certificate.  Otherwise, they wil be instructed to create a &#039;&#039;certificate signing request&#039;&#039; (CSR) for subsequent submission to your CA&lt;br /&gt;
; customcerts/@CAnamesep : defines the name separator for &#039;&#039;customcerts/@CAname&#039;&#039;.  The default is &#039;&amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;&#039; and you must change it to a different value if one of your CAs includes a comma in its name&lt;br /&gt;
; customcerts/@renew : if set and not 0, certificates are replaced by new ones &#039;&#039;n&#039;&#039; days before they expire&lt;br /&gt;
; customcerts/@CAwildcard : normally, the update server will accept a certificate only if its CN matches the device&#039;s serial number.  However, sometimes, so-called &#039;&#039;wildcard certificates&#039;&#039; such as &amp;lt;code&amp;gt;*.innovaphone.com&amp;lt;/code&amp;gt; are used on a device (e.g. on a PBX or on a &#039;&#039;reverse proxy&#039;&#039;).  If set, the update server will also accept a certificate that contains a CN which equals the value of &#039;&#039;customcerts/@CAwildcard&#039;&#039;. Note that the CN must match literally.  For example, if &#039;&#039;&#039;&#039;customcerts/@CAwildcard&#039;&#039; is set to &amp;lt;code&amp;gt;*.innovaphone.com&amp;lt;/code&amp;gt; a CN like &amp;lt;code&amp;gt;host.innovaphone.com&amp;lt;/code&amp;gt; is not accepted&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the update server determines that a device calls in with an un-trusted or expired certificate, it will have it create a signing-request for a new certificate.  The requested certificate properties can be defined:&lt;br /&gt;
&lt;br /&gt;
; customcerts/@CSRkey : the key size, e.g. &amp;lt;code&amp;gt;2048-bit&amp;lt;/code&amp;gt;. Note that we do not recommend keys larger than 2048 bit (see [[Reference7:Certificate_management#Certificate_Key_Length_and_CPU_Usage]] for details)&lt;br /&gt;
; customcerts/@CSRsignature : the signature algorithm, e.g. &amp;lt;code&amp;gt;SH256&amp;lt;/code&amp;gt;&lt;br /&gt;
; customcerts/@CSRdn-cn : the CN (&#039;&#039;common name&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-ou : the OU (&#039;&#039;organizational unit&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-o : the O (&#039;&#039;organization&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-l : the L (&#039;&#039;locality&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-st : the ST (&#039;&#039;state or province&#039;&#039;) part used for the DN&lt;br /&gt;
; customcerts/@CSRdn-c : the C (&#039;&#039;country&#039;&#039;) part used for the DN (note: &#039;&#039;CSRdn&#039;&#039; for many CAs, must be a 2-letter ISO country code)&lt;br /&gt;
; customcerts/@CSRsan-dns-1 : the first of up to three DNS names &lt;br /&gt;
; customcerts/@CSRsan-ip-1 : the first of up to two IP addresses&lt;br /&gt;
&lt;br /&gt;
Within the set of CSR attributes, the following meta-words will be replaced:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;{realip}&amp;lt;/code&amp;gt; : the real IP address of the device as reported in the &amp;lt;code&amp;gt;ip=#i&amp;lt;/code&amp;gt; query argument&lt;br /&gt;
* &amp;lt;code&amp;gt;{ip}&amp;lt;/code&amp;gt; : the IP address of the device as seen by the update server&lt;br /&gt;
* &amp;lt;code&amp;gt;{proxy}&amp;lt;/code&amp;gt; : the IP address of the reverse proxy the device used to reach the update server&lt;br /&gt;
* &amp;lt;code&amp;gt;{sn}&amp;lt;/code&amp;gt; : the serial number of the device as reported in the &amp;lt;code&amp;gt;sn=#m&amp;lt;/code&amp;gt; query argument (e.g. &amp;lt;code&amp;gt;009033030df0&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;{hwid}&amp;lt;/code&amp;gt; : the hardware-id of the device as reported in the &amp;lt;code&amp;gt;sn=#m&amp;lt;/code&amp;gt; query argument (e.g. &amp;lt;code&amp;gt;IP1200-03-0d-f0&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;{name}&amp;lt;/code&amp;gt; : the &#039;&#039;Device Name&#039;&#039; (set in &#039;&#039;General/Admin&#039;&#039;) of the device&lt;br /&gt;
* &amp;lt;code&amp;gt;{rdns}&amp;lt;/code&amp;gt; : the DNS name found in a reverse DNS lookup for the real-ip address reported by the device (see &#039;&#039;{realip}&#039;&#039;) above&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
    &amp;lt;customcerts &lt;br /&gt;
        dir=&amp;quot;certs&amp;quot; &lt;br /&gt;
        CAkeys=&amp;quot;CAkey*&amp;quot; &lt;br /&gt;
        CAtype=&amp;quot;manual&amp;quot; &lt;br /&gt;
        CAname=&amp;quot;innovaphone-INNO-DC-W2K8-Zertifizierungsserver&amp;quot; &lt;br /&gt;
        CAnamesep=&amp;quot;,&amp;quot; &lt;br /&gt;
        CAwildcard=&amp;quot;*.innovaphone.com&amp;quot;&lt;br /&gt;
        CSRkey=&amp;quot;2048-bit&amp;quot; &lt;br /&gt;
        CSRsignature=&amp;quot;SH256&amp;quot; &lt;br /&gt;
        CSRdn-cn=&amp;quot;{hwid}&amp;quot; &lt;br /&gt;
        CSRdn-ou=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-o=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-l=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-st=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRdn-c=&amp;quot;&amp;quot; &lt;br /&gt;
        CSRsan-dns-1=&amp;quot;{name}.company.com&amp;quot; &lt;br /&gt;
        CSRsan-dns-2=&amp;quot;{hwid}.company.com&amp;quot; &lt;br /&gt;
        CSRsan-dns-3=&amp;quot;{rdns}&amp;quot; &lt;br /&gt;
        CSRsan-ip-1=&amp;quot;{realip}&amp;quot; &lt;br /&gt;
        CSRsan-ip-2=&amp;quot;&amp;quot; &lt;br /&gt;
        renew=&amp;quot;90&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries ====&lt;br /&gt;
If queries are defined and applicable for the calling device, it will be instructed to send certain information to the update server which will be stored in the device status file kept on the server.  Each piece of such information is defined usign a separate &#039;&#039;query&#039;&#039; tag.&lt;br /&gt;
&lt;br /&gt;
; queries/@scfg : defines to URL used by the device to send the information.  Normally not changed from the default&lt;br /&gt;
==== queries/query ====&lt;br /&gt;
Defines one piece of information to be submitted to the update server.&lt;br /&gt;
&lt;br /&gt;
; queries/query/@id : a unique name for the query&lt;br /&gt;
; queries/query/@title : a title for this piece of information shown in the device status&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;.&lt;br /&gt;
        &amp;lt;!-- retrieve and show some details from IP4/General/STUN page --&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;media&amp;quot; title=&amp;quot;Media&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd MEDIA xml-info&amp;lt;/cmd&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;*&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;NAT&amp;quot;&amp;gt;concat(/state/queries/media/info/nat/@result, &#039; (&#039;, /state/queries/media/info/nat/@public-addr, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;Server&amp;quot;&amp;gt;concat(&#039;STUN: &#039;, /state/queries/media/info/@stun, &#039; TURN: &#039;, /state/queries/media/info/@turn, &#039; (&#039;, /state/queries/media/info/@turn-user, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;!-- show primary phone registration --&amp;gt;&lt;br /&gt;
        &amp;lt;query id=&amp;quot;registration&amp;quot; title=&amp;quot;Registration&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd PHONE/USER phone-regs /cmd phone-regs&amp;lt;/cmd&amp;gt;&lt;br /&gt;
            &amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;State: User/Number&amp;quot;&amp;gt;concat(/state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@state, &#039;: &#039; , /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@h323, &#039;/&#039;, /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@e164)&amp;lt;/show&amp;gt;&lt;br /&gt;
            &amp;lt;show title=&amp;quot;PBX/ID&amp;quot;&amp;gt;concat(/state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@gk-addr, &#039;/&#039;, /state/queries/registration/info/reg[@id = &amp;quot;0&amp;quot;]/@gk-id)&amp;lt;/show&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries/query/cmd ====&lt;br /&gt;
The content of this tag defines the command to be executed on the device which outputs the requested information. These are &#039;&#039;mod cmd&#039;&#039;s typically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
            &amp;lt;!-- get info for custom certificates --&amp;gt;&lt;br /&gt;
            &amp;lt;cmd&amp;gt;mod cmd X509 xml-info&amp;lt;/cmd&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Howto:Effect_arbitrary_Configuration_Changes_using_a_HTTP_Command_Line_Client_or_from_an_Update#Using_the_Mechanism_for_Device_Status_Queries ]] for details on how to find out whicgh commands to use.&lt;br /&gt;
&lt;br /&gt;
==== queries/query/applies ====&lt;br /&gt;
Defined queries are only executed by devices which belong to the class that is given as tag content.  If the &#039;&#039;env&#039;&#039; atribute is set, the tag content is interpreted as an &#039;&#039;environment&#039;&#039; name which has to match.&lt;br /&gt;
&lt;br /&gt;
; queries/query/applies/@env : if this attribute exists, the tag content is compared with the environments the device is in.  Otherwise, it is compared with the classes it is in (unfortunately, you can not combine bith)&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;!-- applied to phones only --&amp;gt;&lt;br /&gt;
&amp;lt;applies&amp;gt;phone&amp;lt;/applies&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== queries/query/show====&lt;br /&gt;
If one or more  &#039;&#039;show&#039;&#039; tags are defined for the &#039;&#039;query&#039;&#039; tag, the data will be shown in the device status page.  The values shown are defined by the tag content which is an XPath expression selecting the data from the device state.  The XPath expression always begins with &amp;lt;code&amp;gt;/state/queries/&amp;lt;/code&amp;gt;&#039;&#039;query-id&#039;&#039; (as defined by the &#039;&#039;id&#039;&#039; attribute in the query tag).  &lt;br /&gt;
&lt;br /&gt;
; queries/query/show/@title : used as title when the values are displayed in the status page&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;show title=&amp;quot;NAT&amp;quot;&amp;gt;concat(/state/queries/media/info/nat/@result, &#039; (&#039;, /state/queries/media/info/nat/@public-addr, &#039;)&#039;)&amp;lt;/show&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
*[http://download.innovaphone.com/ice/wiki-src#php-update-server http://download.innovaphone.com/ice/wiki-src/] - download the complete file package of scripts and files described in this article&lt;br /&gt;
: you need to use build 2000 or higher.  Older versions are described in [[Howto:PHP_based_Update_Server]]&lt;br /&gt;
&lt;br /&gt;
== Hints for writing your update snippets ==&lt;br /&gt;
Writing update scripts is largely undocumented and sometimes tricky.  Here are some general guidelines.&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;config add/del&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Many setting are done using &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; commands.  So these are very useful in update scripts too.&lt;br /&gt;
&lt;br /&gt;
The straight forward method to find out which commands you need is as follows:&lt;br /&gt;
* get a device of the type in question and do factory reset&lt;br /&gt;
* save the configuration to a file&lt;br /&gt;
* do the desired settings using the normal web admin UI&lt;br /&gt;
* save the resulting configuration to another file&lt;br /&gt;
* compare the saved files&lt;br /&gt;
&lt;br /&gt;
Usually, you want to set only specific parts of the configuration line.  For example, assume you want to set the default coder to &#039;&#039;OPUS-WB&#039;&#039;. Your saved configuration line might look like&lt;br /&gt;
&lt;br /&gt;
 config change PHONE SIG /prot SH323 /gk-addr pbx.innovaphone.com /gk-id innovaphone.com /tones 0 /lcoder OPUS-WB,20, /coder OPUS-WB,20,k1&lt;br /&gt;
&lt;br /&gt;
To set only the coder settings, you would set the relevant options with the &amp;lt;code&amp;gt;config add&amp;lt;/code&amp;gt; command as follows:&lt;br /&gt;
&lt;br /&gt;
 config add PHONE SIG /lcoder OPUS-WB,20,&lt;br /&gt;
 config add PHONE SIG /coder OPUS-WB,20,k1&lt;br /&gt;
&lt;br /&gt;
You can also remove specific options, as in &lt;br /&gt;
&lt;br /&gt;
 config rem PHONE SIG /tones&lt;br /&gt;
&lt;br /&gt;
which would remove the &amp;lt;code&amp;gt;/tones 0&amp;lt;/code&amp;gt; from the configuration line for &amp;lt;code&amp;gt;PHONE SIG&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Note that the PHP update server will add the&lt;br /&gt;
&lt;br /&gt;
 config write&lt;br /&gt;
 config activate &lt;br /&gt;
 iresetn&lt;br /&gt;
&lt;br /&gt;
at the end of the delivered script automatically, so you do not need to do it yourself.  In fact, it is not recommended to have any reset command in your snippets.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;config change&amp;lt;/code&amp;gt; Lines with associated Passwords ====&lt;br /&gt;
Sometimes, there is a password associated with certain configurations.  Consider the STUN/TURN configuration: &lt;br /&gt;
&lt;br /&gt;
 config change MEDIA /stun stun.innovaphone.com /turn turn.innovaphone.com /turn-user innovaphone /turn-pwd 2 /nat-detect 61&lt;br /&gt;
&lt;br /&gt;
The TURN password, being sensitive, needs to be encrypted in your configuration.  This is why it is stored as a &#039;&#039;VAR&#039;&#039;, which provides encryption support (see below):&lt;br /&gt;
&lt;br /&gt;
 vars create MEDIA/TURN-PWD pc ....&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the relationship between an option and an associated VAR needs to be guessed.  You can be sure that the module name in the &amp;lt;code&amp;gt;config changey&amp;lt;/code&amp;gt; matches the modules name in the &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; command. However, the variable name mist be guessed. &lt;br /&gt;
&lt;br /&gt;
You can also set the password in your script using the &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt;&amp;lt;!-- , but this does make sense only in staging (that is pre-update-phase) scripts (see below for a discussion why). If you need to do it in a script snippet for the update phase, you should --&amp;gt;, however, you may also consider using a &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; (see below) such as e.g.&lt;br /&gt;
&lt;br /&gt;
 mod cmd MEDIA form /cmd form /del %2Fstun-slow /stun stun.innovaphone.com /turn turn.innovaphone.com /turn-user innovaphone /turn-pwd my-turn-pw /nat-detect 61&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Sometimes it makes sense to use &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; commands.  The syntax is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; vars create &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;name&amp;gt; &amp;lt;flags&amp;gt; &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&amp;lt;name&amp;gt;&#039;&#039; is a module name followed by a variable name, optionally followed by an index.  For example, a phone will store the currently selected main registration as &amp;lt;code&amp;gt;vars create PHONE/ACTIVE-USER p &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;index&amp;gt;&#039;&#039;.  So the module is &amp;lt;code&amp;gt;PHONE&amp;lt;/code&amp;gt; and the variable name is &amp;lt;code&amp;gt;ACTIVE-USER&amp;lt;/code&amp;gt;.  When the variable is multi-valued, an index is added to the name.  For example, the registration settings for all but the first registration are stored as indexed variable, as in &amp;lt;code&amp;gt;vars create PHONE/USER-REG/00001 p &amp;lt;/code&amp;gt;&#039;&#039;&amp;lt;settings&amp;gt;&#039;&#039;, where &amp;lt;code&amp;gt;00001&amp;lt;/code&amp;gt; is the index (registrations count from 0 in this case).&lt;br /&gt;
&lt;br /&gt;
There are a number of flags which can be combined, the most prominent used in update scripts are:&lt;br /&gt;
; p : permanent.  The var is stored in flash memory (you will almost always use this flag in update scripts)&lt;br /&gt;
; c : crypted.  The var value needs to be encrypted and the &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; given is crypted&lt;br /&gt;
; x : crypted, plain value.  The var needs to be encrypted but the &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is given as plain (that is, un-encrypted) text. This allows you to set an encrypted variable without encrypting the desired value&lt;br /&gt;
; b : binary. The var value is binary.  Its &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is given as a bin2hex string&lt;br /&gt;
&lt;br /&gt;
Please note that using &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; will &#039;&#039;always&#039;&#039; set the internal &#039;&#039;reset needed condition&#039;&#039; in the device (regardless which &#039;&#039;&amp;lt;value&amp;gt;&#039;&#039; is set).  This means that a subsequent &amp;lt;code&amp;gt;resetn&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;iresetn&amp;lt;/code&amp;gt; will always trigger a reset.  So if you use it, make sure that you use the &#039;&#039;times/@check&#039;&#039; ([[#times | see above]]) to protect your script from re-executing the snippet (and thus rebooting the device) all the time. &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
When you use a &amp;lt;code&amp;gt;mod cmd UP1 check ...&amp;lt;/code&amp;gt; command in your script (see times/@check [[#times | above]]), this will create an endless loop if you use &amp;lt;code&amp;gt;vars create&amp;lt;/code&amp;gt; followed by one of the &amp;lt;code&amp;gt;resetn&amp;lt;/code&amp;gt; commands in the code guarded by the &amp;lt;code&amp;gt;check&amp;lt;/code&amp;gt; command. This code will never be fully executed, as the &#039;&#039;reset needed&#039;&#039; condition will always be set and the reset will always happen.  You can use it in &#039;&#039;pre-update-phase&#039;&#039; scripts (that is, during the staging process) as this is not protected by a &amp;lt;code&amp;gt;check&amp;lt;/code&amp;gt; command.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
See [[Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update]] for a discussion of how to use &amp;lt;code&amp;gt;mod cmd&amp;lt;/code&amp;gt; in update scripts.&lt;br /&gt;
&lt;br /&gt;
=== Writing your own Dynamic Scripting Code ===&lt;br /&gt;
NB: this feature is available from build 2020.&lt;br /&gt;
&lt;br /&gt;
By default, the update server delivers update scripts which are composed from a number of static files (so-called &#039;&#039;snippets&#039;&#039;).  Sometimes it makes sense however, to create such snippets dynamically (e.g. based on a database lookup).  Here is how to do this.&lt;br /&gt;
&lt;br /&gt;
Dynamic scripting is implemented by a user-supplied custom &amp;lt;code&amp;gt;class CustomUpdateSnippet&amp;lt;/code&amp;gt;.  The code for this class must be placed in to the file &amp;lt;code&amp;gt;config/scripting.class.php&amp;lt;/code&amp;gt;.  As a starter, sample class code is available in &amp;lt;code&amp;gt;config/sample.scripting.class.php&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * to provide your own runtime generated snippets, rename this file to &#039;scripting.class.php&#039; and &lt;br /&gt;
 * implement the member functions&lt;br /&gt;
 * $property will have one member called &lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
class CustomUpdateSnippet extends UpdateSnippet {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * snippet to deliver after standard text snippets&lt;br /&gt;
     * @return array of string&lt;br /&gt;
     */&lt;br /&gt;
    public function getPostSnippet() {&lt;br /&gt;
        return parent::getPostSnippet();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * snippet to deliver before standard text snippets&lt;br /&gt;
     * @return array of strings&lt;br /&gt;
     */&lt;br /&gt;
    public function getPreSnippet() {&lt;br /&gt;
        return parent::getPreSnippet();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /** &lt;br /&gt;
     * do we want to suppress the standard text snippets?&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function sendStandardSnippets() {&lt;br /&gt;
        return parent::sendStandardSnippets();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample code overrides of the classes member functions just call the base classes which do nothing at all. So if you just copy the sample code into &amp;lt;code&amp;gt;scripting.class.php&amp;lt;/code&amp;gt;, nothing will change.  However, if &amp;lt;code&amp;gt;getPreSnippet()&amp;lt;/code&amp;gt; returns an array of strings (the parent class function returns an empty array), each array member will be sent to the calling device &#039;&#039;before&#039;&#039; the standard snippets are sent.  Likewise, if &amp;lt;code&amp;gt;getPostSnippet()&amp;lt;/code&amp;gt; returns an array of strings (the parent class function returns an empty array), each array member will be sent to the calling device &#039;&#039;after&#039;&#039; the standard snippets are sent. If &amp;lt;code&amp;gt;sendStandardSnippets()&amp;lt;/code&amp;gt; returns false, the standard snippets will not be sent.&lt;br /&gt;
&lt;br /&gt;
To determine the dynamic snippets to send, the user-provided &amp;lt;code&amp;gt;class CustomUpdateSnippet&amp;lt;/code&amp;gt; has access to the members of its base &amp;lt;code&amp;gt;class UpdateSnippet&amp;lt;/code&amp;gt;, namely the &amp;lt;code&amp;gt;var $statexml&amp;lt;/code&amp;gt; member. This member contains a &amp;lt;code&amp;gt;SimpleXMLElement&amp;lt;/code&amp;gt; object with all state information available for the calling device.&lt;br /&gt;
&lt;br /&gt;
Here is a sample state found in &amp;lt;code&amp;gt;$statexml&amp;lt;/code&amp;gt; (as output by the &amp;lt;code&amp;gt;dump()&amp;lt;/code&amp;gt; member function): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;state seen=&amp;quot;1522065435&amp;quot; requested=&amp;quot;130774bootcode&amp;quot; phase=&amp;quot;update&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;device sn=&amp;quot;00-90-33-3e-0c-57&amp;quot; type=&amp;quot;IP112&amp;quot; classes=&amp;quot;phone, opus_phone, phone_newui, hstrace, ip112&amp;quot; ip=&amp;quot;127.0.0.1&amp;quot; rp=&amp;quot;false&amp;quot; phase=&amp;quot;update&amp;quot; environments=&amp;quot;sifi, 172net&amp;quot; certstat=&amp;quot;either certificate handling or state tracking not enabled - not doing any certificate checking&amp;quot; hwid=&amp;quot;IP222-46-5c-77&amp;quot; realip=&amp;quot;172.16.80.241&amp;quot; requestDownloaded=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;firmware requested=&amp;quot;130986&amp;quot; requested-at=&amp;quot;1522065435&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;bootcode requested-at=&amp;quot;1522065435&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;config filename=&amp;quot;scripts/all-all-all.txt&amp;quot; delivered=&amp;quot;1522065426&amp;quot; version=&amp;quot;1486559970&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/state&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The most interesting elements in this XML are probably the attributes of the &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;device&amp;lt;/code&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
== Optional Configurations on the Linux Application Platform ==&lt;br /&gt;
===Support for more Connections===&lt;br /&gt;
By default the LAP&#039;s web server lighttpd allows for 512 concurrent connections with 1024 open file descriptors.  When you serve a huge number of devices with the update server, then this might be too low.  You will see some devices not being able to contact the update server for a while.  This should not be a real issue as the devices will retry.  However, updating all devices may take long due to this.&lt;br /&gt;
&lt;br /&gt;
In the lighttpd log (in &amp;lt;code&amp;gt;/var/log/lighttpd&amp;lt;/code&amp;gt; on the LAP), you will see entries like this:&lt;br /&gt;
&lt;br /&gt;
 2017-10-16 13:45:18: (network_linux_sendfile.c.140) open failed:  Too many open files &lt;br /&gt;
 2017-10-16 13:45:18: (mod_fastcgi.c.3075) write failed: Too many open files 24 &lt;br /&gt;
 2017-10-16 13:45:18: (server.c.1434) [note] sockets disabled, out-of-fds &lt;br /&gt;
 2017-10-16 16:23:25: (response.c.634) file not found ... or so:  Too many open files /mtls/updatev2/web/innovaphone_logo_claim_fisch.png -&amp;gt;&lt;br /&gt;
 2017-10-16 17:57:45: (server.c.1432) [note] sockets disabled, connection limit reached &lt;br /&gt;
&lt;br /&gt;
If you experience such issues, proceed as follows:&lt;br /&gt;
&lt;br /&gt;
* connect to the LAP with SFTP (e.g. using WinSCP)&lt;br /&gt;
* change directory to &amp;lt;code&amp;gt;/etc/lighttpd&amp;lt;/code&amp;gt;&lt;br /&gt;
* edit &amp;lt;code&amp;gt;lighttpd.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
* search for the 2 lines which set &amp;lt;code&amp;gt;server.max-fds&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;server.max-connections&amp;lt;/code&amp;gt;&lt;br /&gt;
* replace the standard values.  We recommend to set the number of file descriptors to 4 times the number of requests when using the update server, e.g. &lt;br /&gt;
: old&lt;br /&gt;
:: server.max-fds             = 1024&lt;br /&gt;
:: server.max-connections     =  512&lt;br /&gt;
: new&lt;br /&gt;
:: server.max-fds             = 8000&lt;br /&gt;
:: server.max-connections     =  2000&lt;br /&gt;
* save the file&lt;br /&gt;
* restart linux (&#039;&#039;Diagnostics/Reset/Reboot&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Be sure to closely monitor the &#039;&#039;Diagnostics/Status&#039;&#039; page for a while after such configuration.  &lt;br /&gt;
&lt;br /&gt;
Also, when you update the LAP, you will have to re-do the changes (as always when you change something &#039;&#039;under the hood&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Debug files rotation based on logrotate ===&lt;br /&gt;
If you have to debug during operation and a lot of devices access the PHP Update Server V2, you have to keep track of the debug files or automatically limit them. For this you can use logrotate on the innovaphone Linux AP. With logrotate you can apply time-based or size-based rules when files are packed and when they are deleted.&lt;br /&gt;
* open the LAP&#039;s file system using a SFTP client such as e.g. [https://winscp.net/eng/index.php WinSCP] (if you have not yet changed it, the default credentials will be &amp;lt;code&amp;gt;root/iplinux&amp;lt;/code&amp;gt;, see [[Reference10:Concept_Linux_Application_Platform#Default_Credentials | Concept Linux Application Platform]]). Note that you must use SFTP rather than WebDAV, as WebDAV will not give access to the executable web server files. &lt;br /&gt;
* Under the path &amp;lt;code&amp;gt;/etc/logrotate.d&amp;lt;/code&amp;gt; create a file e.g. &amp;lt;code&amp;gt;updateserver&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/etc/logrotate.d/updateserver&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this file now enter the following content and save it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 /var/www/innovaphone/mtls/update/debug/*.txt {&lt;br /&gt;
 size 5M&lt;br /&gt;
 missingok&lt;br /&gt;
 rotate 2&lt;br /&gt;
 compress&lt;br /&gt;
 delaycompress&lt;br /&gt;
 notifempty&lt;br /&gt;
 create 644 www-data www-data&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will include all *.txt files from the debug directory of the PHP Update Server V2 in the logrotate process of the operating system.&lt;br /&gt;
&lt;br /&gt;
; size 5M : means every 5MB the file is rotated or zipped&lt;br /&gt;
; size 5k : means every 5kB the file is rotated or zipped&lt;br /&gt;
Alternatively, you can also rotate the file based on time&lt;br /&gt;
; daily : means that every day the file is rotated or zipped&lt;br /&gt;
; weekly : means that the file is rotated or zipped daily&lt;br /&gt;
&lt;br /&gt;
; missingok : if a debug file does not exist, it will be ignored&lt;br /&gt;
; rotate n : files are removed before the last ones are deleted.&lt;br /&gt;
; compress : compresses the old debug files&lt;br /&gt;
; delaycompress : compresses the debug data only after it has been moved once&lt;br /&gt;
; notifempty : empty log files are not rotated&lt;br /&gt;
; create 644 www-data www-data : creates a new, empty debug file with appropriate permissions&lt;br /&gt;
&lt;br /&gt;
== Update Server and Reverse Proxy ==&lt;br /&gt;
It is possible to implement access to the update server through a &#039;&#039;reverse proxy&#039;&#039; (RP).  However, you have to keep some issues in mind:&lt;br /&gt;
* &#039;&#039;Mutual Transport Layer Security&#039;&#039; (MTLS) is not possible&lt;br /&gt;
: MTLS requires a direct TLS connection between the two parties. An RP however would terminate the TLS connection and entertain two independent connections to the parties.  This breaks MTLS.  If you want to use MTLS and serve external clients, you must therefore provide a direct access to the update server (that is an external IP address either directly or through port forwarding)&lt;br /&gt;
: see [[#If_you_want_to_setup_MTLS-restricted_Delivery_of_Update_Scripts]] for details&lt;br /&gt;
* When using the RP, you can choose to forward encrypted traffic (HTTPS) arriving from external to the update server using HTTP (unencrypted). The update server however eventually rewrites the update URL in the calling devices configuration.  In order to do this, it determines the type of the internal connection.  So if the connection from the RP to the update server is using HTTP, it would create a &#039;&#039;http://...&#039;&#039; URL.  Otherwise it would create an &#039;&#039;https://..&#039;&#039; URL (also, it would be using the same port). This way, if the RP forwards requests to the update server with HTTP, the synthesized new URL for the calling client would use HTTP too, even though the original request was sent with HTTPS.  This may or may not be what you want (as all of your clients would end up using non-encrypted traffic). Even worse, it might not work at all, if the RP does not accept HTTP for example.&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
* [[Reference10:Concept_Update_Server]]&lt;br /&gt;
* [[Reference12r1:DHCP_client]]&lt;br /&gt;
* [[Reference10:Concept_Linux_Application_Platform]]&lt;br /&gt;
* [[Reference10:Concept_Provisioning]]&lt;br /&gt;
* [[Howto:PHP_based_Update_Server]] (old version)&lt;br /&gt;
* [[Howto:Creating custom Certificates using a Windows Certificate Authority]]&lt;br /&gt;
* [[Howto:Effect arbitrary Configuration Changes using a HTTP Command Line Client or from an Update]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:Multiple_faxserver_instances_sharing_a_FAX_interface&amp;diff=48223</id>
		<title>Howto:Multiple faxserver instances sharing a FAX interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:Multiple_faxserver_instances_sharing_a_FAX_interface&amp;diff=48223"/>
		<updated>2017-10-30T12:36:32Z</updated>

		<summary type="html">&lt;p&gt;Odawid: /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains the configuration of multiple faxserver instances of the [[Reference10:Concept_Faxserver | innovaphone fax]] solution using the same FAX Interface at an Innovaphone Gateway.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
In case you have multiple faxserver instances but just a single FAX Interface and those faxserver instances should share this FAX Interface you might run into the problem of receiving the error message “sfftobmp failed, exit code 2”. This wiki article should explain how to salvage the situation.&lt;br /&gt;
&lt;br /&gt;
== Applies To ==&lt;br /&gt;
This information applies to the Linux application [[Reference10:Concept_Faxserver | innovaphone Fax]] V10 and innovaphone firmware V10 and later.&lt;br /&gt;
&lt;br /&gt;
== Configuration==&lt;br /&gt;
First of all let’s take a look at the Linux AP. In my case I have three different faxserver instances.&lt;br /&gt;
&lt;br /&gt;
[[Image:Multiple faxserver - one FAX interface 1.png]]&lt;br /&gt;
&lt;br /&gt;
Each faxserver instance is monitoring a different faxserver gateway object in the PBX. In the case of the screenshot it’s the Faxserver1 gateway object.&lt;br /&gt;
&lt;br /&gt;
[[Image:Multiple faxserver - one FAX interface 2.png]]&lt;br /&gt;
&lt;br /&gt;
The next steps have to be done at the PBX. We need to create the corresponding faxserver gateway object. As you see in the screenshot they have an active internal registration. 3 different GW Interface are registered at those gateway object. (don’t forget to turn on T38).&lt;br /&gt;
&lt;br /&gt;
[[Image:Multiple faxserver - one FAX interface 3.png]]&lt;br /&gt;
&lt;br /&gt;
Furthermore the Query User (_TAPI_) needs to be active in the same group as the faxserver gateway objects.&lt;br /&gt;
The tricky part is done in the routing table as you can see in the screenshot. We are adding prefixes in the route to the FAX Interface and we are subtracting the prefix of the CGPN in the outbound route. Verify CGPN needs to be active to route those calls correctly.&lt;br /&gt;
&lt;br /&gt;
[[Image:Multiple faxserver - one FAX interface 4.png]]&lt;br /&gt;
&lt;br /&gt;
In the end don’t forget to set T38 or Audio FAX support at the FAX interface.&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
[[Reference10:Concept_Linux_Application_Platform | Reference: Linux Application Platform]]&lt;br /&gt;
&lt;br /&gt;
[[Reference10:Concept_Faxserver | Reference: Faxserver]]&lt;br /&gt;
&lt;br /&gt;
[[Howto:Step-by-step_faxserver_installation | Howto: Step-by-step faxserver installation]]&lt;br /&gt;
&lt;br /&gt;
[[Howto:Faxserver_with_Exchange | Howto: Faxserver with Exchange]]&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:A_rough_estimate_of_IPVA_Performance&amp;diff=32896</id>
		<title>Howto:A rough estimate of IPVA Performance</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:A_rough_estimate_of_IPVA_Performance&amp;diff=32896"/>
		<updated>2014-03-05T15:08:26Z</updated>

		<summary type="html">&lt;p&gt;Odawid: /* Releated Articles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* IPVA&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Keywords: performance,cycles,calculation,number of clients --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
===Problem Details===&lt;br /&gt;
In many projects, the potential performance of an IPVA running on a PC hardware needs to be calculated.  Here are some thoughts.&lt;br /&gt;
&lt;br /&gt;
Of course it all depends on what you are doing on the machine. So there is no easy answer to it.&lt;br /&gt;
&lt;br /&gt;
But, if you compare a PC-box to an IP6010, then&lt;br /&gt;
&lt;br /&gt;
* RAM on the 6010 is .5 Gig, so spend 1GB for an equivalent IPVA (so as to have room for overhead etc.)&lt;br /&gt;
* Flash is not an issue as it is mapped on disk space (which we probably have plenty of)&lt;br /&gt;
* leaving us with CPU. Just assume an IP6010 runs with 800MHz, a standard Quad Core runs on 2.66GHz. Assume it has really 4 independent cores (not just those pseudo-cores), then this amounts to 13 times the cycles of an IP6010&lt;br /&gt;
&lt;br /&gt;
Looking at the available CPU cycles, it looks as if we can run 13 IP6010 on a PC platform.  To be a little conservative and to account for overhead that may be caused by running mutliple IPVA on this one box (which may or may not be appropriate, depedning on your scenario), lets estimate the overall performance as 10 times an IP6010. Cross check: 1GB RAM times 10 is 10GB, fits in your PC RAM.&lt;br /&gt;
&lt;br /&gt;
One thing to take into account is that the innovaphone operating system is a single-processor OS.  So it will always run on a single CPU.  It is thus impossible to utilize 4 cores with a single IPVA.&lt;br /&gt;
&lt;br /&gt;
So here is your limit, &#039;&#039;if you utilize the full resources that a 6010 would give you&#039;&#039;, then you may run 10 VMWare instances where each of them does the job of a single IP6010.  Or, you can create 4 IPVAs with each 2.5 times the performance of an IP6010.  &lt;br /&gt;
&lt;br /&gt;
This of course is a little rough (as we compare Intel CISC and MIPS RISC CPU cycles here, we ignore memory performance, ...). But - given the fact that it is anyway a rough estimate as it really depends on the usage - it is good enough.&lt;br /&gt;
&lt;br /&gt;
Of course, we have left out some parameters, e.g. network performance and bandwidth.  Although you may use a PC box which has slightly better Ethernet performance than an IP6010, it will not be significant.  Assume even it is 50% better, this is nothing compared to the &#039;&#039;times 10&#039;&#039; factor we have otherwise.  So do we have a bandwidth problem?  Now, in a normal use-case, Ethernet bandwidth is simply not an issue, as call signalling (that&#039;s what a PBX does) is neglect-able from a bandwidth perspective.  However, if it comes to media streams, things are different.  Assume we have a media stream using G.722 or G.711, both use 64k net bandwidth per direction.  This makes for approximately 100k effectively (that is, including protocol overhead) for one direction.  Now let us do the maths:  an IP6010 has an 100Mb interface (full duplex, so 200Mb for both directions).  This is good for 1000 calls.  10 times more makes for 10000 calls.  Can we do this?  First of all, a PC box will sport a Gigabit interface, so yes, we could.  More important: no IP6010 will ever run 1000 parallel media streams (we recommend no more than 72), so the bottom line is: not an issue.&lt;br /&gt;
&lt;br /&gt;
So then, you could ask: is it better to run a single IPVA with huge memory or split it up in several smaller ones?  Well, good question!&lt;br /&gt;
The answer is: hmmm.&lt;br /&gt;
&lt;br /&gt;
There are limits to the sheer number of VMware instances on a single system, but they are changing.  So consult your VMware/VSphere documentation.  Otherwise, we recommend to base your decision on the usage scenario.  If it is benefitial to have multiple PBXs (e.g. cause you are supporting separate customers with distinct numbering plans), then do so.  If you merely think you should split up PBXs (e.g. in masters/slaves) cause you needed to do so when using IP6010, then no, you should not do so any more.  After all, having 2.5 times the performance of an IP6010, you may support a single PBX with 8.000 registered users on our reference PC, or a master and 3 slaves with a total of 32.000 users.  That should suffice for a while.  And no, we have not yet seen such an installation in practice...&lt;br /&gt;
&lt;br /&gt;
Finally, if you can run a single huge PBX, can you also run a huge number of small PBXs? Again, this mainly depends on the VMware platform.  According to the VMware documentation (this is based on VSphere 4.1), there is a limit of &#039;&#039;320 Virtual machines per host&#039;&#039;.  But there are other limits also (such as &#039;&#039;Virtual CPUs per core&#039;&#039; etc.).  Another approach is to consider that a single PBX should not have less CPU performance available than, say, half of an IP30x.  This would amount to 75MHz.  On our reference PC (2.66GHz times 4) this would indicate to run no more than 140 IPVAs.  This seems to be a reasonable load for VMware.&lt;br /&gt;
&lt;br /&gt;
=== Releated Articles ===&lt;br /&gt;
* [[Reference10:Concept Innovaphone Virtual Appliance]]&lt;br /&gt;
* [[Howto:Implement PBX with zero downtime using IPVA and VMWare Fault Tolerance]]&lt;br /&gt;
* [[Howto:Hosting]]&lt;br /&gt;
* [[Howto:How to implement large PBXs]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Reference9:Phone/Preferences&amp;diff=21276</id>
		<title>Reference9:Phone/Preferences</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Reference9:Phone/Preferences&amp;diff=21276"/>
		<updated>2011-06-08T12:58:55Z</updated>

		<summary type="html">&lt;p&gt;Odawid: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &#039;&#039;&#039;Background Image&#039;&#039;&#039;: Only on phones with colour display supported. A URL to a picture - in &#039;&#039;&#039;png&#039;&#039;&#039; format with the size of the Display  - stored at a web server (e.g CF card) must be entered. The IP241 and IP222 having a display size of 320px (width) and 240px (height). The IP232 has a display size of 480 x 272. &#039;&#039;&#039;Important is that you need a png file with exactly the size from the display. Otherwise the phone does not display the customized background.&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;No Call Transfer on Hook-On&#039;&#039;&#039;: By default going on hook or pressing the speaker or the headset key initiates a call transfer when there exist both an active call and a connected call on hold. If this checkmark is set both calls are released when going on hook. A call transfer can be initiated by the R-4 key sequence then (&#039;R&#039; (flash) key immediately followed by the digit 4). &lt;br /&gt;
* &#039;&#039;&#039;No Local Conference Tone&#039;&#039;&#039;: By default a conference tone is merged into conversation when a conference is established. Frequency, volume and pattern of this tone depend on the configured dial tone scheme. If this checkmark is set no conference tone is generated when the phone itself establishes a conference. &lt;br /&gt;
* &#039;&#039;&#039;No Local Intrusion Tone&#039;&#039;&#039;: By default an intrusion tone is generated to notify the user about a call intrusion. If this checkmark is set no intrusion tone is generated the phone itself.&lt;br /&gt;
* &#039;&#039;&#039;Display Name on Pickup/Partner Key&#039;&#039;&#039;: By default the number of the calling/called/connected party is displayed in the label field of a partner or pickup function key. If this checkmark is set the &#039;Name&#039; attribute from the PBX user object (if available) is displayed instead.&lt;br /&gt;
* &#039;&#039;&#039;Start Outbound Call on Electronic Hook Switch (EHS) Signal&#039;&#039;&#039;: A wireless headset usually has an Electronic Hook Switch button. If the base station of the headset is attached to the phone via the DHSG interface the phone receives a hook switch signal whenever the button is pressed. By default this signal is ignored when the phone is in idle mode. When sitting in front of phone it&#039;s quite inconvenient to set up a call by pressing this button, when being far from phone no digits can be dialled. But in some cases it can be useful to set up a call, for example when the phone is configured for direct dialling. If this checkmark is set the Electronic Hook Switch Signal will set up an outbound call when the phone is in idle mode.&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Freeedit:Wiki_Edit_Sandbox&amp;diff=17896</id>
		<title>Freeedit:Wiki Edit Sandbox</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Freeedit:Wiki_Edit_Sandbox&amp;diff=17896"/>
		<updated>2010-06-10T17:39:32Z</updated>

		<summary type="html">&lt;p&gt;Odawid: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a dummy article to safely try editing wiki articles.&lt;br /&gt;
&lt;br /&gt;
Marc Bau &#039;&#039;&#039;Voxtron&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Burbuqe Kadriu &#039;&#039;&#039;EFG Financial Products AG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Michael Scheer &#039;&#039;&#039;Innovaphone AG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Patrick Montaine &#039;&#039;&#039;Ball Packaging Europe&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Christoph Anhorn- &#039;&#039;&#039;swisspro AG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Wiki Syntax ([[Help:Formatting|more about formatting]], [[Help:Contents|generic help]]): = &lt;br /&gt;
&lt;br /&gt;
Italic &#039;&#039;word&#039;&#039;: &amp;lt;code&amp;gt;&#039;&#039;word&#039;&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Bold &#039;&#039;&#039;word&#039;&#039;&#039;: &amp;lt;code&amp;gt;&#039;&#039;&#039;word&#039;&#039;&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:Indented line: &amp;lt;code&amp;gt;:line&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# numbered list item: &amp;lt;code&amp;gt;# list item&amp;lt;/code&amp;gt;&lt;br /&gt;
## numbered list sub item: &amp;lt;code&amp;gt;## list item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* dotted list item: &amp;lt;code&amp;gt;* list item&amp;lt;/code&amp;gt;&lt;br /&gt;
** dotted list sub item: &amp;lt;code&amp;gt;** list item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
hidden search tag: &amp;lt;!-- hiddensearchtag --&amp;gt; &amp;lt;code&amp;gt;&amp;amp;lt;!-- hiddensearchtag --&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Play Arena =&lt;br /&gt;
&amp;lt;!-- ************************************************ Edit below this line ************************************************ --&amp;gt;&lt;br /&gt;
Mathias Kropf, &#039;&#039;&#039;Ascom Deutschland&#039;&#039;&#039;&amp;lt;br&amp;gt; &lt;br /&gt;
Dirk Pedina, &#039;&#039;&#039;Telekommunikation Mittleres Ruhrgebiet GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Andre Lippitz, &#039;&#039;&#039;Sec Com GmbH Recklinghausen&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Manfred Mauler, &#039;&#039;&#039;ACP IT Solutions GmbH, Innsbruck&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Christoph Nyffenegger, &#039;&#039;&#039;Ascom Schweiz AG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
John Larsen &#039;&#039;&#039;Ascom Denmark A/S&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Johann Kiss, &#039;&#039;&#039;Triple AcceSSS IT GmbH, Austria&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marco Koch, &#039;&#039;&#039;Wrocklage Intermedia GmbH Germany&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Frank Schneebeck, &#039;&#039;&#039;ETe Datentechnik GmbH Germany&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Christoph Hanken, Paragon Data GmbH&lt;br /&gt;
Jonas Teckentrup, Paragon Data GmbH&lt;br /&gt;
Porretta Mauro, &#039;&#039;&#039;SARTE S.p.A. Italy&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Kevin Edmonds, &#039;&#039;&#039;Consult Partner GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Karsten Otto, &#039;&#039;&#039;westko network service GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Arne Stark, &#039;&#039;&#039;westko network service GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Henk Schuurman, &#039;&#039;&#039;Soft Solutions&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marko Röhncke, &#039;&#039;&#039;Kevag-Telekom GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Kristijan Fabina, &#039;&#039;&#039;Datentechnik d.o.o.&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Dirk Lange, &#039;&#039;&#039;Nachrichtentechnik Bielefeld GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Ludwig Kempter, &#039;&#039;&#039;LEWTelNet GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Sakari Aaltonen, &#039;&#039;&#039;DigiCenter&#039;&#039;&#039;&amp;lt;BR&amp;gt;&lt;br /&gt;
Jukka Somiska, &#039;&#039;&#039;Daimler Finland&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Gisbert Cremerius, &#039;&#039;&#039;Hack-Attack&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Massimiliano Tamaro &#039;&#039;&#039;Test s.p.a Italy&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marco Boschi &#039;&#039;&#039;Eksaip Vicenza&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Stig Aune, &#039;&#039;&#039;Stig Aune Consulting&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Sandro Haas, &#039;&#039;&#039;KufGem EDV GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Daniel Haidacher, &#039;&#039;&#039;KufGem EDV GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marc Steiner, &#039;&#039;&#039;Inikon AG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Johan de Jong, &#039;&#039;&#039;trizwo GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
René Scholz, &#039;&#039;&#039;Ascom&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Rocco Schmidt, &#039;&#039;&#039;ATS Ascom&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marcel Britten, &#039;&#039;&#039;Connect GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Hans-Joachim Haun, &#039;&#039;&#039;VB OLD&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marco Falger, &#039;&#039;&#039;Koch Media GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Swen Angelstein,&#039;&#039;&#039;ST.AG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Arne Schmidt, &#039;&#039;&#039;TELCAT Multicom GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Liang Zhang, &#039;&#039;&#039;Koch Media GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Dirk-Jan van Dalen, &#039;&#039;&#039;Telematch BV&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Edwin Lansbergen, &#039;&#039;&#039;Telematch BV&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Benjamin Köhler, &#039;&#039;&#039;iits GmbH &amp;amp; Co. KG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Christian Bengtsson, &#039;&#039;&#039;COBS AB. Sweden&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Sebastian Lutz, &#039;&#039;&#039;Oberberg-Online Informationssysteme GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Paul Schrok, &#039;&#039;&#039;Ascom Suisse SA&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Andreas Moser, &#039;&#039;&#039;EFG Financial Products AG&#039;&#039;&#039; &amp;lt;br/&amp;gt;&lt;br /&gt;
Paul Schrok, &#039;&#039;&#039;Ascom Suisse SA&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Dennis Moller &#039;&#039;&#039;Ascom Denmark&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Andre Pooschke &#039;&#039;&#039;Fundamental Consulting GmbH &amp;amp; Co. KG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Roman Pietrowski &#039;&#039;&#039;Bohnen Computer-Technik GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Oliver Dawid &#039;&#039;&#039;ComNet GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Freeedit:Wiki_Edit_Sandbox&amp;diff=17895</id>
		<title>Freeedit:Wiki Edit Sandbox</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Freeedit:Wiki_Edit_Sandbox&amp;diff=17895"/>
		<updated>2010-06-10T17:38:38Z</updated>

		<summary type="html">&lt;p&gt;Odawid: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a dummy article to safely try editing wiki articles.&lt;br /&gt;
&lt;br /&gt;
Marc Bau &#039;&#039;&#039;Voxtron&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Burbuqe Kadriu &#039;&#039;&#039;EFG Financial Products AG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Michael Scheer &#039;&#039;&#039;Innovaphone AG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Patrick Montaine &#039;&#039;&#039;Ball Packaging Europe&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Christoph Anhorn- &#039;&#039;&#039;swisspro AG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Oliver Dawid &#039;&#039;&#039;ComNet GmbH&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Wiki Syntax ([[Help:Formatting|more about formatting]], [[Help:Contents|generic help]]): = &lt;br /&gt;
&lt;br /&gt;
Italic &#039;&#039;word&#039;&#039;: &amp;lt;code&amp;gt;&#039;&#039;word&#039;&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Bold &#039;&#039;&#039;word&#039;&#039;&#039;: &amp;lt;code&amp;gt;&#039;&#039;&#039;word&#039;&#039;&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:Indented line: &amp;lt;code&amp;gt;:line&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# numbered list item: &amp;lt;code&amp;gt;# list item&amp;lt;/code&amp;gt;&lt;br /&gt;
## numbered list sub item: &amp;lt;code&amp;gt;## list item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* dotted list item: &amp;lt;code&amp;gt;* list item&amp;lt;/code&amp;gt;&lt;br /&gt;
** dotted list sub item: &amp;lt;code&amp;gt;** list item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
hidden search tag: &amp;lt;!-- hiddensearchtag --&amp;gt; &amp;lt;code&amp;gt;&amp;amp;lt;!-- hiddensearchtag --&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Play Arena =&lt;br /&gt;
&amp;lt;!-- ************************************************ Edit below this line ************************************************ --&amp;gt;&lt;br /&gt;
Mathias Kropf, &#039;&#039;&#039;Ascom Deutschland&#039;&#039;&#039;&amp;lt;br&amp;gt; &lt;br /&gt;
Dirk Pedina, &#039;&#039;&#039;Telekommunikation Mittleres Ruhrgebiet GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Andre Lippitz, &#039;&#039;&#039;Sec Com GmbH Recklinghausen&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Manfred Mauler, &#039;&#039;&#039;ACP IT Solutions GmbH, Innsbruck&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Christoph Nyffenegger, &#039;&#039;&#039;Ascom Schweiz AG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
John Larsen &#039;&#039;&#039;Ascom Denmark A/S&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Johann Kiss, &#039;&#039;&#039;Triple AcceSSS IT GmbH, Austria&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marco Koch, &#039;&#039;&#039;Wrocklage Intermedia GmbH Germany&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Frank Schneebeck, &#039;&#039;&#039;ETe Datentechnik GmbH Germany&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Christoph Hanken, Paragon Data GmbH&lt;br /&gt;
Jonas Teckentrup, Paragon Data GmbH&lt;br /&gt;
Porretta Mauro, &#039;&#039;&#039;SARTE S.p.A. Italy&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Kevin Edmonds, &#039;&#039;&#039;Consult Partner GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Karsten Otto, &#039;&#039;&#039;westko network service GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Arne Stark, &#039;&#039;&#039;westko network service GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Henk Schuurman, &#039;&#039;&#039;Soft Solutions&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marko Röhncke, &#039;&#039;&#039;Kevag-Telekom GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Kristijan Fabina, &#039;&#039;&#039;Datentechnik d.o.o.&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Dirk Lange, &#039;&#039;&#039;Nachrichtentechnik Bielefeld GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Ludwig Kempter, &#039;&#039;&#039;LEWTelNet GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Sakari Aaltonen, &#039;&#039;&#039;DigiCenter&#039;&#039;&#039;&amp;lt;BR&amp;gt;&lt;br /&gt;
Jukka Somiska, &#039;&#039;&#039;Daimler Finland&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Gisbert Cremerius, &#039;&#039;&#039;Hack-Attack&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Massimiliano Tamaro &#039;&#039;&#039;Test s.p.a Italy&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marco Boschi &#039;&#039;&#039;Eksaip Vicenza&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Stig Aune, &#039;&#039;&#039;Stig Aune Consulting&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Sandro Haas, &#039;&#039;&#039;KufGem EDV GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Daniel Haidacher, &#039;&#039;&#039;KufGem EDV GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marc Steiner, &#039;&#039;&#039;Inikon AG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Johan de Jong, &#039;&#039;&#039;trizwo GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
René Scholz, &#039;&#039;&#039;Ascom&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Rocco Schmidt, &#039;&#039;&#039;ATS Ascom&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marcel Britten, &#039;&#039;&#039;Connect GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Hans-Joachim Haun, &#039;&#039;&#039;VB OLD&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Marco Falger, &#039;&#039;&#039;Koch Media GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Swen Angelstein,&#039;&#039;&#039;ST.AG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Arne Schmidt, &#039;&#039;&#039;TELCAT Multicom GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Liang Zhang, &#039;&#039;&#039;Koch Media GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Dirk-Jan van Dalen, &#039;&#039;&#039;Telematch BV&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Edwin Lansbergen, &#039;&#039;&#039;Telematch BV&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Benjamin Köhler, &#039;&#039;&#039;iits GmbH &amp;amp; Co. KG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Christian Bengtsson, &#039;&#039;&#039;COBS AB. Sweden&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Sebastian Lutz, &#039;&#039;&#039;Oberberg-Online Informationssysteme GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Paul Schrok, &#039;&#039;&#039;Ascom Suisse SA&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Andreas Moser, &#039;&#039;&#039;EFG Financial Products AG&#039;&#039;&#039; &amp;lt;br/&amp;gt;&lt;br /&gt;
Paul Schrok, &#039;&#039;&#039;Ascom Suisse SA&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Dennis Moller &#039;&#039;&#039;Ascom Denmark&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Andre Pooschke &#039;&#039;&#039;Fundamental Consulting GmbH &amp;amp; Co. KG&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Roman Pietrowski &#039;&#039;&#039;Bohnen Computer-Technik GmbH&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Odawid</name></author>
	</entry>
</feed>