--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+# Makefile
+# David Rowe 1 Jan 2010
+#
+# Makefile for Mini Asterisk GUI
+#
+# 1/ Download files to development box for testing:
+#
+# usage: make HOST=test.machine.ip|hostname test
+# make HOST=192.168.1.150 test
+# make HOST=boris test
+#
+# 2/ Create static copy of web pages from HOST for static demo
+#
+# usage: make HOST=test.machine.ip static
+
+test:
+ scp cgi-bin/*.html cgi-bin/*.sh cgi-bin/*.pl cgi-bin/*.js cgi-bin/*.css \
+ cgi-bin/*.png root@$(HOST):/www
+ scp etc/asterisk/*.conf root@$(HOST):/etc/asterisk
+
+.PHONY : static
+static:
+ # generate static pages
+
+ rm -Rf static; mkdir static; cd static; \
+ wget -rEk --header="Cookie: loggedin=1" http://$(HOST)/phones.sh
+
+ # modify links to non-existent scripts on static demo
+
+ sed -i "s,http://$(HOST)/set_network.sh,network.sh.html," static/$(HOST)/network.sh.html
+ sed -i "s,http://$(HOST)/set_ring.sh,phones.sh.html," static/$(HOST)/phones.sh.html
+ sed -i "s,http://$(HOST)/set_voiplines.sh,voiplines.sh.html," static/$(HOST)/voiplines.sh.html
+ sed -i "s,url=login.sh,url=phones.sh.html," static/$(HOST)/logout.sh.html
+
+
--- /dev/null
+Mini Asterisk
+=============
+
+A simple, light weight GUI for Asterisk.
+
+image::/images/ip04/mini.png["Mini Asterisk Demo", link="mini/phones.sh.html"]
+
+Click on the screen shot above for an on line demo.
+
+[[intro]]
+Introduction
+------------
+
+Mini Asterisk is a simple Web GUI for Asterisk with comprehensive tool
+tip documentation and a learning curve of a few minutes. Analog ports
+and IP Phones are automatically detected, and no knowledge of Asterisk
+configuration is required.
+
+Mini Asterisk is "unfeatured" - many of the Asterisk options are not
+available. Instead it tries to make very basic, very common Asterisk
+installations fast and simple, for example:
+
+* An Asterisk server running on your home gateway/firewall/server.
+ You want to connect a few IP Phones and make cheap phones calls
+ using VOIP. An Asterisk distro on a CD is a possibility but you
+ don't want to dedicate a full PC just for Asterisk. You don't
+ really want to learn Asterisk dial plan syntax and yet another conf
+ file format.
+
+* A small office that already has an old analog phone system. You
+ want to keep your current analog lines for incoming calls, but use
+ IP Phones for handsets and VOIP for outgoing calls. You know enough
+ to set up a DSL router and don't want to rely on "the Phone Guy" or
+ "The Computer Guy" at $100/hr to maintain your phone system.
+
+* You are a "Phone Guy" who doesn't understand Linux and Asterisk but
+ you want to install IP-PBXes.
+
+[[why]]
+Why Another Asterisk GUI?
+-------------------------
+
+There are http://www.voip-info.org/wiki/view/Asterisk+GUI[a lot of
+Asterisk GUIs] out there already. So why do we need another one?
+
+Well I needed an Asterisk GUI that was very easy to use for the
+link:ip04.html[IP0X] family. Something that would lower
+the technical skill required to install and maintain an Asterisk Phone
+system. Something my wife and kids could use.
+
+The IP0X can't run a LAMP stack very well so the GUI had to be light
+weight.
+
+I was also interested in exploring the ease-of-use meme, as we have
+been discussing it a lot on the http://villagetelco.org[Village Telco]
+project. Just how easy can we make Asterisk to use? So I scratched
+the itch.
+
+Mini Asterisk has the following features that make it reasonably
+unique. They may be good or bad features depending on your point of
+view!
+
+* Mini Asterisk is "un-featured" - it hides many of the advanced
+ Asterisk features in the interest of simple and fast configuration.
+
+* Light weight so it can run on embedded boxes like the IP0X family.
+ No SQL database or PHP or LAMP. Only a basic web server and a very
+ basic Perl are required (microperl - no CPAN libraries).
+
+* Works directly on extensions.conf and sip.conf, but honors any edits
+ you make to these files. So all the powerful Asterisk features are
+ available if after a while you want to dive into Asterisk conf files.
+
+* Doesn't use AJAX or the built-in Asterisk web server or users.conf
+ magic. Plain old HTML, a little Java-script and CGIs written in
+ shell script and Perl.
+
+* Doesn't use the Asterisk programming model. For example you don't
+ have to understand what a dial plan is, much less understand how to
+ code one. Plain English terms are used instead, for example "Phones
+ and Phone lines". Terms like Asterisk, Linux, SIP, Zap/1 don't even
+ get mentioned.
+
+* Extensive tool tip documentation. No manual.
+
+* Doesn't require a dedicated PC, not installed from an ISO CD. So
+ you can use it as a GUI for Asterisk on a little SOHO Linux box that
+ is also your firewall, server etc.
+
+* Mini Asterisk tells you when something is wrong, for example you get
+ a warning if your Phone System can't see the Internet, or if it can't
+ see your ITSP.
+
+* Extensive pre-configuration of extensions.conf and sip.conf. The
+ phone numbers of extensions are pre-configured and ITSP
+ configurations are selected from a pull-down menu. Analog ports are
+ auto detected, at least on the IP0X. This makes adding phones and
+ ITSPs fast and simple. It also gives people new to Asterisk a
+ working starting point.
+
+[[status]]
+Status
+------
+
+Alpha:
+
+* Works on IP0X.
+* Works on x86 but many features (like upgrades) disabled in the
+ interests of security. These need to be implemented on x86 in a safe way.
+* Tested on asterisk 1.4.x
+* Needs feedback from real users to see how useful the concept is and what
+ (un)features need to be added.
+* Need a few more (un)features to be added, and Voip Line screen
+ populated with more ITSPs.
+* But quite useable as it stands, especially as a way to get started
+ quickly with the IP0X.
+
+[[notes]]
+Implementation Notes
+--------------------
+
+Mini Asterisk is written for the
+http://rowetel.com/ucasterisk/ip04.html[IP0X embedded Asterisk]
+hardware but will also run on x86 and probably many other platforms.
+
+Mini Asterisk has been written to be compatible with regular Asterisk
+conf file configuration. Just leave the conf file lines with
+"mini-asterisk" comments alone. The Asterisk conf files
+extensions.conf and sip.conf are directly modified by Mini Asterisk,
+but changes are limited to the "mini-asterisk" lines.
+
+For Auto-detection of Zap ports Mini Asterisk looks at
+/etc/zapata.conf, so you may need this set up correctly for your
+analog hardware. On the IP0X this happens automatically.
+
+The scripts need to run as root to run asterisk commands. This is
+probably OK an on IP0X but not a good idea on an x86. I am not happy
+with this security model and would appreciate any suggestions on how
+to improve it.
+
+Mini Asterisk uses the following technologies: HTML, CSS, Javascript,
+CGI, Shell scripting, Perl, Asterisk. But most of the work is done in
+shell script and HTML, with a little Perl for the text processing.
+
+The msh shell on the IP0X is fairly basic (no functions, several
+quirks). The shell script has been coded so that it runs OK on the
+IP0X, which is upwards compatible to x86.
+
+You can customise Mini Asterisk by adding your own banner to in
+banner.html.
+
+[[install]]
+Installation
+------------
+
+NOTE: this process may overwrite your Asterisk extensions.conf and
+sip.conf files - back them up if you have an existing Asterisk
+installation that you want to keep. The IP0X ipkg does attempt to
+backup the modified conf files to *.bak but no guarantees....
+
+However once mini-asterisk is installed it should honor any manual
+changes made to extensions.conf and sip.conf.
+
+IP0X Installation
+~~~~~~~~~~~~~~~~~
+
+Installation instructions for IP0X boxes running link:baps.html[BAPS],
+with some version of Asterisk and Zaptel installed.
+
+-------------------------------------------------------------------
+root~> ipkg install mini-asterisk
+-------------------------------------------------------------------
+
+x86 Installation
+~~~~~~~~~~~~~~~~
+
+You need a web server, Asterisk and some sort of Perl installed
+(very basic Perl installation is fine). Configure your web server to
+run CGIs (.sh and .pl) from your server root. Lighttpd config
+instructions are below.
+
+Mini Asterisk expects all files (shell, perl, html etc) to be in the
+same directory. If you find this painful please <<support, let me know>>.
+
+The process below places the web files in /var/www, you may like to
+place the files somewhere else. One of the files is named index.html
+so make sure you don't overwrite an existing index.html.
+
+. Login as root.
+
+. If you haven't done so already install Asterisk 1.4.x:
++
+-------------------------------------------------------------------
+# wget http://downloads.asterisk.org/pub/telephony/asterisk/old-releases/asterisk-1.4.11.tar.gz
+# tar xvzf asterisk-1.4.11.tar.gz
+# cd asterisk-1.4.11
+# ./configure
+# make
+# make install
+# make samples
+-------------------------------------------------------------------
+
+. If you have a running Asterisk installation backup your existing
+extensions.conf & sip.conf in /etc/asterisk
+
+. Installation of Mini Asterisk is basically copying the cgi-bin and etc/asterisk
+files:
++
+-------------------------------------------------------------------
+# cd ~
+# svn co https://freetel.svn.sourceforge.net/svnroot/freetel/mini-asterisk-gui
+# cd mini-asterisk-gui
+# ./update_revision.sh
+# cp etc/asterisk/* /etc/asterisk
+# cp cgi-bin/* /var/www
+# cd /etc/asterisk
+# cp extensions.conf extensions.conf.def
+# cp sip.conf sip.conf.def
+# mv users.conf users.conf.bak
+-------------------------------------------------------------------
++
+The .def copies are required by the "reset defaults" feature on the
+admin screen.
+
+. It's a good idea to switch off the internal Asterisk web server by editing
+/etc/asterisk/http.conf. Make sure the enabled line reads like this:
++
+ enabled=no
++
+Then stop and restart Asterisk.
++
+-------------------------------------------------------------------
+# /etc/init.d/asterisk restart
+-------------------------------------------------------------------
+
+. I use lighttpd as the web server. To enable CGI support:
++
+-------------------------------------------------------------------
+# lighty-enable-mod cgi
+-------------------------------------------------------------------
++
+I then modified 10-cgi-conf to enable perl and shell scripts:
++
+-------------------------------------------------------------------
+cgi.assign = (
+ ".pl" => "/usr/bin/perl",
+ ".sh" => "/bin/sh",
+)
+-------------------------------------------------------------------
++
+Make sure lighttpd runs as root, as we need to run Asterisk etc from
+shell script CGIs:
++
+-------------------------------------------------------------------
+## change uid to <uid> (default: don't care)
+#server.username = "wwwrun"
+
+## change uid to <uid> (default: don't care)
+#server.groupname = "wwwrun"
+-------------------------------------------------------------------
++
+Then restart lighttpd after all the changes:
++
+--------------------------------------------------------------------
+# /etc/init.d/lighttpd restart
+------------------------------------------------------------------
++
+For comparison on the IP04 I just modified /etc/lighttpd.conf:
++
+-------------------------------------------------------------------
+cgi.assign = ( ".sh" => "/bin/sh",".pl" => "/usr/bin/perl" )
+-------------------------------------------------------------------
+
+[[contribute]]
+Contributions
+-------------
+
+. I especially welcome sip.conf entries for your favourite ITSP (VOIP
+service) to help populate the Provider field of the
+link:mini/voiplines.sh.html[Voip Line Screen].
+
+. Suggestions and patches for new features are also very welcome.
+
+. Help making the web pages look nicer.
+
+. Configuration instructions (even photos) for other IP phones.
+
+[[support]]
+Support
+-------
+
+Comments, features request, bugs please let me know using Free
+Telephony Project
+https://lists.sourceforge.net/lists/listinfo/freetel-discuss[Mailing
+List]
+
+[[source]]
+Source Code
+-----------
+
+Browse:
+
+http://freetel.svn.sourceforge.net/viewvc/freetel/mini-asterisk-gui/[http://freetel.svn.sourceforge.net/viewvc/freetel/mini-asterisk-gui/]
+
+Check Out:
+
+ $ svn co https://freetel.svn.sourceforge.net/svnroot/freetel/mini-asterisk-gui
+
+[[test]]
+Testing and debugging scripts
+-----------------------------
+
+. To download all the GUI scripts to an IP0X machine with the host name "ip04":
+
+ [david@bunny mini-asterisk-gui]$ make HOST=ip04 test
++
+
+However this is a bit slow. So when editing on an x86 host and testing
+on an IP0X I used the M-! command on Emacs that lets you execute a
+shell command. I use this to download just the single the shell file
+I am working on, e.g. "scp admin.sh root@ip04".
+
+. A simple cookie is used to indicate logged in status. To run
+ scripts for each screen from the command line (for example to spot
+ script syntax errors):
++
+IP0X:
++
+ root:/www> export HTTP_COOKIE="loggedin=1" ; sh admin.sh
++
+If you encounter a syntax error when testing a script on an IP0X
+then running the same script on an x86 can be useful as it has much
+better error reporting:
++
+x86:
++
+ [david@host cgi-bin]$ export HTTP_COOKIE="loggedin=1" ; sh admin.sh
+
+. If running using the sh command you can also trace execution with
+ the "-x" option:
++
+ [david@host cgi-bin]$ sh -x login.sh
+
+. Testing forms from the command line can be achieved by manually
+setting up the CGI QUERY_STRING environment variable:
++
+ [david@host cgi-bin]$ export QUERY_STRING="pass=uClinux" ; sh login.sh
--- /dev/null
+#!/bin/sh
+# about.sh
+# David Rowe 7 Jan 2010
+# About screen for Mini Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+cat << EOF
+<html>
+<title>Mini Asterisk - About</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <table align="right" width=600>
+ <tr><td align="left" valign="top"><h2>About</h2></td></tr>
+EOF
+echo ' <tr><td><a href="http://rowetel.com/ucasterisk/mini.html">Mini Asterisk</a> Revision: 156 </td></tr> '
+echo ' <tr><td> </td></tr>'
+echo ' <tr><td>Brought to you by the <a href="http://rowetel.com/ucasterisk/index.html">Free Telephony Project</a></td></tr>'
+echo ' <tr><td><a href="http://rowetel.com/ucasterisk/ip04.html"><img src="http://rowetel.com/images/ip04/ip04_case.jpg" border="0" /></a></td></tr>'
+
+more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
+if [ $more -eq 1 ]; then
+ echo
+else
+ echo " <tr><td> </td></tr>"
+ echo ' <tr><td><a href="about.sh?more=1">More</a></td></tr>';
+cat <<EOF
+ </table>
+ </td>
+ </tr>
+</table>
+</body>
+</html>
+EOF
+exit
+fi
+
+echo " <tr><td> </td></tr>"
+echo " <tr><td><h3>cat /proc/version</h3></td></tr>"
+echo " <tr><td>"
+cat /proc/version
+echo " </td></tr>"
+
+which ipkg >> /dev/null
+if [ $? -eq 0 ]; then
+ echo " <tr><td> </td></tr>"
+ echo " <tr><td><h3>ipkg list_installed</h3></td></tr>"
+ echo " <tr><td>"
+ ipkg list_installed | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+ echo " </td></tr>"
+fi
+
+echo " <tr><td> </td></tr>"
+echo " <tr><td><h3>cat /proc/loadavg</h3></td></tr>"
+echo " <tr><td>"
+cat /proc/loadavg
+echo " </td></tr>"
+
+echo " <tr><td> </td></tr>"
+echo " <tr><td><h3>uptime</h3></td></tr>"
+echo " <tr><td>"
+uptime
+echo " </td></tr>"
+
+echo " <tr><td> </td></tr>"
+echo " <tr><td><h3>cat /proc/meminfo</h3></td></tr>"
+echo " <tr><td>"
+cat /proc/meminfo | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+echo " </td></tr>"
+
+echo " <tr><td> </td></tr>"
+echo " <tr><td><h3>cat /proc/cmdline</h3></td></tr>"
+echo " <tr><td>"
+cat /proc/cmdline
+echo " </td></tr>"
+
+echo " <tr><td> </td></tr>"
+echo " <tr><td><h3>cat /proc/cpuinfo</h3></td></tr>"
+echo " <tr><td>"
+cat /proc/cpuinfo
+echo " </td></tr>"
+
+if [ -f /proc/mtd ]; then
+ echo " <tr><td> </td></tr>"
+ echo " <tr><td><h3>cat /proc/mtd</h3></td></tr>"
+ echo " <tr><td>"
+ cat /proc/mtd | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+ echo " </td></tr>"
+fi
+
+if [ -f /proc/yaffs ]; then
+ echo " <tr><td> </td></tr>"
+ echo " <tr><td><h3>cat /proc/yaffs</h3></td></tr>"
+ echo " <tr><td>"
+ cat /proc/yaffs | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+ echo " </td></tr>"
+fi
+
+echo " <tr><td> </td></tr>"
+echo ' <tr><td><a href="about.sh">Less</a></td></tr>';
+
+cat <<EOF
+ </table>
+
+ </td>
+
+ </tr>
+
+</table>
+</body>
+</html>
+EOF
+
--- /dev/null
+#!/bin/sh
+# admin.sh
+# David Rowe 7 Jan 2010
+# Admin screen for Mini Asterisk GUI
+
+# check we are logged in ----------------------------------------
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# check what sort of machine we are running on. Many operations
+# outlawed for x86
+
+cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
+if [ $? -eq 0 ]; then
+ mach="ip0x"
+else
+ mach="x86"
+fi
+
+# set password CGI -----------------------------------------------
+
+echo "$QUERY_STRING" | grep -oe "pass=" > /dev/null
+if [ $? -eq 0 ]; then
+ if [ $mach != "ip0x" ] ; then
+ echo "<html>Sorry, only supported on the IP0X</html>"
+ exit
+ fi
+
+ pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
+ passwd_cmdline $pass
+fi
+
+# restart CGI ----------------------------------------------------
+
+echo "$QUERY_STRING" | grep -oe "restart=1" > /dev/null
+if [ $? -eq 0 ]; then
+
+ if [ $mach != "ip0x" ] ; then
+ echo "<html>Sorry, only supported on the IP0X</html>"
+ exit
+ fi
+
+# kill cookie to log out. This ensures hitting refresh wont run
+# the restart process again
+
+cat <<EOF
+Content-type: text/html
+Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
+
+<head>
+<title>Mini Asterisk - Restart</title>
+</head>
+<body>
+<h2>Restarting...come back in 1 minute</h2>
+</body>
+EOF
+reboot
+fi
+
+# set defaults CGI ----------------------------------------------------
+
+echo "$QUERY_STRING" | grep -oe "defaults=1" > /dev/null
+if [ $? -eq 0 ]; then
+ cp /etc/asterisk/extensions.conf.def /etc/asterisk/extensions.conf
+ cp /etc/asterisk/sip.conf.def /etc/asterisk/sip.conf
+ asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
+ asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
+fi
+
+# Upgrade Mini Asterisk CGI -------------------------------------------
+
+echo "$QUERY_STRING" | grep -oe "upgrade=1" > /dev/null
+if [ $? -eq 0 ]; then
+
+ # test if we are running on an IP0X
+ which ipkg >> /dev/null
+ if [ $? -eq 1 ]; then
+ echo "<html>Sorry, only supported on the IP0X</html>"
+ exit
+ fi
+
+ cat <<EOF
+ <html>
+ <head>
+ <title>Mini Asterisk - Upgrade</title>
+ </head>
+ <body>
+ <h2>Upgrading...</h2>
+EOF
+
+ rev_before=`grep -oe "Revision: [0-9]*" /www/about.sh`
+ echo "<strong>Current $rev_before</strong><br>"
+ echo "<strong>Removing $ver_before</strong><br>"
+ ipkg remove mini-asterisk-gui | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+ echo "<strong>Installing...</strong><br>"
+ ipkg update | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+ ipkg install mini-asterisk-gui | tr '\n' '#' | sed -n 's/\#/<br>/pg'
+
+ # Note - never actually gets here as admin.sh is wiped out by upgrade..
+ # need a better way of handling this....
+
+ rev_after=`grep -oe "Revision: [0-9]*" /www/about.sh`
+ echo "<strong>$rev_after installed</strong>"
+ echo "</body></html>"
+ exit
+fi
+
+# Install New Firmware CGI ----------------------------------------------------
+# this is just a nasty option to run an arbitrary script as root!
+# not a good idea on x86 platforms...but a nice way of upgrading IP0X
+
+echo "$QUERY_STRING" | grep -oe "firmwareurl=" > /dev/null
+if [ $? -eq 0 ]; then
+
+ if [ $mach != "ip0x" ] ; then
+ echo "<html>Sorry, only supported on IP0X</html>"
+ exit
+ fi
+
+ firmwareurl=`echo "$QUERY_STRING" | grep -oe "firmwareurl=[^&?]*" | sed -n "s/firmwareurl=//p"`
+ # convert URL encoded string, this can just handle : and / so be careful
+ # with script names
+ firmwareurl=`echo $firmwareurl | sed -e "s/%3A/:/" -e "s_%2F_/_g"`
+ wget $firmwareurl
+ filename=`echo $firmwareurl | sed 's_^.*/__'`
+ sh $filename
+ exit
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+cat << EOF
+<html>
+<title>Mini Asterisk - Admin</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <table align="right" width=600>
+ <tr><td> </td></tr>
+ <form action="admin.sh" method="get">
+ <tr><td align="left" valign="top"><h2>Admin</h2></td></tr>
+
+ <tr><td> </td></tr>
+ <tr><td colspan="2"><h3>Change Phone System Password</h3></td></tr>
+ <tr><td>New Password:</td><td><input type="password" name="pass" ></td>
+ <td><input type="submit" value="Set Password"></td>
+ </tr>
+ <tr><td> </td></tr>
+ <tr><td></td><td>Default password is uClinux</td>
+ </form>
+
+ <tr><td> </td></tr>
+ <tr><td colspan="2"><h3>Restart Phone System</h3></td>
+ <td onMouseOver="popUp(event,'admin_restart')" onmouseout="popUp(event,'admin_restart')">
+ <form action="admin.sh" method="get">
+ <input type="hidden" name="restart" value="1">
+ <input type="submit" value="Restart">
+ </form>
+ </td>
+ </tr>
+
+ <tr><td> </td></tr>
+ <tr><td colspan="2"><h3>Reset Phone System Defaults</h3></td>
+ <td>
+ <form action="admin.sh" method="get">
+ <input type="hidden" name="defaults" value="1">
+ <input type="submit" value="Reset">
+ </form>
+ </td>
+ </tr>
+
+ <tr><td> </td></tr>
+ <tr onMouseOver="popUp(event,'admin_upgrade')" onmouseout="popUp(event,'admin_upgrade')">
+ <td colspan="2"><h3>Upgrade Mini Asterisk</h3></td>
+ <td>
+ <form action="admin.sh" method="get">
+ <input type="hidden" name="upgrade" value="1">
+ <input type="submit" value="Upgrade">
+ </form>
+ </td>
+ </tr>
+
+ <tr><td> </td></tr>
+ <tr><td colspan="2"><h3>Install New Firmware</h3>
+ <form action="admin.sh" method="get">
+ <tr onMouseOver="popUp(event,'admin_firmware')" onmouseout="popUp(event,'admin_firmware')">
+ <td>Firmware URL:</td>
+ <td><input type="text" size="45" name="firmwareurl" ></td>
+ <td><input type="submit" value="Install"></td>
+ </tr>
+ </form>
+
+ </table>
+ </form>
+
+ </td>
+
+ </tr>
+
+</table>
+</body>
+</html>
+EOF
+
--- /dev/null
+<ol>
+<li>Connect the WAN port of the AT-530 to your network, it will boot and obtain an IP via DHCP.
+<li>Find the <strong>IP</strong> of the phone by pressing the <strong>Sysinfo</strong> button a few times.
+<li>Open another browser window. Go to the phones <strong>IP</strong>, for example <strong>http://192.168.1.160</strong>
+<li>Login to the phone using the username/password <strong>admin/admin</strong>.
+<li>Optional: set a static IP using the WAN menu (I like static IPs for SIP phones).
+<li>Go to the phone <strong>SIP Config</strong> menu.
+<li>Set <strong>Register Server Address</strong> to your Phone System IP Address.
+<li>Set <strong>Register Username</strong> to the phone number (e.g. 6011).
+<li>Also set </strong>Register Password</strong> to the phone number (e.g. 6011) and
+the </strong>Phone Number</strong> to the phone number (e.g. 6011).
+<li>Check the <strong>Enable Register</strong> box.
+<li>Then click on <strong>Apply</strong>.
+<li>On your browser refresh this page to see if the phone is connected to your phone system.
+</ol>
--- /dev/null
+<ol>
+
+<li>Connect the WAN port of the AT-620R to your network, it will boot and obtain an IP via DHCP.
+
+<li>Press the <strong>Menu</strong> button. Enter <strong>123</strong> for the password, and press the <strong>OK</strong> soft button.
+
+<li>Using the <strong>down</strong> direction button (just beneath the menu key) move to the <strong>Product Info</strong> menu. Then press the down button again and select <strong>Network Status</strong>. The IP of the phone will be displayed at the top of the screen, for example 192.168.1.160.
+
+<li>On your PC open another browser window. Go to the phones <strong>IP</strong>, for example <strong>http://192.168.1.160</strong>
+
+<li>Login to the phone using the username/password <strong>admin/admin</strong>.
+
+<li>Go to the phone <strong>VOIP</strong> menu.
+
+<li>Set <strong>Server Address</strong> to your Phone System IP Address.
+
+<li>Set <strong>Account Name</strong> to the phone number (e.g. 6011).
+
+<li>Also set </strong>Password</strong> to the phone number (e.g. 6011) and <strong>Phone Number</strong> and <strong>Display Name</strong> to the phone number (e.g. 6011).
+
+<img src="at-620r.png" />
+
+<li>Check the <strong>Enable Register</strong> box.
+
+<li>Then click on <strong>Apply</strong>.
+
+<li>On your browser refresh this page to see if the phone is connected to your phone system.
+</ol>
+
--- /dev/null
+ <tr><td colspan="2"><h2> </h2></td></tr>
--- /dev/null
+<ol>
+
+<li><strong>How do I set up my Phone system?</strong>
+ <ol>
+ <li> Hover your mouse to get instructions (try the menu to the left).</li>
+ <li> Analog Ports are detected automatically.</li>
+ <li> Set up your <a href="network.sh">Network</a>.</li>
+ <li> Add your <a href="ipphones.sh">IP Phones</a>.</li>
+ <li> Configure your <a href="voiplines.sh">Voip Line</a>.</li>
+ <li> The <a href="phones.sh">Phone System</a> page gives you a
+ summary of your phone system and tells you how to make calls
+ (hover your mouse).</li>
+ </ol>
+</li>
+
+<li><strong>Where can I find out more about Mini Asterisk:</strong> The <a href="http://rowetel.com/ucasterisk/mini.html">Mini Asterisk Home Page</a>.
+
+<li><strong>Where can I get Support:</strong> You can try the
+ <a href="https://lists.sourceforge.net/lists/listinfo/freetel-discuss">Free Telephony Project</a> Mailing List.
+
+<li><strong>Answer a call on another ringing phone</strong>: If you
+ hear another phone ringing and want to answer the call on your
+ phone, just pick up your phone and dial *8. Note an IP phone can
+ pick up a call on a ringing IP phone but not an Analog phone. An
+ Analog pohone can pick up another ringing Analog phone but not an
+ IP phone.
+
+<li><strong>Put a call on hold/transfer:</strong> On an IP Phone try
+ the recall or transfer button. On an Analog Phone hold down the
+ hook button for 1 second then dial the new number.
+
+<li><strong>Why another Asterisk GUI</strong> I had some specific
+ needs for a light weight, very easy to use GUI for
+ the <a href="http://www.rowetel.com/ucasterisk/ip04.html">IP0X</a>
+ line of products. So I scratched the itch. More
+ information <a href="http://www.rowetel.com/ucasterisk/mini.html#why">here</a>.
+
+</ol>
+
+<h2>Resources and Links</h2>
+<ol>
+<li>If you want to learn more about Asterisk a good on-line book is <a href="http://astbook.asteriskdocs.org">Asterisk - The Future of Telephony</a>
+</ol>
--- /dev/null
+#!/bin/sh
+# faq.sh
+# David Rowe 7 Jan 2010
+# FAQ screen for Mini Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+cat << EOF
+<html>
+<title>Mini Asterisk - FAQ</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <table align="right" width=600>
+ <tr><td align="left" valign="top"><h2>FAQ</h2></td></tr>
+ <tr><td>
+EOF
+cat faq.html
+cat <<EOF
+ </td></tr>
+ </table>
+
+ </td>
+
+ </tr>
+
+</table>
+</body>
+</html>
+EOF
+
--- /dev/null
+<html>
+<head>
+<meta http-equiv="REFRESH" content="0;url=http:login.sh">
+</head>
+</html>
\ No newline at end of file
--- /dev/null
+function localInit() {
+}
+
--- /dev/null
+#!usr/bin/perl
+# ipphones.pl
+# David Rowe 6 Jan 2010
+#
+# Text processing for the ipphones screen
+
+$ipaddress = $ARGV[0];
+$more = $ARGV[1];
+
+# Slurp up SIP extension (Sip) data from extensions.conf
+
+my %ip = (); # ip extension keyed on sip.conf name
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) {
+ if (/.*=>[ ]*([0-9]*),1.*SIP\/([0-9]*)\)/) {
+ $ip{$2} = $1;
+ #print "'$1' '$2' $ip{$2}\n";
+ }
+}
+close EXT;
+
+my %sip = (); # SIP IP phone status keyed on sip.conf names
+ # if no entry we can't see IP phone device
+my %voip = (); # SIP trunks status keyed on sip.conf names
+ # if no entry we can't see SIP trunk
+my %ipad = (); # IP address of SIP device keyed on sip.conf names
+
+open SIP, "sipshowpeers.txt";
+while (<SIP>) {
+ if (/^([0-9]*)[\s\/].*(OK)/) {
+ $sip{$1} = $2;
+ #print "'$1' '$2' $sip{$1}\n";
+ $e = $1;
+ if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ $ipad{$e} = $1;
+ #print "'$1'\n";
+ }
+ }
+ if (/^(voip[0-9]*)[\s\/].*(OK)/) {
+ $voip{$1} = $2;
+ #print "'$1' '$2' $voip{$1}\n";
+ $e = $1;
+ if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ $ipad{$e} = $1;
+ #print "'$1'\n";
+ }
+ }
+}
+
+close SIP;
+
+# print list of IP phones with connection status
+
+$unconnected = 0;
+foreach $e (sort keys %ip) {
+ if ($sip{$e} eq "OK") {
+ $icon = "<img src=\"tick.png\" alt=\"Connected\" />";
+ $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_connected')\" onmouseout=\"popUp(event,'ipphones_connected')\"";
+ $comment=$ipad{$e};
+ $tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
+ $tooltip_ip = "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
+ $unconnected = 0;
+ }
+ else {
+ $unconnected = $unconnected + 1;
+ $icon = "<img src=\"cross.png\" alt=\"Not Connected\" />";
+ $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_notconnected')\" onmouseout=\"popUp(event,'ipphones_notconnected')\"";
+ $comment="Available";
+ $tooltip_id = "iphones_$e";
+ print "<div id=\"$tooltip_id\" class=\"tip\"> Configure your IP phone with username/password $e/$e, SIP Server IP $ipaddress</div>";
+ $tooltip_ext = "onMouseOver=\"popUp(event,'$tooltip_id')\" onmouseout=\"popUp(event,'$tooltip_id')\"";
+ $tooltip_ip = "";
+ }
+
+ if ($more == 1 || ($unconnected < 5)) {
+ print "<tr><td $tooltip_ext>$e</td><td></td><td $tooltip_ip>$comment</td><td $tooltip_status>$icon</td></tr>\n";
+ }
+}
+
+if ($more == 0) {
+ print '<tr><td><a href="ipphones.sh?more=1">More</a></td></tr>';
+}
+else {
+ print '<tr><td><a href="ipphones.sh">Less</a></td></tr>';
+}
+
+
--- /dev/null
+#!/bin/sh
+# dashboard.sh
+# David Rowe 6 Jan 2010
+# Dashboard screen for Mini Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
+
+# Build list of interface IPs based on what sort of machine we are
+# running on. For IP0X we just print the IP of the first interface.
+# For other machines the situation is a bit more complex so we print
+# all of them. I figure anyone with multiple interfaces will know
+# enough about what they are doing to figure out the right one to use.
+
+ipaddress=`ifconfig | sed -n 's/.*inet addr:\(.*\) Bcast.*/\1/p'`
+
+cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
+if [ $? -eq 0 ]; then
+ ipaddress=`echo $ipaddress | awk '{ print $1 }'`
+ ipaddress_system=$ipaddress
+ ipaddress_tooltip=$ipaddress
+else
+ ipaddress_system=`echo $ipaddress | sed -n 's/ /<br>/p'`
+
+ # make nice tooltips for multiple ip interfaces on some x86 boxes
+
+ ipaddress_tooltip=`echo $ipaddress | sed -n 's/ / or /p'`
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+echo "<script>"
+echo 'var init_internet="'$internet'";'
+cat ipphones.js
+echo "</script>"
+
+cat << EOF
+<html>
+<title>Mini Asterisk - IP Phones</title>
+<body onload="localInit()">
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800 border=0>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <table align="right" width=600 border=0>
+ <tr><td onMouseOver="popUp(event,'ipphones_ipphones')" onmouseout="popUp(event,'ipphones_ipphones')"
+ colspan="4" align="left" valign="top" ><h2>IP Phones</h2></td></tr>
+ <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
+ <td colspan="3">Phone System IP Address:</td>
+EOF
+echo "<td>$ipaddress_system</td>"
+
+ # use perl to construct list of IP phones for us
+ asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
+ perl ipphones.pl "$ipaddress_tooltip" $more
+
+cat <<EOF
+ </table>
+
+ <h2> <br>How to Configure IP Phones</h2>
+ <h3>1. Atcom AT-530</h3>
+EOF
+cat at-530.html
+echo "<h3>2. Atcom AT-620R</h3>"
+cat at-620r.html
+cat <<EOF
+ </td>
+ </tr>
+
+</table>
+</body>
+</html>
+EOF
+
--- /dev/null
+#!/bin/sh
+# login.sh
+# David Rowe 4 Jan 2010
+# CGI for Mini Asterisk login GUI
+
+pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
+
+echo $QUERY_STRING | grep pass > /dev/null
+if [ $? -eq 1 ]; then
+ # Display form -------------------------------
+
+ cat <<EOF
+ <script src="prototype.js"></script>
+ <script type="text/javascript" src="tooltip.js"></script>
+ <link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+ cat << EOF
+ <html>
+ <title>Mini Asterisk - Login</title>
+ <form action="login.sh" method="get">
+ <table align="center" width=600>
+ <tr><td colspan="2" align="left"><h2>Login</h2></td>
+ <tr>
+ <tr><td>Password:</td><td><input type="password" name="pass" ></td></tr>
+ <tr><td><input type="submit" value="Login"></td></tr>
+ </tr>
+ <tr><td></td><td>Default password is uClinux</td>
+ </table>
+ </form>
+ </html>
+EOF
+else
+
+ # If we are a non-blackfin then use hard coded password for now.
+ # I don't feel comfortable sending root password through a web
+ # GUI for x86 boxes, but this is reasonable approach for embedded
+ # systems. TODO: add a way to store and modify x86 passwds
+
+ cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
+ if [ $? -eq 0 ]; then
+ # Blackfin IP0X system
+ testuser root "$pass"; res=$?
+ else
+ [ $pass = "uClinux" ] ; res=$?
+ fi
+
+ if [ $res -eq 0 ]; then
+
+ # login sucessful
+ echo "Content-type: text/html"
+ echo "Set-Cookie: loggedin=1"
+ echo ""
+ echo "<head>"
+ echo "<title>Mini Asterisk - Login</title>"
+ echo '<meta http-equiv="REFRESH" content="0;url=phones.sh">'
+ echo "</head>"
+ echo "<body>"
+ echo "Please wait a few seconds....."
+ echo "</body>"
+
+ # load mini asterisk conf files in case this is our first login
+
+ asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
+ asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
+
+ else
+ # login failed
+ cat <<EOF
+ <html>
+ <head>
+ <title>Mini Asterisk - Login</title>
+ <meta http-equiv="REFRESH" content="0;url=login.sh">
+ <body>
+ Please wait a few seconds.....
+ </body>
+ </head>
+ </html>
+EOF
+ fi
+fi
+
--- /dev/null
+#!/bin/sh
+# logout.sh
+# David Rowe 4 Jan 2010
+# CGI for Mini Asterisk logout GUI
+
+cat <<EOF
+Content-type: text/html
+Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
+
+<title>Mini Asterisk - Logout</title>
+<meta http-equiv="REFRESH" content="0;url=login.sh"
+EOF
+#echo $HTTP_COOKIE
--- /dev/null
+ <div id="admin_tip" class="tip">Change your password, reset the default settings, upgrade software</div>
+ <div id="network_tip" class="tip">Connect the phone system to your network and the Internet</div>
+ <div id="phones_tip" class="tip">Lists your phones and phone lines</div>
+ <div id="ipphones_tip" class="tip">Set up your IP phones</div>
+ <div id="about_tip" class="tip">Boring information like software version numbers</div>
+ <div id="faq_tip" class="tip">Frequently asked questions and links to further information</div>
+ <div id="logout_tip" class="tip">I think you can work this one out....</div>
+ <div id="voipline_tip" class="tip">Set up your VOIP phone line</div>
+ <td valign="top" >
+ <table align="right" width=200>
+ <tr><td><h2> </h2></td></tr>
+ <tr onMouseOver="popUp(event,'phones_tip')" onmouseout="popUp(event,'phones_tip')">
+ <td><a href="phones.sh">Phone System</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'about_tip')" onmouseout="popUp(event,'about_tip')">
+ <td><a href="about.sh">About</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'admin_tip')" onmouseout="popUp(event,'admin_tip')">
+ <td><a href="admin.sh">Admin</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'faq_tip')" onmouseout="popUp(event,'faq_tip')">
+ <td><a href="faq.sh">FAQ</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'ipphones_tip')" onmouseout="popUp(event,'ipphones_tip')">
+ <td><a href="ipphones.sh">IP Phones</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'logout_tip')" onmouseout="popUp(event,'logout_tip')">
+ <td><a href="logout.sh">Logout</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'network_tip')" onmouseout="popUp(event,'network_tip')">
+ <td><a href="network.sh">Network</a></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'voipline_tip')" onmouseout="popUp(event,'voipline_tip')">
+ <td><a href="voiplines.sh">VOIP Line</a></td>
+ </tr>
+ </table>
+ </td>
--- /dev/null
+body,h1,h2,h3,h4,h5,h6,p,center,td,th,ul,dl,div {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+
+
--- /dev/null
+var script_path = "cgi-bin/";
+
+function doStatic() {
+ $('ipaddress').disabled = 0;
+ $('netmask').disabled = 0;
+ $('gateway').disabled = 0;
+ $('dns').disabled = 0;
+}
+
+function doDHCP() {
+ $('ipaddress').disabled = 1;
+ $('netmask').disabled = 1;
+ $('gateway').disabled = 1;
+ $('dns').disabled = 1;
+}
+
+// http://moblog.bradleyit.com/2009/06/javascript-ip-address-validation.html
+
+function isIP(obj) {
+ var ary = obj.value.split(".");
+ var ip = true;
+
+ ip = (ary.length == 4);
+
+ if (ip) {
+ for (var i=0; i<4; i++) {
+ ip = (!ary[i].match(/^\d{1,3}$/) || (Number(ary[i]) > 255)) ? false : ip;
+ }
+ }
+
+ if (!ip) {
+ // the value is NOT a valid IP address
+ obj.style.background = "red";
+ obj.select();
+ }
+ else { obj.style.background = ""; } // the value IS a valid IP address
+
+ return ip;
+}
+
+function localInit() {
+
+ if (init_dhcp == "yes") {
+ $('dhcp').checked = true;
+ $('ipaddress').disabled = 1;
+ $('netmask').disabled = 1;
+ $('gateway').disabled = 1;
+ $('dns').disabled = 1;
+ }
+ else {
+ $('static').checked = true;
+ $('ipaddress').disabled = 0;
+ $('netmask').disabled = 0;
+ $('gateway').disabled = 0;
+ $('dns').disabled = 0;
+ }
+ $('ipaddress').value = init_ipaddress;
+ $('netmask').value = init_netmask;
+ $('gateway').value = init_gateway;
+ $('dns').value = init_dns;
+ $('backdoor').value = init_backdoor;
+ if (init_internet == "yes")
+ $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
+ else
+ $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
+
+}
+
+function validate_form(form)
+{
+ var valid = true;
+
+ if ($('dhcp').checked == false)
+ valid = isIP(form.ipaddress) && isIP(form.ipaddress) && isIP(form.gateway) && isIP(form.dns);
+
+ return valid;
+}
--- /dev/null
+#!/bin/sh
+# network.sh
+# David Rowe 4 Jan 2010
+# CGI for Mini Asterisk network GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# check what sort of machine we are running on. We only support this screen for
+# IP0X
+
+cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
+if [ ! $? -eq 0 ]; then
+cat <<EOF
+ <html>
+ Sorry, Network configuration is only supported on the IP0X. Anyway you
+ probably have a good way of setting up your network already.
+ </html>
+EOF
+ exit
+fi
+
+grok_network=0
+
+if [ -f /etc/rc.d/S10network ]; then
+ grok_network=1
+ dhcp=yes
+ ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\) Bcast.*/\1/p'`
+ netmask=`ifconfig eth0 | sed -n 's/.*Mask:\(.*\)\s*/\1/p'`
+ gateway=`route -n | awk '/^0.0.0.0/ {print $2}'`
+ dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
+fi
+
+if [ -f /etc/rc.d/S10network-static ]
+then
+ grok_network=1
+ dhcp=no
+ ipaddress=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-static`
+ netmask=`sed -n 's/NETMASK="\(.*\)"/\1/p' /etc/init.d/network-static`
+ gateway=`sed -n 's/GATEWAY="\(.*\)"/\1/p' /etc/init.d/network-static`
+ dns=`sed -n 's/DNS="\(.*\)"/\1/p' /etc/init.d/network-static`
+fi
+
+# if we don't understand this machines network config then bail
+
+if [ $groknetwork -eq 0 ]; then
+cat << EOF
+<html>
+<title>Mini Asterisk - Network</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800 border=0>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+ <table align="center" width=600 border=0>
+ <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
+ <tr><td>Sorry - I can't edit the Network configuration on this machine</td></tr>
+ </td>
+ </table>
+ </td>
+ </tr>
+
+</table>
+
+</html>
+EOF
+fi
+
+if [ -f /etc/rc.d/S05network-backdoor ]; then
+ backdoor=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-backdoor`
+fi
+
+# See if we have Internet connectivity, first check dns as time outs can be very slow
+
+dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
+internet="no";
+if [ $dns_packet_loss = "0" ]; then
+ packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
+ if [ $packet_loss = "0" ]; then
+ internet="yes";
+ fi
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+echo "<script>"
+echo 'var init_dhcp="'$dhcp'";'
+echo 'var init_ipaddress="'$ipaddress'";'
+echo 'var init_netmask="'$netmask'";'
+echo 'var init_gateway="'$gateway'";'
+echo 'var init_dns="'$dns'";'
+echo 'var init_backdoor="'$backdoor'";'
+echo 'var init_internet="'$internet'";'
+cat network.js
+echo "</script>"
+
+cat << EOF
+<html>
+<title>Mini Asterisk - Network</title>
+<body onload="localInit()">
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800 border=0>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <form action="set_network.sh" onsubmit="return validate_form(this)" method="get">
+ <table align="center" width=600 border=0>
+ <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
+ <tr>
+ <td><input type="radio" id="static" name="dhcp" value="no" onClick="doStatic()">Static</td>
+ <td><input type="radio" id="dhcp" name="dhcp" value="yes" onClick="doDHCP()">DHCP</td>
+ </tr>
+ <tr><td>IP Address:</td><td><input type="text" name="ipaddress" id="ipaddress" onBlur="isIP(this)"></td></tr>
+ <tr><td>Netmask:</td><td><input type="text" name="netmask" id="netmask" onBlur="isIP(this)"></td></tr>
+ <tr><td>Gateway:</td><td><input type="text" name="gateway" id="gateway" onBlur="isIP(this)"></td></tr>
+ <tr><td>DNS:</td><td><input type="text" name="dns" id="dns" onBlur="isIP(this)"></td></tr>
+ <tr onMouseOver="popUp(event,'network_backdoor')" onmouseout="popUp(event,'network_backdoor')">
+ <td>Emergency IP:</td><td><input type="text" name="backdoor" id="backdoor" onBlur="isIP(this)"></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">
+ <td>Internet Connection:</td>
+ <td><div id="internet" >
+ <span style="margin-left: 4px;font-weight:bold"> </span></div></td>
+
+ </tr>
+ <tr><td><input id="networkapply" type="submit" value="Apply"></td></tr>
+ </table>
+ </form>
+
+ </td>
+
+ </tr>
+
+</table>
+
+</html>
+EOF
+
--- /dev/null
+function localInit() {
+ if (init_internet == "yes")
+ $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
+ else
+ $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
+}
+
--- /dev/null
+#!/usr/bin/perl
+# phones.pl
+# David Rowe 5 Jan 2010
+#
+# Text processing for the phones screen.
+
+$tool_tip = "onMouseOver=\"popUp(event,'network_internet')\" onmouseout=\"popUp(event,'network_internet')\"";
+
+# Slurp up analog port (Zap) data from extensions.conf
+
+my %analog = (); # analog extension keyed on zap port
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) {
+ if (/.*=>[ ]*([0-9]*),1.*Zap\/([0-9]*)\)/) {
+ $analog{$2} = $1;
+ #print "'$1' '$2' $analog{$2}\n";
+ }
+}
+close EXT;
+
+# Slurp up data on installed zaptel ports from /etc/zaptel.conf
+
+my %zap = (); # zaptel port type keyed on zap port
+ # (fxs/fxo or no entry if not live)
+open ZAP, "/etc/zaptel.conf";
+while (<ZAP>) {
+ if (/fxoks=(.*)/) {
+ @fxs = split(/,/, $1);
+ foreach (@fxs) {
+ $zap{$_} = "fxs";
+ }
+ }
+ if (/fxsks=(.*)/) {
+ @fxo = split(/,/, $1);
+ foreach (@fxo) {
+ $zap{$_} = "fxo";
+ }
+ }
+}
+close ZAP;
+
+# Slurp up SIP extension (Sip) data from extensions.conf
+
+my %ip = (); # ip extension keyed on sip.conf name
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) {
+ if (/.*=>[ ]*([0-9]*),1.*Sip\/([0-9]*)\)/) {
+ $ip{$2} = $1;
+ #print "'$1' '$2' $ip{$2}\n";
+ }
+}
+close EXT;
+
+# Determine which extenions are "Reception", i.e. set to ring on incoming
+# calls
+
+my %zap_ring = (); # ring flag keyed on Zap port (1,2...)
+my %sip_ring = (); # ring flag keyed on sip.cong ext name (6011,6012 etc)
+
+open EXT, "/etc/asterisk/extensions.conf";
+while (<EXT>) {
+ if (/s,1,Dial\((.*)\) ;; mini/) {
+ @ring = split(/&/, $1);
+ #print "'$1' '@ring'\n foreach:\n";
+ foreach (@ring) {
+ #print " $_\n";
+ if (/Zap\/([0-9]*)/) {
+ $zap_ring{$1} = 1;
+ #print "'$_' $1 \n";
+ }
+ if (/SIP\/([0-9]*)/) {
+ $sip_ring{$1} = 1;
+ #print "'$_' $1 \n";
+ }
+ }
+ }
+}
+close EXT;
+
+
+# work out which IP phones are registered -----------------------------------
+
+my %sip = (); # SIP IP phone status keyed on sip.conf names (6011,6012 etc)
+ # if no entry we can't see IP phone device
+my %ipad = (); # IP address of SIP device keyed on sip.conf names
+
+open SIP, "sipshowpeers.txt";
+while (<SIP>) {
+
+ # just look for 4 digit extensions starting with 6 so we don't
+ # confuse with Voip Line
+
+ if (/^(6[0-9][0-9][0-9])[\s\/].*(OK)/) {
+ $sip{$1} = $2;
+ #print "'$1' '$2' $sip{$1}\n";
+ $e = $1;
+ if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ $ipad{$e} = $1;
+ #print "'$1'\n";
+ }
+ }
+
+ if (/^(.*)\/.*(OK)/) {
+ #$sip{$1} = $2;
+ #print "'$1' '$2' $sip{$1}\n";
+ $e = $1;
+ if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ $ipad{$e} = $1;
+ #print "'$1'\n";
+ }
+ }
+}
+
+close SIP;
+
+# Determine if Asterisk can see current voip line (SIP trunk)
+# sipshowpeers.txt needs to be generated before calling this perl
+# script
+
+my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
+ # if no entry we can't see SIP trunk
+
+open SIP, "sipshowregistry.txt";
+while (<SIP>) {
+ if (/^(.*):.*(Registered)/) {
+ $voip{$1} = $2;
+ #print "'$1' '$2' $voip{$1}\n";
+ }
+}
+
+close SIP;
+
+# start phones ringing form -------------------------------------------
+
+print '<form action="set_ring.sh" method="get">';
+
+# print list of analog phones
+
+$tooltip_anphone = "onMouseOver=\"popUp(event,'phone_anphone')\" onmouseout=\"popUp(event,'phone_anphone')\"";
+$tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
+$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_phone')\" onmouseout=\"popUp(event,'phone_port_phone')\"";
+$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
+
+foreach $a (sort keys %analog) {
+ if ($zap{$a} eq "fxs") {
+ $icon = "<img src=\"tick.png\" alt=\"Analog Phone OK\" />";
+ print "<tr><td $tooltip_ext>$analog{$a}</td><td $tooltip_anphone>Analog Phone</td><td $tooltip_port>Port $a</td>";
+ if ($zap_ring{$a} == 1) {
+ $checked = "checked";
+ }
+ else {
+ $checked = "";
+ }
+ print "<td $tooltip_reception><input type=\"checkbox\" name=\"Zap_$a\" $checked>Reception</td><td>$icon</td></tr>\n";
+ }
+}
+
+# print list of IP phones
+
+$tooltip_ipphone = "onMouseOver=\"popUp(event,'phone_ipphone')\" onmouseout=\"popUp(event,'phone_ipphone')\"";
+$tooltip_ipphone_ip = "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
+$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
+
+foreach $s (sort keys %sip) {
+ if ($sip{$s} eq "OK") {
+ $icon = "<img src=\"tick.png\" alt=\"IP Phone OK\" />";
+ print "<tr><td $tooltip_ext>$s</td><td $tooltip_ipphone>IP Phone</td><td $tooltip_ipphone_ip>$ipad{$s}</td>";
+ if ($sip_ring{$s} == 1) {
+ $checked = "checked";
+ }
+ else {
+ $checked = "";
+ }
+ print "<td $tooltip_reception><input type=\"checkbox\" name=\"SIP_$s\" $checked>Reception</td><td>$icon</td></tr>\n";
+ }
+}
+
+print '<tr><td> </td></tr>';
+print "<tr><td colspan=\"2\" onMouseOver=\"popUp(event,'phone_addipphone')\" onmouseout=\"popUp(event,'phone_addipphone')\">";
+
+$tooltip_update_reception = "onMouseOver=\"popUp(event,'phone_update_reception')\" onmouseout=\"popUp(event,'phone_update_reception')\"";
+print "<a href=\"ipphones.sh\">Add IP Phone</a></td><td></td><td $tooltip_update_reception><input type=\"submit\" value=\"Update Reception\"></td></tr>";
+
+$tool_tip = "onMouseOver=\"popUp(event,'phone_lines')\" onmouseout=\"popUp(event,'phone_lines')\"";
+
+print '<tr><td> </td></tr>';
+print "<tr $tool_tip><td colspan=\"4\" align=\"left\" valign=\"top\" ><h2>Phone Lines</h2></td></tr>
+";
+
+print "</form>";
+
+# print list of analog phone lines
+
+$tooltip_phoneline = "onMouseOver=\"popUp(event,'phone_phoneline')\" onmouseout=\"popUp(event,'phone_phoneline')\"";
+$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_line')\" onmouseout=\"popUp(event,'phone_port_line')\"";
+$tooltip_line_prefix = "onMouseOver=\"popUp(event,'phone_line_prefix')\" onmouseout=\"popUp(event,'phone_line_prefix')\"";
+
+foreach $a (sort keys %analog) {
+ if ($zap{$a} eq "fxo") {
+ $icon = "<img src=\"tick.png\" alt=\"Phone Line OK\" />";
+ print "<tr><td $tooltip_line_prefix>0</td><td $tooltip_phoneline>Analog Line</td><td $tooltip_port>Port $a</td><td></td><td>$icon</td></tr>\n";
+ }
+}
+
+# print list of SIP VOIP trunks
+
+$tooltip_voipline = "onMouseOver=\"popUp(event,'phone_voipline')\" onmouseout=\"popUp(event,'phone_voipline')\"";
+$tooltip_voipline_ip = "onMouseOver=\"popUp(event,'phone_voipline_ip')\" onmouseout=\"popUp(event,'phone_voipline_ip')\"";
+$tooltip_voipline_prefix = "onMouseOver=\"popUp(event,'phone_voipline_prefix')\" onmouseout=\"popUp(event,'phone_voipline_prefix')\"";
+
+foreach $s (sort keys %voip) {
+ if ($voip{$s} eq "Registered") {
+ $icon = "<img src=\"tick.png\" alt=\"VOIP Line OK\" />";
+ print "<tr><td $tooltip_voipline_prefix>1</td><td $tooltip_voipline>VOIP Line</td><td $tooltip_voipline_ip>$ipad{$s}</td><td></td><td>$icon</td></tr>\n";
+ }
+}
+
+print '<tr><td> </td></tr>';
+print "<tr><td colspan=2 onMouseOver=\"popUp(event,'phone_addvoipline')\" onmouseout=\"popUp(event,'phone_addvoipline')\">";
+print "<a href=\"voiplines.sh\">Set Up VOIP Line</a></td></tr>";
--- /dev/null
+#!/bin/sh
+# phones.sh
+# David Rowe 4 Jan 2010
+# Phones screen for Mini Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# See if we have Internet connectivity, first check dns as time outs can be very slow
+
+dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
+dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
+internet="no";
+if [ $dns_packet_loss = "0" ]; then
+ packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
+ if [ $packet_loss = "0" ]; then
+ internet="yes";
+ fi
+fi
+
+# Build list of interface IPs based on what sort of machine we are
+# running on. For IP0X we just print the IP of the first interface.
+# For other machines the situation is a bit more complex so we print
+# all of them. I figure anyone with multiple interfaces will know
+# enough about what they are doing to figure out the right one to use.
+
+ipaddress=`ifconfig | sed -n 's/.*inet addr:\(.*\) Bcast.*/\1/p'`
+
+cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
+if [ $? -eq 0 ]; then
+ ipaddress=`echo $ipaddress | awk '{ print $1 }'`
+else
+ ipaddress=`echo $ipaddress | sed -n 's/ /<br>/p'`
+fi
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+EOF
+
+echo "<script>"
+echo 'var init_internet="'$internet'";'
+cat phones.js
+echo "</script>"
+
+cat << EOF
+<html>
+<title>Mini Asterisk - Phones</title>
+<body onload="localInit()">
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <table align="right" width=600>
+ <col width="50" /><col width="150" />
+ <tr>
+ <td onMouseOver="popUp(event,'phone_system')" onmouseout="popUp(event,'phone_system')" colspan="4" align="left" valign="top"><h2>Phone System</h2></td>
+ </tr>
+ <tr>
+ <td colspan="3" onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">Internet Connection:</td>
+ <td></td><td><div id="internet" > </div></td>
+ </tr>
+ <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
+ <td colspan="4">Phone System IP Address:</td>
+EOF
+echo "<td>$ipaddress</td>"
+cat <<EOF
+ </tr>
+ <tr><td> </td></tr>
+ <tr>
+ <td onMouseOver="popUp(event,'phone_phones')" onmouseout="popUp(event,'phone_phones')"
+ colspan="3" align="left" valign="top" ><h2>Phones</h2></td>
+ </tr>
+EOF
+
+# use perl to construct list of phones and phone lines for us
+asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
+perl ./phones.pl
+
+cat<<EOF
+ </table>
+
+ </td>
+
+ </tr>
+
+</table>
+</body>
+</html>
+EOF
+
--- /dev/null
+/* Prototype JavaScript framework, version 1.4.0
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+ *
+/*--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.4.0',
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+
+ emptyFunction: function() {},
+ K: function(x) {return x}
+}
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+ for (property in source) {
+ destination[property] = source[property];
+ }
+ return destination;
+}
+
+Object.inspect = function(object) {
+ try {
+ if (object == undefined) return 'undefined';
+ if (object == null) return 'null';
+ return object.inspect ? object.inspect() : object.toString();
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+}
+
+Function.prototype.bind = function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+ var __method = this;
+ return function(event) {
+ return __method.call(object, event || window.event);
+ }
+}
+
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ var digits = this.toString(16);
+ if (this < 16) return '0' + digits;
+ return digits;
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ }
+});
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0; i < arguments.length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) {}
+ }
+
+ return returnValue;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.callback();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+function $() {
+ var elements = new Array();
+
+ for (var i = 0; i < arguments.length; i++) {
+ var element = arguments[i];
+ if (typeof element == 'string')
+ element = document.getElementById(element);
+
+ if (arguments.length == 1)
+ return element;
+
+ elements.push(element);
+ }
+
+ return elements;
+}
+Object.extend(String.prototype, {
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(eval);
+ },
+
+ escapeHTML: function() {
+ var div = document.createElement('div');
+ var text = document.createTextNode(this);
+ div.appendChild(text);
+ return div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = document.createElement('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+ },
+
+ toQueryParams: function() {
+ var pairs = this.match(/^\??(.*)$/)[1].split('&');
+ return pairs.inject({}, function(params, pairString) {
+ var pair = pairString.split('=');
+ params[pair[0]] = pair[1];
+ return params;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ camelize: function() {
+ var oStringList = this.split('-');
+ if (oStringList.length == 1) return oStringList[0];
+
+ var camelizedString = this.indexOf('-') == 0
+ ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
+ : oStringList[0];
+
+ for (var i = 1, len = oStringList.length; i < len; i++) {
+ var s = oStringList[i];
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
+ }
+
+ return camelizedString;
+ },
+
+ inspect: function() {
+ return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
+ }
+});
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+var $break = new Object();
+var $continue = new Object();
+
+var Enumerable = {
+ each: function(iterator) {
+ var index = 0;
+ try {
+ this._each(function(value) {
+ try {
+ iterator(value, index++);
+ } catch (e) {
+ if (e != $continue) throw e;
+ }
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ },
+
+ all: function(iterator) {
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!(iterator || Prototype.K)(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator) {
+ var result = true;
+ this.each(function(value, index) {
+ if (result = !!(iterator || Prototype.K)(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function (iterator) {
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(pattern, iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ var stringValue = value.toString();
+ if (stringValue.match(pattern))
+ results.push((iterator || Prototype.K)(value, index));
+ })
+ return results;
+ },
+
+ include: function(object) {
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inject: function(memo, iterator) {
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.collect(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator) {
+ var result;
+ this.each(function(value, index) {
+ value = (iterator || Prototype.K)(value, index);
+ if (value >= (result || value))
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator) {
+ var result;
+ this.each(function(value, index) {
+ value = (iterator || Prototype.K)(value, index);
+ if (value <= (result || value))
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator) {
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ ((iterator || Prototype.K)(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value, index) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator) {
+ return this.collect(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.collect(Prototype.K);
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (typeof args.last() == 'function')
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ iterator(value = collections.pluck(index));
+ return value;
+ });
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+}
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) {
+ return iterable.toArray();
+ } else {
+ var results = [];
+ for (var i = 0; i < iterable.length; i++)
+ results.push(iterable[i]);
+ return results;
+ }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0; i < this.length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != undefined || value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(value.constructor == Array ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ indexOf: function(object) {
+ for (var i = 0; i < this.length; i++)
+ if (this[i] == object) return i;
+ return -1;
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ shift: function() {
+ var result = this[0];
+ for (var i = 0; i < this.length - 1; i++)
+ this[i] = this[i + 1];
+ this.length--;
+ return result;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ }
+});
+var Hash = {
+ _each: function(iterator) {
+ for (key in this) {
+ var value = this[key];
+ if (typeof value == 'function') continue;
+
+ var pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ merge: function(hash) {
+ return $H(hash).inject($H(this), function(mergedHash, pair) {
+ mergedHash[pair.key] = pair.value;
+ return mergedHash;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ return pair.map(encodeURIComponent).join('=');
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ }
+}
+
+function $H(object) {
+ var hash = Object.extend({}, object || {});
+ Object.extend(hash, Enumerable);
+ Object.extend(hash, Hash);
+ return hash;
+}
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ do {
+ iterator(value);
+ value = value.succ();
+ } while (this.include(value));
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')},
+ function() {return new XMLHttpRequest()}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+}
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responderToAdd) {
+ if (!this.include(responderToAdd))
+ this.responders.push(responderToAdd);
+ },
+
+ unregister: function(responderToRemove) {
+ this.responders = this.responders.without(responderToRemove);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (responder[callback] && typeof responder[callback] == 'function') {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) {}
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() {
+ Ajax.activeRequestCount++;
+ },
+
+ onComplete: function() {
+ Ajax.activeRequestCount--;
+ }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ parameters: ''
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ responseIsSuccess: function() {
+ return this.transport.status == undefined
+ || this.transport.status == 0
+ || (this.transport.status >= 200 && this.transport.status < 300);
+ },
+
+ responseIsFailure: function() {
+ return !this.responseIsSuccess();
+ }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+ initialize: function(url, options) {
+ this.transport = Ajax.getTransport();
+ this.setOptions(options);
+ this.request(url);
+ },
+
+ request: function(url) {
+ var parameters = this.options.parameters || '';
+ if (parameters.length > 0) parameters += '&_=';
+
+ try {
+ this.url = url;
+ if (this.options.method == 'get' && parameters.length > 0)
+ this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+ this.transport.open(this.options.method, this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) {
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
+ }
+
+ this.setRequestHeaders();
+
+ var body = this.options.postBody ? this.options.postBody : parameters;
+ this.transport.send(this.options.method == 'post' ? body : null);
+
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ setRequestHeaders: function() {
+ var requestHeaders =
+ ['X-Requested-With', 'XMLHttpRequest',
+ 'X-Prototype-Version', Prototype.Version];
+
+ if (this.options.method == 'post') {
+ requestHeaders.push('Content-type',
+ 'application/x-www-form-urlencoded');
+
+ /* Force "Connection: close" for Mozilla browsers to work around
+ * a bug where XMLHttpReqeuest sends an incorrect Content-length
+ * header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType)
+ requestHeaders.push('Connection', 'close');
+ }
+
+ if (this.options.requestHeaders)
+ requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+
+ for (var i = 0; i < requestHeaders.length; i += 2)
+ this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState != 1)
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ header: function(name) {
+ try {
+ return this.transport.getResponseHeader(name);
+ } catch (e) {}
+ },
+
+ evalJSON: function() {
+ try {
+ return eval(this.header('X-JSON'));
+ } catch (e) {}
+ },
+
+ evalResponse: function() {
+ try {
+ return eval(this.transport.responseText);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ respondToReadyState: function(readyState) {
+ var event = Ajax.Request.Events[readyState];
+ var transport = this.transport, json = this.evalJSON();
+
+ if (event == 'Complete') {
+ try {
+ (this.options['on' + this.transport.status]
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if ((this.header('Content-type') || '').match(/^text\/javascript/i))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+ if (event == 'Complete')
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+ initialize: function(container, url, options) {
+ this.containers = {
+ success: container.success ? $(container.success) : $(container),
+ failure: container.failure ? $(container.failure) :
+ (container.success ? null : $(container))
+ }
+
+ this.transport = Ajax.getTransport();
+ this.setOptions(options);
+
+ var onComplete = this.options.onComplete || Prototype.emptyFunction;
+ this.options.onComplete = (function(transport, object) {
+ this.updateContent();
+ onComplete(transport, object);
+ }).bind(this);
+
+ this.request(url);
+ },
+
+ updateContent: function() {
+ var receiver = this.responseIsSuccess() ?
+ this.containers.success : this.containers.failure;
+ var response = this.transport.responseText;
+
+ if (!this.options.evalScripts)
+ response = response.stripScripts();
+
+ if (receiver) {
+ if (this.options.insertion) {
+ new this.options.insertion(receiver, response);
+ } else {
+ Element.update(receiver, response);
+ }
+ }
+
+ if (this.responseIsSuccess()) {
+ if (this.onComplete)
+ setTimeout(this.onComplete.bind(this), 10);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+ initialize: function(container, url, options) {
+ this.setOptions(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = {};
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(request) {
+ if (this.options.decay) {
+ this.decay = (request.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = request.responseText;
+ }
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
+ this.decay * this.frequency * 1000);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+document.getElementsByClassName = function(className, parentElement) {
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
+ return $A(children).inject([], function(elements, child) {
+ if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+ elements.push(child);
+ return elements;
+ });
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element) {
+ var Element = new Object();
+}
+
+Object.extend(Element, {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function() {
+ for (var i = 0; i < arguments.length; i++) {
+ var element = $(arguments[i]);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ }
+ },
+
+ hide: function() {
+ for (var i = 0; i < arguments.length; i++) {
+ var element = $(arguments[i]);
+ element.style.display = 'none';
+ }
+ },
+
+ show: function() {
+ for (var i = 0; i < arguments.length; i++) {
+ var element = $(arguments[i]);
+ element.style.display = '';
+ }
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ update: function(element, html) {
+ $(element).innerHTML = html.stripScripts();
+ setTimeout(function() {html.evalScripts()}, 10);
+ },
+
+ getHeight: function(element) {
+ element = $(element);
+ return element.offsetHeight;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return Element.classNames(element).include(className);
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return Element.classNames(element).add(className);
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return Element.classNames(element).remove(className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ for (var i = 0; i < element.childNodes.length; i++) {
+ var node = element.childNodes[i];
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ Element.remove(node);
+ }
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.match(/^\s*$/);
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var x = element.x ? element.x : element.offsetLeft,
+ y = element.y ? element.y : element.offsetTop;
+ window.scrollTo(x, y);
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ var value = element.style[style.camelize()];
+ if (!value) {
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css.getPropertyValue(style) : null;
+ } else if (element.currentStyle) {
+ value = element.currentStyle[style.camelize()];
+ }
+ }
+
+ if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
+ if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+
+ return value == 'auto' ? null : value;
+ },
+
+ setStyle: function(element, style) {
+ element = $(element);
+ for (name in style)
+ element.style[name.camelize()] = style[name];
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ if (Element.getStyle(element, 'display') != 'none')
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = '';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = 'none';
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return;
+ element._overflow = element.style.overflow;
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+ element.style.overflow = 'hidden';
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return;
+ element.style.overflow = element._overflow;
+ element._overflow = undefined;
+ }
+});
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+ this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+ initialize: function(element, content) {
+ this.element = $(element);
+ this.content = content.stripScripts();
+
+ if (this.adjacency && this.element.insertAdjacentHTML) {
+ try {
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
+ } catch (e) {
+ if (this.element.tagName.toLowerCase() == 'tbody') {
+ this.insertContent(this.contentFromAnonymousTable());
+ } else {
+ throw e;
+ }
+ }
+ } else {
+ this.range = this.element.ownerDocument.createRange();
+ if (this.initializeRange) this.initializeRange();
+ this.insertContent([this.range.createContextualFragment(this.content)]);
+ }
+
+ setTimeout(function() {content.evalScripts()}, 10);
+ },
+
+ contentFromAnonymousTable: function() {
+ var div = document.createElement('div');
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+ return $A(div.childNodes[0].childNodes[0].childNodes);
+ }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+ initializeRange: function() {
+ this.range.setStartBefore(this.element);
+ },
+
+ insertContent: function(fragments) {
+ fragments.each((function(fragment) {
+ this.element.parentNode.insertBefore(fragment, this.element);
+ }).bind(this));
+ }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+ initializeRange: function() {
+ this.range.selectNodeContents(this.element);
+ this.range.collapse(true);
+ },
+
+ insertContent: function(fragments) {
+ fragments.reverse(false).each((function(fragment) {
+ this.element.insertBefore(fragment, this.element.firstChild);
+ }).bind(this));
+ }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+ initializeRange: function() {
+ this.range.selectNodeContents(this.element);
+ this.range.collapse(this.element);
+ },
+
+ insertContent: function(fragments) {
+ fragments.each((function(fragment) {
+ this.element.appendChild(fragment);
+ }).bind(this));
+ }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+ initializeRange: function() {
+ this.range.setStartAfter(this.element);
+ },
+
+ insertContent: function(fragments) {
+ fragments.each((function(fragment) {
+ this.element.parentNode.insertBefore(fragment,
+ this.element.nextSibling);
+ }).bind(this));
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set(this.toArray().concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set(this.select(function(className) {
+ return className != classNameToRemove;
+ }).join(' '));
+ },
+
+ toString: function() {
+ return this.toArray().join(' ');
+ }
+}
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+var Field = {
+ clear: function() {
+ for (var i = 0; i < arguments.length; i++)
+ $(arguments[i]).value = '';
+ },
+
+ focus: function(element) {
+ $(element).focus();
+ },
+
+ present: function() {
+ for (var i = 0; i < arguments.length; i++)
+ if ($(arguments[i]).value == '') return false;
+ return true;
+ },
+
+ select: function(element) {
+ $(element).select();
+ },
+
+ activate: function(element) {
+ element = $(element);
+ element.focus();
+ if (element.select)
+ element.select();
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Form = {
+ serialize: function(form) {
+ var elements = Form.getElements($(form));
+ var queryComponents = new Array();
+
+ for (var i = 0; i < elements.length; i++) {
+ var queryComponent = Form.Element.serialize(elements[i]);
+ if (queryComponent)
+ queryComponents.push(queryComponent);
+ }
+
+ return queryComponents.join('&');
+ },
+
+ getElements: function(form) {
+ form = $(form);
+ var elements = new Array();
+
+ for (tagName in Form.Element.Serializers) {
+ var tagElements = form.getElementsByTagName(tagName);
+ for (var j = 0; j < tagElements.length; j++)
+ elements.push(tagElements[j]);
+ }
+ return elements;
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name)
+ return inputs;
+
+ var matchingInputs = new Array();
+ for (var i = 0; i < inputs.length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) ||
+ (name && input.name != name))
+ continue;
+ matchingInputs.push(input);
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ var elements = Form.getElements(form);
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ element.blur();
+ element.disabled = 'true';
+ }
+ },
+
+ enable: function(form) {
+ var elements = Form.getElements(form);
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ element.disabled = '';
+ }
+ },
+
+ findFirstElement: function(form) {
+ return Form.getElements(form).find(function(element) {
+ return element.type != 'hidden' && !element.disabled &&
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ Field.activate(Form.findFirstElement(form));
+ },
+
+ reset: function(form) {
+ $(form).reset();
+ }
+}
+
+Form.Element = {
+ serialize: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ var parameter = Form.Element.Serializers[method](element);
+
+ if (parameter) {
+ var key = encodeURIComponent(parameter[0]);
+ if (key.length == 0) return;
+
+ if (parameter[1].constructor != Array)
+ parameter[1] = [parameter[1]];
+
+ return parameter[1].map(function(value) {
+ return key + '=' + encodeURIComponent(value);
+ }).join('&');
+ }
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ var parameter = Form.Element.Serializers[method](element);
+
+ if (parameter)
+ return parameter[1];
+ }
+}
+
+Form.Element.Serializers = {
+ input: function(element) {
+ switch (element.type.toLowerCase()) {
+ case 'submit':
+ case 'hidden':
+ case 'password':
+ case 'text':
+ return Form.Element.Serializers.textarea(element);
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element);
+ }
+ return false;
+ },
+
+ inputSelector: function(element) {
+ if (element.checked)
+ return [element.name, element.value];
+ },
+
+ textarea: function(element) {
+ return [element.name, element.value];
+ },
+
+ select: function(element) {
+ return Form.Element.Serializers[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ },
+
+ selectOne: function(element) {
+ var value = '', opt, index = element.selectedIndex;
+ if (index >= 0) {
+ opt = element.options[index];
+ value = opt.value;
+ if (!value && !('value' in opt))
+ value = opt.text;
+ }
+ return [element.name, value];
+ },
+
+ selectMany: function(element) {
+ var value = new Array();
+ for (var i = 0; i < element.length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) {
+ var optValue = opt.value;
+ if (!optValue && !('value' in opt))
+ optValue = opt.text;
+ value.push(optValue);
+ }
+ }
+ return [element.name, value];
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+ initialize: function(element, frequency, callback) {
+ this.frequency = frequency;
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ onTimerEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ var elements = Form.getElements(this.element);
+ for (var i = 0; i < elements.length; i++)
+ this.registerCallback(elements[i]);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ case 'password':
+ case 'text':
+ case 'textarea':
+ case 'select-one':
+ case 'select-multiple':
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) {
+ var Event = new Object();
+}
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+
+ element: function(event) {
+ return event.target || event.srcElement;
+ },
+
+ isLeftClick: function(event) {
+ return (((event.which) && (event.which == 1)) ||
+ ((event.button) && (event.button == 1)));
+ },
+
+ pointerX: function(event) {
+ return event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft));
+ },
+
+ pointerY: function(event) {
+ return event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop));
+ },
+
+ stop: function(event) {
+ if (event.preventDefault) {
+ event.preventDefault();
+ event.stopPropagation();
+ } else {
+ event.returnValue = false;
+ event.cancelBubble = true;
+ }
+ },
+
+ // find the first node with the given tagName, starting from the
+ // node the event was triggered on; traverses the DOM upwards
+ findElement: function(event, tagName) {
+ var element = Event.element(event);
+ while (element.parentNode && (!element.tagName ||
+ (element.tagName.toUpperCase() != tagName.toUpperCase())))
+ element = element.parentNode;
+ return element;
+ },
+
+ observers: false,
+
+ _observeAndCache: function(element, name, observer, useCapture) {
+ if (!this.observers) this.observers = [];
+ if (element.addEventListener) {
+ this.observers.push([element, name, observer, useCapture]);
+ element.addEventListener(name, observer, useCapture);
+ } else if (element.attachEvent) {
+ this.observers.push([element, name, observer, useCapture]);
+ element.attachEvent('on' + name, observer);
+ }
+ },
+
+ unloadCache: function() {
+ if (!Event.observers) return;
+ for (var i = 0; i < Event.observers.length; i++) {
+ Event.stopObserving.apply(this, Event.observers[i]);
+ Event.observers[i][0] = null;
+ }
+ Event.observers = false;
+ },
+
+ observe: function(element, name, observer, useCapture) {
+ var element = $(element);
+ useCapture = useCapture || false;
+
+ if (name == 'keypress' &&
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+ || element.attachEvent))
+ name = 'keydown';
+
+ this._observeAndCache(element, name, observer, useCapture);
+ },
+
+ stopObserving: function(element, name, observer, useCapture) {
+ var element = $(element);
+ useCapture = useCapture || false;
+
+ if (name == 'keypress' &&
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+ || element.detachEvent))
+ name = 'keydown';
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, observer, useCapture);
+ } else if (element.detachEvent) {
+ element.detachEvent('on' + name, observer);
+ }
+ }
+});
+
+/* prevent memory leaks in IE */
+Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ realOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return [valueL, valueT];
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ p = Element.getStyle(element, 'position');
+ if (p == 'relative' || p == 'absolute') break;
+ }
+ } while (element);
+ return [valueL, valueT];
+ },
+
+ offsetParent: function(element) {
+ if (element.offsetParent) return element.offsetParent;
+ if (element == document.body) return element;
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return element;
+
+ return document.body;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = this.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = this.realOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = this.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ clone: function(source, target) {
+ source = $(source);
+ target = $(target);
+ target.style.position = 'absolute';
+ var offsets = this.cumulativeOffset(source);
+ target.style.top = offsets[1] + 'px';
+ target.style.left = offsets[0] + 'px';
+ target.style.width = source.offsetWidth + 'px';
+ target.style.height = source.offsetHeight + 'px';
+ },
+
+ page: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent==document.body)
+ if (Element.getStyle(element,'position')=='absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ } while (element = element.parentNode);
+
+ return [valueL, valueT];
+ },
+
+ clone: function(source, target) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || {})
+
+ // find page position of source
+ source = $(source);
+ var p = Position.page(source);
+
+ // find coordinate system to use
+ target = $(target);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(target,'position') == 'absolute') {
+ parent = Position.offsetParent(target);
+ delta = Position.page(parent);
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.style.position == 'absolute') return;
+ Position.prepare();
+
+ var offsets = Position.positionedOffset(element);
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';;
+ element.style.left = left + 'px';;
+ element.style.width = width + 'px';;
+ element.style.height = height + 'px';;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.style.position == 'relative') return;
+ Position.prepare();
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned. For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+ Position.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return [valueL, valueT];
+ }
+}
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+# set_network.sh
+#
+# CGI to set network parameters of an IP0X.
+
+cat <<EOF
+<html>
+<head>
+<title>set_network.sh</title>
+<meta http-equiv="REFRESH" content="0;url=network.sh">
+<body>
+Please wait a few seconds.....
+</body>
+</head>
+</html>
+EOF
+
+dhcp=`echo "$QUERY_STRING" | grep -oe "dhcp=[^&?]*" | sed -n "s/dhcp=//p"`
+ipaddress=`echo "$QUERY_STRING" | grep -oe "ipaddress=[^&?]*" | sed -n "s/ipaddress=//p"`
+netmask=`echo "$QUERY_STRING" | grep -oe "netmask=[^&?]*" | sed -n "s/netmask=//p"`
+gateway=`echo "$QUERY_STRING" | grep -oe "gateway=[^&?]*" | sed -n "s/gateway=//p"`
+dns=`echo "$QUERY_STRING" | grep -oe "dns=[^&?]*" | sed -n "s/dns=//p"`
+backdoor=`echo "$QUERY_STRING" | grep -oe "backdoor=[^&?]*" | sed -n "s/backdoor=//p"`
+
+if [ $dhcp = "yes" ]; then
+
+ # DHCP
+
+ if [ -f /etc/rc.d/S10network-static ]; then
+ /etc/init.d/network-static disable
+ /etc/init.d/network-static stop
+ /etc/init.d/network enable
+ /etc/init.d/network start
+ else
+ # if already running restart service
+ /etc/init.d/network stop
+ /etc/init.d/network start
+ fi
+fi
+
+if [ $dhcp = "no" ]; then
+
+ # Static IP
+
+ if [ -f /etc/rc.d/S10network ]; then
+ /etc/init.d/network stop
+ /etc/init.d/network disable
+ /etc/init.d/network-static enable
+ fi
+
+ sed -i "s/DHCPD=.*/DHCPD=no/g" /etc/init.d/network-static
+ sed -i "s/IPADDRESS=.*/IPADDRESS=\"$ipaddress\"/g" /etc/init.d/network-static
+ sed -i "s/NETMASK=.*/NETMASK=\"$netmask\"/g" /etc/init.d/network-static
+ sed -i "s/GATEWAY=.*/GATEWAY=\"$gateway\"/g" /etc/init.d/network-static
+ sed -i "s/DNS=.*/DNS=\"$dns\"/g" /etc/init.d/network-static
+ /etc/init.d/network-static stop
+ /etc/init.d/network-static start
+fi
+
+if [ -f /etc/rc.d/S05network-backdoor ]; then
+ sed -i "s/IPADDRESS=.*/IPADDRESS=\"$backdoor\"/g" /etc/init.d/network-backdoor
+ /etc/init.d/network-backdoor stop
+ /etc/init.d/network-backdoor start
+fi
--- /dev/null
+#!/bin/sh -x
+# set_ring.sh
+# David Rowe 4 Jan 2010
+# CGI to set which extensions ring on uncoming calls
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# extract extensions to ring and reload extensions.conf
+
+a=`echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'`
+
+# escape & if present
+echo "$a" | grep "&" >> /dev/null
+if [ $? -eq 0 ]; then
+ a=`echo $a | sed -n "s/&/\\\\&/pg"`
+fi
+
+sed -i "s_s,1,Dial(.*) ;; mini-asterisk_s,1,Dial($a) ;; mini-asterisk_" /etc/asterisk/extensions.conf
+asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
+
+# bounce us back to Phones screen
+
+cat <<EOF
+<html>
+<head>
+<title>Mini Asterisk - Set Ring</title>
+<meta http-equiv="REFRESH" content="0;url=phones.sh">
+<body>
+Please wait a few seconds.....
+EOF
+#echo $QUERY_STRING "<br>"
+#echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'
+#echo "<br>"
+#echo $a
+
+cat <<EOF
+</body>
+</head>
+</html>
+EOF
+
--- /dev/null
+#!/usr/bin/perl
+# set_voiplines.pl
+# David Rowe 12 Jan 2010
+#
+# Replaces fields in sip.conf, outputs new sip.conf contents to stdout
+# Gets run when "OK" is pressed on the Voip Lines screen
+
+$user = $ARGV[0];
+$pass = $ARGV[1];
+$host = $ARGV[2];
+$provider_new = $ARGV[3];
+
+# We need to slurp up the mini asterisk providers and spit them
+# back out. All must be commented out except for the one that
+# is selected. Hopefully non-mini asterisk content of sip.conf
+# won't be affected.
+
+open SIP, "/etc/asterisk/sip.conf";
+$provider = "";
+while (<SIP>) {
+
+ # start of any new stanza switches off parsing. It may get
+ # switched back on below if it contains mini-asterisk
+ # keyword. This allows non-mini asterisk SIP stanzas to be
+ # included in sip.conf
+
+ if (/\[/) {
+ $stanza = "";
+ }
+
+ # look for commented or uncommented mini asterisk provider stanza
+
+ if (/\[(.*)\].* \"(.*)\" mini-asterisk/) {
+ $stanza = $1;
+ $provider = $2;
+ }
+
+ if ($stanza eq "") {
+ # we are not in an mini-asterisk provider stanza
+
+ # however we may hit a mini-asterisk register line here
+
+ if (/.*register => (\S*)@(\S*).*;.*(mini-asterisk.*)/) {
+ # the mini-asterisk register line, not only one register supported
+ # at the moment (one VOIP line)
+
+ #print "XX provider_new='$provider_new' '$1' '$2' '$3'\n";
+
+ # commentout register if "none" selected
+
+ if ($user eq "none") {
+ print ";";
+ }
+
+ # note final /$user seems to be necessary so that incoming VOIP
+ # calls work. I really don't get the syntax but messed around for
+ # hours until it worked!
+
+ print "register => $user\@$user/$user; $3\n";
+ }
+ else {
+ # OK so this is a regular sip.conf line, just echo to stdout
+ print $_;
+ }
+ }
+ else {
+ # OK, we are in an mini-asterisk stanza
+
+ # strip off leading ";", except for comments lines which start
+ # with ;;
+
+ unless (/^;;/) {
+ $_ =~ s/^\;//;
+ }
+
+ if ($provider eq $provider_new) {
+
+ # this stanza should be uncommented
+
+ if (/\[.*\].* \".*\" mini-asterisk/) {
+ # rename stanza name to user name
+ # this is required to make incoming calls work
+ print "[$user] ; \"$provider\" mini-asterisk do not remove this comment\n";
+ }
+ elsif (/^username=/) {
+ print "username=$user\n";
+ }
+ elsif (/^fromuser=/) {
+ print "fromuser=$user\n";
+ }
+ elsif (/^secret=/) {
+ print "secret=$pass\n";
+ }
+ elsif (/^host=/) {
+ print "host=$host\n";
+ }
+ else {
+ print $_;
+ }
+ }
+ else {
+ # comment out unused mini-asterisk stanzas
+ if (/^;;/) {
+ # special csse for comment lines
+ print "$_";
+ }
+ else {
+ print ";$_";
+ }
+ }
+ }
+
+}
+close SIP;
+
--- /dev/null
+#!/bin/sh
+# set_voipline.sh
+# # David Rowe 12 Jan 2010
+#
+# CGI to set voip line parameters in sip.conf.
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+user=`echo "$QUERY_STRING" | grep -oe "user=[^&?]*" | sed -n "s/user=//p"`
+pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
+host=`echo "$QUERY_STRING" | grep -oe "host=[^&?]*" | sed -n "s/host=//p"`
+provider=`echo "$QUERY_STRING" | grep -oe "provider=[^&?]*" | sed -n "s/provider=//p"`
+
+# create new sip.conf with selected provider uncommented
+
+echo "set_voiplines.sh" $user $pass $host $provider >> /tmp/log.txt
+perl set_voiplines.pl $user $pass $host $provider > /etc/asterisk/sip.conf.new
+mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.bak
+mv /etc/asterisk/sip.conf.new /etc/asterisk/sip.conf
+
+# modify extensions.conf for new provider
+
+sed -i "s#_1.,1,Dial(.*)#_1.,1,Dial(SIP/$user/\${EXTEN:1})#" /etc/asterisk/extensions.conf
+asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
+
+# get asterisk to load changes
+
+asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
+
+cat <<EOF
+<html>
+<head>
+<title>set_voiplines.sh</title>
+<meta http-equiv="REFRESH" content="0;url=voiplines.sh">
+<body>
+Please wait a few seconds.....
+</body>
+</head>
+</html>
+EOF
+
--- /dev/null
+.tip {font:14px/16px
+Arial,Helvetica,sans-serif; border:solid 1px
+#666666; width:270px; padding:1px;
+position:absolute; z-index:100;
+visibility:hidden; color:#333333; top:20px;
+left:90px; background-color:#ffffcc;
+layer-background-color:#ffffcc;}
--- /dev/null
+// Extended Tooltip Javascript
+// copyright 9th August 2002, 3rd July 2005, 24th August 2008
+// by Stephen Chapman, Felgall Pty Ltd
+
+// permission is granted to use this javascript provided that the below code is not altered
+function pw() {return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth}; function mouseX(evt) {return evt.clientX ? evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) : evt.pageX;} function mouseY(evt) {return evt.clientY ? evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop) : evt.pageY} function popUp(evt,oi) {if (document.getElementById) {var wp = pw(); dm = document.getElementById(oi); ds = dm.style; st = ds.visibility; if (dm.offsetWidth) ew = dm.offsetWidth; else if (dm.clip.width) ew = dm.clip.width; if (st == "visible" || st == "show") { ds.visibility = "hidden"; } else {tv = mouseY(evt) + 20; lv = mouseX(evt) - (ew/4); if (lv < 2) lv = 2; else if (lv + ew > wp) lv -= ew/2; lv += 'px';tv += 'px'; ds.left = lv; ds.top = tv; ds.visibility = "visible";}}}
+
--- /dev/null
+<div id="network_internet" class="tip">
+ A tick means your phone system can reach the Internet. You need the Internet for VOIP calls
+ and software upgrades.
+ If you have a problem reaching the Internet check your Network settings, in
+ particular Gateway and DNS.</div>
+
+<div id="network_backdoor" class="tip">
+ Emergency backdoor IP. Useful if you get locked out of the main network connection, for
+ example due to DHCP problems on your network or a configuration mistake.
+ Write this number down somewhere!</div>
+
+<div id="phone_reception" class="tip">
+ If ticked this phone will ring when some one
+ calls the phone system from an outside Analog
+ or VOIP Line. More than one phone can be
+ ticked. You can answer a call on another
+ ringing phone by dialling *8 on your phone -
+ see FAQ for details.</div>
+
+<div id="phone_update_reception" class="tip">
+ Press this button to lock in any changes you
+ have made to the Reception check-boxes above.</div>
+
+<div id="phone_anphone" class="tip">
+ Analog Phone: Normal telephone plugged into a
+ port on your phone system. </div> <div
+ id="phone_ipphone" class="tip"> IP Phone
+ plugged into your network. </div> <div
+ id="phone_line" class="tip"> Analog Phone
+ Line: Analog telephone line plugged into a
+ port on your phone system. </div> <div
+ id="phone_voipline" class="tip"> VOIP Phone
+ Line: Make and receive phone calls over the
+ Internet. </div>
+
+<div id="phone_system" class="tip">
+ Important information about your Phone System.</div>
+
+<div id="phone_ipaddress" class="tip">
+ The address of your Phone System
+ on your network. Use this address to connect
+ IP Phones to your Phone System. </div>
+
+<div id="phone_phones" class="tip">
+ List of phones connected to your Phone
+ System. You can connect Analog or IP Phones
+ to your system. When IP Phones are
+ configured correctly, they appear on this
+ list. If an IP phone is not configured
+ correctly, it will not appear on this list.
+ Analog phones require hardware to be
+ installed in your Phone system.</div>
+
+<div id="phone_lines" class="tip">
+ List of phone lines available. Phone lines
+ are used to make and receive outside calls.
+ You can use regular Analog phone lines or
+ VOIP. VOIP phone lines require an account
+ with an Internet Telephone Service Provider.
+ Analog phone lines require hardware to be
+ installed in your Phone System.</div>
+
+<div id="phone_ext" class="tip">
+ Dial this number to call this phone</div>
+
+<div id="phone_port_phone" class="tip">
+ Port (socket) on the rear of your Phone System. Plug the phone into this Port.</div>
+
+<div id="phone_port_line" class="tip">
+ Port (socket) on the rear of your Phone
+ System. Plug the phone line into this
+ Port.</div>
+
+<div id="phone_line_prefix" class="tip">
+ Dial 0 for an Analog outside line. For example to call 5551234 dial 05551234. Don't pause after the 0, just dial 0 and the outside number together.</div>
+
+<div id="phone_ipphone_ip" class="tip">
+ IP Address of this phone on your network</div>
+
+<div id="phone_voipline_ip" class="tip">
+ IP Address of the VOIP Internet Telephone Service Provider</div>
+
+<div id="phone_voipline_prefix" class="tip">
+ Dial 1 for a VOIP outside line. For example to call 5551234 dial 15551234. Don't pause after the 1, just dial 1 and the outside number together.</div>
+
+<div id="phone_addipphone" class="tip">
+ Instructions and help on adding a new IP phone</div>
+
+<div id="phone_addvoipline" class="tip">
+ Instructions and help on VOIP Line set up</div>
+
+<div id="ipphones_ipphones" class="tip">
+ List of possible IP phones. For a new phone
+ choose any Available number. Refresh this
+ page to update</div>
+
+<div id="ipphones_connected" class="tip">
+ The IP phone is connected to your phone system and ready to use</div>
+
+<div id="ipphones_notconnected" class="tip">
+ No IP phone is connected. Either no IP phone
+ is present, or the IP phone has not been set
+ up.</div>
+
+<div id="voiplines_voiplines" class="tip">
+ A VOIP line allows you to make and receive
+ phones calls over the Internet. Normally a
+ VOIP line is provided by an Internet Telephony
+ Service Provider (ITSP). They will give you
+ an account, which includes the user and
+ password details that you can fill in below.
+ Refresh this page on your browser to see if
+ your VOIP line is working. </div>
+
+<div id="voiplines_provider" class="tip">
+ Your Internet Telephony Service Provider.
+ They will give you an account with a user name
+ and password.</div>
+
+<div id="voiplines_user" class="tip">
+ Your account name with your Internet Telephony Service Provider</div>
+
+<div id="voiplines_pass" class="tip">
+ The password for your Internet Telephony Service Provider account</div>
+
+<div id="voiplines_host" class="tip">
+ The Internet address of your Internet
+ Telephony Service Provider. This will usually
+ be filled in automatically.</div>
+
+<div id="voiplines_status" class="tip">
+ A tick means you are connected to your
+ Internet Telephony Service Provider. Refresh
+ your browser to update.</div>
+
+<div id="admin_restart" class="tip">
+ Press this button to restart your phone
+ system. This is the same as turning the power
+ off and back on. </div>
+
+<div id="admin_upgrade" class="tip">
+ Press this button to install the latest
+ version of Mini Asterisk. An Mini Asterisk
+ upgrade requires an Internet connection.</div>
+
+<div id="admin_firmware" class="tip">
+ Enter the URL of a firmware update script.
+ This option can be used to install new
+ firmware on your Phone System. Installing new
+ firmware requires an Internet connection. the
+ full URL Must be entered,
+ e.g. http://rowetel.com/ucasterisk/mini/test.sh</div>
+
--- /dev/null
+function changeProvider() {
+ provider = $('provider').value;
+ $('user').value = users[provider];
+ $('pass').value = passwords[provider];
+ $('host').value = hosts[provider];
+ $('comment').innerHTML = comments[provider];
+ $('status').innerHTML = '<img src="cross.png" alt=\"Not OK\" />';
+}
--- /dev/null
+#!/usr/bin/perl
+# voiplines.pl
+# David Rowe 12 Jan 2010
+#
+# Text processing for the voiplines screen
+
+# slurp up list of possible voip line providers --------------------------------
+# one of these will be currently selected
+
+open SIP, "/etc/asterisk/sip.conf";
+my $provider = ""; # current provider bring parsed in sip.conf
+my @providers=(); # list of all providers
+my %user = (); # user keyed on provider
+my %pass = (); # password keyed on provider
+my %host = (); # host name keyed on provider
+
+my $provider_current = "none";
+push (@providers, "none");
+$comment{"none"} = " ";
+
+while (<SIP>) {
+
+ # start of any stanza switches off parsing. It may get switched
+ # back on below if it contains mini-asterisk keyword. This allows
+ # non-mini asterisk SIP devices to be included in sip.conf
+
+ if (/\[/) {
+ $provider = "";
+ }
+
+ # currently disabled mini-asterisk provider
+
+ if (/^;\[.*\].* \"(.*)\" mini-asterisk/) {
+ push (@providers, $1);
+ $provider = $1;
+ #print "'$1'\n";
+ }
+
+ # current mini-asterisk provider
+
+ if (/^\[(.*)\].* \"(.*)\" mini-asterisk/) {
+ push (@providers, $2);
+ $provider = $2;
+ $provider_current = $2;
+ $stanza_current = $1;
+ #print "'$1' '$2'\n";
+ }
+
+ if ($provider ne "") {
+ #print $_;
+
+ if (/^;*username=(.*)/) {
+ $user{$provider} = $1;
+ }
+ if (/^;*secret=(.*)/) {
+ $pass{$provider} = $1;
+ }
+ if (/^;*host=(.*)/) {
+ $host{$provider} = $1;
+ }
+
+ if (/^;; (.*)/) {
+ $comment{$provider} = $1;
+ }
+ }
+
+ $state = $next_state;
+}
+close SIP;
+
+# Determine if Asterisk can see current voip line (SIP trunk)
+# sipshowpeers.txt needs to be generated before calling this perl
+# script
+
+my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
+ # if no entry we can't see SIP trunk
+
+open SIP, "sipshowregistry.txt";
+while (<SIP>) {
+ if (/^(.*):.*(Registered)/) {
+ $voip{$1} = $2;
+ #print "'$1' '$2' $voip{$1}\n";
+ }
+}
+
+close SIP;
+
+# javascript to handle changing providers
+
+print "<script>\n";
+print "var hosts = new Array();\n";
+print "var users = new Array();\n";
+print "var passwords = new Array();\n";
+print "var stanzas = new Array();\n";
+print "var comments = new Array();\n";
+foreach (@providers) {
+ print "hosts[\'$_\'] = \'$host{$_}\';\n";
+ print "users[\'$_\'] = \'$user{$_}\';\n";
+ print "passwords[\'$_\'] = \'$pass{$_}\';\n";
+ print "comments[\'$_\'] = \'$comment{$_}\';\n";
+}
+print "</script>\n";
+
+# generate form fields -------------------------------------------
+
+$tt_provider = "onMouseOver=\"popUp(event,'voiplines_provider')\" onmouseout=\"popUp(event,'voiplines_provider')\"";
+$tt_user = "onMouseOver=\"popUp(event,'voiplines_user')\" onmouseout=\"popUp(event,'voiplines_user')\"";
+$tt_pass = "onMouseOver=\"popUp(event,'voiplines_pass')\" onmouseout=\"popUp(event,'voiplines_pass')\"";
+$tt_host = "onMouseOver=\"popUp(event,'voiplines_host')\" onmouseout=\"popUp(event,'voiplines_host')\"";
+$tt_status = "onMouseOver=\"popUp(event,'voiplines_status')\" onmouseout=\"popUp(event,'voiplines_status')\"";
+
+print "<tr $tt_provider><td>Provider</td><td>\n";
+print "<select name=\"provider\" id=\"provider\" onchange=\"changeProvider()\">\n";
+foreach (@providers) {
+ if ($_ eq $provider_current) {
+ print "<option selected=\"yes\">$_</option>\n";
+ }
+ else {
+ print "<option>$_</option>\n";
+ }
+}
+print "</select></td></tr>\n";
+
+print "<tr $tt_user><td>User:</td><td><input type=\"text\" name=\"user\" id=\"user\" value=\"$user{$provider_current}\"></td></tr>\n";
+print "<tr $tt_pass><td >Password:</td><td><input type=\"password\" name=\"pass\" id=\"pass\" value=\"$pass{$provider_current}\"></td></tr>\n";
+print "<tr $tt_host><td >Host:</td><td><input type=\"text\" name=\"host\" id=\"host\" value=\"$host{$provider_current}\"></td></tr>\n";
+
+#print "\nXXX $provider_current $stanza_current} $voip{$stanza_current}\n";
+
+if ($voip{$stanza_current} eq "Registered") {
+ $icon = "<img src=\"tick.png\" alt=\"OK\" />";
+}
+else {
+ $icon = "<img src=\"cross.png\" alt=\"Not OK\" />";
+}
+print "<tr $tt_status><td>Voip Line Status:</td><td><div id=\"status\" >$icon</div></td></tr>\n";
+
+print "<tr><td> </td></tr>\n";
+print "<tr><td colspan=\"2\"><div id=\"comment\">$comment{$provider_current}</div></td></tr>\n";
+print "<tr><td> </td></tr>\n";
--- /dev/null
+#!/bin/sh
+# voiplines.sh
+# David Rowe 12 Jan 2010
+# VOIP Line screen for Mini Asterisk GUI
+
+# check we are logged in
+
+echo $HTTP_COOKIE | grep "loggedin" > /dev/null
+if [ $? -eq 1 ]; then
+ echo "<html>"
+ echo "<head>"
+ echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
+ echo "</head>"
+ echo "</html>"
+ exit
+fi
+
+# See if we have can reach the VOIP Line provider
+
+asterisk "-rx sip show registry" 2>/dev/null > sipshowregistry.txt
+
+# Construct the web page -------------------------------
+
+cat <<EOF
+<script src="prototype.js"></script>
+<script type="text/javascript" src="tooltip.js"></script>
+<link rel="stylesheet" href="tooltip.css" type="text/css" />
+<script>
+EOF
+
+cat voiplines.js
+
+cat << EOF
+</script>
+<html>
+<title>Mini Asterisk - VOIP Line</title>
+EOF
+
+cat tooltips.html
+echo '<table align="center" width=800>'
+cat banner.html
+echo " <tr>"
+cat menu.html
+cat <<EOF
+
+ <td valign="top">
+
+ <table align="right" width=600>
+ <tr><td> </td></tr>
+ <form action="set_voiplines.sh" method="get">
+ <tr><td onMouseOver="popUp(event,'voiplines_voiplines')" onmouseout="popUp(event,'voiplines_voiplines')" align="left" valign="top" colspan="3"><h2>VOIP Line</h2></td></tr>
+
+ <tr><td> </td></tr>
+EOF
+
+perl ./voiplines.pl
+
+cat <<EOF
+
+ <tr><td colspan="2">Sometimes it takes a few seconds to connect
+ your Voip Line. After clicking OK refresh
+ your browser to update Voip Line status.
+ </td></tr>
+
+ <tr><td> </td></tr>
+ <tr><td><input type="submit" value="OK"></td></tr>
+
+ </form>
+
+ </table>
+ </form>
+
+ </td>
+
+ </tr>
+
+</table>
+</body>
+</html>
+EOF
+
--- /dev/null
+; extensions.conf
+; David Rowe 4 Jan 2010
+;
+
+; Designed for Mini Asterisk GUI. However you can hand modify as much
+; as you like, as GUI scripts read/and write regular extensions.conf
+; without messing with your custom dialplan
+
+
+[general]
+static = yes
+writeprotect = no
+autofallthrough = yes
+clearglobalvars = no
+priorityjumping = no
+
+[default]
+
+; Pre-configured analog extensions, depends on IP0X model and what modules
+; are installed. Some of these may map to FXO ports
+
+exten => 6001,1,Dial(Zap/1)
+exten => 6002,1,Dial(Zap/2)
+exten => 6003,1,Dial(Zap/3)
+exten => 6004,1,Dial(Zap/4)
+exten => 6005,1,Dial(Zap/5)
+exten => 6006,1,Dial(Zap/6)
+exten => 6007,1,Dial(Zap/7)
+exten => 6008,1,Dial(Zap/8)
+
+; Pre-configured SIP-phone extensions. Primary use case is multiple SIP
+; extensions and FXO analog Ports
+
+exten => 6011,1,Dial(SIP/6011)
+exten => 6012,1,Dial(SIP/6012)
+exten => 6013,1,Dial(SIP/6013)
+exten => 6014,1,Dial(SIP/6014)
+exten => 6015,1,Dial(SIP/6015)
+exten => 6016,1,Dial(SIP/6016)
+exten => 6017,1,Dial(SIP/6017)
+exten => 6018,1,Dial(SIP/6018)
+exten => 6019,1,Dial(SIP/6019)
+exten => 6020,1,Dial(SIP/6020)
+exten => 6021,1,Dial(SIP/6021)
+exten => 6022,1,Dial(SIP/6022)
+
+; Pre-configured mini-asterisk outgoing Analog group
+
+exten => _0.,1,Dial(Zap/g2/${EXTEN:1})
+
+; Pre-configured mini-asterisk outgoing VOIP line
+
+exten => _1.,1,Dial(SIP/voip/${EXTEN:1})
+
+; Pre-configured incoming calls
+
+exten => s,1,Dial(SIP/6011) ;; mini-asterisk - don't remove this comment
+
--- /dev/null
+
+; Inter-Asterisk eXchange driver definition
+;
+; This configuration is re-read at reload
+; or with the CLI command
+; reload chan_iax2.so
+;
+; General settings, like port number to bind to, and
+; an option address (the default is to bind to all
+; local addresses).
+;
+[general]
+;bindport=4569 ; bindport and bindaddr may be specified
+; ; NOTE: bindport must be specified BEFORE bindaddr
+; ; or may be specified on a specific bindaddr if followed by
+; ; colon and port (e.g. bindaddr=192.168.0.1:4569)
+;bindaddr=192.168.0.1 ; more than once to bind to multiple
+; ; addresses, but the first will be the
+; ; default
+;
+; Set iaxcompat to yes if you plan to use layered switches or
+; some other scenario which may cause some delay when doing a
+; lookup in the dialplan. It incurs a small performance hit to
+; enable it. This option causes Asterisk to spawn a separate thread
+; when it receives an IAX DPREQ (Dialplan Request) instead of
+; blocking while it waits for a response.
+;
+;iaxcompat=yes
+;
+; Disable UDP checksums (if nochecksums is set, then no checkums will
+; be calculated/checked on systems supporting this feature)
+;
+;nochecksums=no
+;
+;
+; For increased security against brute force password attacks
+; enable "delayreject" which will delay the sending of authentication
+; reject for REGREQ or AUTHREP if there is a password.
+;
+;delayreject=yes
+;
+; You may specify a global default AMA flag for iaxtel calls. It must be
+; one of 'default', 'omit', 'billing', or 'documentation'. These flags
+; are used in the generation of call detail records.
+;
+;amaflags=default
+;
+; You may specify a default account for Call Detail Records in addition
+; to specifying on a per-user basis
+;
+;accountcode=lss0101
+;
+; You may specify a global default language for users.
+; Can be specified also on a per-user basis
+; If omitted, will fallback to english
+;
+;language=en
+;
+; Specify bandwidth of low, medium, or high to control which codecs are used
+; in general.
+;
+bandwidth=low
+;
+; You can also fine tune codecs here using "allow" and "disallow" clauses
+; with specific codecs. Use "all" to represent all formats.
+;
+;allow=all ; same as bandwidth=high
+;disallow=g723.1 ; Hm... Proprietary, don't use it...
+disallow=lpc10 ; Icky sound quality... Mr. Roboto.
+;allow=gsm ; Always allow GSM, it's cool :)
+;
+
+; You can adjust several parameters relating to the jitter buffer.
+; The jitter buffer's function is to compensate for varying
+; network delay.
+;
+; There are presently two jitterbuffer implementations available for Asterisk
+; and chan_iax2; the classic and the new, channel/application independent
+; implementation. These are controlled at compile-time. The new jitterbuffer
+; additionally has support for PLC which greatly improves quality as the
+; jitterbuffer adapts size, and in compensating for lost packets.
+;
+; All the jitter buffer settings except dropcount are in milliseconds.
+; The jitter buffer works for INCOMING audio - the outbound audio
+; will be dejittered by the jitter buffer at the other end.
+;
+; jitterbuffer=yes|no: global default as to whether you want
+; the jitter buffer at all.
+;
+; forcejitterbuffer=yes|no: in the ideal world, when we bridge VoIP channels
+; we don't want to do jitterbuffering on the switch, since the endpoints
+; can each handle this. However, some endpoints may have poor jitterbuffers
+; themselves, so this option will force * to always jitterbuffer, even in this
+; case.
+; [This option presently applies only to the new jitterbuffer implementation]
+;
+; dropcount: the jitter buffer is sized such that no more than "dropcount"
+; frames would have been "too late" over the last 2 seconds.
+; Set to a small number. "3" represents 1.5% of frames dropped
+; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
+;
+; maxjitterbuffer: a maximum size for the jitter buffer.
+; Setting a reasonable maximum here will prevent the call delay
+; from rising to silly values in extreme situations; you'll hear
+; SOMETHING, even though it will be jittery.
+;
+; resyncthreshold: when the jitterbuffer notices a significant change in delay
+; that continues over a few frames, it will resync, assuming that the change in
+; delay was caused by a timestamping mix-up. The threshold for noticing a
+; change in delay is measured as twice the measured jitter plus this resync
+; threshold.
+; Resyncing can be disabled by setting this parameter to -1.
+; [This option presently applies only to the new jitterbuffer implementation]
+;
+; maxjitterinterps: the maximum number of interpolation frames the jitterbuffer
+; should return in a row. Since some clients do not send CNG/DTX frames to
+; indicate silence, the jitterbuffer will assume silence has begun after
+; returning this many interpolations. This prevents interpolating throughout
+; a long silence.
+; [This option presently applies only to the new jitterbuffer implementation]
+;
+; maxexcessbuffer: If conditions improve after a period of high jitter,
+; the jitter buffer can end up bigger than necessary. If it ends up
+; more than "maxexcessbuffer" bigger than needed, Asterisk will start
+; gradually decreasing the amount of jitter buffering.
+; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
+;
+; minexcessbuffer: Sets a desired mimimum amount of headroom in
+; the jitter buffer. If Asterisk has less headroom than this, then
+; it will start gradually increasing the amount of jitter buffering.
+; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
+;
+; jittershrinkrate: when the jitter buffer is being gradually shrunk
+; (or enlarged), how many millisecs shall we take off per 20ms frame
+; received? Use a small number, or you will be able to hear it
+; changing. An example: if you set this to 2, then the jitter buffer
+; size will change by 100 millisecs per second.
+; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
+
+jitterbuffer=no
+forcejitterbuffer=no
+;dropcount=2
+;maxjitterbuffer=1000
+;maxjitterinterps=10
+;resyncthreshold=1000
+;maxexcessbuffer=80
+;minexcessbuffer=10
+;jittershrinkrate=1
+
+;trunkfreq=20 ; How frequently to send trunk msgs (in ms)
+
+; Should we send timestamps for the individual sub-frames within trunk frames?
+; There is a small bandwidth use for these (less than 1kbps/call), but they
+; ensure that frame timestamps get sent end-to-end properly. If both ends of
+; all your trunks go directly to TDM, _and_ your trunkfreq equals the frame
+; length for your codecs, you can probably suppress these. The receiver must
+; also support this feature, although they do not also need to have it enabled.
+;
+; trunktimestamps=yes
+;
+; Minimum and maximum amounts of time that IAX peers can request as
+; a registration expiration interval (in seconds).
+; minregexpire = 60
+; maxregexpire = 60
+;
+; We can register with another IAX server to let him know where we are
+; in case we have a dynamic IP address for example
+;
+; Register with tormenta using username marko and password secretpass
+;
+;register => marko:secretpass@tormenta.linux-support.net
+;
+; Register joe at remote host with no password
+;
+;register => joe@remotehost:5656
+;
+; Register marko at tormenta.linux-support.net using RSA key "torkey"
+;
+;register => marko:[torkey]@tormenta.linux-support.net
+;
+; Sample Registration for iaxtel
+;
+; Visit http://www.iaxtel.com to register with iaxtel. Replace "user"
+; and "pass" with your username and password for iaxtel. Incoming
+; calls arrive at the "s" extension of "default" context.
+;
+;register => user:pass@iaxtel.com
+;
+; Sample Registration for IAX + FWD
+;
+; To register using IAX with FWD, it must be enabled by visiting the URL
+; http://www.fwdnet.net/index.php?section_id=112
+;
+; Note that you need an extension in you default context which matches
+; your free world dialup number. Please replace "FWDNumber" with your
+; FWD number and "passwd" with your password.
+;
+;register => FWDNumber:passwd@iax.fwdnet.net
+;
+;
+; You can disable authentication debugging to reduce the amount of
+; debugging traffic.
+;
+;authdebug=no
+;
+; Finally, you can set values for your TOS bits to help improve
+; performance. Valid values are:
+; lowdelay -- Minimize delay
+; throughput -- Maximize throughput
+; reliability -- Maximize reliability
+; mincost -- Minimize cost
+; none -- No flags
+;
+tos=lowdelay
+;
+; If mailboxdetail is set to "yes", the user receives
+; the actual new/old message counts, not just a yes/no
+; as to whether they have messages. this can be set on
+; a per-peer basis as well
+;
+;mailboxdetail=yes
+;
+; If regcontext is specified, Asterisk will dynamically create and destroy
+; a NoOp priority 1 extension for a given peer who registers or unregisters
+; with us. The actual extension is the 'regexten' parameter of the registering
+; peer or its name if 'regexten' is not provided. More than one regexten
+; may be supplied if they are separated by '&'. Patterns may be used in
+; regexten.
+;
+;regcontext=iaxregistrations
+;
+; If we don't get ACK to our NEW within 2000ms, and autokill is set to yes,
+; then we cancel the whole thing (that's enough time for one retransmission
+; only). This is used to keep things from stalling for a long time for a host
+; that is not available, but would be ill advised for bad connections. In
+; addition to 'yes' or 'no' you can also specify a number of milliseconds.
+; See 'qualify' for individual peers to turn on for just a specific peer.
+;
+autokill=yes
+;
+; codecpriority controls the codec negotiation of an inbound IAX call.
+; This option is inherited to all user entities. It can also be defined
+; in each user entity separately which will override the setting in general.
+;
+; The valid values are:
+;
+; caller - Consider the callers preferred order ahead of the host's.
+; host - Consider the host's preferred order ahead of the caller's.
+; disabled - Disable the consideration of codec preference alltogether.
+; (this is the original behaviour before preferences were added)
+; reqonly - Same as disabled, only do not consider capabilities if
+; the requested format is not available the call will only
+; be accepted if the requested format is available.
+;
+; The default value is 'host'
+;
+;codecpriority=host
+
+;rtcachefriends=yes ; Cache realtime friends by adding them to the internal list
+ ; just like friends added from the config file only on a
+ ; as-needed basis? (yes|no)
+
+;rtupdate=yes ; Send registry updates to database using realtime? (yes|no)
+ ; If set to yes, when a IAX2 peer registers successfully, the ip address,
+ ; the origination port, the registration period, and the username of
+ ; the peer will be set to database via realtime. If not present, defaults to 'yes'.
+
+;rtautoclear=yes ; Auto-Expire friends created on the fly on the same schedule
+ ; as if it had just registered? (yes|no|<seconds>)
+ ; If set to yes, when the registration expires, the friend will vanish from
+ ; the configuration until requested again. If set to an integer,
+ ; friends expire within this number of seconds instead of the
+ ; registration interval.
+
+;rtignoreexpire=yes ; When reading a peer from Realtime, if the peer's registration
+ ; has expired based on its registration interval, used the stored
+ ; address information regardless. (yes|no)
+
+iaxthreadcount = 8
+
+[misery]
+type=user
+context=default
+
+; Guest sections for unauthenticated connection attempts. Just specify an
+; empty secret, or provide no secret section.
+;
+;[guest]
+;type=user
+;context=default
+;callerid="Guest IAX User"
+
+;
+; Trust Caller*ID Coming from iaxtel.com
+;
+[iaxtel]
+type=user
+context=default
+auth=rsa
+inkeys=iaxtel
+
+;
+; Trust Caller*ID Coming from iax.fwdnet.net
+;
+[iaxfwd]
+type=user
+context=default
+auth=rsa
+inkeys=freeworlddialup
+
+;
+; Trust callerid delivered over DUNDi/e164
+;
+;
+;[dundi]
+;type=user
+;dbsecret=dundi/secret
+;context=dundi-e164-local
+
+;
+; Further user sections may be added, specifying a context and a secret used
+; for connections with that given authentication name. Limited IP based
+; access control is allowed by use of "allow" and "deny" keywords. Multiple
+; rules are permitted. Multiple permitted contexts may be specified, in
+; which case the first will be the default. You can also override caller*ID
+; so that when you receive a call you set the Caller*ID to be what you want
+; instead of trusting what the remote user provides
+;
+; There are three authentication methods that are supported: md5, plaintext,
+; and rsa. The least secure is "plaintext", which sends passwords cleartext
+; across the net. "md5" uses a challenge/response md5 sum arrangement, but
+; still requires both ends have plain text access to the secret. "rsa" allows
+; unidirectional secret knowledge through public/private keys. If "rsa"
+; authentication is used, "inkeys" is a list of acceptable public keys on the
+; local system that can be used to authenticate the remote peer, separated by
+; the ":" character. "outkey" is a single, private key to use to authenticate
+; to the other side. Public keys are named /var/lib/asterisk/keys/<name>.pub
+; while private keys are named /var/lib/asterisk/keys/<name>.key. Private
+; keys should always be 3DES encrypted.
+;
+;
+;[markster]
+;type=user
+;context=default
+;context=local
+;auth=md5,plaintext,rsa
+;secret=markpasswd
+;setvar=foo=bar
+;dbsecret=mysecrets/place ; Secrets can be stored in astdb, too
+;notransfer=yes ; Disable IAX native transfer
+;jitterbuffer=yes ; Override global setting an enable jitter buffer
+; ; for this user
+;callerid="Mark Spencer" <(256) 428-6275>
+;deny=0.0.0.0/0.0.0.0
+;accountcode=markster0101
+;permit=209.16.236.73/255.255.255.0
+;language=en ; Use english as default language
+;
+; Peers may also be specified, with a secret and
+; a remote hostname.
+;
+[demo]
+type=peer
+username=asterisk
+secret=supersecret
+host=216.207.245.47
+;sendani=no
+;host=asterisk.linux-support.net
+;port=5036
+;mask=255.255.255.255
+;qualify=yes ; Make sure this peer is alive
+;qualifysmoothing = yes ; use an average of the last two PONG
+ ; results to reduce falsly detected LAGGED hosts
+ ; Default: Off
+;qualifyfreqok = 60000 ; how frequently to ping the peer when
+ ; everything seems to be ok, in milliseconds
+;qualifyfreqnotok = 10000 ; how frequently to ping the peer when it's
+ ; either LAGGED or UNAVAILABLE, in milliseconds
+;jitterbuffer=no ; Turn off jitter buffer for this peer
+
+;
+; Peers can remotely register as well, so that they can be mobile. Default
+; IP's can also optionally be given but are not required. Caller*ID can be
+; suggested to the other side as well if it is for example a phone instead of
+; another PBX.
+;
+
+;[dynamichost]
+;host=dynamic
+;secret=mysecret
+;mailbox=1234 ; Notify about mailbox 1234
+;inkeys=key1:key2
+;peercontext=local ; Default context to request for calls to peer
+;defaultip=216.207.245.34
+;callerid="Some Host" <(256) 428-6011>
+;
+
+;
+;[biggateway]
+;type=peer
+;host=192.168.0.1
+;context=*
+;secret=myscret
+;trunk=yes ; Use IAX2 trunking with this host
+;timezone=America/New_York ; Set a timezone for the date/time IE
+;
+
+;
+; Friends are a short cut for creating a user and
+; a peer with the same values.
+;
+;[marko]
+;type=friend
+;host=dynamic
+;regexten=1234
+;secret=moofoo
+;context=default
+;permit=0.0.0.0/0.0.0.0
+
--- /dev/null
+;
+; SIP Configuration example for Asterisk
+;
+; Syntax for specifying a SIP device in extensions.conf is
+; SIP/devicename where devicename is defined in a section below.
+;
+; You may also use
+; SIP/username@domain to call any SIP user on the Internet
+; (Don't forget to enable DNS SRV records if you want to use this)
+;
+; If you define a SIP proxy as a peer below, you may call
+; SIP/proxyhostname/user or SIP/user@proxyhostname
+; where the proxyhostname is defined in a section below
+;
+; Useful CLI commands to check peers/users:
+; sip show peers Show all SIP peers (including friends)
+; sip show users Show all SIP users (including friends)
+; sip show registry Show status of hosts we register with
+;
+; sip debug Show all SIP messages
+;
+; reload chan_sip.so Reload configuration file
+; Active SIP peers will not be reconfigured
+;
+
+[general]
+context=default ; Default context for incoming calls
+allowguest=no ; Allow or reject guest calls (default is yes, this can also be set to 'osp'
+ ; if asterisk was compiled with OSP support.
+;realm=mydomain.tld ; Realm for digest authentication
+ ; defaults to "asterisk"
+ ; Realms MUST be globally unique according to RFC 3261
+ ; Set this to your host name or domain name
+bindport=5060 ; UDP Port to bind to (SIP standard port is 5060)
+bindaddr=0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all)
+srvlookup=yes ; Enable DNS SRV lookups on outbound calls
+ ; Note: Asterisk only uses the first host
+ ; in SRV records
+ ; Disabling DNS SRV lookups disables the
+ ; ability to place SIP calls based on domain
+ ; names to some other SIP users on the Internet
+
+;domain=mydomain.tld ; Set default domain for this host
+ ; If configured, Asterisk will only allow
+ ; INVITE and REFER to non-local domains
+ ; Use "sip show domains" to list local domains
+;domain=mydomain.tld,mydomain-incoming
+ ; Add domain and configure incoming context
+ ; for external calls to this domain
+;domain=1.2.3.4 ; Add IP address as local domain
+ ; You can have several "domain" settings
+;allowexternalinvites=no ; Disable INVITE and REFER to non-local domains
+ ; Default is yes
+;autodomain=yes ; Turn this on to have Asterisk add local host
+ ; name and local IP to domain list.
+;pedantic=yes ; Enable slow, pedantic checking for Pingtel
+ ; and multiline formatted headers for strict
+ ; SIP compatibility (defaults to "no")
+;tos=184 ; Set IP QoS to either a keyword or numeric val
+;tos=lowdelay ; lowdelay,throughput,reliability,mincost,none
+;maxexpiry=3600 ; Max length of incoming registration we allow
+;defaultexpiry=120 ; Default length of incoming/outoing registration
+;notifymimetype=text/plain ; Allow overriding of mime type in MWI NOTIFY
+;checkmwi=10 ; Default time between mailbox checks for peers
+;vmexten=voicemail ; dialplan extension to reach mailbox sets the
+ ; Message-Account in the MWI notify message
+ ; defaults to "asterisk"
+;videosupport=yes ; Turn on support for SIP video
+;recordhistory=yes ; Record SIP history by default
+ ; (see sip history / sip no history)
+
+;disallow=all ; First disallow all codecs
+;allow=ulaw ; Allow codecs in order of preference
+;allow=ilbc ;
+;musicclass=default ; Sets the default music on hold class for all SIP calls
+ ; This may also be set for individual users/peers
+;language=en ; Default language setting for all users/peers
+ ; This may also be set for individual users/peers
+;relaxdtmf=yes ; Relax dtmf handling
+;rtptimeout=60 ; Terminate call if 60 seconds of no RTP activity
+ ; when we're not on hold
+;rtpholdtimeout=300 ; Terminate call if 300 seconds of no RTP activity
+ ; when we're on hold (must be > rtptimeout)
+;trustrpid = no ; If Remote-Party-ID should be trusted
+;sendrpid = yes ; If Remote-Party-ID should be sent
+;progressinband=never ; If we should generate in-band ringing always
+ ; use 'never' to never use in-band signalling, even in cases
+ ; where some buggy devices might not render it
+;useragent=Asterisk PBX ; Allows you to change the user agent string
+;promiscredir = no ; If yes, allows 302 or REDIR to non-local SIP address
+ ; Note that promiscredir when redirects are made to the
+ ; local system will cause loops since SIP is incapable
+ ; of performing a "hairpin" call.
+;usereqphone = no ; If yes, ";user=phone" is added to uri that contains
+ ; a valid phone number
+;dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833
+ ; Other options:
+ ; info : SIP INFO messages
+ ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
+ ; auto : Use rfc2833 if offered, inband otherwise
+
+;compactheaders = yes ; send compact sip headers.
+;sipdebug = yes ; Turn on SIP debugging by default, from
+ ; the moment the channel loads this configuration
+;subscribecontext = default ; Set a specific context for SUBSCRIBE requests
+ ; Useful to limit subscriptions to local extensions
+ ; Settable per peer/user also
+;notifyringing = yes ; Notify subscriptions on RINGING state
+
+;
+; If regcontext is specified, Asterisk will dynamically create and destroy a
+; NoOp priority 1 extension for a given peer who registers or unregisters with
+; us. The actual extension is the 'regexten' parameter of the registering
+; peer or its name if 'regexten' is not provided. More than one regexten may
+; be supplied if they are separated by '&'. Patterns may be used in regexten.
+;
+;regcontext=sipregistrations
+;
+; Asterisk can register as a SIP user agent to a SIP proxy (provider)
+; Format for the register statement is:
+; register => user[:secret[:authuser]]@host[:port][/extension]
+;
+; If no extension is given, the 's' extension is used. The extension needs to
+; be defined in extensions.conf to be able to accept calls from this SIP proxy
+; (provider).
+;
+; host is either a host name defined in DNS or the name of a section defined
+; below.
+;
+; Examples:
+;
+;register => 1234:password@mysipprovider.com
+;
+; This will pass incoming calls to the 's' extension
+;
+;
+;register => 2345:password@sip_proxy/1234
+;
+; Register 2345 at sip provider 'sip_proxy'. Calls from this provider
+; connect to local extension 1234 in extensions.conf, default context,
+; unless you configure a [sip_proxy] section below, and configure a
+; context.
+; Tip 1: Avoid assigning hostname to a sip.conf section like [provider.com]
+; Tip 2: Use separate type=peer and type=user sections for SIP providers
+; (instead of type=friend) if you have calls in both directions
+
+;registertimeout=20 ; retry registration calls every 20 seconds (default)
+;registerattempts=10 ; Number of registration attempts before we give up
+ ; 0 = continue forever, hammering the other server until it
+ ; accepts the registration
+ ; Default is 0 tries, continue forever
+;callevents=no ; generate manager events when sip ua performs events (e.g. hold)
+
+; register mini-asterisk voip line providers here
+
+;register => user@user/user ; mini-asterisk - do not change this comment
+
+;----------------------------------------- NAT SUPPORT ------------------------
+; The externip, externhost and localnet settings are used if you use Asterisk
+; behind a NAT device to communicate with services on the outside.
+
+;externip = 200.201.202.203 ; Address that we're going to put in outbound SIP messages
+ ; if we're behind a NAT
+
+ ; The externip and localnet is used
+ ; when registering and communicating with other proxies
+ ; that we're registered with
+;externhost=foo.dyndns.net ; Alternatively you can specify an
+ ; external host, and Asterisk will
+ ; perform DNS queries periodically. Not
+ ; recommended for production
+ ; environments! Use externip instead
+;externrefresh=10 ; How often to refresh externhost if
+ ; used
+ ; You may add multiple local networks. A reasonable set of defaults
+ ; are:
+;localnet=192.168.0.0/255.255.0.0; All RFC 1918 addresses are local networks
+;localnet=10.0.0.0/255.0.0.0 ; Also RFC1918
+;localnet=172.16.0.0/12 ; Another RFC1918 with CIDR notation
+;localnet=169.254.0.0/255.255.0.0 ;Zero conf local network
+
+; The nat= setting is used when Asterisk is on a public IP, communicating with
+; devices hidden behind a NAT device (broadband router). If you have one-way
+; audio problems, you usually have problems with your NAT configuration or your
+; firewall's support of SIP+RTP ports. You configure Asterisk choice of RTP
+; ports for incoming audio in rtp.conf
+;
+;nat=no ; Global NAT settings (Affects all peers and users)
+ ; yes = Always ignore info and assume NAT
+ ; no = Use NAT mode only according to RFC3581
+ ; never = Never attempt NAT mode or RFC3581 support
+ ; route = Assume NAT, don't send rport
+ ; (work around more UNIDEN bugs)
+
+;rtcachefriends=yes ; Cache realtime friends by adding them to the internal list
+ ; just like friends added from the config file only on a
+ ; as-needed basis? (yes|no)
+
+;rtupdate=yes ; Send registry updates to database using realtime? (yes|no)
+ ; If set to yes, when a SIP UA registers successfully, the ip address,
+ ; the origination port, the registration period, and the username of
+ ; the UA will be set to database via realtime. If not present, defaults to 'yes'.
+
+;rtautoclear=yes ; Auto-Expire friends created on the fly on the same schedule
+ ; as if it had just registered? (yes|no|<seconds>)
+ ; If set to yes, when the registration expires, the friend will vanish from
+ ; the configuration until requested again. If set to an integer,
+ ; friends expire within this number of seconds instead of the
+ ; registration interval.
+
+;ignoreregexpire=yes ; Enabling this setting has two functions:
+ ;
+ ; For non-realtime peers, when their registration expires, the information
+ ; will _not_ be removed from memory or the Asterisk database; if you attempt
+ ; to place a call to the peer, the existing information will be used in spite
+ ; of it having expired
+ ;
+ ; For realtime peers, when the peer is retrieved from realtime storage,
+ ; the registration information will be used regardless of whether
+ ; it has expired or not; if it expires while the realtime peer is still in
+ ; memory (due to caching or other reasons), the information will not be
+ ; removed from realtime storage
+
+; Incoming INVITE and REFER messages can be matched against a list of 'allowed'
+; domains, each of which can direct the call to a specific context if desired.
+; By default, all domains are accepted and sent to the default context or the
+; context associated with the user/peer placing the call.
+; Domains can be specified using:
+; domain=<domain>[,<context>]
+; Examples:
+; domain=myasterisk.dom
+; domain=customer.com,customer-context
+;
+; In addition, all the 'default' domains associated with a server should be
+; added if incoming request filtering is desired.
+; autodomain=yes
+;
+; To disallow requests for domains not serviced by this server:
+; allowexternaldomains=no
+
+; fromdomain=mydomain.tld ; When making outbound SIP INVITEs to
+ ; non-peers, use your primary domain "identity"
+ ; for From: headers instead of just your IP
+ ; address. This is to be polite and
+ ; it may be a mandatory requirement for some
+ ; destinations which do not have a prior
+ ; account relationship with your server.
+
+[authentication]
+; Global credentials for outbound calls, i.e. when a proxy challenges your
+; Asterisk server for authentication. These credentials override
+; any credentials in peer/register definition if realm is matched.
+;
+; This way, Asterisk can authenticate for outbound calls to other
+; realms. We match realm on the proxy challenge and pick an set of
+; credentials from this list
+; Syntax:
+; auth = <user>:<secret>@<realm>
+; auth = <user>#<md5secret>@<realm>
+; Example:
+;auth=mark:topsecret@digium.com
+;
+; You may also add auth= statements to [peer] definitions
+; Peer auth= override all other authentication settings if we match on realm
+
+;------------------------------------------------------------------------------
+; Users and peers have different settings available. Friends have all settings,
+; since a friend is both a peer and a user
+;
+; User config options: Peer configuration:
+; -------------------- -------------------
+; context context
+; permit permit
+; deny deny
+; secret secret
+; md5secret md5secret
+; dtmfmode dtmfmode
+; canreinvite canreinvite
+; nat nat
+; callgroup callgroup
+; pickupgroup pickupgroup
+; language language
+; allow allow
+; disallow disallow
+; insecure insecure
+; trustrpid trustrpid
+; progressinband progressinband
+; promiscredir promiscredir
+; useclientcode useclientcode
+; accountcode accountcode
+; setvar setvar
+; callerid callerid
+; amaflags amaflags
+; call-limit call-limit
+; restrictcid restrictcid
+; subscribecontext subscribecontext
+; videosupport videosupport
+; mailbox
+; username
+; template
+; fromdomain
+; regexten
+; fromuser
+; host
+; port
+; qualify
+; defaultip
+; rtptimeout
+; rtpholdtimeout
+; sendrpid
+
+;[sip_proxy]
+; For incoming calls only. Example: FWD (Free World Dialup)
+; We match on IP address of the proxy for incoming calls
+; since we can not match on username (caller id)
+;type=peer
+;context=from-fwd
+;host=fwd.pulver.com
+
+;[sip_proxy-out]
+;type=peer ; we only want to call out, not be called
+;secret=guessit
+;username=yourusername ; Authentication user for outbound proxies
+;fromuser=yourusername ; Many SIP providers require this!
+;fromdomain=provider.sip.domain
+;host=box.provider.com
+;usereqphone=yes ; This provider requires ";user=phone" on URI
+;call-limit=5 ; permit only 5 simultaneous outgoing calls to this peer
+
+;------------------------------------------------------------------------------
+; Definitions of locally connected SIP phones
+;
+; type = user a device that authenticates to us by "from" field to place calls
+; type = peer a device we place calls to or that calls us and we match by host
+; type = friend two configurations (peer+user) in one
+;
+; For local phones, type=friend works most of the time
+;
+; If you have one-way audio, you propably have NAT problems.
+; If Asterisk is on a public IP, and the phone is inside of a NAT device
+; you will need to configure nat option for those phones.
+; Also, turn on qualify=yes to keep the nat session open
+
+;[grandstream1]
+;type=friend
+;context=from-sip ; Where to start in the dialplan when this phone calls
+;callerid=John Doe <1234> ; Full caller ID, to override the phones config
+;host=192.168.0.23 ; we have a static but private IP address
+ ; No registration allowed
+;nat=no ; there is not NAT between phone and Asterisk
+;canreinvite=yes ; allow RTP voice traffic to bypass Asterisk
+;dtmfmode=info ; either RFC2833 or INFO for the BudgeTone
+;call-limit=1 ; permit only 1 outgoing call and 1 incoming call at a time
+ ; from the phone to asterisk
+ ; (1 for the explicit peer, 1 for the explicit user,
+ ; remember that a friend equals 1 peer and 1 user in
+ ; memory)
+;mailbox=1234@default ; mailbox 1234 in voicemail context "default"
+;disallow=all ; need to disallow=all before we can use allow=
+;allow=ulaw ; Note: In user sections the order of codecs
+ ; listed with allow= does NOT matter!
+;allow=alaw
+;allow=g723.1 ; Asterisk only supports g723.1 pass-thru!
+;allow=g729 ; Pass-thru only unless g729 license obtained
+;astdb=chan2ext/SIP/grandstream1=1234 ; ensures an astDB entry exists
+
+
+;[xlite1]
+; Turn off silence suppression in X-Lite ("Transmit Silence"=YES)!
+; Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed
+;type=friend
+;regexten=1234 ; When they register, create extension 1234
+;callerid="Jane Smith" <5678>
+;host=dynamic ; This device needs to register
+;nat=yes ; X-Lite is behind a NAT router
+;canreinvite=no ; Typically set to NO if behind NAT
+;disallow=all
+;allow=gsm ; GSM consumes far less bandwidth than ulaw
+;allow=ulaw
+;allow=alaw
+;mailbox=1234@default,1233@default ; Subscribe to status of multiple mailboxes
+
+
+;[snom]
+;type=friend ; Friends place calls and receive calls
+;context=from-sip ; Context for incoming calls from this user
+;secret=blah
+;subscribecontext=localextensions ; Only allow SUBSCRIBE for local extensions
+;language=de ; Use German prompts for this user
+;host=dynamic ; This peer register with us
+;dtmfmode=inband ; Choices are inband, rfc2833, or info
+;defaultip=192.168.0.59 ; IP used until peer registers
+;mailbox=1234@context,2345 ; Mailbox(-es) for message waiting indicator
+;vmexten=voicemail ; dialplan extension to reach mailbox
+ ; sets the Message-Account in the MWI notify message
+ ; defaults to global vmexten which defaults to "asterisk"
+;restrictcid=yes ; To have the callerid restriced -> sent as ANI
+;disallow=all
+;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw!
+
+
+;[polycom]
+;type=friend ; Friends place calls and receive calls
+;context=from-sip ; Context for incoming calls from this user
+;secret=blahpoly
+;host=dynamic ; This peer register with us
+;dtmfmode=rfc2833 ; Choices are inband, rfc2833, or info
+;username=polly ; Username to use in INVITE until peer registers
+ ; Normally you do NOT need to set this parameter
+;disallow=all
+;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw!
+;progressinband=no ; Polycom phones don't work properly with "never"
+
+
+;[pingtel]
+;type=friend
+;secret=blah
+;host=dynamic
+;insecure=port ; Allow matching of peer by IP address without matching port number
+;insecure=invite ; Do not require authentication of incoming INVITEs
+;insecure=port,invite ; (both)
+;qualify=1000 ; Consider it down if it's 1 second to reply
+ ; Helps with NAT session
+ ; qualify=yes uses default value
+;callgroup=1,3-4 ; We are in caller groups 1,3,4
+;pickupgroup=1,3-5 ; We can do call pick-p for call group 1,3,4,5
+;defaultip=192.168.0.60 ; IP address to use if peer has not registred
+
+;[cisco1]
+;type=friend
+;secret=blah
+;qualify=200 ; Qualify peer is no more than 200ms away
+;nat=yes ; This phone may be natted
+ ; Send SIP and RTP to the IP address that packet is
+ ; received from instead of trusting SIP headers
+;host=dynamic ; This device registers with us
+;canreinvite=no ; Asterisk by default tries to redirect the
+ ; RTP media stream (audio) to go directly from
+ ; the caller to the callee. Some devices do not
+ ; support this (especially if one of them is
+ ; behind a NAT).
+;defaultip=192.168.0.4 ; IP address to use until registration
+;username=goran ; Username to use when calling this device before registration
+ ; Normally you do NOT need to set this parameter
+;setvar=CUSTID=5678 ; Channel variable to be set for all calls from this device
+
+; Pre-configured SIP extensions
+
+[6011]
+type=friend
+context=default
+host=dynamic
+secret=6011
+canreinvite=no
+callerid=6011
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6012]
+type=friend
+context=default
+host=dynamic
+secret=6012
+canreinvite=no
+callerid=6012
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6013]
+type=friend
+context=default
+host=dynamic
+secret=6013
+canreinvite=no
+callerid=6013
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6014]
+type=friend
+context=default
+host=dynamic
+secret=6014
+canreinvite=no
+callerid=6014
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6015]
+type=friend
+context=default
+host=dynamic
+secret=6015
+canreinvite=no
+callerid=6015
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6016]
+type=friend
+context=default
+host=dynamic
+secret=6016
+canreinvite=no
+callerid=6016
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6017]
+type=friend
+context=default
+host=dynamic
+secret=6017
+canreinvite=no
+callerid=6017
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6018]
+type=friend
+context=default
+host=dynamic
+secret=6018
+canreinvite=no
+callerid=6018
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6019]
+type=friend
+context=default
+host=dynamic
+secret=6019
+canreinvite=no
+callerid=6019
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6020]
+type=friend
+context=default
+host=dynamic
+secret=6020
+canreinvite=no
+callerid=6020
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6021]
+type=friend
+context=default
+host=dynamic
+secret=6021
+canreinvite=no
+callerid=6021
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+[6022]
+type=friend
+context=default
+host=dynamic
+secret=6022
+canreinvite=no
+callerid=6022
+disallow=all
+allow=ulaw,alaw
+qualify=yes
+
+; Pre-configured mini-asterisk SIP trunks
+
+;[user] ; "SIP-NAT" mini-asterisk do not remove this comment
+;; You reach your ITSP via a NAT router (most common)
+;type=friend
+;context=default
+;username=user
+;secret=password
+;host=192.168.1.28
+;canreinvite=no
+;disallow=all
+;allow=ulaw,alaw
+;qualify=yes
+;nat=yes
+
+;[user] ; "SIP" mini-asterisk do not remove this comment
+;; No NAT router between your Phone system and your ITSP
+;type=friend
+;context=default
+;username=user
+;secret=password
+;host=192.168.1.28
+;canreinvite=no
+;disallow=all
+;allow=ulaw,alaw
+;qualify=yes
+
+;[user] ; "Jazmin" mini-asterisk do not remove this comment
+;; <a href="http://www.jazmin.com.au/">Jazmin</a> are a South Australian ITSP
+;host=sip.jazmin.net.au
+;secret=<Password>
+;username=<username>
+;fromdomain=sip.jazmin.net.au
+;fromuser=<username>
+;insecure=port,invite
+;type=friend
+;disallow=all
+;allow=ulaw
+;allow=alaw
+;dtmfmod=rfc2833
+;qualify=yes
+;canreinvite=no
+;nat=yes
+
--- /dev/null
+#!/bin/sh
+# update_revision.sh
+#
+# Sets correct Revision number in the about screen. Good idea to
+# run this before installing
+
+ver=`svn info | grep Revision`
+sed -i "s/Revision: [0-9]*/$ver/" cgi-bin/about.sh
+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-\f
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-\f
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
+++ /dev/null
-# Makefile
-# David Rowe 1 Jan 2010
-#
-# Makefile for Mini Asterisk GUI
-#
-# 1/ Download files to development box for testing:
-#
-# usage: make HOST=test.machine.ip|hostname test
-# make HOST=192.168.1.150 test
-# make HOST=boris test
-#
-# 2/ Create static copy of web pages from HOST for static demo
-#
-# usage: make HOST=test.machine.ip static
-
-test:
- scp cgi-bin/*.html cgi-bin/*.sh cgi-bin/*.pl cgi-bin/*.js cgi-bin/*.css \
- cgi-bin/*.png root@$(HOST):/www
- scp etc/asterisk/*.conf root@$(HOST):/etc/asterisk
-
-.PHONY : static
-static:
- # generate static pages
-
- rm -Rf static; mkdir static; cd static; \
- wget -rEk --header="Cookie: loggedin=1" http://$(HOST)/phones.sh
-
- # modify links to non-existent scripts on static demo
-
- sed -i "s,http://$(HOST)/set_network.sh,network.sh.html," static/$(HOST)/network.sh.html
- sed -i "s,http://$(HOST)/set_ring.sh,phones.sh.html," static/$(HOST)/phones.sh.html
- sed -i "s,http://$(HOST)/set_voiplines.sh,voiplines.sh.html," static/$(HOST)/voiplines.sh.html
- sed -i "s,url=login.sh,url=phones.sh.html," static/$(HOST)/logout.sh.html
-
-
+++ /dev/null
-Mini Asterisk
-=============
-
-A simple, light weight GUI for Asterisk.
-
-image::/images/ip04/mini.png["Mini Asterisk Demo", link="mini/phones.sh.html"]
-
-Click on the screen shot above for an on line demo.
-
-[[intro]]
-Introduction
-------------
-
-Mini Asterisk is a simple Web GUI for Asterisk with comprehensive tool
-tip documentation and a learning curve of a few minutes. Analog ports
-and IP Phones are automatically detected, and no knowledge of Asterisk
-configuration is required.
-
-Mini Asterisk is "unfeatured" - many of the Asterisk options are not
-available. Instead it tries to make very basic, very common Asterisk
-installations fast and simple, for example:
-
-* An Asterisk server running on your home gateway/firewall/server.
- You want to connect a few IP Phones and make cheap phones calls
- using VOIP. An Asterisk distro on a CD is a possibility but you
- don't want to dedicate a full PC just for Asterisk. You don't
- really want to learn Asterisk dial plan syntax and yet another conf
- file format.
-
-* A small office that already has an old analog phone system. You
- want to keep your current analog lines for incoming calls, but use
- IP Phones for handsets and VOIP for outgoing calls. You know enough
- to set up a DSL router and don't want to rely on "the Phone Guy" or
- "The Computer Guy" at $100/hr to maintain your phone system.
-
-* You are a "Phone Guy" who doesn't understand Linux and Asterisk but
- you want to install IP-PBXes.
-
-[[why]]
-Why Another Asterisk GUI?
--------------------------
-
-There are http://www.voip-info.org/wiki/view/Asterisk+GUI[a lot of
-Asterisk GUIs] out there already. So why do we need another one?
-
-Well I needed an Asterisk GUI that was very easy to use for the
-link:ip04.html[IP0X] family. Something that would lower
-the technical skill required to install and maintain an Asterisk Phone
-system. Something my wife and kids could use.
-
-The IP0X can't run a LAMP stack very well so the GUI had to be light
-weight.
-
-I was also interested in exploring the ease-of-use meme, as we have
-been discussing it a lot on the http://villagetelco.org[Village Telco]
-project. Just how easy can we make Asterisk to use? So I scratched
-the itch.
-
-Mini Asterisk has the following features that make it reasonably
-unique. They may be good or bad features depending on your point of
-view!
-
-* Mini Asterisk is "un-featured" - it hides many of the advanced
- Asterisk features in the interest of simple and fast configuration.
-
-* Light weight so it can run on embedded boxes like the IP0X family.
- No SQL database or PHP or LAMP. Only a basic web server and a very
- basic Perl are required (microperl - no CPAN libraries).
-
-* Works directly on extensions.conf and sip.conf, but honors any edits
- you make to these files. So all the powerful Asterisk features are
- available if after a while you want to dive into Asterisk conf files.
-
-* Doesn't use AJAX or the built-in Asterisk web server or users.conf
- magic. Plain old HTML, a little Java-script and CGIs written in
- shell script and Perl.
-
-* Doesn't use the Asterisk programming model. For example you don't
- have to understand what a dial plan is, much less understand how to
- code one. Plain English terms are used instead, for example "Phones
- and Phone lines". Terms like Asterisk, Linux, SIP, Zap/1 don't even
- get mentioned.
-
-* Extensive tool tip documentation. No manual.
-
-* Doesn't require a dedicated PC, not installed from an ISO CD. So
- you can use it as a GUI for Asterisk on a little SOHO Linux box that
- is also your firewall, server etc.
-
-* Mini Asterisk tells you when something is wrong, for example you get
- a warning if your Phone System can't see the Internet, or if it can't
- see your ITSP.
-
-* Extensive pre-configuration of extensions.conf and sip.conf. The
- phone numbers of extensions are pre-configured and ITSP
- configurations are selected from a pull-down menu. Analog ports are
- auto detected, at least on the IP0X. This makes adding phones and
- ITSPs fast and simple. It also gives people new to Asterisk a
- working starting point.
-
-[[status]]
-Status
-------
-
-Alpha:
-
-* Works on IP0X.
-* Works on x86 but many features (like upgrades) disabled in the
- interests of security. These need to be implemented on x86 in a safe way.
-* Tested on asterisk 1.4.x
-* Needs feedback from real users to see how useful the concept is and what
- (un)features need to be added.
-* Need a few more (un)features to be added, and Voip Line screen
- populated with more ITSPs.
-* But quite useable as it stands, especially as a way to get started
- quickly with the IP0X.
-
-[[notes]]
-Implementation Notes
---------------------
-
-Mini Asterisk is written for the
-http://rowetel.com/ucasterisk/ip04.html[IP0X embedded Asterisk]
-hardware but will also run on x86 and probably many other platforms.
-
-Mini Asterisk has been written to be compatible with regular Asterisk
-conf file configuration. Just leave the conf file lines with
-"mini-asterisk" comments alone. The Asterisk conf files
-extensions.conf and sip.conf are directly modified by Mini Asterisk,
-but changes are limited to the "mini-asterisk" lines.
-
-For Auto-detection of Zap ports Mini Asterisk looks at
-/etc/zapata.conf, so you may need this set up correctly for your
-analog hardware. On the IP0X this happens automatically.
-
-The scripts need to run as root to run asterisk commands. This is
-probably OK an on IP0X but not a good idea on an x86. I am not happy
-with this security model and would appreciate any suggestions on how
-to improve it.
-
-Mini Asterisk uses the following technologies: HTML, CSS, Javascript,
-CGI, Shell scripting, Perl, Asterisk. But most of the work is done in
-shell script and HTML, with a little Perl for the text processing.
-
-The msh shell on the IP0X is fairly basic (no functions, several
-quirks). The shell script has been coded so that it runs OK on the
-IP0X, which is upwards compatible to x86.
-
-You can customise Mini Asterisk by adding your own banner to in
-banner.html.
-
-[[install]]
-Installation
-------------
-
-NOTE: this process may overwrite your Asterisk extensions.conf and
-sip.conf files - back them up if you have an existing Asterisk
-installation that you want to keep. The IP0X ipkg does attempt to
-backup the modified conf files to *.bak but no guarantees....
-
-However once mini-asterisk is installed it should honor any manual
-changes made to extensions.conf and sip.conf.
-
-IP0X Installation
-~~~~~~~~~~~~~~~~~
-
-Installation instructions for IP0X boxes running link:baps.html[BAPS],
-with some version of Asterisk and Zaptel installed.
-
--------------------------------------------------------------------
-root~> ipkg install mini-asterisk
--------------------------------------------------------------------
-
-x86 Installation
-~~~~~~~~~~~~~~~~
-
-You need a web server, Asterisk and some sort of Perl installed
-(very basic Perl installation is fine). Configure your web server to
-run CGIs (.sh and .pl) from your server root. Lighttpd config
-instructions are below.
-
-Mini Asterisk expects all files (shell, perl, html etc) to be in the
-same directory. If you find this painful please <<support, let me know>>.
-
-The process below places the web files in /var/www, you may like to
-place the files somewhere else. One of the files is named index.html
-so make sure you don't overwrite an existing index.html.
-
-. Login as root.
-
-. If you haven't done so already install Asterisk 1.4.x:
-+
--------------------------------------------------------------------
-# wget http://downloads.asterisk.org/pub/telephony/asterisk/old-releases/asterisk-1.4.11.tar.gz
-# tar xvzf asterisk-1.4.11.tar.gz
-# cd asterisk-1.4.11
-# ./configure
-# make
-# make install
-# make samples
--------------------------------------------------------------------
-
-. If you have a running Asterisk installation backup your existing
-extensions.conf & sip.conf in /etc/asterisk
-
-. Installation of Mini Asterisk is basically copying the cgi-bin and etc/asterisk
-files:
-+
--------------------------------------------------------------------
-# cd ~
-# svn co https://freetel.svn.sourceforge.net/svnroot/freetel/mini-asterisk-gui
-# cd mini-asterisk-gui
-# ./update_revision.sh
-# cp etc/asterisk/* /etc/asterisk
-# cp cgi-bin/* /var/www
-# cd /etc/asterisk
-# cp extensions.conf extensions.conf.def
-# cp sip.conf sip.conf.def
-# mv users.conf users.conf.bak
--------------------------------------------------------------------
-+
-The .def copies are required by the "reset defaults" feature on the
-admin screen.
-
-. It's a good idea to switch off the internal Asterisk web server by editing
-/etc/asterisk/http.conf. Make sure the enabled line reads like this:
-+
- enabled=no
-+
-Then stop and restart Asterisk.
-+
--------------------------------------------------------------------
-# /etc/init.d/asterisk restart
--------------------------------------------------------------------
-
-. I use lighttpd as the web server. To enable CGI support:
-+
--------------------------------------------------------------------
-# lighty-enable-mod cgi
--------------------------------------------------------------------
-+
-I then modified 10-cgi-conf to enable perl and shell scripts:
-+
--------------------------------------------------------------------
-cgi.assign = (
- ".pl" => "/usr/bin/perl",
- ".sh" => "/bin/sh",
-)
--------------------------------------------------------------------
-+
-Make sure lighttpd runs as root, as we need to run Asterisk etc from
-shell script CGIs:
-+
--------------------------------------------------------------------
-## change uid to <uid> (default: don't care)
-#server.username = "wwwrun"
-
-## change uid to <uid> (default: don't care)
-#server.groupname = "wwwrun"
--------------------------------------------------------------------
-+
-Then restart lighttpd after all the changes:
-+
---------------------------------------------------------------------
-# /etc/init.d/lighttpd restart
-------------------------------------------------------------------
-+
-For comparison on the IP04 I just modified /etc/lighttpd.conf:
-+
--------------------------------------------------------------------
-cgi.assign = ( ".sh" => "/bin/sh",".pl" => "/usr/bin/perl" )
--------------------------------------------------------------------
-
-[[contribute]]
-Contributions
--------------
-
-. I especially welcome sip.conf entries for your favourite ITSP (VOIP
-service) to help populate the Provider field of the
-link:mini/voiplines.sh.html[Voip Line Screen].
-
-. Suggestions and patches for new features are also very welcome.
-
-. Help making the web pages look nicer.
-
-. Configuration instructions (even photos) for other IP phones.
-
-[[support]]
-Support
--------
-
-Comments, features request, bugs please let me know using Free
-Telephony Project
-https://lists.sourceforge.net/lists/listinfo/freetel-discuss[Mailing
-List]
-
-[[source]]
-Source Code
------------
-
-Browse:
-
-http://freetel.svn.sourceforge.net/viewvc/freetel/mini-asterisk-gui/[http://freetel.svn.sourceforge.net/viewvc/freetel/mini-asterisk-gui/]
-
-Check Out:
-
- $ svn co https://freetel.svn.sourceforge.net/svnroot/freetel/mini-asterisk-gui
-
-[[test]]
-Testing and debugging scripts
------------------------------
-
-. To download all the GUI scripts to an IP0X machine with the host name "ip04":
-
- [david@bunny mini-asterisk-gui]$ make HOST=ip04 test
-+
-
-However this is a bit slow. So when editing on an x86 host and testing
-on an IP0X I used the M-! command on Emacs that lets you execute a
-shell command. I use this to download just the single the shell file
-I am working on, e.g. "scp admin.sh root@ip04".
-
-. A simple cookie is used to indicate logged in status. To run
- scripts for each screen from the command line (for example to spot
- script syntax errors):
-+
-IP0X:
-+
- root:/www> export HTTP_COOKIE="loggedin=1" ; sh admin.sh
-+
-If you encounter a syntax error when testing a script on an IP0X
-then running the same script on an x86 can be useful as it has much
-better error reporting:
-+
-x86:
-+
- [david@host cgi-bin]$ export HTTP_COOKIE="loggedin=1" ; sh admin.sh
-
-. If running using the sh command you can also trace execution with
- the "-x" option:
-+
- [david@host cgi-bin]$ sh -x login.sh
-
-. Testing forms from the command line can be achieved by manually
-setting up the CGI QUERY_STRING environment variable:
-+
- [david@host cgi-bin]$ export QUERY_STRING="pass=uClinux" ; sh login.sh
+++ /dev/null
-#!/bin/sh
-# about.sh
-# David Rowe 7 Jan 2010
-# About screen for Mini Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-cat << EOF
-<html>
-<title>Mini Asterisk - About</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <table align="right" width=600>
- <tr><td align="left" valign="top"><h2>About</h2></td></tr>
-EOF
-echo ' <tr><td><a href="http://rowetel.com/ucasterisk/mini.html">Mini Asterisk</a> Revision: 156 </td></tr> '
-echo ' <tr><td> </td></tr>'
-echo ' <tr><td>Brought to you by the <a href="http://rowetel.com/ucasterisk/index.html">Free Telephony Project</a></td></tr>'
-echo ' <tr><td><a href="http://rowetel.com/ucasterisk/ip04.html"><img src="http://rowetel.com/images/ip04/ip04_case.jpg" border="0" /></a></td></tr>'
-
-more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
-if [ $more -eq 1 ]; then
- echo
-else
- echo " <tr><td> </td></tr>"
- echo ' <tr><td><a href="about.sh?more=1">More</a></td></tr>';
-cat <<EOF
- </table>
- </td>
- </tr>
-</table>
-</body>
-</html>
-EOF
-exit
-fi
-
-echo " <tr><td> </td></tr>"
-echo " <tr><td><h3>cat /proc/version</h3></td></tr>"
-echo " <tr><td>"
-cat /proc/version
-echo " </td></tr>"
-
-which ipkg >> /dev/null
-if [ $? -eq 0 ]; then
- echo " <tr><td> </td></tr>"
- echo " <tr><td><h3>ipkg list_installed</h3></td></tr>"
- echo " <tr><td>"
- ipkg list_installed | tr '\n' '#' | sed -n 's/\#/<br>/pg'
- echo " </td></tr>"
-fi
-
-echo " <tr><td> </td></tr>"
-echo " <tr><td><h3>cat /proc/loadavg</h3></td></tr>"
-echo " <tr><td>"
-cat /proc/loadavg
-echo " </td></tr>"
-
-echo " <tr><td> </td></tr>"
-echo " <tr><td><h3>uptime</h3></td></tr>"
-echo " <tr><td>"
-uptime
-echo " </td></tr>"
-
-echo " <tr><td> </td></tr>"
-echo " <tr><td><h3>cat /proc/meminfo</h3></td></tr>"
-echo " <tr><td>"
-cat /proc/meminfo | tr '\n' '#' | sed -n 's/\#/<br>/pg'
-echo " </td></tr>"
-
-echo " <tr><td> </td></tr>"
-echo " <tr><td><h3>cat /proc/cmdline</h3></td></tr>"
-echo " <tr><td>"
-cat /proc/cmdline
-echo " </td></tr>"
-
-echo " <tr><td> </td></tr>"
-echo " <tr><td><h3>cat /proc/cpuinfo</h3></td></tr>"
-echo " <tr><td>"
-cat /proc/cpuinfo
-echo " </td></tr>"
-
-if [ -f /proc/mtd ]; then
- echo " <tr><td> </td></tr>"
- echo " <tr><td><h3>cat /proc/mtd</h3></td></tr>"
- echo " <tr><td>"
- cat /proc/mtd | tr '\n' '#' | sed -n 's/\#/<br>/pg'
- echo " </td></tr>"
-fi
-
-if [ -f /proc/yaffs ]; then
- echo " <tr><td> </td></tr>"
- echo " <tr><td><h3>cat /proc/yaffs</h3></td></tr>"
- echo " <tr><td>"
- cat /proc/yaffs | tr '\n' '#' | sed -n 's/\#/<br>/pg'
- echo " </td></tr>"
-fi
-
-echo " <tr><td> </td></tr>"
-echo ' <tr><td><a href="about.sh">Less</a></td></tr>';
-
-cat <<EOF
- </table>
-
- </td>
-
- </tr>
-
-</table>
-</body>
-</html>
-EOF
-
+++ /dev/null
-#!/bin/sh
-# admin.sh
-# David Rowe 7 Jan 2010
-# Admin screen for Mini Asterisk GUI
-
-# check we are logged in ----------------------------------------
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# check what sort of machine we are running on. Many operations
-# outlawed for x86
-
-cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
-if [ $? -eq 0 ]; then
- mach="ip0x"
-else
- mach="x86"
-fi
-
-# set password CGI -----------------------------------------------
-
-echo "$QUERY_STRING" | grep -oe "pass=" > /dev/null
-if [ $? -eq 0 ]; then
- if [ $mach != "ip0x" ] ; then
- echo "<html>Sorry, only supported on the IP0X</html>"
- exit
- fi
-
- pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
- passwd_cmdline $pass
-fi
-
-# restart CGI ----------------------------------------------------
-
-echo "$QUERY_STRING" | grep -oe "restart=1" > /dev/null
-if [ $? -eq 0 ]; then
-
- if [ $mach != "ip0x" ] ; then
- echo "<html>Sorry, only supported on the IP0X</html>"
- exit
- fi
-
-# kill cookie to log out. This ensures hitting refresh wont run
-# the restart process again
-
-cat <<EOF
-Content-type: text/html
-Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
-
-<head>
-<title>Mini Asterisk - Restart</title>
-</head>
-<body>
-<h2>Restarting...come back in 1 minute</h2>
-</body>
-EOF
-reboot
-fi
-
-# set defaults CGI ----------------------------------------------------
-
-echo "$QUERY_STRING" | grep -oe "defaults=1" > /dev/null
-if [ $? -eq 0 ]; then
- cp /etc/asterisk/extensions.conf.def /etc/asterisk/extensions.conf
- cp /etc/asterisk/sip.conf.def /etc/asterisk/sip.conf
- asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
- asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
-fi
-
-# Upgrade Mini Asterisk CGI -------------------------------------------
-
-echo "$QUERY_STRING" | grep -oe "upgrade=1" > /dev/null
-if [ $? -eq 0 ]; then
-
- # test if we are running on an IP0X
- which ipkg >> /dev/null
- if [ $? -eq 1 ]; then
- echo "<html>Sorry, only supported on the IP0X</html>"
- exit
- fi
-
- cat <<EOF
- <html>
- <head>
- <title>Mini Asterisk - Upgrade</title>
- </head>
- <body>
- <h2>Upgrading...</h2>
-EOF
-
- rev_before=`grep -oe "Revision: [0-9]*" /www/about.sh`
- echo "<strong>Current $rev_before</strong><br>"
- echo "<strong>Removing $ver_before</strong><br>"
- ipkg remove mini-asterisk-gui | tr '\n' '#' | sed -n 's/\#/<br>/pg'
- echo "<strong>Installing...</strong><br>"
- ipkg update | tr '\n' '#' | sed -n 's/\#/<br>/pg'
- ipkg install mini-asterisk-gui | tr '\n' '#' | sed -n 's/\#/<br>/pg'
-
- # Note - never actually gets here as admin.sh is wiped out by upgrade..
- # need a better way of handling this....
-
- rev_after=`grep -oe "Revision: [0-9]*" /www/about.sh`
- echo "<strong>$rev_after installed</strong>"
- echo "</body></html>"
- exit
-fi
-
-# Install New Firmware CGI ----------------------------------------------------
-# this is just a nasty option to run an arbitrary script as root!
-# not a good idea on x86 platforms...but a nice way of upgrading IP0X
-
-echo "$QUERY_STRING" | grep -oe "firmwareurl=" > /dev/null
-if [ $? -eq 0 ]; then
-
- if [ $mach != "ip0x" ] ; then
- echo "<html>Sorry, only supported on IP0X</html>"
- exit
- fi
-
- firmwareurl=`echo "$QUERY_STRING" | grep -oe "firmwareurl=[^&?]*" | sed -n "s/firmwareurl=//p"`
- # convert URL encoded string, this can just handle : and / so be careful
- # with script names
- firmwareurl=`echo $firmwareurl | sed -e "s/%3A/:/" -e "s_%2F_/_g"`
- wget $firmwareurl
- filename=`echo $firmwareurl | sed 's_^.*/__'`
- sh $filename
- exit
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-cat << EOF
-<html>
-<title>Mini Asterisk - Admin</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <table align="right" width=600>
- <tr><td> </td></tr>
- <form action="admin.sh" method="get">
- <tr><td align="left" valign="top"><h2>Admin</h2></td></tr>
-
- <tr><td> </td></tr>
- <tr><td colspan="2"><h3>Change Phone System Password</h3></td></tr>
- <tr><td>New Password:</td><td><input type="password" name="pass" ></td>
- <td><input type="submit" value="Set Password"></td>
- </tr>
- <tr><td> </td></tr>
- <tr><td></td><td>Default password is uClinux</td>
- </form>
-
- <tr><td> </td></tr>
- <tr><td colspan="2"><h3>Restart Phone System</h3></td>
- <td onMouseOver="popUp(event,'admin_restart')" onmouseout="popUp(event,'admin_restart')">
- <form action="admin.sh" method="get">
- <input type="hidden" name="restart" value="1">
- <input type="submit" value="Restart">
- </form>
- </td>
- </tr>
-
- <tr><td> </td></tr>
- <tr><td colspan="2"><h3>Reset Phone System Defaults</h3></td>
- <td>
- <form action="admin.sh" method="get">
- <input type="hidden" name="defaults" value="1">
- <input type="submit" value="Reset">
- </form>
- </td>
- </tr>
-
- <tr><td> </td></tr>
- <tr onMouseOver="popUp(event,'admin_upgrade')" onmouseout="popUp(event,'admin_upgrade')">
- <td colspan="2"><h3>Upgrade Mini Asterisk</h3></td>
- <td>
- <form action="admin.sh" method="get">
- <input type="hidden" name="upgrade" value="1">
- <input type="submit" value="Upgrade">
- </form>
- </td>
- </tr>
-
- <tr><td> </td></tr>
- <tr><td colspan="2"><h3>Install New Firmware</h3>
- <form action="admin.sh" method="get">
- <tr onMouseOver="popUp(event,'admin_firmware')" onmouseout="popUp(event,'admin_firmware')">
- <td>Firmware URL:</td>
- <td><input type="text" size="45" name="firmwareurl" ></td>
- <td><input type="submit" value="Install"></td>
- </tr>
- </form>
-
- </table>
- </form>
-
- </td>
-
- </tr>
-
-</table>
-</body>
-</html>
-EOF
-
+++ /dev/null
-<ol>
-<li>Connect the WAN port of the AT-530 to your network, it will boot and obtain an IP via DHCP.
-<li>Find the <strong>IP</strong> of the phone by pressing the <strong>Sysinfo</strong> button a few times.
-<li>Open another browser window. Go to the phones <strong>IP</strong>, for example <strong>http://192.168.1.160</strong>
-<li>Login to the phone using the username/password <strong>admin/admin</strong>.
-<li>Optional: set a static IP using the WAN menu (I like static IPs for SIP phones).
-<li>Go to the phone <strong>SIP Config</strong> menu.
-<li>Set <strong>Register Server Address</strong> to your Phone System IP Address.
-<li>Set <strong>Register Username</strong> to the phone number (e.g. 6011).
-<li>Also set </strong>Register Password</strong> to the phone number (e.g. 6011) and
-the </strong>Phone Number</strong> to the phone number (e.g. 6011).
-<li>Check the <strong>Enable Register</strong> box.
-<li>Then click on <strong>Apply</strong>.
-<li>On your browser refresh this page to see if the phone is connected to your phone system.
-</ol>
+++ /dev/null
-<ol>
-
-<li>Connect the WAN port of the AT-620R to your network, it will boot and obtain an IP via DHCP.
-
-<li>Press the <strong>Menu</strong> button. Enter <strong>123</strong> for the password, and press the <strong>OK</strong> soft button.
-
-<li>Using the <strong>down</strong> direction button (just beneath the menu key) move to the <strong>Product Info</strong> menu. Then press the down button again and select <strong>Network Status</strong>. The IP of the phone will be displayed at the top of the screen, for example 192.168.1.160.
-
-<li>On your PC open another browser window. Go to the phones <strong>IP</strong>, for example <strong>http://192.168.1.160</strong>
-
-<li>Login to the phone using the username/password <strong>admin/admin</strong>.
-
-<li>Go to the phone <strong>VOIP</strong> menu.
-
-<li>Set <strong>Server Address</strong> to your Phone System IP Address.
-
-<li>Set <strong>Account Name</strong> to the phone number (e.g. 6011).
-
-<li>Also set </strong>Password</strong> to the phone number (e.g. 6011) and <strong>Phone Number</strong> and <strong>Display Name</strong> to the phone number (e.g. 6011).
-
-<img src="at-620r.png" />
-
-<li>Check the <strong>Enable Register</strong> box.
-
-<li>Then click on <strong>Apply</strong>.
-
-<li>On your browser refresh this page to see if the phone is connected to your phone system.
-</ol>
-
+++ /dev/null
- <tr><td colspan="2"><h2> </h2></td></tr>
+++ /dev/null
-<ol>
-
-<li><strong>How do I set up my Phone system?</strong>
- <ol>
- <li> Hover your mouse to get instructions (try the menu to the left).</li>
- <li> Analog Ports are detected automatically.</li>
- <li> Set up your <a href="network.sh">Network</a>.</li>
- <li> Add your <a href="ipphones.sh">IP Phones</a>.</li>
- <li> Configure your <a href="voiplines.sh">Voip Line</a>.</li>
- <li> The <a href="phones.sh">Phone System</a> page gives you a
- summary of your phone system and tells you how to make calls
- (hover your mouse).</li>
- </ol>
-</li>
-
-<li><strong>Where can I find out more about Mini Asterisk:</strong> The <a href="http://rowetel.com/ucasterisk/mini.html">Mini Asterisk Home Page</a>.
-
-<li><strong>Where can I get Support:</strong> You can try the
- <a href="https://lists.sourceforge.net/lists/listinfo/freetel-discuss">Free Telephony Project</a> Mailing List.
-
-<li><strong>Answer a call on another ringing phone</strong>: If you
- hear another phone ringing and want to answer the call on your
- phone, just pick up your phone and dial *8. Note an IP phone can
- pick up a call on a ringing IP phone but not an Analog phone. An
- Analog pohone can pick up another ringing Analog phone but not an
- IP phone.
-
-<li><strong>Put a call on hold/transfer:</strong> On an IP Phone try
- the recall or transfer button. On an Analog Phone hold down the
- hook button for 1 second then dial the new number.
-
-<li><strong>Why another Asterisk GUI</strong> I had some specific
- needs for a light weight, very easy to use GUI for
- the <a href="http://www.rowetel.com/ucasterisk/ip04.html">IP0X</a>
- line of products. So I scratched the itch. More
- information <a href="http://www.rowetel.com/ucasterisk/mini.html#why">here</a>.
-
-</ol>
-
-<h2>Resources and Links</h2>
-<ol>
-<li>If you want to learn more about Asterisk a good on-line book is <a href="http://astbook.asteriskdocs.org">Asterisk - The Future of Telephony</a>
-</ol>
+++ /dev/null
-#!/bin/sh
-# faq.sh
-# David Rowe 7 Jan 2010
-# FAQ screen for Mini Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-cat << EOF
-<html>
-<title>Mini Asterisk - FAQ</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <table align="right" width=600>
- <tr><td align="left" valign="top"><h2>FAQ</h2></td></tr>
- <tr><td>
-EOF
-cat faq.html
-cat <<EOF
- </td></tr>
- </table>
-
- </td>
-
- </tr>
-
-</table>
-</body>
-</html>
-EOF
-
+++ /dev/null
-<html>
-<head>
-<meta http-equiv="REFRESH" content="0;url=http:login.sh">
-</head>
-</html>
\ No newline at end of file
+++ /dev/null
-function localInit() {
-}
-
+++ /dev/null
-#!usr/bin/perl
-# ipphones.pl
-# David Rowe 6 Jan 2010
-#
-# Text processing for the ipphones screen
-
-$ipaddress = $ARGV[0];
-$more = $ARGV[1];
-
-# Slurp up SIP extension (Sip) data from extensions.conf
-
-my %ip = (); # ip extension keyed on sip.conf name
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) {
- if (/.*=>[ ]*([0-9]*),1.*SIP\/([0-9]*)\)/) {
- $ip{$2} = $1;
- #print "'$1' '$2' $ip{$2}\n";
- }
-}
-close EXT;
-
-my %sip = (); # SIP IP phone status keyed on sip.conf names
- # if no entry we can't see IP phone device
-my %voip = (); # SIP trunks status keyed on sip.conf names
- # if no entry we can't see SIP trunk
-my %ipad = (); # IP address of SIP device keyed on sip.conf names
-
-open SIP, "sipshowpeers.txt";
-while (<SIP>) {
- if (/^([0-9]*)[\s\/].*(OK)/) {
- $sip{$1} = $2;
- #print "'$1' '$2' $sip{$1}\n";
- $e = $1;
- if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
- $ipad{$e} = $1;
- #print "'$1'\n";
- }
- }
- if (/^(voip[0-9]*)[\s\/].*(OK)/) {
- $voip{$1} = $2;
- #print "'$1' '$2' $voip{$1}\n";
- $e = $1;
- if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
- $ipad{$e} = $1;
- #print "'$1'\n";
- }
- }
-}
-
-close SIP;
-
-# print list of IP phones with connection status
-
-$unconnected = 0;
-foreach $e (sort keys %ip) {
- if ($sip{$e} eq "OK") {
- $icon = "<img src=\"tick.png\" alt=\"Connected\" />";
- $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_connected')\" onmouseout=\"popUp(event,'ipphones_connected')\"";
- $comment=$ipad{$e};
- $tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
- $tooltip_ip = "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
- $unconnected = 0;
- }
- else {
- $unconnected = $unconnected + 1;
- $icon = "<img src=\"cross.png\" alt=\"Not Connected\" />";
- $tooltip_status = "onMouseOver=\"popUp(event,'ipphones_notconnected')\" onmouseout=\"popUp(event,'ipphones_notconnected')\"";
- $comment="Available";
- $tooltip_id = "iphones_$e";
- print "<div id=\"$tooltip_id\" class=\"tip\"> Configure your IP phone with username/password $e/$e, SIP Server IP $ipaddress</div>";
- $tooltip_ext = "onMouseOver=\"popUp(event,'$tooltip_id')\" onmouseout=\"popUp(event,'$tooltip_id')\"";
- $tooltip_ip = "";
- }
-
- if ($more == 1 || ($unconnected < 5)) {
- print "<tr><td $tooltip_ext>$e</td><td></td><td $tooltip_ip>$comment</td><td $tooltip_status>$icon</td></tr>\n";
- }
-}
-
-if ($more == 0) {
- print '<tr><td><a href="ipphones.sh?more=1">More</a></td></tr>';
-}
-else {
- print '<tr><td><a href="ipphones.sh">Less</a></td></tr>';
-}
-
-
+++ /dev/null
-#!/bin/sh
-# dashboard.sh
-# David Rowe 6 Jan 2010
-# Dashboard screen for Mini Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-more=`echo "$QUERY_STRING" | grep -oe "more=[^&?]*" | sed -n "s/more=//p"`
-
-# Build list of interface IPs based on what sort of machine we are
-# running on. For IP0X we just print the IP of the first interface.
-# For other machines the situation is a bit more complex so we print
-# all of them. I figure anyone with multiple interfaces will know
-# enough about what they are doing to figure out the right one to use.
-
-ipaddress=`ifconfig | sed -n 's/.*inet addr:\(.*\) Bcast.*/\1/p'`
-
-cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
-if [ $? -eq 0 ]; then
- ipaddress=`echo $ipaddress | awk '{ print $1 }'`
- ipaddress_system=$ipaddress
- ipaddress_tooltip=$ipaddress
-else
- ipaddress_system=`echo $ipaddress | sed -n 's/ /<br>/p'`
-
- # make nice tooltips for multiple ip interfaces on some x86 boxes
-
- ipaddress_tooltip=`echo $ipaddress | sed -n 's/ / or /p'`
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-echo "<script>"
-echo 'var init_internet="'$internet'";'
-cat ipphones.js
-echo "</script>"
-
-cat << EOF
-<html>
-<title>Mini Asterisk - IP Phones</title>
-<body onload="localInit()">
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800 border=0>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <table align="right" width=600 border=0>
- <tr><td onMouseOver="popUp(event,'ipphones_ipphones')" onmouseout="popUp(event,'ipphones_ipphones')"
- colspan="4" align="left" valign="top" ><h2>IP Phones</h2></td></tr>
- <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
- <td colspan="3">Phone System IP Address:</td>
-EOF
-echo "<td>$ipaddress_system</td>"
-
- # use perl to construct list of IP phones for us
- asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
- perl ipphones.pl "$ipaddress_tooltip" $more
-
-cat <<EOF
- </table>
-
- <h2> <br>How to Configure IP Phones</h2>
- <h3>1. Atcom AT-530</h3>
-EOF
-cat at-530.html
-echo "<h3>2. Atcom AT-620R</h3>"
-cat at-620r.html
-cat <<EOF
- </td>
- </tr>
-
-</table>
-</body>
-</html>
-EOF
-
+++ /dev/null
-#!/bin/sh
-# login.sh
-# David Rowe 4 Jan 2010
-# CGI for Mini Asterisk login GUI
-
-pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
-
-echo $QUERY_STRING | grep pass > /dev/null
-if [ $? -eq 1 ]; then
- # Display form -------------------------------
-
- cat <<EOF
- <script src="prototype.js"></script>
- <script type="text/javascript" src="tooltip.js"></script>
- <link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
- cat << EOF
- <html>
- <title>Mini Asterisk - Login</title>
- <form action="login.sh" method="get">
- <table align="center" width=600>
- <tr><td colspan="2" align="left"><h2>Login</h2></td>
- <tr>
- <tr><td>Password:</td><td><input type="password" name="pass" ></td></tr>
- <tr><td><input type="submit" value="Login"></td></tr>
- </tr>
- <tr><td></td><td>Default password is uClinux</td>
- </table>
- </form>
- </html>
-EOF
-else
-
- # If we are a non-blackfin then use hard coded password for now.
- # I don't feel comfortable sending root password through a web
- # GUI for x86 boxes, but this is reasonable approach for embedded
- # systems. TODO: add a way to store and modify x86 passwds
-
- cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
- if [ $? -eq 0 ]; then
- # Blackfin IP0X system
- testuser root "$pass"; res=$?
- else
- [ $pass = "uClinux" ] ; res=$?
- fi
-
- if [ $res -eq 0 ]; then
-
- # login sucessful
- echo "Content-type: text/html"
- echo "Set-Cookie: loggedin=1"
- echo ""
- echo "<head>"
- echo "<title>Mini Asterisk - Login</title>"
- echo '<meta http-equiv="REFRESH" content="0;url=phones.sh">'
- echo "</head>"
- echo "<body>"
- echo "Please wait a few seconds....."
- echo "</body>"
-
- # load mini asterisk conf files in case this is our first login
-
- asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
- asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
-
- else
- # login failed
- cat <<EOF
- <html>
- <head>
- <title>Mini Asterisk - Login</title>
- <meta http-equiv="REFRESH" content="0;url=login.sh">
- <body>
- Please wait a few seconds.....
- </body>
- </head>
- </html>
-EOF
- fi
-fi
-
+++ /dev/null
-#!/bin/sh
-# logout.sh
-# David Rowe 4 Jan 2010
-# CGI for Mini Asterisk logout GUI
-
-cat <<EOF
-Content-type: text/html
-Set-Cookie: loggedin=1; expires=Thursday, 01-Jan-98 12:00:00 GMT
-
-<title>Mini Asterisk - Logout</title>
-<meta http-equiv="REFRESH" content="0;url=login.sh"
-EOF
-#echo $HTTP_COOKIE
+++ /dev/null
- <div id="admin_tip" class="tip">Change your password, reset the default settings, upgrade software</div>
- <div id="network_tip" class="tip">Connect the phone system to your network and the Internet</div>
- <div id="phones_tip" class="tip">Lists your phones and phone lines</div>
- <div id="ipphones_tip" class="tip">Set up your IP phones</div>
- <div id="about_tip" class="tip">Boring information like software version numbers</div>
- <div id="faq_tip" class="tip">Frequently asked questions and links to further information</div>
- <div id="logout_tip" class="tip">I think you can work this one out....</div>
- <div id="voipline_tip" class="tip">Set up your VOIP phone line</div>
- <td valign="top" >
- <table align="right" width=200>
- <tr><td><h2> </h2></td></tr>
- <tr onMouseOver="popUp(event,'phones_tip')" onmouseout="popUp(event,'phones_tip')">
- <td><a href="phones.sh">Phone System</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'about_tip')" onmouseout="popUp(event,'about_tip')">
- <td><a href="about.sh">About</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'admin_tip')" onmouseout="popUp(event,'admin_tip')">
- <td><a href="admin.sh">Admin</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'faq_tip')" onmouseout="popUp(event,'faq_tip')">
- <td><a href="faq.sh">FAQ</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'ipphones_tip')" onmouseout="popUp(event,'ipphones_tip')">
- <td><a href="ipphones.sh">IP Phones</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'logout_tip')" onmouseout="popUp(event,'logout_tip')">
- <td><a href="logout.sh">Logout</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'network_tip')" onmouseout="popUp(event,'network_tip')">
- <td><a href="network.sh">Network</a></td>
- </tr>
- <tr onMouseOver="popUp(event,'voipline_tip')" onmouseout="popUp(event,'voipline_tip')">
- <td><a href="voiplines.sh">VOIP Line</a></td>
- </tr>
- </table>
- </td>
+++ /dev/null
-body,h1,h2,h3,h4,h5,h6,p,center,td,th,ul,dl,div {
- font-family: Geneva, Arial, Helvetica, sans-serif;
- }
-
-
+++ /dev/null
-var script_path = "cgi-bin/";
-
-function doStatic() {
- $('ipaddress').disabled = 0;
- $('netmask').disabled = 0;
- $('gateway').disabled = 0;
- $('dns').disabled = 0;
-}
-
-function doDHCP() {
- $('ipaddress').disabled = 1;
- $('netmask').disabled = 1;
- $('gateway').disabled = 1;
- $('dns').disabled = 1;
-}
-
-// http://moblog.bradleyit.com/2009/06/javascript-ip-address-validation.html
-
-function isIP(obj) {
- var ary = obj.value.split(".");
- var ip = true;
-
- ip = (ary.length == 4);
-
- if (ip) {
- for (var i=0; i<4; i++) {
- ip = (!ary[i].match(/^\d{1,3}$/) || (Number(ary[i]) > 255)) ? false : ip;
- }
- }
-
- if (!ip) {
- // the value is NOT a valid IP address
- obj.style.background = "red";
- obj.select();
- }
- else { obj.style.background = ""; } // the value IS a valid IP address
-
- return ip;
-}
-
-function localInit() {
-
- if (init_dhcp == "yes") {
- $('dhcp').checked = true;
- $('ipaddress').disabled = 1;
- $('netmask').disabled = 1;
- $('gateway').disabled = 1;
- $('dns').disabled = 1;
- }
- else {
- $('static').checked = true;
- $('ipaddress').disabled = 0;
- $('netmask').disabled = 0;
- $('gateway').disabled = 0;
- $('dns').disabled = 0;
- }
- $('ipaddress').value = init_ipaddress;
- $('netmask').value = init_netmask;
- $('gateway').value = init_gateway;
- $('dns').value = init_dns;
- $('backdoor').value = init_backdoor;
- if (init_internet == "yes")
- $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
- else
- $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
-
-}
-
-function validate_form(form)
-{
- var valid = true;
-
- if ($('dhcp').checked == false)
- valid = isIP(form.ipaddress) && isIP(form.ipaddress) && isIP(form.gateway) && isIP(form.dns);
-
- return valid;
-}
+++ /dev/null
-#!/bin/sh
-# network.sh
-# David Rowe 4 Jan 2010
-# CGI for Mini Asterisk network GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# check what sort of machine we are running on. We only support this screen for
-# IP0X
-
-cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
-if [ ! $? -eq 0 ]; then
-cat <<EOF
- <html>
- Sorry, Network configuration is only supported on the IP0X. Anyway you
- probably have a good way of setting up your network already.
- </html>
-EOF
- exit
-fi
-
-grok_network=0
-
-if [ -f /etc/rc.d/S10network ]; then
- grok_network=1
- dhcp=yes
- ipaddress=`ifconfig eth0 | sed -n 's/.*inet addr:\(.*\) Bcast.*/\1/p'`
- netmask=`ifconfig eth0 | sed -n 's/.*Mask:\(.*\)\s*/\1/p'`
- gateway=`route -n | awk '/^0.0.0.0/ {print $2}'`
- dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
-fi
-
-if [ -f /etc/rc.d/S10network-static ]
-then
- grok_network=1
- dhcp=no
- ipaddress=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-static`
- netmask=`sed -n 's/NETMASK="\(.*\)"/\1/p' /etc/init.d/network-static`
- gateway=`sed -n 's/GATEWAY="\(.*\)"/\1/p' /etc/init.d/network-static`
- dns=`sed -n 's/DNS="\(.*\)"/\1/p' /etc/init.d/network-static`
-fi
-
-# if we don't understand this machines network config then bail
-
-if [ $groknetwork -eq 0 ]; then
-cat << EOF
-<html>
-<title>Mini Asterisk - Network</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800 border=0>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
- <table align="center" width=600 border=0>
- <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
- <tr><td>Sorry - I can't edit the Network configuration on this machine</td></tr>
- </td>
- </table>
- </td>
- </tr>
-
-</table>
-
-</html>
-EOF
-fi
-
-if [ -f /etc/rc.d/S05network-backdoor ]; then
- backdoor=`sed -n 's/IPADDRESS="\(.*\)"/\1/p' /etc/init.d/network-backdoor`
-fi
-
-# See if we have Internet connectivity, first check dns as time outs can be very slow
-
-dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
-internet="no";
-if [ $dns_packet_loss = "0" ]; then
- packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
- if [ $packet_loss = "0" ]; then
- internet="yes";
- fi
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-echo "<script>"
-echo 'var init_dhcp="'$dhcp'";'
-echo 'var init_ipaddress="'$ipaddress'";'
-echo 'var init_netmask="'$netmask'";'
-echo 'var init_gateway="'$gateway'";'
-echo 'var init_dns="'$dns'";'
-echo 'var init_backdoor="'$backdoor'";'
-echo 'var init_internet="'$internet'";'
-cat network.js
-echo "</script>"
-
-cat << EOF
-<html>
-<title>Mini Asterisk - Network</title>
-<body onload="localInit()">
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800 border=0>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <form action="set_network.sh" onsubmit="return validate_form(this)" method="get">
- <table align="center" width=600 border=0>
- <tr><td colspan="2" align="left" valign="top"><h2>Network</h2></td></tr>
- <tr>
- <td><input type="radio" id="static" name="dhcp" value="no" onClick="doStatic()">Static</td>
- <td><input type="radio" id="dhcp" name="dhcp" value="yes" onClick="doDHCP()">DHCP</td>
- </tr>
- <tr><td>IP Address:</td><td><input type="text" name="ipaddress" id="ipaddress" onBlur="isIP(this)"></td></tr>
- <tr><td>Netmask:</td><td><input type="text" name="netmask" id="netmask" onBlur="isIP(this)"></td></tr>
- <tr><td>Gateway:</td><td><input type="text" name="gateway" id="gateway" onBlur="isIP(this)"></td></tr>
- <tr><td>DNS:</td><td><input type="text" name="dns" id="dns" onBlur="isIP(this)"></td></tr>
- <tr onMouseOver="popUp(event,'network_backdoor')" onmouseout="popUp(event,'network_backdoor')">
- <td>Emergency IP:</td><td><input type="text" name="backdoor" id="backdoor" onBlur="isIP(this)"></td>
- </tr>
- <tr onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">
- <td>Internet Connection:</td>
- <td><div id="internet" >
- <span style="margin-left: 4px;font-weight:bold"> </span></div></td>
-
- </tr>
- <tr><td><input id="networkapply" type="submit" value="Apply"></td></tr>
- </table>
- </form>
-
- </td>
-
- </tr>
-
-</table>
-
-</html>
-EOF
-
+++ /dev/null
-function localInit() {
- if (init_internet == "yes")
- $('internet').innerHTML = '<img src="tick.png" alt="tick" />';
- else
- $('internet').innerHTML = '<img src="cross.png" alt="tick" />';
-}
-
+++ /dev/null
-#!/usr/bin/perl
-# phones.pl
-# David Rowe 5 Jan 2010
-#
-# Text processing for the phones screen.
-
-$tool_tip = "onMouseOver=\"popUp(event,'network_internet')\" onmouseout=\"popUp(event,'network_internet')\"";
-
-# Slurp up analog port (Zap) data from extensions.conf
-
-my %analog = (); # analog extension keyed on zap port
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) {
- if (/.*=>[ ]*([0-9]*),1.*Zap\/([0-9]*)\)/) {
- $analog{$2} = $1;
- #print "'$1' '$2' $analog{$2}\n";
- }
-}
-close EXT;
-
-# Slurp up data on installed zaptel ports from /etc/zaptel.conf
-
-my %zap = (); # zaptel port type keyed on zap port
- # (fxs/fxo or no entry if not live)
-open ZAP, "/etc/zaptel.conf";
-while (<ZAP>) {
- if (/fxoks=(.*)/) {
- @fxs = split(/,/, $1);
- foreach (@fxs) {
- $zap{$_} = "fxs";
- }
- }
- if (/fxsks=(.*)/) {
- @fxo = split(/,/, $1);
- foreach (@fxo) {
- $zap{$_} = "fxo";
- }
- }
-}
-close ZAP;
-
-# Slurp up SIP extension (Sip) data from extensions.conf
-
-my %ip = (); # ip extension keyed on sip.conf name
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) {
- if (/.*=>[ ]*([0-9]*),1.*Sip\/([0-9]*)\)/) {
- $ip{$2} = $1;
- #print "'$1' '$2' $ip{$2}\n";
- }
-}
-close EXT;
-
-# Determine which extenions are "Reception", i.e. set to ring on incoming
-# calls
-
-my %zap_ring = (); # ring flag keyed on Zap port (1,2...)
-my %sip_ring = (); # ring flag keyed on sip.cong ext name (6011,6012 etc)
-
-open EXT, "/etc/asterisk/extensions.conf";
-while (<EXT>) {
- if (/s,1,Dial\((.*)\) ;; mini/) {
- @ring = split(/&/, $1);
- #print "'$1' '@ring'\n foreach:\n";
- foreach (@ring) {
- #print " $_\n";
- if (/Zap\/([0-9]*)/) {
- $zap_ring{$1} = 1;
- #print "'$_' $1 \n";
- }
- if (/SIP\/([0-9]*)/) {
- $sip_ring{$1} = 1;
- #print "'$_' $1 \n";
- }
- }
- }
-}
-close EXT;
-
-
-# work out which IP phones are registered -----------------------------------
-
-my %sip = (); # SIP IP phone status keyed on sip.conf names (6011,6012 etc)
- # if no entry we can't see IP phone device
-my %ipad = (); # IP address of SIP device keyed on sip.conf names
-
-open SIP, "sipshowpeers.txt";
-while (<SIP>) {
-
- # just look for 4 digit extensions starting with 6 so we don't
- # confuse with Voip Line
-
- if (/^(6[0-9][0-9][0-9])[\s\/].*(OK)/) {
- $sip{$1} = $2;
- #print "'$1' '$2' $sip{$1}\n";
- $e = $1;
- if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
- $ipad{$e} = $1;
- #print "'$1'\n";
- }
- }
-
- if (/^(.*)\/.*(OK)/) {
- #$sip{$1} = $2;
- #print "'$1' '$2' $sip{$1}\n";
- $e = $1;
- if (/\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
- $ipad{$e} = $1;
- #print "'$1'\n";
- }
- }
-}
-
-close SIP;
-
-# Determine if Asterisk can see current voip line (SIP trunk)
-# sipshowpeers.txt needs to be generated before calling this perl
-# script
-
-my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
- # if no entry we can't see SIP trunk
-
-open SIP, "sipshowregistry.txt";
-while (<SIP>) {
- if (/^(.*):.*(Registered)/) {
- $voip{$1} = $2;
- #print "'$1' '$2' $voip{$1}\n";
- }
-}
-
-close SIP;
-
-# start phones ringing form -------------------------------------------
-
-print '<form action="set_ring.sh" method="get">';
-
-# print list of analog phones
-
-$tooltip_anphone = "onMouseOver=\"popUp(event,'phone_anphone')\" onmouseout=\"popUp(event,'phone_anphone')\"";
-$tooltip_ext = "onMouseOver=\"popUp(event,'phone_ext')\" onmouseout=\"popUp(event,'phone_ext')\"";
-$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_phone')\" onmouseout=\"popUp(event,'phone_port_phone')\"";
-$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
-
-foreach $a (sort keys %analog) {
- if ($zap{$a} eq "fxs") {
- $icon = "<img src=\"tick.png\" alt=\"Analog Phone OK\" />";
- print "<tr><td $tooltip_ext>$analog{$a}</td><td $tooltip_anphone>Analog Phone</td><td $tooltip_port>Port $a</td>";
- if ($zap_ring{$a} == 1) {
- $checked = "checked";
- }
- else {
- $checked = "";
- }
- print "<td $tooltip_reception><input type=\"checkbox\" name=\"Zap_$a\" $checked>Reception</td><td>$icon</td></tr>\n";
- }
-}
-
-# print list of IP phones
-
-$tooltip_ipphone = "onMouseOver=\"popUp(event,'phone_ipphone')\" onmouseout=\"popUp(event,'phone_ipphone')\"";
-$tooltip_ipphone_ip = "onMouseOver=\"popUp(event,'phone_ipphone_ip')\" onmouseout=\"popUp(event,'phone_ipphone_ip')\"";
-$tooltip_reception = "onMouseOver=\"popUp(event,'phone_reception')\" onmouseout=\"popUp(event,'phone_reception')\"";
-
-foreach $s (sort keys %sip) {
- if ($sip{$s} eq "OK") {
- $icon = "<img src=\"tick.png\" alt=\"IP Phone OK\" />";
- print "<tr><td $tooltip_ext>$s</td><td $tooltip_ipphone>IP Phone</td><td $tooltip_ipphone_ip>$ipad{$s}</td>";
- if ($sip_ring{$s} == 1) {
- $checked = "checked";
- }
- else {
- $checked = "";
- }
- print "<td $tooltip_reception><input type=\"checkbox\" name=\"SIP_$s\" $checked>Reception</td><td>$icon</td></tr>\n";
- }
-}
-
-print '<tr><td> </td></tr>';
-print "<tr><td colspan=\"2\" onMouseOver=\"popUp(event,'phone_addipphone')\" onmouseout=\"popUp(event,'phone_addipphone')\">";
-
-$tooltip_update_reception = "onMouseOver=\"popUp(event,'phone_update_reception')\" onmouseout=\"popUp(event,'phone_update_reception')\"";
-print "<a href=\"ipphones.sh\">Add IP Phone</a></td><td></td><td $tooltip_update_reception><input type=\"submit\" value=\"Update Reception\"></td></tr>";
-
-$tool_tip = "onMouseOver=\"popUp(event,'phone_lines')\" onmouseout=\"popUp(event,'phone_lines')\"";
-
-print '<tr><td> </td></tr>';
-print "<tr $tool_tip><td colspan=\"4\" align=\"left\" valign=\"top\" ><h2>Phone Lines</h2></td></tr>
-";
-
-print "</form>";
-
-# print list of analog phone lines
-
-$tooltip_phoneline = "onMouseOver=\"popUp(event,'phone_phoneline')\" onmouseout=\"popUp(event,'phone_phoneline')\"";
-$tooltip_port = "onMouseOver=\"popUp(event,'phone_port_line')\" onmouseout=\"popUp(event,'phone_port_line')\"";
-$tooltip_line_prefix = "onMouseOver=\"popUp(event,'phone_line_prefix')\" onmouseout=\"popUp(event,'phone_line_prefix')\"";
-
-foreach $a (sort keys %analog) {
- if ($zap{$a} eq "fxo") {
- $icon = "<img src=\"tick.png\" alt=\"Phone Line OK\" />";
- print "<tr><td $tooltip_line_prefix>0</td><td $tooltip_phoneline>Analog Line</td><td $tooltip_port>Port $a</td><td></td><td>$icon</td></tr>\n";
- }
-}
-
-# print list of SIP VOIP trunks
-
-$tooltip_voipline = "onMouseOver=\"popUp(event,'phone_voipline')\" onmouseout=\"popUp(event,'phone_voipline')\"";
-$tooltip_voipline_ip = "onMouseOver=\"popUp(event,'phone_voipline_ip')\" onmouseout=\"popUp(event,'phone_voipline_ip')\"";
-$tooltip_voipline_prefix = "onMouseOver=\"popUp(event,'phone_voipline_prefix')\" onmouseout=\"popUp(event,'phone_voipline_prefix')\"";
-
-foreach $s (sort keys %voip) {
- if ($voip{$s} eq "Registered") {
- $icon = "<img src=\"tick.png\" alt=\"VOIP Line OK\" />";
- print "<tr><td $tooltip_voipline_prefix>1</td><td $tooltip_voipline>VOIP Line</td><td $tooltip_voipline_ip>$ipad{$s}</td><td></td><td>$icon</td></tr>\n";
- }
-}
-
-print '<tr><td> </td></tr>';
-print "<tr><td colspan=2 onMouseOver=\"popUp(event,'phone_addvoipline')\" onmouseout=\"popUp(event,'phone_addvoipline')\">";
-print "<a href=\"voiplines.sh\">Set Up VOIP Line</a></td></tr>";
+++ /dev/null
-#!/bin/sh
-# phones.sh
-# David Rowe 4 Jan 2010
-# Phones screen for Mini Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# See if we have Internet connectivity, first check dns as time outs can be very slow
-
-dns=`cat /etc/resolv.conf | awk '/^nameserver/ {print $2}'`
-dns_packet_loss=`ping $dns -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
-internet="no";
-if [ $dns_packet_loss = "0" ]; then
- packet_loss=`ping google.com -c 1 -q | sed -n 's/.*received, \(.*\)%.*/\1/p'`
- if [ $packet_loss = "0" ]; then
- internet="yes";
- fi
-fi
-
-# Build list of interface IPs based on what sort of machine we are
-# running on. For IP0X we just print the IP of the first interface.
-# For other machines the situation is a bit more complex so we print
-# all of them. I figure anyone with multiple interfaces will know
-# enough about what they are doing to figure out the right one to use.
-
-ipaddress=`ifconfig | sed -n 's/.*inet addr:\(.*\) Bcast.*/\1/p'`
-
-cat /proc/cpuinfo | grep "CPU:.*ADSP" > /dev/null
-if [ $? -eq 0 ]; then
- ipaddress=`echo $ipaddress | awk '{ print $1 }'`
-else
- ipaddress=`echo $ipaddress | sed -n 's/ /<br>/p'`
-fi
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-EOF
-
-echo "<script>"
-echo 'var init_internet="'$internet'";'
-cat phones.js
-echo "</script>"
-
-cat << EOF
-<html>
-<title>Mini Asterisk - Phones</title>
-<body onload="localInit()">
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <table align="right" width=600>
- <col width="50" /><col width="150" />
- <tr>
- <td onMouseOver="popUp(event,'phone_system')" onmouseout="popUp(event,'phone_system')" colspan="4" align="left" valign="top"><h2>Phone System</h2></td>
- </tr>
- <tr>
- <td colspan="3" onMouseOver="popUp(event,'network_internet')" onmouseout="popUp(event,'network_internet')">Internet Connection:</td>
- <td></td><td><div id="internet" > </div></td>
- </tr>
- <tr onMouseOver="popUp(event,'phone_ipaddress')" onmouseout="popUp(event,'phone_ipaddress')">
- <td colspan="4">Phone System IP Address:</td>
-EOF
-echo "<td>$ipaddress</td>"
-cat <<EOF
- </tr>
- <tr><td> </td></tr>
- <tr>
- <td onMouseOver="popUp(event,'phone_phones')" onmouseout="popUp(event,'phone_phones')"
- colspan="3" align="left" valign="top" ><h2>Phones</h2></td>
- </tr>
-EOF
-
-# use perl to construct list of phones and phone lines for us
-asterisk "-rx sip show peers" 2>/dev/null > sipshowpeers.txt
-perl ./phones.pl
-
-cat<<EOF
- </table>
-
- </td>
-
- </tr>
-
-</table>
-</body>
-</html>
-EOF
-
+++ /dev/null
-/* Prototype JavaScript framework, version 1.4.0
- * (c) 2005 Sam Stephenson <sam@conio.net>
- *
- * Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
- *
-/*--------------------------------------------------------------------------*/
-
-var Prototype = {
- Version: '1.4.0',
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
-
- emptyFunction: function() {},
- K: function(x) {return x}
-}
-
-var Class = {
- create: function() {
- return function() {
- this.initialize.apply(this, arguments);
- }
- }
-}
-
-var Abstract = new Object();
-
-Object.extend = function(destination, source) {
- for (property in source) {
- destination[property] = source[property];
- }
- return destination;
-}
-
-Object.inspect = function(object) {
- try {
- if (object == undefined) return 'undefined';
- if (object == null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
- } catch (e) {
- if (e instanceof RangeError) return '...';
- throw e;
- }
-}
-
-Function.prototype.bind = function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
-}
-
-Function.prototype.bindAsEventListener = function(object) {
- var __method = this;
- return function(event) {
- return __method.call(object, event || window.event);
- }
-}
-
-Object.extend(Number.prototype, {
- toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
- },
-
- succ: function() {
- return this + 1;
- },
-
- times: function(iterator) {
- $R(0, this, true).each(iterator);
- return this;
- }
-});
-
-var Try = {
- these: function() {
- var returnValue;
-
- for (var i = 0; i < arguments.length; i++) {
- var lambda = arguments[i];
- try {
- returnValue = lambda();
- break;
- } catch (e) {}
- }
-
- return returnValue;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
- initialize: function(callback, frequency) {
- this.callback = callback;
- this.frequency = frequency;
- this.currentlyExecuting = false;
-
- this.registerCallback();
- },
-
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
- if (!this.currentlyExecuting) {
- try {
- this.currentlyExecuting = true;
- this.callback();
- } finally {
- this.currentlyExecuting = false;
- }
- }
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-function $() {
- var elements = new Array();
-
- for (var i = 0; i < arguments.length; i++) {
- var element = arguments[i];
- if (typeof element == 'string')
- element = document.getElementById(element);
-
- if (arguments.length == 1)
- return element;
-
- elements.push(element);
- }
-
- return elements;
-}
-Object.extend(String.prototype, {
- stripTags: function() {
- return this.replace(/<\/?[^>]+>/gi, '');
- },
-
- stripScripts: function() {
- return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
- },
-
- extractScripts: function() {
- var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
- var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
- return (this.match(matchAll) || []).map(function(scriptTag) {
- return (scriptTag.match(matchOne) || ['', ''])[1];
- });
- },
-
- evalScripts: function() {
- return this.extractScripts().map(eval);
- },
-
- escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
- },
-
- unescapeHTML: function() {
- var div = document.createElement('div');
- div.innerHTML = this.stripTags();
- return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
- },
-
- toQueryParams: function() {
- var pairs = this.match(/^\??(.*)$/)[1].split('&');
- return pairs.inject({}, function(params, pairString) {
- var pair = pairString.split('=');
- params[pair[0]] = pair[1];
- return params;
- });
- },
-
- toArray: function() {
- return this.split('');
- },
-
- camelize: function() {
- var oStringList = this.split('-');
- if (oStringList.length == 1) return oStringList[0];
-
- var camelizedString = this.indexOf('-') == 0
- ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
- : oStringList[0];
-
- for (var i = 1, len = oStringList.length; i < len; i++) {
- var s = oStringList[i];
- camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
- }
-
- return camelizedString;
- },
-
- inspect: function() {
- return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
- }
-});
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-var $break = new Object();
-var $continue = new Object();
-
-var Enumerable = {
- each: function(iterator) {
- var index = 0;
- try {
- this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
- });
- } catch (e) {
- if (e != $break) throw e;
- }
- },
-
- all: function(iterator) {
- var result = true;
- this.each(function(value, index) {
- result = result && !!(iterator || Prototype.K)(value, index);
- if (!result) throw $break;
- });
- return result;
- },
-
- any: function(iterator) {
- var result = true;
- this.each(function(value, index) {
- if (result = !!(iterator || Prototype.K)(value, index))
- throw $break;
- });
- return result;
- },
-
- collect: function(iterator) {
- var results = [];
- this.each(function(value, index) {
- results.push(iterator(value, index));
- });
- return results;
- },
-
- detect: function (iterator) {
- var result;
- this.each(function(value, index) {
- if (iterator(value, index)) {
- result = value;
- throw $break;
- }
- });
- return result;
- },
-
- findAll: function(iterator) {
- var results = [];
- this.each(function(value, index) {
- if (iterator(value, index))
- results.push(value);
- });
- return results;
- },
-
- grep: function(pattern, iterator) {
- var results = [];
- this.each(function(value, index) {
- var stringValue = value.toString();
- if (stringValue.match(pattern))
- results.push((iterator || Prototype.K)(value, index));
- })
- return results;
- },
-
- include: function(object) {
- var found = false;
- this.each(function(value) {
- if (value == object) {
- found = true;
- throw $break;
- }
- });
- return found;
- },
-
- inject: function(memo, iterator) {
- this.each(function(value, index) {
- memo = iterator(memo, value, index);
- });
- return memo;
- },
-
- invoke: function(method) {
- var args = $A(arguments).slice(1);
- return this.collect(function(value) {
- return value[method].apply(value, args);
- });
- },
-
- max: function(iterator) {
- var result;
- this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (value >= (result || value))
- result = value;
- });
- return result;
- },
-
- min: function(iterator) {
- var result;
- this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (value <= (result || value))
- result = value;
- });
- return result;
- },
-
- partition: function(iterator) {
- var trues = [], falses = [];
- this.each(function(value, index) {
- ((iterator || Prototype.K)(value, index) ?
- trues : falses).push(value);
- });
- return [trues, falses];
- },
-
- pluck: function(property) {
- var results = [];
- this.each(function(value, index) {
- results.push(value[property]);
- });
- return results;
- },
-
- reject: function(iterator) {
- var results = [];
- this.each(function(value, index) {
- if (!iterator(value, index))
- results.push(value);
- });
- return results;
- },
-
- sortBy: function(iterator) {
- return this.collect(function(value, index) {
- return {value: value, criteria: iterator(value, index)};
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- return a < b ? -1 : a > b ? 1 : 0;
- }).pluck('value');
- },
-
- toArray: function() {
- return this.collect(Prototype.K);
- },
-
- zip: function() {
- var iterator = Prototype.K, args = $A(arguments);
- if (typeof args.last() == 'function')
- iterator = args.pop();
-
- var collections = [this].concat(args).map($A);
- return this.map(function(value, index) {
- iterator(value = collections.pluck(index));
- return value;
- });
- },
-
- inspect: function() {
- return '#<Enumerable:' + this.toArray().inspect() + '>';
- }
-}
-
-Object.extend(Enumerable, {
- map: Enumerable.collect,
- find: Enumerable.detect,
- select: Enumerable.findAll,
- member: Enumerable.include,
- entries: Enumerable.toArray
-});
-var $A = Array.from = function(iterable) {
- if (!iterable) return [];
- if (iterable.toArray) {
- return iterable.toArray();
- } else {
- var results = [];
- for (var i = 0; i < iterable.length; i++)
- results.push(iterable[i]);
- return results;
- }
-}
-
-Object.extend(Array.prototype, Enumerable);
-
-Array.prototype._reverse = Array.prototype.reverse;
-
-Object.extend(Array.prototype, {
- _each: function(iterator) {
- for (var i = 0; i < this.length; i++)
- iterator(this[i]);
- },
-
- clear: function() {
- this.length = 0;
- return this;
- },
-
- first: function() {
- return this[0];
- },
-
- last: function() {
- return this[this.length - 1];
- },
-
- compact: function() {
- return this.select(function(value) {
- return value != undefined || value != null;
- });
- },
-
- flatten: function() {
- return this.inject([], function(array, value) {
- return array.concat(value.constructor == Array ?
- value.flatten() : [value]);
- });
- },
-
- without: function() {
- var values = $A(arguments);
- return this.select(function(value) {
- return !values.include(value);
- });
- },
-
- indexOf: function(object) {
- for (var i = 0; i < this.length; i++)
- if (this[i] == object) return i;
- return -1;
- },
-
- reverse: function(inline) {
- return (inline !== false ? this : this.toArray())._reverse();
- },
-
- shift: function() {
- var result = this[0];
- for (var i = 0; i < this.length - 1; i++)
- this[i] = this[i + 1];
- this.length--;
- return result;
- },
-
- inspect: function() {
- return '[' + this.map(Object.inspect).join(', ') + ']';
- }
-});
-var Hash = {
- _each: function(iterator) {
- for (key in this) {
- var value = this[key];
- if (typeof value == 'function') continue;
-
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- },
-
- keys: function() {
- return this.pluck('key');
- },
-
- values: function() {
- return this.pluck('value');
- },
-
- merge: function(hash) {
- return $H(hash).inject($H(this), function(mergedHash, pair) {
- mergedHash[pair.key] = pair.value;
- return mergedHash;
- });
- },
-
- toQueryString: function() {
- return this.map(function(pair) {
- return pair.map(encodeURIComponent).join('=');
- }).join('&');
- },
-
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
- }
-}
-
-function $H(object) {
- var hash = Object.extend({}, object || {});
- Object.extend(hash, Enumerable);
- Object.extend(hash, Hash);
- return hash;
-}
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
- initialize: function(start, end, exclusive) {
- this.start = start;
- this.end = end;
- this.exclusive = exclusive;
- },
-
- _each: function(iterator) {
- var value = this.start;
- do {
- iterator(value);
- value = value.succ();
- } while (this.include(value));
- },
-
- include: function(value) {
- if (value < this.start)
- return false;
- if (this.exclusive)
- return value < this.end;
- return value <= this.end;
- }
-});
-
-var $R = function(start, end, exclusive) {
- return new ObjectRange(start, end, exclusive);
-}
-
-var Ajax = {
- getTransport: function() {
- return Try.these(
- function() {return new ActiveXObject('Msxml2.XMLHTTP')},
- function() {return new ActiveXObject('Microsoft.XMLHTTP')},
- function() {return new XMLHttpRequest()}
- ) || false;
- },
-
- activeRequestCount: 0
-}
-
-Ajax.Responders = {
- responders: [],
-
- _each: function(iterator) {
- this.responders._each(iterator);
- },
-
- register: function(responderToAdd) {
- if (!this.include(responderToAdd))
- this.responders.push(responderToAdd);
- },
-
- unregister: function(responderToRemove) {
- this.responders = this.responders.without(responderToRemove);
- },
-
- dispatch: function(callback, request, transport, json) {
- this.each(function(responder) {
- if (responder[callback] && typeof responder[callback] == 'function') {
- try {
- responder[callback].apply(responder, [request, transport, json]);
- } catch (e) {}
- }
- });
- }
-};
-
-Object.extend(Ajax.Responders, Enumerable);
-
-Ajax.Responders.register({
- onCreate: function() {
- Ajax.activeRequestCount++;
- },
-
- onComplete: function() {
- Ajax.activeRequestCount--;
- }
-});
-
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
- setOptions: function(options) {
- this.options = {
- method: 'post',
- asynchronous: true,
- parameters: ''
- }
- Object.extend(this.options, options || {});
- },
-
- responseIsSuccess: function() {
- return this.transport.status == undefined
- || this.transport.status == 0
- || (this.transport.status >= 200 && this.transport.status < 300);
- },
-
- responseIsFailure: function() {
- return !this.responseIsSuccess();
- }
-}
-
-Ajax.Request = Class.create();
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(url, options) {
- this.transport = Ajax.getTransport();
- this.setOptions(options);
- this.request(url);
- },
-
- request: function(url) {
- var parameters = this.options.parameters || '';
- if (parameters.length > 0) parameters += '&_=';
-
- try {
- this.url = url;
- if (this.options.method == 'get' && parameters.length > 0)
- this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
-
- Ajax.Responders.dispatch('onCreate', this, this.transport);
-
- this.transport.open(this.options.method, this.url,
- this.options.asynchronous);
-
- if (this.options.asynchronous) {
- this.transport.onreadystatechange = this.onStateChange.bind(this);
- setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
- }
-
- this.setRequestHeaders();
-
- var body = this.options.postBody ? this.options.postBody : parameters;
- this.transport.send(this.options.method == 'post' ? body : null);
-
- } catch (e) {
- this.dispatchException(e);
- }
- },
-
- setRequestHeaders: function() {
- var requestHeaders =
- ['X-Requested-With', 'XMLHttpRequest',
- 'X-Prototype-Version', Prototype.Version];
-
- if (this.options.method == 'post') {
- requestHeaders.push('Content-type',
- 'application/x-www-form-urlencoded');
-
- /* Force "Connection: close" for Mozilla browsers to work around
- * a bug where XMLHttpReqeuest sends an incorrect Content-length
- * header. See Mozilla Bugzilla #246651.
- */
- if (this.transport.overrideMimeType)
- requestHeaders.push('Connection', 'close');
- }
-
- if (this.options.requestHeaders)
- requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
-
- for (var i = 0; i < requestHeaders.length; i += 2)
- this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
- },
-
- onStateChange: function() {
- var readyState = this.transport.readyState;
- if (readyState != 1)
- this.respondToReadyState(this.transport.readyState);
- },
-
- header: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) {}
- },
-
- evalJSON: function() {
- try {
- return eval(this.header('X-JSON'));
- } catch (e) {}
- },
-
- evalResponse: function() {
- try {
- return eval(this.transport.responseText);
- } catch (e) {
- this.dispatchException(e);
- }
- },
-
- respondToReadyState: function(readyState) {
- var event = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.evalJSON();
-
- if (event == 'Complete') {
- try {
- (this.options['on' + this.transport.status]
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(transport, json);
- } catch (e) {
- this.dispatchException(e);
- }
-
- if ((this.header('Content-type') || '').match(/^text\/javascript/i))
- this.evalResponse();
- }
-
- try {
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + event, this, transport, json);
- } catch (e) {
- this.dispatchException(e);
- }
-
- /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
- if (event == 'Complete')
- this.transport.onreadystatechange = Prototype.emptyFunction;
- },
-
- dispatchException: function(exception) {
- (this.options.onException || Prototype.emptyFunction)(this, exception);
- Ajax.Responders.dispatch('onException', this, exception);
- }
-});
-
-Ajax.Updater = Class.create();
-
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
- initialize: function(container, url, options) {
- this.containers = {
- success: container.success ? $(container.success) : $(container),
- failure: container.failure ? $(container.failure) :
- (container.success ? null : $(container))
- }
-
- this.transport = Ajax.getTransport();
- this.setOptions(options);
-
- var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, object) {
- this.updateContent();
- onComplete(transport, object);
- }).bind(this);
-
- this.request(url);
- },
-
- updateContent: function() {
- var receiver = this.responseIsSuccess() ?
- this.containers.success : this.containers.failure;
- var response = this.transport.responseText;
-
- if (!this.options.evalScripts)
- response = response.stripScripts();
-
- if (receiver) {
- if (this.options.insertion) {
- new this.options.insertion(receiver, response);
- } else {
- Element.update(receiver, response);
- }
- }
-
- if (this.responseIsSuccess()) {
- if (this.onComplete)
- setTimeout(this.onComplete.bind(this), 10);
- }
- }
-});
-
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(container, url, options) {
- this.setOptions(options);
- this.onComplete = this.options.onComplete;
-
- this.frequency = (this.options.frequency || 2);
- this.decay = (this.options.decay || 1);
-
- this.updater = {};
- this.container = container;
- this.url = url;
-
- this.start();
- },
-
- start: function() {
- this.options.onComplete = this.updateComplete.bind(this);
- this.onTimerEvent();
- },
-
- stop: function() {
- this.updater.onComplete = undefined;
- clearTimeout(this.timer);
- (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
- },
-
- updateComplete: function(request) {
- if (this.options.decay) {
- this.decay = (request.responseText == this.lastText ?
- this.decay * this.options.decay : 1);
-
- this.lastText = request.responseText;
- }
- this.timer = setTimeout(this.onTimerEvent.bind(this),
- this.decay * this.frequency * 1000);
- },
-
- onTimerEvent: function() {
- this.updater = new Ajax.Updater(this.container, this.url, this.options);
- }
-});
-document.getElementsByClassName = function(className, parentElement) {
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
- return $A(children).inject([], function(elements, child) {
- if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- elements.push(child);
- return elements;
- });
-}
-
-/*--------------------------------------------------------------------------*/
-
-if (!window.Element) {
- var Element = new Object();
-}
-
-Object.extend(Element, {
- visible: function(element) {
- return $(element).style.display != 'none';
- },
-
- toggle: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- Element[Element.visible(element) ? 'hide' : 'show'](element);
- }
- },
-
- hide: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- element.style.display = 'none';
- }
- },
-
- show: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- element.style.display = '';
- }
- },
-
- remove: function(element) {
- element = $(element);
- element.parentNode.removeChild(element);
- },
-
- update: function(element, html) {
- $(element).innerHTML = html.stripScripts();
- setTimeout(function() {html.evalScripts()}, 10);
- },
-
- getHeight: function(element) {
- element = $(element);
- return element.offsetHeight;
- },
-
- classNames: function(element) {
- return new Element.ClassNames(element);
- },
-
- hasClassName: function(element, className) {
- if (!(element = $(element))) return;
- return Element.classNames(element).include(className);
- },
-
- addClassName: function(element, className) {
- if (!(element = $(element))) return;
- return Element.classNames(element).add(className);
- },
-
- removeClassName: function(element, className) {
- if (!(element = $(element))) return;
- return Element.classNames(element).remove(className);
- },
-
- // removes whitespace-only text node children
- cleanWhitespace: function(element) {
- element = $(element);
- for (var i = 0; i < element.childNodes.length; i++) {
- var node = element.childNodes[i];
- if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
- Element.remove(node);
- }
- },
-
- empty: function(element) {
- return $(element).innerHTML.match(/^\s*$/);
- },
-
- scrollTo: function(element) {
- element = $(element);
- var x = element.x ? element.x : element.offsetLeft,
- y = element.y ? element.y : element.offsetTop;
- window.scrollTo(x, y);
- },
-
- getStyle: function(element, style) {
- element = $(element);
- var value = element.style[style.camelize()];
- if (!value) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css.getPropertyValue(style) : null;
- } else if (element.currentStyle) {
- value = element.currentStyle[style.camelize()];
- }
- }
-
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
- if (Element.getStyle(element, 'position') == 'static') value = 'auto';
-
- return value == 'auto' ? null : value;
- },
-
- setStyle: function(element, style) {
- element = $(element);
- for (name in style)
- element.style[name.camelize()] = style[name];
- },
-
- getDimensions: function(element) {
- element = $(element);
- if (Element.getStyle(element, 'display') != 'none')
- return {width: element.offsetWidth, height: element.offsetHeight};
-
- // All *Width and *Height properties give 0 on elements with display none,
- // so enable the element temporarily
- var els = element.style;
- var originalVisibility = els.visibility;
- var originalPosition = els.position;
- els.visibility = 'hidden';
- els.position = 'absolute';
- els.display = '';
- var originalWidth = element.clientWidth;
- var originalHeight = element.clientHeight;
- els.display = 'none';
- els.position = originalPosition;
- els.visibility = originalVisibility;
- return {width: originalWidth, height: originalHeight};
- },
-
- makePositioned: function(element) {
- element = $(element);
- var pos = Element.getStyle(element, 'position');
- if (pos == 'static' || !pos) {
- element._madePositioned = true;
- element.style.position = 'relative';
- // Opera returns the offset relative to the positioning context, when an
- // element is position relative but top and left have not been defined
- if (window.opera) {
- element.style.top = 0;
- element.style.left = 0;
- }
- }
- },
-
- undoPositioned: function(element) {
- element = $(element);
- if (element._madePositioned) {
- element._madePositioned = undefined;
- element.style.position =
- element.style.top =
- element.style.left =
- element.style.bottom =
- element.style.right = '';
- }
- },
-
- makeClipping: function(element) {
- element = $(element);
- if (element._overflow) return;
- element._overflow = element.style.overflow;
- if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
- element.style.overflow = 'hidden';
- },
-
- undoClipping: function(element) {
- element = $(element);
- if (element._overflow) return;
- element.style.overflow = element._overflow;
- element._overflow = undefined;
- }
-});
-
-var Toggle = new Object();
-Toggle.display = Element.toggle;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.Insertion = function(adjacency) {
- this.adjacency = adjacency;
-}
-
-Abstract.Insertion.prototype = {
- initialize: function(element, content) {
- this.element = $(element);
- this.content = content.stripScripts();
-
- if (this.adjacency && this.element.insertAdjacentHTML) {
- try {
- this.element.insertAdjacentHTML(this.adjacency, this.content);
- } catch (e) {
- if (this.element.tagName.toLowerCase() == 'tbody') {
- this.insertContent(this.contentFromAnonymousTable());
- } else {
- throw e;
- }
- }
- } else {
- this.range = this.element.ownerDocument.createRange();
- if (this.initializeRange) this.initializeRange();
- this.insertContent([this.range.createContextualFragment(this.content)]);
- }
-
- setTimeout(function() {content.evalScripts()}, 10);
- },
-
- contentFromAnonymousTable: function() {
- var div = document.createElement('div');
- div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
- return $A(div.childNodes[0].childNodes[0].childNodes);
- }
-}
-
-var Insertion = new Object();
-
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
- initializeRange: function() {
- this.range.setStartBefore(this.element);
- },
-
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment, this.element);
- }).bind(this));
- }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(true);
- },
-
- insertContent: function(fragments) {
- fragments.reverse(false).each((function(fragment) {
- this.element.insertBefore(fragment, this.element.firstChild);
- }).bind(this));
- }
-});
-
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(this.element);
- },
-
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.appendChild(fragment);
- }).bind(this));
- }
-});
-
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
- initializeRange: function() {
- this.range.setStartAfter(this.element);
- },
-
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment,
- this.element.nextSibling);
- }).bind(this));
- }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
-
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
- },
-
- set: function(className) {
- this.element.className = className;
- },
-
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set(this.toArray().concat(classNameToAdd).join(' '));
- },
-
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set(this.select(function(className) {
- return className != classNameToRemove;
- }).join(' '));
- },
-
- toString: function() {
- return this.toArray().join(' ');
- }
-}
-
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Field = {
- clear: function() {
- for (var i = 0; i < arguments.length; i++)
- $(arguments[i]).value = '';
- },
-
- focus: function(element) {
- $(element).focus();
- },
-
- present: function() {
- for (var i = 0; i < arguments.length; i++)
- if ($(arguments[i]).value == '') return false;
- return true;
- },
-
- select: function(element) {
- $(element).select();
- },
-
- activate: function(element) {
- element = $(element);
- element.focus();
- if (element.select)
- element.select();
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Form = {
- serialize: function(form) {
- var elements = Form.getElements($(form));
- var queryComponents = new Array();
-
- for (var i = 0; i < elements.length; i++) {
- var queryComponent = Form.Element.serialize(elements[i]);
- if (queryComponent)
- queryComponents.push(queryComponent);
- }
-
- return queryComponents.join('&');
- },
-
- getElements: function(form) {
- form = $(form);
- var elements = new Array();
-
- for (tagName in Form.Element.Serializers) {
- var tagElements = form.getElementsByTagName(tagName);
- for (var j = 0; j < tagElements.length; j++)
- elements.push(tagElements[j]);
- }
- return elements;
- },
-
- getInputs: function(form, typeName, name) {
- form = $(form);
- var inputs = form.getElementsByTagName('input');
-
- if (!typeName && !name)
- return inputs;
-
- var matchingInputs = new Array();
- for (var i = 0; i < inputs.length; i++) {
- var input = inputs[i];
- if ((typeName && input.type != typeName) ||
- (name && input.name != name))
- continue;
- matchingInputs.push(input);
- }
-
- return matchingInputs;
- },
-
- disable: function(form) {
- var elements = Form.getElements(form);
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- element.blur();
- element.disabled = 'true';
- }
- },
-
- enable: function(form) {
- var elements = Form.getElements(form);
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- element.disabled = '';
- }
- },
-
- findFirstElement: function(form) {
- return Form.getElements(form).find(function(element) {
- return element.type != 'hidden' && !element.disabled &&
- ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
- });
- },
-
- focusFirstElement: function(form) {
- Field.activate(Form.findFirstElement(form));
- },
-
- reset: function(form) {
- $(form).reset();
- }
-}
-
-Form.Element = {
- serialize: function(element) {
- element = $(element);
- var method = element.tagName.toLowerCase();
- var parameter = Form.Element.Serializers[method](element);
-
- if (parameter) {
- var key = encodeURIComponent(parameter[0]);
- if (key.length == 0) return;
-
- if (parameter[1].constructor != Array)
- parameter[1] = [parameter[1]];
-
- return parameter[1].map(function(value) {
- return key + '=' + encodeURIComponent(value);
- }).join('&');
- }
- },
-
- getValue: function(element) {
- element = $(element);
- var method = element.tagName.toLowerCase();
- var parameter = Form.Element.Serializers[method](element);
-
- if (parameter)
- return parameter[1];
- }
-}
-
-Form.Element.Serializers = {
- input: function(element) {
- switch (element.type.toLowerCase()) {
- case 'submit':
- case 'hidden':
- case 'password':
- case 'text':
- return Form.Element.Serializers.textarea(element);
- case 'checkbox':
- case 'radio':
- return Form.Element.Serializers.inputSelector(element);
- }
- return false;
- },
-
- inputSelector: function(element) {
- if (element.checked)
- return [element.name, element.value];
- },
-
- textarea: function(element) {
- return [element.name, element.value];
- },
-
- select: function(element) {
- return Form.Element.Serializers[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
- },
-
- selectOne: function(element) {
- var value = '', opt, index = element.selectedIndex;
- if (index >= 0) {
- opt = element.options[index];
- value = opt.value;
- if (!value && !('value' in opt))
- value = opt.text;
- }
- return [element.name, value];
- },
-
- selectMany: function(element) {
- var value = new Array();
- for (var i = 0; i < element.length; i++) {
- var opt = element.options[i];
- if (opt.selected) {
- var optValue = opt.value;
- if (!optValue && !('value' in opt))
- optValue = opt.text;
- value.push(optValue);
- }
- }
- return [element.name, value];
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
- initialize: function(element, frequency, callback) {
- this.frequency = frequency;
- this.element = $(element);
- this.callback = callback;
-
- this.lastValue = this.getValue();
- this.registerCallback();
- },
-
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
- var value = this.getValue();
- if (this.lastValue != value) {
- this.callback(this.element, value);
- this.lastValue = value;
- }
- }
-}
-
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
- getValue: function() {
- return Form.Element.getValue(this.element);
- }
-});
-
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
- getValue: function() {
- return Form.serialize(this.element);
- }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
- initialize: function(element, callback) {
- this.element = $(element);
- this.callback = callback;
-
- this.lastValue = this.getValue();
- if (this.element.tagName.toLowerCase() == 'form')
- this.registerFormCallbacks();
- else
- this.registerCallback(this.element);
- },
-
- onElementEvent: function() {
- var value = this.getValue();
- if (this.lastValue != value) {
- this.callback(this.element, value);
- this.lastValue = value;
- }
- },
-
- registerFormCallbacks: function() {
- var elements = Form.getElements(this.element);
- for (var i = 0; i < elements.length; i++)
- this.registerCallback(elements[i]);
- },
-
- registerCallback: function(element) {
- if (element.type) {
- switch (element.type.toLowerCase()) {
- case 'checkbox':
- case 'radio':
- Event.observe(element, 'click', this.onElementEvent.bind(this));
- break;
- case 'password':
- case 'text':
- case 'textarea':
- case 'select-one':
- case 'select-multiple':
- Event.observe(element, 'change', this.onElementEvent.bind(this));
- break;
- }
- }
- }
-}
-
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
- getValue: function() {
- return Form.Element.getValue(this.element);
- }
-});
-
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
- getValue: function() {
- return Form.serialize(this.element);
- }
-});
-if (!window.Event) {
- var Event = new Object();
-}
-
-Object.extend(Event, {
- KEY_BACKSPACE: 8,
- KEY_TAB: 9,
- KEY_RETURN: 13,
- KEY_ESC: 27,
- KEY_LEFT: 37,
- KEY_UP: 38,
- KEY_RIGHT: 39,
- KEY_DOWN: 40,
- KEY_DELETE: 46,
-
- element: function(event) {
- return event.target || event.srcElement;
- },
-
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
-
- pointerX: function(event) {
- return event.pageX || (event.clientX +
- (document.documentElement.scrollLeft || document.body.scrollLeft));
- },
-
- pointerY: function(event) {
- return event.pageY || (event.clientY +
- (document.documentElement.scrollTop || document.body.scrollTop));
- },
-
- stop: function(event) {
- if (event.preventDefault) {
- event.preventDefault();
- event.stopPropagation();
- } else {
- event.returnValue = false;
- event.cancelBubble = true;
- }
- },
-
- // find the first node with the given tagName, starting from the
- // node the event was triggered on; traverses the DOM upwards
- findElement: function(event, tagName) {
- var element = Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase())))
- element = element.parentNode;
- return element;
- },
-
- observers: false,
-
- _observeAndCache: function(element, name, observer, useCapture) {
- if (!this.observers) this.observers = [];
- if (element.addEventListener) {
- this.observers.push([element, name, observer, useCapture]);
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- this.observers.push([element, name, observer, useCapture]);
- element.attachEvent('on' + name, observer);
- }
- },
-
- unloadCache: function() {
- if (!Event.observers) return;
- for (var i = 0; i < Event.observers.length; i++) {
- Event.stopObserving.apply(this, Event.observers[i]);
- Event.observers[i][0] = null;
- }
- Event.observers = false;
- },
-
- observe: function(element, name, observer, useCapture) {
- var element = $(element);
- useCapture = useCapture || false;
-
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent))
- name = 'keydown';
-
- this._observeAndCache(element, name, observer, useCapture);
- },
-
- stopObserving: function(element, name, observer, useCapture) {
- var element = $(element);
- useCapture = useCapture || false;
-
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.detachEvent))
- name = 'keydown';
-
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element.detachEvent) {
- element.detachEvent('on' + name, observer);
- }
- }
-});
-
-/* prevent memory leaks in IE */
-Event.observe(window, 'unload', Event.unloadCache, false);
-var Position = {
- // set to true if needed, warning: firefox performance problems
- // NOT neeeded for page scrolling, only if draggable contained in
- // scrollable elements
- includeScrollOffsets: false,
-
- // must be called before calling withinIncludingScrolloffset, every time the
- // page is scrolled
- prepare: function() {
- this.deltaX = window.pageXOffset
- || document.documentElement.scrollLeft
- || document.body.scrollLeft
- || 0;
- this.deltaY = window.pageYOffset
- || document.documentElement.scrollTop
- || document.body.scrollTop
- || 0;
- },
-
- realOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return [valueL, valueT];
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return [valueL, valueT];
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
- }
- } while (element);
- return [valueL, valueT];
- },
-
- offsetParent: function(element) {
- if (element.offsetParent) return element.offsetParent;
- if (element == document.body) return element;
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return element;
-
- return document.body;
- },
-
- // caches x/y coordinate pair to use with overlap
- within: function(element, x, y) {
- if (this.includeScrollOffsets)
- return this.withinIncludingScrolloffsets(element, x, y);
- this.xcomp = x;
- this.ycomp = y;
- this.offset = this.cumulativeOffset(element);
-
- return (y >= this.offset[1] &&
- y < this.offset[1] + element.offsetHeight &&
- x >= this.offset[0] &&
- x < this.offset[0] + element.offsetWidth);
- },
-
- withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = this.realOffset(element);
-
- this.xcomp = x + offsetcache[0] - this.deltaX;
- this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = this.cumulativeOffset(element);
-
- return (this.ycomp >= this.offset[1] &&
- this.ycomp < this.offset[1] + element.offsetHeight &&
- this.xcomp >= this.offset[0] &&
- this.xcomp < this.offset[0] + element.offsetWidth);
- },
-
- // within must be called directly before
- overlap: function(mode, element) {
- if (!mode) return 0;
- if (mode == 'vertical')
- return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
- element.offsetHeight;
- if (mode == 'horizontal')
- return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
- element.offsetWidth;
- },
-
- clone: function(source, target) {
- source = $(source);
- target = $(target);
- target.style.position = 'absolute';
- var offsets = this.cumulativeOffset(source);
- target.style.top = offsets[1] + 'px';
- target.style.left = offsets[0] + 'px';
- target.style.width = source.offsetWidth + 'px';
- target.style.height = source.offsetHeight + 'px';
- },
-
- page: function(forElement) {
- var valueT = 0, valueL = 0;
-
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
-
- // Safari fix
- if (element.offsetParent==document.body)
- if (Element.getStyle(element,'position')=='absolute') break;
-
- } while (element = element.offsetParent);
-
- element = forElement;
- do {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- } while (element = element.parentNode);
-
- return [valueL, valueT];
- },
-
- clone: function(source, target) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || {})
-
- // find page position of source
- source = $(source);
- var p = Position.page(source);
-
- // find coordinate system to use
- target = $(target);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(target,'position') == 'absolute') {
- parent = Position.offsetParent(target);
- delta = Position.page(parent);
- }
-
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
- }
-
- // set position
- if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if(options.setWidth) target.style.width = source.offsetWidth + 'px';
- if(options.setHeight) target.style.height = source.offsetHeight + 'px';
- },
-
- absolutize: function(element) {
- element = $(element);
- if (element.style.position == 'absolute') return;
- Position.prepare();
-
- var offsets = Position.positionedOffset(element);
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
-
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
-
- element.style.position = 'absolute';
- element.style.top = top + 'px';;
- element.style.left = left + 'px';;
- element.style.width = width + 'px';;
- element.style.height = height + 'px';;
- },
-
- relativize: function(element) {
- element = $(element);
- if (element.style.position == 'relative') return;
- Position.prepare();
-
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
- }
-}
-
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned. For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- Position.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
-
- element = element.offsetParent;
- } while (element);
-
- return [valueL, valueT];
- }
-}
\ No newline at end of file
+++ /dev/null
-#!/bin/sh
-# set_network.sh
-#
-# CGI to set network parameters of an IP0X.
-
-cat <<EOF
-<html>
-<head>
-<title>set_network.sh</title>
-<meta http-equiv="REFRESH" content="0;url=network.sh">
-<body>
-Please wait a few seconds.....
-</body>
-</head>
-</html>
-EOF
-
-dhcp=`echo "$QUERY_STRING" | grep -oe "dhcp=[^&?]*" | sed -n "s/dhcp=//p"`
-ipaddress=`echo "$QUERY_STRING" | grep -oe "ipaddress=[^&?]*" | sed -n "s/ipaddress=//p"`
-netmask=`echo "$QUERY_STRING" | grep -oe "netmask=[^&?]*" | sed -n "s/netmask=//p"`
-gateway=`echo "$QUERY_STRING" | grep -oe "gateway=[^&?]*" | sed -n "s/gateway=//p"`
-dns=`echo "$QUERY_STRING" | grep -oe "dns=[^&?]*" | sed -n "s/dns=//p"`
-backdoor=`echo "$QUERY_STRING" | grep -oe "backdoor=[^&?]*" | sed -n "s/backdoor=//p"`
-
-if [ $dhcp = "yes" ]; then
-
- # DHCP
-
- if [ -f /etc/rc.d/S10network-static ]; then
- /etc/init.d/network-static disable
- /etc/init.d/network-static stop
- /etc/init.d/network enable
- /etc/init.d/network start
- else
- # if already running restart service
- /etc/init.d/network stop
- /etc/init.d/network start
- fi
-fi
-
-if [ $dhcp = "no" ]; then
-
- # Static IP
-
- if [ -f /etc/rc.d/S10network ]; then
- /etc/init.d/network stop
- /etc/init.d/network disable
- /etc/init.d/network-static enable
- fi
-
- sed -i "s/DHCPD=.*/DHCPD=no/g" /etc/init.d/network-static
- sed -i "s/IPADDRESS=.*/IPADDRESS=\"$ipaddress\"/g" /etc/init.d/network-static
- sed -i "s/NETMASK=.*/NETMASK=\"$netmask\"/g" /etc/init.d/network-static
- sed -i "s/GATEWAY=.*/GATEWAY=\"$gateway\"/g" /etc/init.d/network-static
- sed -i "s/DNS=.*/DNS=\"$dns\"/g" /etc/init.d/network-static
- /etc/init.d/network-static stop
- /etc/init.d/network-static start
-fi
-
-if [ -f /etc/rc.d/S05network-backdoor ]; then
- sed -i "s/IPADDRESS=.*/IPADDRESS=\"$backdoor\"/g" /etc/init.d/network-backdoor
- /etc/init.d/network-backdoor stop
- /etc/init.d/network-backdoor start
-fi
+++ /dev/null
-#!/bin/sh -x
-# set_ring.sh
-# David Rowe 4 Jan 2010
-# CGI to set which extensions ring on uncoming calls
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# extract extensions to ring and reload extensions.conf
-
-a=`echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'`
-
-# escape & if present
-echo "$a" | grep "&" >> /dev/null
-if [ $? -eq 0 ]; then
- a=`echo $a | sed -n "s/&/\\\\&/pg"`
-fi
-
-sed -i "s_s,1,Dial(.*) ;; mini-asterisk_s,1,Dial($a) ;; mini-asterisk_" /etc/asterisk/extensions.conf
-asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
-
-# bounce us back to Phones screen
-
-cat <<EOF
-<html>
-<head>
-<title>Mini Asterisk - Set Ring</title>
-<meta http-equiv="REFRESH" content="0;url=phones.sh">
-<body>
-Please wait a few seconds.....
-EOF
-#echo $QUERY_STRING "<br>"
-#echo "$QUERY_STRING" | sed -n "s/=on*//pg" | sed -n 's,_,/,pg'
-#echo "<br>"
-#echo $a
-
-cat <<EOF
-</body>
-</head>
-</html>
-EOF
-
+++ /dev/null
-#!/usr/bin/perl
-# set_voiplines.pl
-# David Rowe 12 Jan 2010
-#
-# Replaces fields in sip.conf, outputs new sip.conf contents to stdout
-# Gets run when "OK" is pressed on the Voip Lines screen
-
-$user = $ARGV[0];
-$pass = $ARGV[1];
-$host = $ARGV[2];
-$provider_new = $ARGV[3];
-
-# We need to slurp up the mini asterisk providers and spit them
-# back out. All must be commented out except for the one that
-# is selected. Hopefully non-mini asterisk content of sip.conf
-# won't be affected.
-
-open SIP, "/etc/asterisk/sip.conf";
-$provider = "";
-while (<SIP>) {
-
- # start of any new stanza switches off parsing. It may get
- # switched back on below if it contains mini-asterisk
- # keyword. This allows non-mini asterisk SIP stanzas to be
- # included in sip.conf
-
- if (/\[/) {
- $stanza = "";
- }
-
- # look for commented or uncommented mini asterisk provider stanza
-
- if (/\[(.*)\].* \"(.*)\" mini-asterisk/) {
- $stanza = $1;
- $provider = $2;
- }
-
- if ($stanza eq "") {
- # we are not in an mini-asterisk provider stanza
-
- # however we may hit a mini-asterisk register line here
-
- if (/.*register => (\S*)@(\S*).*;.*(mini-asterisk.*)/) {
- # the mini-asterisk register line, not only one register supported
- # at the moment (one VOIP line)
-
- #print "XX provider_new='$provider_new' '$1' '$2' '$3'\n";
-
- # commentout register if "none" selected
-
- if ($user eq "none") {
- print ";";
- }
-
- # note final /$user seems to be necessary so that incoming VOIP
- # calls work. I really don't get the syntax but messed around for
- # hours until it worked!
-
- print "register => $user\@$user/$user; $3\n";
- }
- else {
- # OK so this is a regular sip.conf line, just echo to stdout
- print $_;
- }
- }
- else {
- # OK, we are in an mini-asterisk stanza
-
- # strip off leading ";", except for comments lines which start
- # with ;;
-
- unless (/^;;/) {
- $_ =~ s/^\;//;
- }
-
- if ($provider eq $provider_new) {
-
- # this stanza should be uncommented
-
- if (/\[.*\].* \".*\" mini-asterisk/) {
- # rename stanza name to user name
- # this is required to make incoming calls work
- print "[$user] ; \"$provider\" mini-asterisk do not remove this comment\n";
- }
- elsif (/^username=/) {
- print "username=$user\n";
- }
- elsif (/^fromuser=/) {
- print "fromuser=$user\n";
- }
- elsif (/^secret=/) {
- print "secret=$pass\n";
- }
- elsif (/^host=/) {
- print "host=$host\n";
- }
- else {
- print $_;
- }
- }
- else {
- # comment out unused mini-asterisk stanzas
- if (/^;;/) {
- # special csse for comment lines
- print "$_";
- }
- else {
- print ";$_";
- }
- }
- }
-
-}
-close SIP;
-
+++ /dev/null
-#!/bin/sh
-# set_voipline.sh
-# # David Rowe 12 Jan 2010
-#
-# CGI to set voip line parameters in sip.conf.
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-user=`echo "$QUERY_STRING" | grep -oe "user=[^&?]*" | sed -n "s/user=//p"`
-pass=`echo "$QUERY_STRING" | grep -oe "pass=[^&?]*" | sed -n "s/pass=//p"`
-host=`echo "$QUERY_STRING" | grep -oe "host=[^&?]*" | sed -n "s/host=//p"`
-provider=`echo "$QUERY_STRING" | grep -oe "provider=[^&?]*" | sed -n "s/provider=//p"`
-
-# create new sip.conf with selected provider uncommented
-
-echo "set_voiplines.sh" $user $pass $host $provider >> /tmp/log.txt
-perl set_voiplines.pl $user $pass $host $provider > /etc/asterisk/sip.conf.new
-mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.bak
-mv /etc/asterisk/sip.conf.new /etc/asterisk/sip.conf
-
-# modify extensions.conf for new provider
-
-sed -i "s#_1.,1,Dial(.*)#_1.,1,Dial(SIP/$user/\${EXTEN:1})#" /etc/asterisk/extensions.conf
-asterisk -rx "dialplan reload" 2>/dev/null 1 > /dev/null
-
-# get asterisk to load changes
-
-asterisk -rx "sip reload" 2>/dev/null 1 > /dev/null
-
-cat <<EOF
-<html>
-<head>
-<title>set_voiplines.sh</title>
-<meta http-equiv="REFRESH" content="0;url=voiplines.sh">
-<body>
-Please wait a few seconds.....
-</body>
-</head>
-</html>
-EOF
-
+++ /dev/null
-.tip {font:14px/16px
-Arial,Helvetica,sans-serif; border:solid 1px
-#666666; width:270px; padding:1px;
-position:absolute; z-index:100;
-visibility:hidden; color:#333333; top:20px;
-left:90px; background-color:#ffffcc;
-layer-background-color:#ffffcc;}
+++ /dev/null
-// Extended Tooltip Javascript
-// copyright 9th August 2002, 3rd July 2005, 24th August 2008
-// by Stephen Chapman, Felgall Pty Ltd
-
-// permission is granted to use this javascript provided that the below code is not altered
-function pw() {return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth}; function mouseX(evt) {return evt.clientX ? evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) : evt.pageX;} function mouseY(evt) {return evt.clientY ? evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop) : evt.pageY} function popUp(evt,oi) {if (document.getElementById) {var wp = pw(); dm = document.getElementById(oi); ds = dm.style; st = ds.visibility; if (dm.offsetWidth) ew = dm.offsetWidth; else if (dm.clip.width) ew = dm.clip.width; if (st == "visible" || st == "show") { ds.visibility = "hidden"; } else {tv = mouseY(evt) + 20; lv = mouseX(evt) - (ew/4); if (lv < 2) lv = 2; else if (lv + ew > wp) lv -= ew/2; lv += 'px';tv += 'px'; ds.left = lv; ds.top = tv; ds.visibility = "visible";}}}
-
+++ /dev/null
-<div id="network_internet" class="tip">
- A tick means your phone system can reach the Internet. You need the Internet for VOIP calls
- and software upgrades.
- If you have a problem reaching the Internet check your Network settings, in
- particular Gateway and DNS.</div>
-
-<div id="network_backdoor" class="tip">
- Emergency backdoor IP. Useful if you get locked out of the main network connection, for
- example due to DHCP problems on your network or a configuration mistake.
- Write this number down somewhere!</div>
-
-<div id="phone_reception" class="tip">
- If ticked this phone will ring when some one
- calls the phone system from an outside Analog
- or VOIP Line. More than one phone can be
- ticked. You can answer a call on another
- ringing phone by dialling *8 on your phone -
- see FAQ for details.</div>
-
-<div id="phone_update_reception" class="tip">
- Press this button to lock in any changes you
- have made to the Reception check-boxes above.</div>
-
-<div id="phone_anphone" class="tip">
- Analog Phone: Normal telephone plugged into a
- port on your phone system. </div> <div
- id="phone_ipphone" class="tip"> IP Phone
- plugged into your network. </div> <div
- id="phone_line" class="tip"> Analog Phone
- Line: Analog telephone line plugged into a
- port on your phone system. </div> <div
- id="phone_voipline" class="tip"> VOIP Phone
- Line: Make and receive phone calls over the
- Internet. </div>
-
-<div id="phone_system" class="tip">
- Important information about your Phone System.</div>
-
-<div id="phone_ipaddress" class="tip">
- The address of your Phone System
- on your network. Use this address to connect
- IP Phones to your Phone System. </div>
-
-<div id="phone_phones" class="tip">
- List of phones connected to your Phone
- System. You can connect Analog or IP Phones
- to your system. When IP Phones are
- configured correctly, they appear on this
- list. If an IP phone is not configured
- correctly, it will not appear on this list.
- Analog phones require hardware to be
- installed in your Phone system.</div>
-
-<div id="phone_lines" class="tip">
- List of phone lines available. Phone lines
- are used to make and receive outside calls.
- You can use regular Analog phone lines or
- VOIP. VOIP phone lines require an account
- with an Internet Telephone Service Provider.
- Analog phone lines require hardware to be
- installed in your Phone System.</div>
-
-<div id="phone_ext" class="tip">
- Dial this number to call this phone</div>
-
-<div id="phone_port_phone" class="tip">
- Port (socket) on the rear of your Phone System. Plug the phone into this Port.</div>
-
-<div id="phone_port_line" class="tip">
- Port (socket) on the rear of your Phone
- System. Plug the phone line into this
- Port.</div>
-
-<div id="phone_line_prefix" class="tip">
- Dial 0 for an Analog outside line. For example to call 5551234 dial 05551234. Don't pause after the 0, just dial 0 and the outside number together.</div>
-
-<div id="phone_ipphone_ip" class="tip">
- IP Address of this phone on your network</div>
-
-<div id="phone_voipline_ip" class="tip">
- IP Address of the VOIP Internet Telephone Service Provider</div>
-
-<div id="phone_voipline_prefix" class="tip">
- Dial 1 for a VOIP outside line. For example to call 5551234 dial 15551234. Don't pause after the 1, just dial 1 and the outside number together.</div>
-
-<div id="phone_addipphone" class="tip">
- Instructions and help on adding a new IP phone</div>
-
-<div id="phone_addvoipline" class="tip">
- Instructions and help on VOIP Line set up</div>
-
-<div id="ipphones_ipphones" class="tip">
- List of possible IP phones. For a new phone
- choose any Available number. Refresh this
- page to update</div>
-
-<div id="ipphones_connected" class="tip">
- The IP phone is connected to your phone system and ready to use</div>
-
-<div id="ipphones_notconnected" class="tip">
- No IP phone is connected. Either no IP phone
- is present, or the IP phone has not been set
- up.</div>
-
-<div id="voiplines_voiplines" class="tip">
- A VOIP line allows you to make and receive
- phones calls over the Internet. Normally a
- VOIP line is provided by an Internet Telephony
- Service Provider (ITSP). They will give you
- an account, which includes the user and
- password details that you can fill in below.
- Refresh this page on your browser to see if
- your VOIP line is working. </div>
-
-<div id="voiplines_provider" class="tip">
- Your Internet Telephony Service Provider.
- They will give you an account with a user name
- and password.</div>
-
-<div id="voiplines_user" class="tip">
- Your account name with your Internet Telephony Service Provider</div>
-
-<div id="voiplines_pass" class="tip">
- The password for your Internet Telephony Service Provider account</div>
-
-<div id="voiplines_host" class="tip">
- The Internet address of your Internet
- Telephony Service Provider. This will usually
- be filled in automatically.</div>
-
-<div id="voiplines_status" class="tip">
- A tick means you are connected to your
- Internet Telephony Service Provider. Refresh
- your browser to update.</div>
-
-<div id="admin_restart" class="tip">
- Press this button to restart your phone
- system. This is the same as turning the power
- off and back on. </div>
-
-<div id="admin_upgrade" class="tip">
- Press this button to install the latest
- version of Mini Asterisk. An Mini Asterisk
- upgrade requires an Internet connection.</div>
-
-<div id="admin_firmware" class="tip">
- Enter the URL of a firmware update script.
- This option can be used to install new
- firmware on your Phone System. Installing new
- firmware requires an Internet connection. the
- full URL Must be entered,
- e.g. http://rowetel.com/ucasterisk/mini/test.sh</div>
-
+++ /dev/null
-function changeProvider() {
- provider = $('provider').value;
- $('user').value = users[provider];
- $('pass').value = passwords[provider];
- $('host').value = hosts[provider];
- $('comment').innerHTML = comments[provider];
- $('status').innerHTML = '<img src="cross.png" alt=\"Not OK\" />';
-}
+++ /dev/null
-#!/usr/bin/perl
-# voiplines.pl
-# David Rowe 12 Jan 2010
-#
-# Text processing for the voiplines screen
-
-# slurp up list of possible voip line providers --------------------------------
-# one of these will be currently selected
-
-open SIP, "/etc/asterisk/sip.conf";
-my $provider = ""; # current provider bring parsed in sip.conf
-my @providers=(); # list of all providers
-my %user = (); # user keyed on provider
-my %pass = (); # password keyed on provider
-my %host = (); # host name keyed on provider
-
-my $provider_current = "none";
-push (@providers, "none");
-$comment{"none"} = " ";
-
-while (<SIP>) {
-
- # start of any stanza switches off parsing. It may get switched
- # back on below if it contains mini-asterisk keyword. This allows
- # non-mini asterisk SIP devices to be included in sip.conf
-
- if (/\[/) {
- $provider = "";
- }
-
- # currently disabled mini-asterisk provider
-
- if (/^;\[.*\].* \"(.*)\" mini-asterisk/) {
- push (@providers, $1);
- $provider = $1;
- #print "'$1'\n";
- }
-
- # current mini-asterisk provider
-
- if (/^\[(.*)\].* \"(.*)\" mini-asterisk/) {
- push (@providers, $2);
- $provider = $2;
- $provider_current = $2;
- $stanza_current = $1;
- #print "'$1' '$2'\n";
- }
-
- if ($provider ne "") {
- #print $_;
-
- if (/^;*username=(.*)/) {
- $user{$provider} = $1;
- }
- if (/^;*secret=(.*)/) {
- $pass{$provider} = $1;
- }
- if (/^;*host=(.*)/) {
- $host{$provider} = $1;
- }
-
- if (/^;; (.*)/) {
- $comment{$provider} = $1;
- }
- }
-
- $state = $next_state;
-}
-close SIP;
-
-# Determine if Asterisk can see current voip line (SIP trunk)
-# sipshowpeers.txt needs to be generated before calling this perl
-# script
-
-my %voip = (); # SIP trunks status keyed on sip.conf stanza name/username
- # if no entry we can't see SIP trunk
-
-open SIP, "sipshowregistry.txt";
-while (<SIP>) {
- if (/^(.*):.*(Registered)/) {
- $voip{$1} = $2;
- #print "'$1' '$2' $voip{$1}\n";
- }
-}
-
-close SIP;
-
-# javascript to handle changing providers
-
-print "<script>\n";
-print "var hosts = new Array();\n";
-print "var users = new Array();\n";
-print "var passwords = new Array();\n";
-print "var stanzas = new Array();\n";
-print "var comments = new Array();\n";
-foreach (@providers) {
- print "hosts[\'$_\'] = \'$host{$_}\';\n";
- print "users[\'$_\'] = \'$user{$_}\';\n";
- print "passwords[\'$_\'] = \'$pass{$_}\';\n";
- print "comments[\'$_\'] = \'$comment{$_}\';\n";
-}
-print "</script>\n";
-
-# generate form fields -------------------------------------------
-
-$tt_provider = "onMouseOver=\"popUp(event,'voiplines_provider')\" onmouseout=\"popUp(event,'voiplines_provider')\"";
-$tt_user = "onMouseOver=\"popUp(event,'voiplines_user')\" onmouseout=\"popUp(event,'voiplines_user')\"";
-$tt_pass = "onMouseOver=\"popUp(event,'voiplines_pass')\" onmouseout=\"popUp(event,'voiplines_pass')\"";
-$tt_host = "onMouseOver=\"popUp(event,'voiplines_host')\" onmouseout=\"popUp(event,'voiplines_host')\"";
-$tt_status = "onMouseOver=\"popUp(event,'voiplines_status')\" onmouseout=\"popUp(event,'voiplines_status')\"";
-
-print "<tr $tt_provider><td>Provider</td><td>\n";
-print "<select name=\"provider\" id=\"provider\" onchange=\"changeProvider()\">\n";
-foreach (@providers) {
- if ($_ eq $provider_current) {
- print "<option selected=\"yes\">$_</option>\n";
- }
- else {
- print "<option>$_</option>\n";
- }
-}
-print "</select></td></tr>\n";
-
-print "<tr $tt_user><td>User:</td><td><input type=\"text\" name=\"user\" id=\"user\" value=\"$user{$provider_current}\"></td></tr>\n";
-print "<tr $tt_pass><td >Password:</td><td><input type=\"password\" name=\"pass\" id=\"pass\" value=\"$pass{$provider_current}\"></td></tr>\n";
-print "<tr $tt_host><td >Host:</td><td><input type=\"text\" name=\"host\" id=\"host\" value=\"$host{$provider_current}\"></td></tr>\n";
-
-#print "\nXXX $provider_current $stanza_current} $voip{$stanza_current}\n";
-
-if ($voip{$stanza_current} eq "Registered") {
- $icon = "<img src=\"tick.png\" alt=\"OK\" />";
-}
-else {
- $icon = "<img src=\"cross.png\" alt=\"Not OK\" />";
-}
-print "<tr $tt_status><td>Voip Line Status:</td><td><div id=\"status\" >$icon</div></td></tr>\n";
-
-print "<tr><td> </td></tr>\n";
-print "<tr><td colspan=\"2\"><div id=\"comment\">$comment{$provider_current}</div></td></tr>\n";
-print "<tr><td> </td></tr>\n";
+++ /dev/null
-#!/bin/sh
-# voiplines.sh
-# David Rowe 12 Jan 2010
-# VOIP Line screen for Mini Asterisk GUI
-
-# check we are logged in
-
-echo $HTTP_COOKIE | grep "loggedin" > /dev/null
-if [ $? -eq 1 ]; then
- echo "<html>"
- echo "<head>"
- echo '<meta http-equiv="REFRESH" content="0;url=login.sh">'
- echo "</head>"
- echo "</html>"
- exit
-fi
-
-# See if we have can reach the VOIP Line provider
-
-asterisk "-rx sip show registry" 2>/dev/null > sipshowregistry.txt
-
-# Construct the web page -------------------------------
-
-cat <<EOF
-<script src="prototype.js"></script>
-<script type="text/javascript" src="tooltip.js"></script>
-<link rel="stylesheet" href="tooltip.css" type="text/css" />
-<script>
-EOF
-
-cat voiplines.js
-
-cat << EOF
-</script>
-<html>
-<title>Mini Asterisk - VOIP Line</title>
-EOF
-
-cat tooltips.html
-echo '<table align="center" width=800>'
-cat banner.html
-echo " <tr>"
-cat menu.html
-cat <<EOF
-
- <td valign="top">
-
- <table align="right" width=600>
- <tr><td> </td></tr>
- <form action="set_voiplines.sh" method="get">
- <tr><td onMouseOver="popUp(event,'voiplines_voiplines')" onmouseout="popUp(event,'voiplines_voiplines')" align="left" valign="top" colspan="3"><h2>VOIP Line</h2></td></tr>
-
- <tr><td> </td></tr>
-EOF
-
-perl ./voiplines.pl
-
-cat <<EOF
-
- <tr><td colspan="2">Sometimes it takes a few seconds to connect
- your Voip Line. After clicking OK refresh
- your browser to update Voip Line status.
- </td></tr>
-
- <tr><td> </td></tr>
- <tr><td><input type="submit" value="OK"></td></tr>
-
- </form>
-
- </table>
- </form>
-
- </td>
-
- </tr>
-
-</table>
-</body>
-</html>
-EOF
-
+++ /dev/null
-; extensions.conf
-; David Rowe 4 Jan 2010
-;
-
-; Designed for Mini Asterisk GUI. However you can hand modify as much
-; as you like, as GUI scripts read/and write regular extensions.conf
-; without messing with your custom dialplan
-
-
-[general]
-static = yes
-writeprotect = no
-autofallthrough = yes
-clearglobalvars = no
-priorityjumping = no
-
-[default]
-
-; Pre-configured analog extensions, depends on IP0X model and what modules
-; are installed. Some of these may map to FXO ports
-
-exten => 6001,1,Dial(Zap/1)
-exten => 6002,1,Dial(Zap/2)
-exten => 6003,1,Dial(Zap/3)
-exten => 6004,1,Dial(Zap/4)
-exten => 6005,1,Dial(Zap/5)
-exten => 6006,1,Dial(Zap/6)
-exten => 6007,1,Dial(Zap/7)
-exten => 6008,1,Dial(Zap/8)
-
-; Pre-configured SIP-phone extensions. Primary use case is multiple SIP
-; extensions and FXO analog Ports
-
-exten => 6011,1,Dial(SIP/6011)
-exten => 6012,1,Dial(SIP/6012)
-exten => 6013,1,Dial(SIP/6013)
-exten => 6014,1,Dial(SIP/6014)
-exten => 6015,1,Dial(SIP/6015)
-exten => 6016,1,Dial(SIP/6016)
-exten => 6017,1,Dial(SIP/6017)
-exten => 6018,1,Dial(SIP/6018)
-exten => 6019,1,Dial(SIP/6019)
-exten => 6020,1,Dial(SIP/6020)
-exten => 6021,1,Dial(SIP/6021)
-exten => 6022,1,Dial(SIP/6022)
-
-; Pre-configured mini-asterisk outgoing Analog group
-
-exten => _0.,1,Dial(Zap/g2/${EXTEN:1})
-
-; Pre-configured mini-asterisk outgoing VOIP line
-
-exten => _1.,1,Dial(SIP/voip/${EXTEN:1})
-
-; Pre-configured incoming calls
-
-exten => s,1,Dial(SIP/6011) ;; mini-asterisk - don't remove this comment
-
+++ /dev/null
-
-; Inter-Asterisk eXchange driver definition
-;
-; This configuration is re-read at reload
-; or with the CLI command
-; reload chan_iax2.so
-;
-; General settings, like port number to bind to, and
-; an option address (the default is to bind to all
-; local addresses).
-;
-[general]
-;bindport=4569 ; bindport and bindaddr may be specified
-; ; NOTE: bindport must be specified BEFORE bindaddr
-; ; or may be specified on a specific bindaddr if followed by
-; ; colon and port (e.g. bindaddr=192.168.0.1:4569)
-;bindaddr=192.168.0.1 ; more than once to bind to multiple
-; ; addresses, but the first will be the
-; ; default
-;
-; Set iaxcompat to yes if you plan to use layered switches or
-; some other scenario which may cause some delay when doing a
-; lookup in the dialplan. It incurs a small performance hit to
-; enable it. This option causes Asterisk to spawn a separate thread
-; when it receives an IAX DPREQ (Dialplan Request) instead of
-; blocking while it waits for a response.
-;
-;iaxcompat=yes
-;
-; Disable UDP checksums (if nochecksums is set, then no checkums will
-; be calculated/checked on systems supporting this feature)
-;
-;nochecksums=no
-;
-;
-; For increased security against brute force password attacks
-; enable "delayreject" which will delay the sending of authentication
-; reject for REGREQ or AUTHREP if there is a password.
-;
-;delayreject=yes
-;
-; You may specify a global default AMA flag for iaxtel calls. It must be
-; one of 'default', 'omit', 'billing', or 'documentation'. These flags
-; are used in the generation of call detail records.
-;
-;amaflags=default
-;
-; You may specify a default account for Call Detail Records in addition
-; to specifying on a per-user basis
-;
-;accountcode=lss0101
-;
-; You may specify a global default language for users.
-; Can be specified also on a per-user basis
-; If omitted, will fallback to english
-;
-;language=en
-;
-; Specify bandwidth of low, medium, or high to control which codecs are used
-; in general.
-;
-bandwidth=low
-;
-; You can also fine tune codecs here using "allow" and "disallow" clauses
-; with specific codecs. Use "all" to represent all formats.
-;
-;allow=all ; same as bandwidth=high
-;disallow=g723.1 ; Hm... Proprietary, don't use it...
-disallow=lpc10 ; Icky sound quality... Mr. Roboto.
-;allow=gsm ; Always allow GSM, it's cool :)
-;
-
-; You can adjust several parameters relating to the jitter buffer.
-; The jitter buffer's function is to compensate for varying
-; network delay.
-;
-; There are presently two jitterbuffer implementations available for Asterisk
-; and chan_iax2; the classic and the new, channel/application independent
-; implementation. These are controlled at compile-time. The new jitterbuffer
-; additionally has support for PLC which greatly improves quality as the
-; jitterbuffer adapts size, and in compensating for lost packets.
-;
-; All the jitter buffer settings except dropcount are in milliseconds.
-; The jitter buffer works for INCOMING audio - the outbound audio
-; will be dejittered by the jitter buffer at the other end.
-;
-; jitterbuffer=yes|no: global default as to whether you want
-; the jitter buffer at all.
-;
-; forcejitterbuffer=yes|no: in the ideal world, when we bridge VoIP channels
-; we don't want to do jitterbuffering on the switch, since the endpoints
-; can each handle this. However, some endpoints may have poor jitterbuffers
-; themselves, so this option will force * to always jitterbuffer, even in this
-; case.
-; [This option presently applies only to the new jitterbuffer implementation]
-;
-; dropcount: the jitter buffer is sized such that no more than "dropcount"
-; frames would have been "too late" over the last 2 seconds.
-; Set to a small number. "3" represents 1.5% of frames dropped
-; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
-;
-; maxjitterbuffer: a maximum size for the jitter buffer.
-; Setting a reasonable maximum here will prevent the call delay
-; from rising to silly values in extreme situations; you'll hear
-; SOMETHING, even though it will be jittery.
-;
-; resyncthreshold: when the jitterbuffer notices a significant change in delay
-; that continues over a few frames, it will resync, assuming that the change in
-; delay was caused by a timestamping mix-up. The threshold for noticing a
-; change in delay is measured as twice the measured jitter plus this resync
-; threshold.
-; Resyncing can be disabled by setting this parameter to -1.
-; [This option presently applies only to the new jitterbuffer implementation]
-;
-; maxjitterinterps: the maximum number of interpolation frames the jitterbuffer
-; should return in a row. Since some clients do not send CNG/DTX frames to
-; indicate silence, the jitterbuffer will assume silence has begun after
-; returning this many interpolations. This prevents interpolating throughout
-; a long silence.
-; [This option presently applies only to the new jitterbuffer implementation]
-;
-; maxexcessbuffer: If conditions improve after a period of high jitter,
-; the jitter buffer can end up bigger than necessary. If it ends up
-; more than "maxexcessbuffer" bigger than needed, Asterisk will start
-; gradually decreasing the amount of jitter buffering.
-; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
-;
-; minexcessbuffer: Sets a desired mimimum amount of headroom in
-; the jitter buffer. If Asterisk has less headroom than this, then
-; it will start gradually increasing the amount of jitter buffering.
-; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
-;
-; jittershrinkrate: when the jitter buffer is being gradually shrunk
-; (or enlarged), how many millisecs shall we take off per 20ms frame
-; received? Use a small number, or you will be able to hear it
-; changing. An example: if you set this to 2, then the jitter buffer
-; size will change by 100 millisecs per second.
-; [This option is not applicable to, and ignored by the new jitterbuffer implementation]
-
-jitterbuffer=no
-forcejitterbuffer=no
-;dropcount=2
-;maxjitterbuffer=1000
-;maxjitterinterps=10
-;resyncthreshold=1000
-;maxexcessbuffer=80
-;minexcessbuffer=10
-;jittershrinkrate=1
-
-;trunkfreq=20 ; How frequently to send trunk msgs (in ms)
-
-; Should we send timestamps for the individual sub-frames within trunk frames?
-; There is a small bandwidth use for these (less than 1kbps/call), but they
-; ensure that frame timestamps get sent end-to-end properly. If both ends of
-; all your trunks go directly to TDM, _and_ your trunkfreq equals the frame
-; length for your codecs, you can probably suppress these. The receiver must
-; also support this feature, although they do not also need to have it enabled.
-;
-; trunktimestamps=yes
-;
-; Minimum and maximum amounts of time that IAX peers can request as
-; a registration expiration interval (in seconds).
-; minregexpire = 60
-; maxregexpire = 60
-;
-; We can register with another IAX server to let him know where we are
-; in case we have a dynamic IP address for example
-;
-; Register with tormenta using username marko and password secretpass
-;
-;register => marko:secretpass@tormenta.linux-support.net
-;
-; Register joe at remote host with no password
-;
-;register => joe@remotehost:5656
-;
-; Register marko at tormenta.linux-support.net using RSA key "torkey"
-;
-;register => marko:[torkey]@tormenta.linux-support.net
-;
-; Sample Registration for iaxtel
-;
-; Visit http://www.iaxtel.com to register with iaxtel. Replace "user"
-; and "pass" with your username and password for iaxtel. Incoming
-; calls arrive at the "s" extension of "default" context.
-;
-;register => user:pass@iaxtel.com
-;
-; Sample Registration for IAX + FWD
-;
-; To register using IAX with FWD, it must be enabled by visiting the URL
-; http://www.fwdnet.net/index.php?section_id=112
-;
-; Note that you need an extension in you default context which matches
-; your free world dialup number. Please replace "FWDNumber" with your
-; FWD number and "passwd" with your password.
-;
-;register => FWDNumber:passwd@iax.fwdnet.net
-;
-;
-; You can disable authentication debugging to reduce the amount of
-; debugging traffic.
-;
-;authdebug=no
-;
-; Finally, you can set values for your TOS bits to help improve
-; performance. Valid values are:
-; lowdelay -- Minimize delay
-; throughput -- Maximize throughput
-; reliability -- Maximize reliability
-; mincost -- Minimize cost
-; none -- No flags
-;
-tos=lowdelay
-;
-; If mailboxdetail is set to "yes", the user receives
-; the actual new/old message counts, not just a yes/no
-; as to whether they have messages. this can be set on
-; a per-peer basis as well
-;
-;mailboxdetail=yes
-;
-; If regcontext is specified, Asterisk will dynamically create and destroy
-; a NoOp priority 1 extension for a given peer who registers or unregisters
-; with us. The actual extension is the 'regexten' parameter of the registering
-; peer or its name if 'regexten' is not provided. More than one regexten
-; may be supplied if they are separated by '&'. Patterns may be used in
-; regexten.
-;
-;regcontext=iaxregistrations
-;
-; If we don't get ACK to our NEW within 2000ms, and autokill is set to yes,
-; then we cancel the whole thing (that's enough time for one retransmission
-; only). This is used to keep things from stalling for a long time for a host
-; that is not available, but would be ill advised for bad connections. In
-; addition to 'yes' or 'no' you can also specify a number of milliseconds.
-; See 'qualify' for individual peers to turn on for just a specific peer.
-;
-autokill=yes
-;
-; codecpriority controls the codec negotiation of an inbound IAX call.
-; This option is inherited to all user entities. It can also be defined
-; in each user entity separately which will override the setting in general.
-;
-; The valid values are:
-;
-; caller - Consider the callers preferred order ahead of the host's.
-; host - Consider the host's preferred order ahead of the caller's.
-; disabled - Disable the consideration of codec preference alltogether.
-; (this is the original behaviour before preferences were added)
-; reqonly - Same as disabled, only do not consider capabilities if
-; the requested format is not available the call will only
-; be accepted if the requested format is available.
-;
-; The default value is 'host'
-;
-;codecpriority=host
-
-;rtcachefriends=yes ; Cache realtime friends by adding them to the internal list
- ; just like friends added from the config file only on a
- ; as-needed basis? (yes|no)
-
-;rtupdate=yes ; Send registry updates to database using realtime? (yes|no)
- ; If set to yes, when a IAX2 peer registers successfully, the ip address,
- ; the origination port, the registration period, and the username of
- ; the peer will be set to database via realtime. If not present, defaults to 'yes'.
-
-;rtautoclear=yes ; Auto-Expire friends created on the fly on the same schedule
- ; as if it had just registered? (yes|no|<seconds>)
- ; If set to yes, when the registration expires, the friend will vanish from
- ; the configuration until requested again. If set to an integer,
- ; friends expire within this number of seconds instead of the
- ; registration interval.
-
-;rtignoreexpire=yes ; When reading a peer from Realtime, if the peer's registration
- ; has expired based on its registration interval, used the stored
- ; address information regardless. (yes|no)
-
-iaxthreadcount = 8
-
-[misery]
-type=user
-context=default
-
-; Guest sections for unauthenticated connection attempts. Just specify an
-; empty secret, or provide no secret section.
-;
-;[guest]
-;type=user
-;context=default
-;callerid="Guest IAX User"
-
-;
-; Trust Caller*ID Coming from iaxtel.com
-;
-[iaxtel]
-type=user
-context=default
-auth=rsa
-inkeys=iaxtel
-
-;
-; Trust Caller*ID Coming from iax.fwdnet.net
-;
-[iaxfwd]
-type=user
-context=default
-auth=rsa
-inkeys=freeworlddialup
-
-;
-; Trust callerid delivered over DUNDi/e164
-;
-;
-;[dundi]
-;type=user
-;dbsecret=dundi/secret
-;context=dundi-e164-local
-
-;
-; Further user sections may be added, specifying a context and a secret used
-; for connections with that given authentication name. Limited IP based
-; access control is allowed by use of "allow" and "deny" keywords. Multiple
-; rules are permitted. Multiple permitted contexts may be specified, in
-; which case the first will be the default. You can also override caller*ID
-; so that when you receive a call you set the Caller*ID to be what you want
-; instead of trusting what the remote user provides
-;
-; There are three authentication methods that are supported: md5, plaintext,
-; and rsa. The least secure is "plaintext", which sends passwords cleartext
-; across the net. "md5" uses a challenge/response md5 sum arrangement, but
-; still requires both ends have plain text access to the secret. "rsa" allows
-; unidirectional secret knowledge through public/private keys. If "rsa"
-; authentication is used, "inkeys" is a list of acceptable public keys on the
-; local system that can be used to authenticate the remote peer, separated by
-; the ":" character. "outkey" is a single, private key to use to authenticate
-; to the other side. Public keys are named /var/lib/asterisk/keys/<name>.pub
-; while private keys are named /var/lib/asterisk/keys/<name>.key. Private
-; keys should always be 3DES encrypted.
-;
-;
-;[markster]
-;type=user
-;context=default
-;context=local
-;auth=md5,plaintext,rsa
-;secret=markpasswd
-;setvar=foo=bar
-;dbsecret=mysecrets/place ; Secrets can be stored in astdb, too
-;notransfer=yes ; Disable IAX native transfer
-;jitterbuffer=yes ; Override global setting an enable jitter buffer
-; ; for this user
-;callerid="Mark Spencer" <(256) 428-6275>
-;deny=0.0.0.0/0.0.0.0
-;accountcode=markster0101
-;permit=209.16.236.73/255.255.255.0
-;language=en ; Use english as default language
-;
-; Peers may also be specified, with a secret and
-; a remote hostname.
-;
-[demo]
-type=peer
-username=asterisk
-secret=supersecret
-host=216.207.245.47
-;sendani=no
-;host=asterisk.linux-support.net
-;port=5036
-;mask=255.255.255.255
-;qualify=yes ; Make sure this peer is alive
-;qualifysmoothing = yes ; use an average of the last two PONG
- ; results to reduce falsly detected LAGGED hosts
- ; Default: Off
-;qualifyfreqok = 60000 ; how frequently to ping the peer when
- ; everything seems to be ok, in milliseconds
-;qualifyfreqnotok = 10000 ; how frequently to ping the peer when it's
- ; either LAGGED or UNAVAILABLE, in milliseconds
-;jitterbuffer=no ; Turn off jitter buffer for this peer
-
-;
-; Peers can remotely register as well, so that they can be mobile. Default
-; IP's can also optionally be given but are not required. Caller*ID can be
-; suggested to the other side as well if it is for example a phone instead of
-; another PBX.
-;
-
-;[dynamichost]
-;host=dynamic
-;secret=mysecret
-;mailbox=1234 ; Notify about mailbox 1234
-;inkeys=key1:key2
-;peercontext=local ; Default context to request for calls to peer
-;defaultip=216.207.245.34
-;callerid="Some Host" <(256) 428-6011>
-;
-
-;
-;[biggateway]
-;type=peer
-;host=192.168.0.1
-;context=*
-;secret=myscret
-;trunk=yes ; Use IAX2 trunking with this host
-;timezone=America/New_York ; Set a timezone for the date/time IE
-;
-
-;
-; Friends are a short cut for creating a user and
-; a peer with the same values.
-;
-;[marko]
-;type=friend
-;host=dynamic
-;regexten=1234
-;secret=moofoo
-;context=default
-;permit=0.0.0.0/0.0.0.0
-
+++ /dev/null
-;
-; SIP Configuration example for Asterisk
-;
-; Syntax for specifying a SIP device in extensions.conf is
-; SIP/devicename where devicename is defined in a section below.
-;
-; You may also use
-; SIP/username@domain to call any SIP user on the Internet
-; (Don't forget to enable DNS SRV records if you want to use this)
-;
-; If you define a SIP proxy as a peer below, you may call
-; SIP/proxyhostname/user or SIP/user@proxyhostname
-; where the proxyhostname is defined in a section below
-;
-; Useful CLI commands to check peers/users:
-; sip show peers Show all SIP peers (including friends)
-; sip show users Show all SIP users (including friends)
-; sip show registry Show status of hosts we register with
-;
-; sip debug Show all SIP messages
-;
-; reload chan_sip.so Reload configuration file
-; Active SIP peers will not be reconfigured
-;
-
-[general]
-context=default ; Default context for incoming calls
-allowguest=no ; Allow or reject guest calls (default is yes, this can also be set to 'osp'
- ; if asterisk was compiled with OSP support.
-;realm=mydomain.tld ; Realm for digest authentication
- ; defaults to "asterisk"
- ; Realms MUST be globally unique according to RFC 3261
- ; Set this to your host name or domain name
-bindport=5060 ; UDP Port to bind to (SIP standard port is 5060)
-bindaddr=0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all)
-srvlookup=yes ; Enable DNS SRV lookups on outbound calls
- ; Note: Asterisk only uses the first host
- ; in SRV records
- ; Disabling DNS SRV lookups disables the
- ; ability to place SIP calls based on domain
- ; names to some other SIP users on the Internet
-
-;domain=mydomain.tld ; Set default domain for this host
- ; If configured, Asterisk will only allow
- ; INVITE and REFER to non-local domains
- ; Use "sip show domains" to list local domains
-;domain=mydomain.tld,mydomain-incoming
- ; Add domain and configure incoming context
- ; for external calls to this domain
-;domain=1.2.3.4 ; Add IP address as local domain
- ; You can have several "domain" settings
-;allowexternalinvites=no ; Disable INVITE and REFER to non-local domains
- ; Default is yes
-;autodomain=yes ; Turn this on to have Asterisk add local host
- ; name and local IP to domain list.
-;pedantic=yes ; Enable slow, pedantic checking for Pingtel
- ; and multiline formatted headers for strict
- ; SIP compatibility (defaults to "no")
-;tos=184 ; Set IP QoS to either a keyword or numeric val
-;tos=lowdelay ; lowdelay,throughput,reliability,mincost,none
-;maxexpiry=3600 ; Max length of incoming registration we allow
-;defaultexpiry=120 ; Default length of incoming/outoing registration
-;notifymimetype=text/plain ; Allow overriding of mime type in MWI NOTIFY
-;checkmwi=10 ; Default time between mailbox checks for peers
-;vmexten=voicemail ; dialplan extension to reach mailbox sets the
- ; Message-Account in the MWI notify message
- ; defaults to "asterisk"
-;videosupport=yes ; Turn on support for SIP video
-;recordhistory=yes ; Record SIP history by default
- ; (see sip history / sip no history)
-
-;disallow=all ; First disallow all codecs
-;allow=ulaw ; Allow codecs in order of preference
-;allow=ilbc ;
-;musicclass=default ; Sets the default music on hold class for all SIP calls
- ; This may also be set for individual users/peers
-;language=en ; Default language setting for all users/peers
- ; This may also be set for individual users/peers
-;relaxdtmf=yes ; Relax dtmf handling
-;rtptimeout=60 ; Terminate call if 60 seconds of no RTP activity
- ; when we're not on hold
-;rtpholdtimeout=300 ; Terminate call if 300 seconds of no RTP activity
- ; when we're on hold (must be > rtptimeout)
-;trustrpid = no ; If Remote-Party-ID should be trusted
-;sendrpid = yes ; If Remote-Party-ID should be sent
-;progressinband=never ; If we should generate in-band ringing always
- ; use 'never' to never use in-band signalling, even in cases
- ; where some buggy devices might not render it
-;useragent=Asterisk PBX ; Allows you to change the user agent string
-;promiscredir = no ; If yes, allows 302 or REDIR to non-local SIP address
- ; Note that promiscredir when redirects are made to the
- ; local system will cause loops since SIP is incapable
- ; of performing a "hairpin" call.
-;usereqphone = no ; If yes, ";user=phone" is added to uri that contains
- ; a valid phone number
-;dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833
- ; Other options:
- ; info : SIP INFO messages
- ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
- ; auto : Use rfc2833 if offered, inband otherwise
-
-;compactheaders = yes ; send compact sip headers.
-;sipdebug = yes ; Turn on SIP debugging by default, from
- ; the moment the channel loads this configuration
-;subscribecontext = default ; Set a specific context for SUBSCRIBE requests
- ; Useful to limit subscriptions to local extensions
- ; Settable per peer/user also
-;notifyringing = yes ; Notify subscriptions on RINGING state
-
-;
-; If regcontext is specified, Asterisk will dynamically create and destroy a
-; NoOp priority 1 extension for a given peer who registers or unregisters with
-; us. The actual extension is the 'regexten' parameter of the registering
-; peer or its name if 'regexten' is not provided. More than one regexten may
-; be supplied if they are separated by '&'. Patterns may be used in regexten.
-;
-;regcontext=sipregistrations
-;
-; Asterisk can register as a SIP user agent to a SIP proxy (provider)
-; Format for the register statement is:
-; register => user[:secret[:authuser]]@host[:port][/extension]
-;
-; If no extension is given, the 's' extension is used. The extension needs to
-; be defined in extensions.conf to be able to accept calls from this SIP proxy
-; (provider).
-;
-; host is either a host name defined in DNS or the name of a section defined
-; below.
-;
-; Examples:
-;
-;register => 1234:password@mysipprovider.com
-;
-; This will pass incoming calls to the 's' extension
-;
-;
-;register => 2345:password@sip_proxy/1234
-;
-; Register 2345 at sip provider 'sip_proxy'. Calls from this provider
-; connect to local extension 1234 in extensions.conf, default context,
-; unless you configure a [sip_proxy] section below, and configure a
-; context.
-; Tip 1: Avoid assigning hostname to a sip.conf section like [provider.com]
-; Tip 2: Use separate type=peer and type=user sections for SIP providers
-; (instead of type=friend) if you have calls in both directions
-
-;registertimeout=20 ; retry registration calls every 20 seconds (default)
-;registerattempts=10 ; Number of registration attempts before we give up
- ; 0 = continue forever, hammering the other server until it
- ; accepts the registration
- ; Default is 0 tries, continue forever
-;callevents=no ; generate manager events when sip ua performs events (e.g. hold)
-
-; register mini-asterisk voip line providers here
-
-;register => user@user/user ; mini-asterisk - do not change this comment
-
-;----------------------------------------- NAT SUPPORT ------------------------
-; The externip, externhost and localnet settings are used if you use Asterisk
-; behind a NAT device to communicate with services on the outside.
-
-;externip = 200.201.202.203 ; Address that we're going to put in outbound SIP messages
- ; if we're behind a NAT
-
- ; The externip and localnet is used
- ; when registering and communicating with other proxies
- ; that we're registered with
-;externhost=foo.dyndns.net ; Alternatively you can specify an
- ; external host, and Asterisk will
- ; perform DNS queries periodically. Not
- ; recommended for production
- ; environments! Use externip instead
-;externrefresh=10 ; How often to refresh externhost if
- ; used
- ; You may add multiple local networks. A reasonable set of defaults
- ; are:
-;localnet=192.168.0.0/255.255.0.0; All RFC 1918 addresses are local networks
-;localnet=10.0.0.0/255.0.0.0 ; Also RFC1918
-;localnet=172.16.0.0/12 ; Another RFC1918 with CIDR notation
-;localnet=169.254.0.0/255.255.0.0 ;Zero conf local network
-
-; The nat= setting is used when Asterisk is on a public IP, communicating with
-; devices hidden behind a NAT device (broadband router). If you have one-way
-; audio problems, you usually have problems with your NAT configuration or your
-; firewall's support of SIP+RTP ports. You configure Asterisk choice of RTP
-; ports for incoming audio in rtp.conf
-;
-;nat=no ; Global NAT settings (Affects all peers and users)
- ; yes = Always ignore info and assume NAT
- ; no = Use NAT mode only according to RFC3581
- ; never = Never attempt NAT mode or RFC3581 support
- ; route = Assume NAT, don't send rport
- ; (work around more UNIDEN bugs)
-
-;rtcachefriends=yes ; Cache realtime friends by adding them to the internal list
- ; just like friends added from the config file only on a
- ; as-needed basis? (yes|no)
-
-;rtupdate=yes ; Send registry updates to database using realtime? (yes|no)
- ; If set to yes, when a SIP UA registers successfully, the ip address,
- ; the origination port, the registration period, and the username of
- ; the UA will be set to database via realtime. If not present, defaults to 'yes'.
-
-;rtautoclear=yes ; Auto-Expire friends created on the fly on the same schedule
- ; as if it had just registered? (yes|no|<seconds>)
- ; If set to yes, when the registration expires, the friend will vanish from
- ; the configuration until requested again. If set to an integer,
- ; friends expire within this number of seconds instead of the
- ; registration interval.
-
-;ignoreregexpire=yes ; Enabling this setting has two functions:
- ;
- ; For non-realtime peers, when their registration expires, the information
- ; will _not_ be removed from memory or the Asterisk database; if you attempt
- ; to place a call to the peer, the existing information will be used in spite
- ; of it having expired
- ;
- ; For realtime peers, when the peer is retrieved from realtime storage,
- ; the registration information will be used regardless of whether
- ; it has expired or not; if it expires while the realtime peer is still in
- ; memory (due to caching or other reasons), the information will not be
- ; removed from realtime storage
-
-; Incoming INVITE and REFER messages can be matched against a list of 'allowed'
-; domains, each of which can direct the call to a specific context if desired.
-; By default, all domains are accepted and sent to the default context or the
-; context associated with the user/peer placing the call.
-; Domains can be specified using:
-; domain=<domain>[,<context>]
-; Examples:
-; domain=myasterisk.dom
-; domain=customer.com,customer-context
-;
-; In addition, all the 'default' domains associated with a server should be
-; added if incoming request filtering is desired.
-; autodomain=yes
-;
-; To disallow requests for domains not serviced by this server:
-; allowexternaldomains=no
-
-; fromdomain=mydomain.tld ; When making outbound SIP INVITEs to
- ; non-peers, use your primary domain "identity"
- ; for From: headers instead of just your IP
- ; address. This is to be polite and
- ; it may be a mandatory requirement for some
- ; destinations which do not have a prior
- ; account relationship with your server.
-
-[authentication]
-; Global credentials for outbound calls, i.e. when a proxy challenges your
-; Asterisk server for authentication. These credentials override
-; any credentials in peer/register definition if realm is matched.
-;
-; This way, Asterisk can authenticate for outbound calls to other
-; realms. We match realm on the proxy challenge and pick an set of
-; credentials from this list
-; Syntax:
-; auth = <user>:<secret>@<realm>
-; auth = <user>#<md5secret>@<realm>
-; Example:
-;auth=mark:topsecret@digium.com
-;
-; You may also add auth= statements to [peer] definitions
-; Peer auth= override all other authentication settings if we match on realm
-
-;------------------------------------------------------------------------------
-; Users and peers have different settings available. Friends have all settings,
-; since a friend is both a peer and a user
-;
-; User config options: Peer configuration:
-; -------------------- -------------------
-; context context
-; permit permit
-; deny deny
-; secret secret
-; md5secret md5secret
-; dtmfmode dtmfmode
-; canreinvite canreinvite
-; nat nat
-; callgroup callgroup
-; pickupgroup pickupgroup
-; language language
-; allow allow
-; disallow disallow
-; insecure insecure
-; trustrpid trustrpid
-; progressinband progressinband
-; promiscredir promiscredir
-; useclientcode useclientcode
-; accountcode accountcode
-; setvar setvar
-; callerid callerid
-; amaflags amaflags
-; call-limit call-limit
-; restrictcid restrictcid
-; subscribecontext subscribecontext
-; videosupport videosupport
-; mailbox
-; username
-; template
-; fromdomain
-; regexten
-; fromuser
-; host
-; port
-; qualify
-; defaultip
-; rtptimeout
-; rtpholdtimeout
-; sendrpid
-
-;[sip_proxy]
-; For incoming calls only. Example: FWD (Free World Dialup)
-; We match on IP address of the proxy for incoming calls
-; since we can not match on username (caller id)
-;type=peer
-;context=from-fwd
-;host=fwd.pulver.com
-
-;[sip_proxy-out]
-;type=peer ; we only want to call out, not be called
-;secret=guessit
-;username=yourusername ; Authentication user for outbound proxies
-;fromuser=yourusername ; Many SIP providers require this!
-;fromdomain=provider.sip.domain
-;host=box.provider.com
-;usereqphone=yes ; This provider requires ";user=phone" on URI
-;call-limit=5 ; permit only 5 simultaneous outgoing calls to this peer
-
-;------------------------------------------------------------------------------
-; Definitions of locally connected SIP phones
-;
-; type = user a device that authenticates to us by "from" field to place calls
-; type = peer a device we place calls to or that calls us and we match by host
-; type = friend two configurations (peer+user) in one
-;
-; For local phones, type=friend works most of the time
-;
-; If you have one-way audio, you propably have NAT problems.
-; If Asterisk is on a public IP, and the phone is inside of a NAT device
-; you will need to configure nat option for those phones.
-; Also, turn on qualify=yes to keep the nat session open
-
-;[grandstream1]
-;type=friend
-;context=from-sip ; Where to start in the dialplan when this phone calls
-;callerid=John Doe <1234> ; Full caller ID, to override the phones config
-;host=192.168.0.23 ; we have a static but private IP address
- ; No registration allowed
-;nat=no ; there is not NAT between phone and Asterisk
-;canreinvite=yes ; allow RTP voice traffic to bypass Asterisk
-;dtmfmode=info ; either RFC2833 or INFO for the BudgeTone
-;call-limit=1 ; permit only 1 outgoing call and 1 incoming call at a time
- ; from the phone to asterisk
- ; (1 for the explicit peer, 1 for the explicit user,
- ; remember that a friend equals 1 peer and 1 user in
- ; memory)
-;mailbox=1234@default ; mailbox 1234 in voicemail context "default"
-;disallow=all ; need to disallow=all before we can use allow=
-;allow=ulaw ; Note: In user sections the order of codecs
- ; listed with allow= does NOT matter!
-;allow=alaw
-;allow=g723.1 ; Asterisk only supports g723.1 pass-thru!
-;allow=g729 ; Pass-thru only unless g729 license obtained
-;astdb=chan2ext/SIP/grandstream1=1234 ; ensures an astDB entry exists
-
-
-;[xlite1]
-; Turn off silence suppression in X-Lite ("Transmit Silence"=YES)!
-; Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed
-;type=friend
-;regexten=1234 ; When they register, create extension 1234
-;callerid="Jane Smith" <5678>
-;host=dynamic ; This device needs to register
-;nat=yes ; X-Lite is behind a NAT router
-;canreinvite=no ; Typically set to NO if behind NAT
-;disallow=all
-;allow=gsm ; GSM consumes far less bandwidth than ulaw
-;allow=ulaw
-;allow=alaw
-;mailbox=1234@default,1233@default ; Subscribe to status of multiple mailboxes
-
-
-;[snom]
-;type=friend ; Friends place calls and receive calls
-;context=from-sip ; Context for incoming calls from this user
-;secret=blah
-;subscribecontext=localextensions ; Only allow SUBSCRIBE for local extensions
-;language=de ; Use German prompts for this user
-;host=dynamic ; This peer register with us
-;dtmfmode=inband ; Choices are inband, rfc2833, or info
-;defaultip=192.168.0.59 ; IP used until peer registers
-;mailbox=1234@context,2345 ; Mailbox(-es) for message waiting indicator
-;vmexten=voicemail ; dialplan extension to reach mailbox
- ; sets the Message-Account in the MWI notify message
- ; defaults to global vmexten which defaults to "asterisk"
-;restrictcid=yes ; To have the callerid restriced -> sent as ANI
-;disallow=all
-;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw!
-
-
-;[polycom]
-;type=friend ; Friends place calls and receive calls
-;context=from-sip ; Context for incoming calls from this user
-;secret=blahpoly
-;host=dynamic ; This peer register with us
-;dtmfmode=rfc2833 ; Choices are inband, rfc2833, or info
-;username=polly ; Username to use in INVITE until peer registers
- ; Normally you do NOT need to set this parameter
-;disallow=all
-;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw!
-;progressinband=no ; Polycom phones don't work properly with "never"
-
-
-;[pingtel]
-;type=friend
-;secret=blah
-;host=dynamic
-;insecure=port ; Allow matching of peer by IP address without matching port number
-;insecure=invite ; Do not require authentication of incoming INVITEs
-;insecure=port,invite ; (both)
-;qualify=1000 ; Consider it down if it's 1 second to reply
- ; Helps with NAT session
- ; qualify=yes uses default value
-;callgroup=1,3-4 ; We are in caller groups 1,3,4
-;pickupgroup=1,3-5 ; We can do call pick-p for call group 1,3,4,5
-;defaultip=192.168.0.60 ; IP address to use if peer has not registred
-
-;[cisco1]
-;type=friend
-;secret=blah
-;qualify=200 ; Qualify peer is no more than 200ms away
-;nat=yes ; This phone may be natted
- ; Send SIP and RTP to the IP address that packet is
- ; received from instead of trusting SIP headers
-;host=dynamic ; This device registers with us
-;canreinvite=no ; Asterisk by default tries to redirect the
- ; RTP media stream (audio) to go directly from
- ; the caller to the callee. Some devices do not
- ; support this (especially if one of them is
- ; behind a NAT).
-;defaultip=192.168.0.4 ; IP address to use until registration
-;username=goran ; Username to use when calling this device before registration
- ; Normally you do NOT need to set this parameter
-;setvar=CUSTID=5678 ; Channel variable to be set for all calls from this device
-
-; Pre-configured SIP extensions
-
-[6011]
-type=friend
-context=default
-host=dynamic
-secret=6011
-canreinvite=no
-callerid=6011
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6012]
-type=friend
-context=default
-host=dynamic
-secret=6012
-canreinvite=no
-callerid=6012
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6013]
-type=friend
-context=default
-host=dynamic
-secret=6013
-canreinvite=no
-callerid=6013
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6014]
-type=friend
-context=default
-host=dynamic
-secret=6014
-canreinvite=no
-callerid=6014
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6015]
-type=friend
-context=default
-host=dynamic
-secret=6015
-canreinvite=no
-callerid=6015
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6016]
-type=friend
-context=default
-host=dynamic
-secret=6016
-canreinvite=no
-callerid=6016
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6017]
-type=friend
-context=default
-host=dynamic
-secret=6017
-canreinvite=no
-callerid=6017
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6018]
-type=friend
-context=default
-host=dynamic
-secret=6018
-canreinvite=no
-callerid=6018
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6019]
-type=friend
-context=default
-host=dynamic
-secret=6019
-canreinvite=no
-callerid=6019
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6020]
-type=friend
-context=default
-host=dynamic
-secret=6020
-canreinvite=no
-callerid=6020
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6021]
-type=friend
-context=default
-host=dynamic
-secret=6021
-canreinvite=no
-callerid=6021
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-[6022]
-type=friend
-context=default
-host=dynamic
-secret=6022
-canreinvite=no
-callerid=6022
-disallow=all
-allow=ulaw,alaw
-qualify=yes
-
-; Pre-configured mini-asterisk SIP trunks
-
-;[user] ; "SIP-NAT" mini-asterisk do not remove this comment
-;; You reach your ITSP via a NAT router (most common)
-;type=friend
-;context=default
-;username=user
-;secret=password
-;host=192.168.1.28
-;canreinvite=no
-;disallow=all
-;allow=ulaw,alaw
-;qualify=yes
-;nat=yes
-
-;[user] ; "SIP" mini-asterisk do not remove this comment
-;; No NAT router between your Phone system and your ITSP
-;type=friend
-;context=default
-;username=user
-;secret=password
-;host=192.168.1.28
-;canreinvite=no
-;disallow=all
-;allow=ulaw,alaw
-;qualify=yes
-
-;[user] ; "Jazmin" mini-asterisk do not remove this comment
-;; <a href="http://www.jazmin.com.au/">Jazmin</a> are a South Australian ITSP
-;host=sip.jazmin.net.au
-;secret=<Password>
-;username=<username>
-;fromdomain=sip.jazmin.net.au
-;fromuser=<username>
-;insecure=port,invite
-;type=friend
-;disallow=all
-;allow=ulaw
-;allow=alaw
-;dtmfmod=rfc2833
-;qualify=yes
-;canreinvite=no
-;nat=yes
-
+++ /dev/null
-#!/bin/sh
-# update_revision.sh
-#
-# Sets correct Revision number in the about screen. Good idea to
-# run this before installing
-
-ver=`svn info | grep Revision`
-sed -i "s/Revision: [0-9]*/$ver/" cgi-bin/about.sh