[Pkg-voip-commits] r1785 - / op-panel op-panel/branches op-panel/branches/upstream op-panel/branches/upstream/current op-panel/branches/upstream/current/dhtml op-panel/branches/upstream/current/dhtml/css op-panel/branches/upstream/current/dhtml/images op-panel/branches/upstream/current/dhtml/js op-panel/branches/upstream/current/flash op-panel/branches/upstream/current/init op-panel/branches/upstream/current/ming-source

Santiago Ruano Rincón santiago at costa.debian.org
Tue May 30 19:47:47 UTC 2006


Author: santiago
Date: 2006-05-30 19:47:29 +0000 (Tue, 30 May 2006)
New Revision: 1785

Added:
   op-panel/
   op-panel/branches/
   op-panel/branches/upstream/
   op-panel/branches/upstream/current/
   op-panel/branches/upstream/current/CHANGES
   op-panel/branches/upstream/current/FAQ
   op-panel/branches/upstream/current/LICENSE
   op-panel/branches/upstream/current/README
   op-panel/branches/upstream/current/RECIPES
   op-panel/branches/upstream/current/TODO
   op-panel/branches/upstream/current/UPGRADE
   op-panel/branches/upstream/current/dhtml/
   op-panel/branches/upstream/current/dhtml/comunicator.pl
   op-panel/branches/upstream/current/dhtml/css/
   op-panel/branches/upstream/current/dhtml/css/default.css
   op-panel/branches/upstream/current/dhtml/css/operator.css
   op-panel/branches/upstream/current/dhtml/images/
   op-panel/branches/upstream/current/dhtml/images/bottom_left.gif
   op-panel/branches/upstream/current/dhtml/images/bottom_mid.gif
   op-panel/branches/upstream/current/dhtml/images/bottom_right.gif
   op-panel/branches/upstream/current/dhtml/images/bottom_right_resize.gif
   op-panel/branches/upstream/current/dhtml/images/bug.png
   op-panel/branches/upstream/current/dhtml/images/center_left.gif
   op-panel/branches/upstream/current/dhtml/images/center_right.gif
   op-panel/branches/upstream/current/dhtml/images/close.gif
   op-panel/branches/upstream/current/dhtml/images/email.png
   op-panel/branches/upstream/current/dhtml/images/group.png
   op-panel/branches/upstream/current/dhtml/images/mail.gif
   op-panel/branches/upstream/current/dhtml/images/overlay.png
   op-panel/branches/upstream/current/dhtml/images/phone.png
   op-panel/branches/upstream/current/dhtml/images/phone_sound.png
   op-panel/branches/upstream/current/dhtml/images/resize.gif
   op-panel/branches/upstream/current/dhtml/images/sizer.gif
   op-panel/branches/upstream/current/dhtml/images/status_online.png
   op-panel/branches/upstream/current/dhtml/images/telephone.png
   op-panel/branches/upstream/current/dhtml/images/telephone_go.png
   op-panel/branches/upstream/current/dhtml/images/top_left.gif
   op-panel/branches/upstream/current/dhtml/images/top_mid.gif
   op-panel/branches/upstream/current/dhtml/images/top_right.gif
   op-panel/branches/upstream/current/dhtml/index.php
   op-panel/branches/upstream/current/dhtml/js/
   op-panel/branches/upstream/current/dhtml/js/base64.js
   op-panel/branches/upstream/current/dhtml/js/builder.js
   op-panel/branches/upstream/current/dhtml/js/controls.js
   op-panel/branches/upstream/current/dhtml/js/dhtmltooltip.js
   op-panel/branches/upstream/current/dhtml/js/dragdrop.js
   op-panel/branches/upstream/current/dhtml/js/effects.js
   op-panel/branches/upstream/current/dhtml/js/operator.js
   op-panel/branches/upstream/current/dhtml/js/prototype.js
   op-panel/branches/upstream/current/dhtml/js/scriptaculous.js
   op-panel/branches/upstream/current/dhtml/js/slider.js
   op-panel/branches/upstream/current/dhtml/js/window.js
   op-panel/branches/upstream/current/dhtml/variables.php
   op-panel/branches/upstream/current/extensions.conf.sample
   op-panel/branches/upstream/current/flash/
   op-panel/branches/upstream/current/flash/help_de.html
   op-panel/branches/upstream/current/flash/help_en.html
   op-panel/branches/upstream/current/flash/help_es.html
   op-panel/branches/upstream/current/flash/help_fr.html
   op-panel/branches/upstream/current/flash/help_it.html
   op-panel/branches/upstream/current/flash/help_se.html
   op-panel/branches/upstream/current/flash/index-clicktodial.html
   op-panel/branches/upstream/current/flash/index-crm.html
   op-panel/branches/upstream/current/flash/index-fixed.html
   op-panel/branches/upstream/current/flash/index-restrict.html
   op-panel/branches/upstream/current/flash/index.html
   op-panel/branches/upstream/current/flash/mypage.php
   op-panel/branches/upstream/current/init/
   op-panel/branches/upstream/current/init/op_panel_debian.sh
   op-panel/branches/upstream/current/init/op_panel_redhat.sh
   op-panel/branches/upstream/current/init/op_panel_suse.sh
   op-panel/branches/upstream/current/ming-source/
   op-panel/branches/upstream/current/ming-source/README
   op-panel/branches/upstream/current/ming-source/operator_panel.pl
   op-panel/branches/upstream/current/op_astdb.cfg
   op-panel/branches/upstream/current/op_buttons.cfg
   op-panel/branches/upstream/current/op_lang_ca.cfg
   op-panel/branches/upstream/current/op_lang_de.cfg
   op-panel/branches/upstream/current/op_lang_en.cfg
   op-panel/branches/upstream/current/op_lang_es.cfg
   op-panel/branches/upstream/current/op_lang_fr.cfg
   op-panel/branches/upstream/current/op_lang_it.cfg
   op-panel/branches/upstream/current/op_lang_se.cfg
   op-panel/branches/upstream/current/op_server.cfg
   op-panel/branches/upstream/current/op_server.pl
   op-panel/branches/upstream/current/op_style.cfg
   op-panel/tags/
Log:
[svn-inject] Installing original source of op-panel

Added: op-panel/branches/upstream/current/CHANGES
===================================================================
--- op-panel/branches/upstream/current/CHANGES	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/CHANGES	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,750 @@
+Version .26
+
+Tue May  9 19:24:08 ART 2006  nicolas at house.com.ar
+  * New dhtml client
+
+Tue May  9 15:05:22 ART 2006  nicolas at house.com.ar
+  * assorted client fixes, removed scriptable actions for now,
+    add side scrolling when you have buttons that do not fit
+    on the screen.
+
+Tue May  9 15:03:27 ART 2006  nicolas at house.com.ar
+  * remove scriptable actions and assorted bug fixes
+
+Sat Apr 29 15:41:14 ART 2006  nicolas at house.com.ar
+  * ming client updates
+
+Sat Apr 29 15:40:06 ART 2006  nicolas at house.com.ar
+  * formatting fixes. Add includes to op_style.cfg
+
+Sat Apr 29 13:04:58 ART 2006  nicolas at house.com.ar
+  * set clid format on link event
+
+Sat Apr 29 13:04:43 ART 2006  nicolas at house.com.ar
+  * fix auto counters when using regexp butons
+
+Sat Apr 29 13:03:25 ART 2006  nicolas at house.com.ar
+  * scriptable actions, tovoicemail actions, formatting fixes
+
+Sat Apr 29 12:58:54 ART 2006  nicolas at house.com.ar
+  * includes style, simplify read configs, formatting fixes, removed comments
+
+Sat Apr 29 12:57:22 ART 2006  nicolas at house.com.ar
+  * log fake events
+
+Sat Apr 29 12:52:48 ART 2006  nicolas at house.com.ar
+  * transfer to voicemail
+
+Sat Apr 29 11:40:50 ART 2006  nicolas at house.com.ar
+  * agent status updates, paused and some formatting fixes
+
+Sat Apr 29 11:13:04 ART 2006  nicolas at house.com.ar
+  * clid privacy per button
+
+Sat Apr 29 11:02:16 ART 2006  nicolas at house.com.ar
+  * background jpg for buttons
+
+Thu Mar 23 14:47:57 ART 2006  nicolas at house.com.ar
+  * remove duplicated code
+
+Thu Mar 23 14:47:18 ART 2006  nicolas at house.com.ar
+  * suse init fixes
+
+Thu Mar 23 14:46:39 ART 2006  nicolas at house.com.ar
+  * configurable dimm/alpha
+
+Thu Mar 16 16:14:36 ART 2006  nicolas at house.com.ar
+  tagged 0.26
+
+Version .25
+
+Mon Mar 13 17:01:23 ART 2006  nicolas at house.com.ar
+  * documentation updates
+
+Mon Mar 13 16:56:00 ART 2006  nicolas at house.com.ar
+  * queueagent optimizations
+
+Fri Mar 10 17:33:25 ART 2006  nicolas at house.com.ar
+  * clean internal state when connecting to server
+
+Fri Mar 10 17:07:09 ART 2006  nicolas at house.com.ar
+  * add_server_to_fake_events
+  We need to add the server header to fake events!
+
+Fri Mar 10 17:06:44 ART 2006  nicolas at house.com.ar
+  * formatting_fixes
+
+Fri Mar 10 17:05:03 ART 2006  nicolas at house.com.ar
+  * update docs
+
+Mon Feb 27 19:40:37 ART 2006  nicolas at house.com.ar
+  * updated docs
+
+Mon Feb 27 19:27:28 ART 2006  nicolas at house.com.ar
+  * do not send settimer for nonexistant queues
+
+Mon Feb 27 19:25:36 ART 2006  nicolas at house.com.ar
+  * Clear counter when there are no calls in queue
+
+Mon Feb 27 17:27:41 ART 2006  nicolas at house.com.ar
+  * restrict to channel name same as mybutton
+
+Tue Feb 21 17:26:13 ART 2006  nicolas at house.com.ar
+  * fix meetme sccp
+
+Tue Feb 21 16:09:02 ART 2006  nicolas at house.com.ar
+  * Catalan language
+
+Mon Feb 20 16:10:40 ART 2006  nicolas at house.com.ar
+  * suse_init
+
+Mon Feb 20 15:55:22 ART 2006  nicolas at house.com.ar
+  * link_buttons
+  Add url and target to the button definition so you can hyperlink
+  to anything you want from any button.
+  Also added the enable_label_background that sets the background
+  color on the labels to the led colors depeding on state.
+
+Thu Feb  2 17:51:42 ART 2006  nicolas at house.com.ar
+  * listen_addr
+  Add listen_addr parameter to select the ip address the server will bind to
+
+Tue Jan 31 20:49:13 ART 2006  nicolas at house.com.ar
+  * NewSwf
+
+Tue Jan 31 20:47:11 ART 2006  nicolas at house.com.ar
+  * fontfix
+  Fix several font issues on the flash client
+
+Tue Jan 31 20:41:04 ART 2006  nicolas at house.com.ar
+  * Remove channel from queue hash on rename.. fix for queue buttons
+
+Tue Jan 31 20:32:40 ART 2006  nicolas at house.com.ar
+  * Ignore <MASQ> & <ZOMBIE> from trunk sessions, fix TRUNK problem.
+
+Tue Dec 27 00:33:17 ART 2005  nicolas at house.com.ar
+  * Fixed trunk sticky problem
+
+  - Fixed choppig the last character from op_server.cfg
+    when there was no end of line
+
+  - Fixed text on buttons when using crypto and the text
+    was empty
+
+  - Changed the mute/unmute to gray out a button when muted
+
+  - Fixed agentlogoff for channels with a hypen in the name
+
+  - New states for sccp, thanks to Laurent Mele
+
+  - New parameter to pass to operator_panel.swf: nohighligh. If set
+    to 1, button highlighting when mouse over will be disabled.
+
+  - New LEGEND attributes: URL, TARGET, NO_BASE64. Url for making an
+    hyperlink out of the legend to that url, TARGET to use that html
+    target when clicking the hyperlink, and NO_BASE64 to not convert
+    the legend to base64 (it is not useful at all) 
+
+  - Drag&Drop channels into queues. Just drag an unused button into a 
+    queue button and it will be added to that queue. If dragged again,
+    it will remove it from that queue.  
+
+  - astmanproxy support
+
+  - Added Meetme participants buttons (they show each participant)
+
+  - Added Queue position buttons (they show each position on a queue, 
+    with the corresponding timer and callerid)
+
+  - Added queue_hide option in op_server.cfg. If set, queue position
+    buttons won't be displayed if they are unused (so you only see 
+    the actual number of people waiting on the queue)
+
+  - Fixed bugs for queue positions when reloading
+
+  - Fixed timers when reloading
+
+.24
+ Sep 12 2005:
+
+  - Small bugfix, the security code is now working for everybody
+
+  - Added swedish translation
+
+  - Improved efficiency of regexp button matching
+
+.23
+ Sep 9 2005:
+
+  - FOP now tries to keep track of the number of agents logged into
+    each queue, and displays that info in the queue detailed status box.
+
+  - Added Mask filter for manager events. The new parameter 
+    is "event_mask" and should be written just below each server
+    definition. View op_server.cfg for a sample. 
+
+  - Added Queue Position status. Just change your queue buttons to use
+    more than one position. Then, instead of having a summary button for
+    your queue you will have each button position occupied by the person 
+    waiting  in that same position on your queue. You can drag them as any
+    other button to transfer.
+
+  - Internationalization support. 'language' configuration directive
+    in op_server.cfg and op_lang_XX.cfg files and help_XX.html
+
+  - Support for command line parameters, start the server with --help
+    to see the list of supported options
+
+  - The web_hostname and port settings in op_server.cfg are now optional
+    If omited it will connect to the same host where the .swf resides and
+    port 4445
+
+  - Added restriction for mybutton to FOP_Popup userevent, just add the
+    (optional) Button parameter with the button position (that must be
+    set in the client's mybutton parameter)
+
+      UserEvent(FOP_Popup|URL: page.php?e=${EXTEN}^Target: top^Button: 1)
+
+  - Added font and shadow color parameters for button labels, text
+    legends, clid and timer. In op_style.cfg you have 4 optional new
+    parameters:
+
+        label_font_color = 000000
+        label_shadow_color = FFFFFF
+        clid_font_color = 000000
+        timer_font_color = 4000FF
+
+    You have to put the hex color code for each one. To change the color of
+    a legend use the parameter:
+
+        font_color = FF0000
+
+  - Improved debian init script. Thanks to Tzafir Cohen.
+
+  - It uses a lot less CPU than previous versions on heavy asterisk boxes
+
+  - Improved support for parking when using native sip transfers
+
+  - Minor bugfixes
+
+.22
+ Jun 9 2005:
+  
+  - Minor bugfixes
+
+.21
+ May 29 2005:
+
+  - You can use 'transparent' as a fade_color for a button in 
+    op_style.cfg. That button will only display its borders, with
+    no background color. You can use the background.jpg in creative
+    ways now.
+
+  - The restrict input parameter can be set to a channel name
+    instead of just the button possition. The restricted button
+    will be hightlithed.
+
+  - Added margintop and marginleft to the input parameters taken by
+    operator_panel.swf, to set the global margins for the swf object.
+    You can experiment by loading the .swf file directly like:
+    operator_panel.swf?margintop=20&marginleft=40
+
+  - Added voicemail_extension parameter to op_server.cfg. If set,
+    FOP will originate a call to that extension when double clicking
+    on the MWI icon.
+
+  - Added version checking between client & server
+
+  - You can disable the icon for a button by using icon=0
+
+  - Added support for Zap DND state. You have to define the 'dnd'
+    family in op_astdb.cfg
+
+  - Added astdb checks. See op_astdb.cfg and extensions.conf.sample
+    for details. You can check for day/time mode or anything that its
+    stored on asterisk db.
+
+  - Changed the PARKXXX buttons to PARK/XXX for consistency. The old
+    syntax will still work fine.
+
+  - Added monitoring for callerid instead of channel name. Use
+    [CLID/XXXXXX] as the button name in op_buttons.cfg. Its experimental
+    Commands like originates and others might not work. This kind
+    of button will work with CVS-HEAD and without using the dial 'o'
+    flag.
+
+  - Added persistent security code. It remembers your last input so
+    you don't have to complete it the next time you open FOP.
+
+  - Added Panel_Context=* to op_buttons.cfg files, with it, that entry
+    will be added to every panel context defined.
+
+  - Fixed callerid on CVS-HEAD, now it works without using
+    the dial 'o' flag
+
+  - Added agent status. It displays Idle status an its
+    timers, and refresh queue statistics after each agent
+    call. Set agent_status to 1 in op_server.cfg
+
+  - Added the option to change the led color from asterisk's
+    dialplan:
+
+    exten => 1,1,UserEvent(FOP_ledcolor|Color: 0x0000FF^State: 0)
+
+    The color can be any hex value. The State is:
+
+       0 for available status (channel not in use)
+       1 for busy status (channel in use)
+       2 for agent status (channel not in use and logged in agent)
+
+  - Added the option to fire screen pops from asterisk's
+    dialplan:
+
+    exten => 1,1,UserEvent(FOP_Popup|URL: page.php?e=${EXTEN}^Target: top)
+
+  - Removed some DOWN status events that were redundant
+
+  - Added callerid name in screen popups, look at the
+    mypage.php sample in the html directory 
+
+  - Initial Status is fetched from op_server.pl memory
+    instead of querying asterisk every time. Saves lots
+    of asterisk resources and speeds things up
+
+  - Fixed infobox bug when a button has multiple matches
+
+  - Background image. Just place a background.jpg file
+    in the same directory as the .swf file and it will
+    be displayed as the background. The canvas size is
+    996x600
+
+  - REGEXP buttons. Wildcard buttons are discarded in
+    favor of the more powerful REGEXP buttons. If you
+    use wildcard buttons, replace them with a REGEXP
+    (Ex: if you have [SIP/*] change it to [_SIP/.*])
+
+  - The security code is now optional (leave it blank
+    in op_server.cfg for no security code when performing 
+    actions)
+
+  - Added absolute timeout for transferred calls
+
+  - Added the option to restart asterisk instead of reload
+    the panel when hitting the reload button (enable_restart
+    in op_server.cfg)
+
+  - Reworked some button matching routines, now it should
+    support Modem[i4l], oh323/* and mISDN
+
+.20
+ Feb 22 2005:
+
+  - Added support for monitoring multiple asterisk servers
+
+  - Added wildcard buttons (IAX2/*)
+
+  - Added Park Slot buttons (PARK701)
+
+  - Barge Muted (barge_muted in op_server.cfg)
+        Will start the 3rd leg muted when barging in
+
+  - CallerID Privacy (clid_privacy in op_server.cfg)
+        Will hide the callerid number in the buttons
+
+  - Show IP address of peers (show_ip in op_server.cfg)
+        Will show the ip address of peers in their buttons
+
+  - Text legends (LEGEND primitive in op_buttons.cfg)
+
+  - Highlight of linked buttons
+
+  - Added Mailbox parameter to the button definition
+
+  - You can specify a channel name in the dial parameter
+    when using click-to-dial features, thus making it easier
+    to implement
+
+.19
+ Nov 04 2004:
+
+  - Improved call details, now there is a queue/agent information
+    window and last call details window.
+
+  - Bugfixes and visual layout tweaks. You can set the highlight color, etc.
+
+  - You can define a distinct style per panel context. See op_style.cfg
+
+  - You can include files in op_buttons.cfg with the keyword 'include =>'
+
+  - The swf client is compressed and much smaller.
+
+  - When op_server.pl recconects, it close flash clients connections to
+    force a reconnect and update on their status.
+
+.18
+ Oct 29 2004:
+
+  - Ming client is now the default, the new features work with
+    that client only.
+
+  - Led color configurable via op_style.cfg
+
+  - More label renaming options 
+    (rename to agent name, rename queuememebers, etc)
+
+  - Option to change led color for logged in agents
+
+  - New click to dial feature, accesible via javascript
+    (examples in the html subdir)
+
+  - Ability to draw rectangles (see op_buttons.cfg for examples)
+
+  - Added polling for IAX presence 
+
+.17
+ Oct 21 2004:
+
+  - Mostly a bug fix release. Fixed the reload button in the ming client.
+
+  - Added polling of agents status on connect 
+
+  - Initial take on showing detail info on each agent
+
+.16
+ Oct 20 2004:
+
+  - Bug fixes: parked channel feature works again, ringing state too.
+
+  - Encryption is now optional, you can enable or disable it by changing
+    enable_crypto in op_style.cfg (while is this parameter in op_style
+    you may ask? well, the client has the ability to request encryption or
+    not, op_style.cfg sets not only visual parameters, but any client
+    parameter. I might change the configuration file name to op_client.cfg
+    in the future. Without encryption the client uses less CPU.
+
+  - Include the option for polling voicemail status together with sip
+    peers (poll_voicemail in op_server.cfg)
+
+  - New feature: ability to rename button labels when agents log in (
+    rename_label_agentlogin and rename_label_callbacklogin inside
+    op_server.cfg)
+
+  - New Ming client included. Ming is a library for generating .swf files
+    with wrappers in several languages. I used the perl wrapper to produce
+    a complete client. The source is included in the ming-source directory
+    The precompiled .swf file is in the html directory together with the
+    native flash client. Further development might be done exclusively in
+    Ming.
+
+  - The Ming client treats fonts a little diferent. If you enable 
+    use_embed_fonts in op_style.cfg, then all the font_family values will
+    be overriden by the only embedded font in the .swf. The
+    embedded font looks uniform compared to system (or browser) fonts. You 
+    *can* use any font_family available in your platform: just disable the 
+    use of embed fonts and select the family for each legend in a button.. 
+    but you might end up with chopped text depending of the type of font 
+    you use.
+
+
+.15
+ Oct 1st 2004:
+
+  - New configuration file format, there is an utility to convert
+    your old configuration to the new format. See UPGRADE, and don't
+    forget to backup first. Be sure to run the utility only with
+    old configuration files, use it once and then remove it just in
+    case.
+
+  - Fixed MessageWaiting when channel was in another context
+
+  - MD5 Authentication to Asterisk Manager (md5_auth in op_server.cfg)
+  
+  - Improved context handling in general. Now you can have a security
+    code for each context, as well as meetme rooms to use for bargein.
+
+  - There is no more auto_conf_exten for finding an empty meetme for
+    barge-ins. You now have to specify the rooms available for that
+    feature with the parameter barge_rooms in op_server.cfg
+
+  - Timers are now polled from Asterisk on initial connect. (If you open
+    the panel when a conversation was going, you will see the real duration
+    of the call)
+
+  - TEA Encryption for messages sent from server to client. MD5 used for
+    hashing the password.
+
+  - Many cosmetical changes to the flash movie, as well as optimizations
+    and rewrites. There are new icons, animations, etc.
+
+  - More information available when a call is disconnected, including
+    queue status information (completed calls, average holdtime, etc)
+    To get the info double click on the arrow when a call is finished.
+
+  - Added ability to mute/unmute meetme participants by clicking on the
+    arrow.
+
+  - Supports for register/unregister/unreachable/lagged realtime events
+    for SIP and IAX peers
+
+  - You can restrict the drag and drop commands to one button only, see
+    index-restrict.html in the html subdirectory
+
+.14
+ Jul 28th 2004:
+
+  - You can run the op_server.pl dettached from the console by starting it
+    with the parameter '-d'. There are sample init scripts in the init 
+    directory for redhat and debian.
+
+  - You can now drag a parked channel and transfer it to an available 
+    extension just like any other transfer.
+
+  - Changed to work well with Asterisk RC1 (IAX2 channel names have changed
+    from "IAX2[ext at context]" to IAX2/ext at context. Your IAX2 channels in 
+    op_buttons.cfg must be renamed if you use RC1. If you do not user RC1,
+    it might work as before, but I have not tested it.
+
+  - The flash side has a lot of improvements and changes. The fonts _sans
+    and _serif are now embedded, so they will look consistent in different
+    client computers (the tradeoff is a bigger swf file). When a channel is 
+    offline, the label text will also be grayed out. When dragging an icon, 
+    there is now visual feedback for the destination button. Added transparent
+    mask to the icons to make drag easier. If the client looses connection to
+    the op_server.pl, it will try to reconnect by itself (it does not work 
+    on linux, its a flash bug).
+
+  - Also in the flash side, there are new elements. A little arrow showing 
+    the direction of the call. And if you double click that little arrow 
+    after a call is made, you can see the last call status. The new parameters
+    for op_style.cfg are described in UPGRADE
+
+  - There is a new parameter in op_server.cfg: clid_format
+    You can choose the format for the caller id to be presented in the client
+    The letter 'x' will be replaced with a number, any other text will be
+    preserved. 
+
+.13
+ Jul 12th 2004:
+
+  - Fixed an annoying bug that prevented the initial status to be displayed
+    (the context for wich the panel request events was sent after the
+    status events, so they were ignored by the flash client)
+
+  - Fixed another annoying bug, the clid text was of an incorrect height,
+    and the drag and drop was erratic because of this
+
+  - Improved the parking display on the channels. Now you have a flashing
+    led and a text in the button itself
+
+  - Added a timer with the duration of a call to each button
+
+  - Still more bugs to clean on the trunk feature, please report feedback
+    on the mailing list..
+
+.12
+ Jul 5th 2004:
+
+  - Added a caller id display on the button itself
+
+  - The status of meetme and queues is queried on initial connect
+
+  - The event handling was rewriten. Now the flash client receives the
+    events for its own context (in previous versions, the events were
+    broadcasted to all clients)
+
+  - Cleaned the debug output a bit. 
+
+  - You can send a USR1 signal to the server and look at some state 
+    variables.
+
+  
+.11
+ Jun 29th 2004:
+
+  - Added 'trunk' buttons. You can define many buttons for just one user.
+    It is not well tested, as I do not have the means to test it. It might
+    introduce bugs!
+
+  - Added CRM software integration. You can monitor a button, and when it
+    rings, a web page is requested in the url and target you specify, with
+    the clid sent as a GET variable.
+
+  - The debug option in op_server.cfg has changed. See the UPGRADE file or
+    the online documentation, or the comments on op_server.cfg
+  
+.10
+ Jun 22th 2004:
+
+  - Added Contexts for the panel. You can have one server and several 
+    different panels.
+
+  - Added 'Parked calls' as a status for a defined channel/button
+
+  - Fixed important bugs (MWI with contexts not working, transfers not
+    working in particular situations)
+
+  - Totally new webpage, for up to date documentation, go there
+
+  - You can send a HUP signal to op_server.pl and it will rewrite the
+    configuration files for the flash applet.
+
+  - New RELOAD button in flash, it will reread the server configuration 
+    and refresh the display.
+
+.09 
+ Jun 8th 2004:
+
+  - Added Message Waiting count. When passing the mouse over the envelope
+    icon the status shows the New and Old messages in that mailbox
+
+  - The server sets the CallerID when originating a call.
+  
+  - Changed the debug parameter in op_server.cfg to a bitmap for greater 
+    control off debug output.
+    
+  - Changed the way it handles extension numbers (column number 4) in 
+    op_buttons.cfg. Now you can specify the context where the extension 
+    resides by using the syntax:
+    
+      extension at context  
+    
+    If the extension is not reachable from the default context, you must 
+    specify its context there.
+    
+  - Changed the way it handles IAX2 channels. To specify an IAX channel you 
+    have to specify its name only, without '@context', eg: 
+    
+      IAX2[john]
+     
+
+.08
+ Jun 2nd 2004:
+
+  - Added "Extra Info" Input box
+
+      You can write any text you want in that box. When transferring or 
+      originating a call, that text will be used as the callerid text for
+      that call. This way you can pass usefull information to the person
+      you are transferring the call. In order for this feature to work you
+      need to modify your dialplan ("extensions.conf"). There is an example
+      extensions.conf provided.
+
+  - Configurable layout of the toolbar
+
+      The bar at the top of the flash applet is now configurable. There are
+      new parameters in op_style.cfg to adjust the layout:
+
+        clid_label=Extra Info:
+        security_label=Security Code:
+        btn_help_label=Help
+        btn_log_label=Debug
+        show_security_code=1
+        show_clid_info=2
+        show_status=3
+        show_btn_help=4
+        show_btn_debug=5
+
+      The numbers in the show_xxx varialbes indicates the position in the 
+      toolbar. If you do not want to display an element, set it to 0. 
+
+  - Added HELP button and text to the flash movie
+
+      You can add a help.txt file in the same directory as the flash movie
+      on your webserver. This file will be displayed inside the help window
+      of the flash movie. You can use basic html tags. You *must* start the
+      file with the words "text="
+       
+.07
+  May 19th 2004:
+
+  - Added conference buttons
+
+      The channel column (first one) in op_buttons.cfg must be named with 
+      the number of the meetme conference. Eg: you have a meetme conference
+      number 901, the name of the channel must be '901'. Look at the example
+      config.
+
+  - Added tranfer of an empty channel to an already connected call and 
+    automatically conference the three parties together
+
+      You have two new parameters in op_server.cfg:
+
+        auto_conference_extension
+        conference_context 
+
+      Set them up and look at op_server.cfg for an example configuration for 
+      asterisk in extensions.conf and meetme.conf
+
+  - Added origination of calls
+
+      You can drag an available button to another available button. This
+      will originate a call from the first channel to the extension defined
+      in the desintation button.
+
+  - More readable output log for op_server.pl
+
+.06
+  May 12th 2004
+
+  - Added voicemail notification: 
+
+      There is a new parameter in op_buttons.cfg. The last column has the 
+      voicemail context of the extension. You can leave it blank and it will 
+      not check/show the voicemail status for that button (if its a queue 
+      button or an extension without voicemail on). 
+
+      You also have three new parameters in op_style.cfg:
+
+        mail_margin_left
+        mail_margin_top
+        mail_scale
+
+      to set the placement and size of the voicemail icon in the button.
+
+.05
+  Apr 17th 2004
+
+  - Fixed a typo that prevented the applet from working.
+
+.04
+  Apr 16th 2004
+
+    - Changed configuration files
+
+        The configuration files are different: in version .03 the
+        op_server.cfg had the button configuration and layout. In version
+        .04 that information is stored in op_buttons.cfg. There are 2 new
+        parameters in op_buttons.cfg, extension and icon.
+
+        op_server.cfg is now used for the parameters of the op_server
+        itself, like port to listent to, security code, debug level. You
+        don't have to modify op_server.pl anymore. All configuration is done
+        in the cfg files.
+
+        There is a new configuration file: op_style.cfg with the style and
+        size of the buttons.
+
+     - Added Queues buttons
+
+         You can display call queues on a button. Just put the name
+         of the queue as the channel name.
+
+     - Reconnection to Asterisk Manager port
+
+         The op_server now tries to reconnect to Asterisk Manager
+         port in case of disconnection. So if you restart Asterisk
+         you don't need to restart the op_server.pl, it will reconnect
+         by itself.
+
+     - Totally redone flash movie: operator_panel3.swf
+     
+         The flash applet in version .04 is totally rewriten. IÏt 
+         has no bitmaps. All graphics are vector based, so you can
+         change the style and sizes without loosing detail. There
+         is no timer or status on each button in order to save space.
+         You can see the status of a channel by passing the mouse
+         over the red oval.
+
+         The new op_server.pl is compatible with the flash applet
+         of previous versions (operator_panel.swf), with fixed 24 
+         buttons display, timers, and scrolling info on each channel.

Added: op-panel/branches/upstream/current/FAQ
===================================================================
--- op-panel/branches/upstream/current/FAQ	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/FAQ	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,65 @@
+Flash Operator Panel frequently asked questions:
+------------------------------------------------
+
+Q0: Do I have to run a webserver?
+
+A0: Yes, its a Flash applet, it works from a web browser. You can use apache
+    or any other webserver you like. It was tested with Windows, Linux, and
+    Mac browsers. Its truly multiplatform!
+
+
+Q1: Do I need to install additional Perl modules to run op_server.pl?
+
+A1: No, it works without extra modules.
+
+
+Q2: International characters are not displayed in button labels! Is it
+    possible to use foreign characters?
+ 
+A2: Yes, its possible. The flash movie will display international
+    characters if you encode the text with UTF-8. You can encode the files
+    from the command line using vi:
+
+        vi -c ":wq! ++enc=utf8" op_buttons.cfg
+
+    There is a downside to this. If you originate calls from the panel, the
+    caller id will be set with the utf8 label (ilegible characters in the
+    clid)
+
+Q3: I do not want to mess with the caller id text and the asterisk database.
+    Can I disable that feature?
+
+A3: Sure, just modify op_style.cfg and set the show_clid_info variable to 0
+    (zero).
+
+
+Q4: When I try to open the webpage, the browser hangs. Whats wrong?
+
+A4: The flash movie tries to read a file named 'variables.txt' that is
+    generated by op_server.pl in the same directory where the .swf file
+    lives. If this file is corrupted or incomplete, the flash movie might
+    loop forever. Make sure you have the file in place. If its not there,
+    you might have permissions problems or you forgot to run op_server.pl.
+
+
+Q5: I changed the style op_style.cfg, but when I reload the page I don't 
+    see the changes. What's up?
+
+A5: The flash movie requests the file variables.txt when it starts. If your
+    browser caches that file, you won't see the changes you made unless you
+    clear your browser cache, or maybe just requesting the variables.txt
+    file and hitting reload a couple of times. 
+
+Q6: I do not like editing a text file to change a visual layout!
+
+A6: Me neither, I dream of a visual layout configuration. But I do not have
+    the time to make it happen. Maybe in the future. 
+
+Q7: Where is the .fla file?
+	
+A7: The flash client is done with MING: you will find the perl source for
+    generating a working .swf client under ming-source. 
+
+	If you want the ancient .fla for the first versions, I will trade them
+    for a new apple mac mini core duo or macbook pro.
+

Added: op-panel/branches/upstream/current/LICENSE
===================================================================
--- op-panel/branches/upstream/current/LICENSE	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/LICENSE	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,341 @@
+
+		    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.
+
+		    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.)
+
+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.
+
+  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.
+
+  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
+
+	    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) 19yy  <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) 19yy 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.

Added: op-panel/branches/upstream/current/README
===================================================================
--- op-panel/branches/upstream/current/README	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/README	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,186 @@
+Asterisk Flash Operator Panel
+Copyright (c) 2006 Nicolás Gudiño.  All rights reserved.
+http://www.asternic.org
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+For complete and up to date documentation, please visit the web page
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+What is Flash Operator Panel?
+-----------------------------
+
+The Flash Operator panel is a 'switchboard' application for the Asterisk PBX
+system. It displays information about your Asterisk PBX activity in real
+time via a standard web browser with Flash plugin. The display and button
+layout is configurable, you can have more than a 100 buttons on the screen
+at once. 
+
+You can see at a glance:
+
+   * What extensions are busy, ringing or available
+   * Who is talking and to whom (clid, context, priority)
+   * SIP registration status and reachability 
+   * Meetme room status (number of users) in the room
+   * Queue status (number of users waiting)
+   * Parked extensions
+   * Call duration Timers
+   * Logged in Agents
+
+You can perform these actions:
+
+   * Hang-up a channel (double click the colored dot on the button)
+   * Transfer a call leg via drag&drop (drag the phone icon on a button to
+     another button)
+   * Originate calls via drag&drop
+   * Drag an available extension to an ongoing conversation and conference
+     the three together. 
+   * Change the callerid text to something meaningfull when transferring or
+     originating a call
+   * Mute/Unmute meetme participants
+
+Requirements
+------------
+
+* You need PERL and basic knowledge on how to use Asterisk.
+
+* You have to add a user to asterisk's manager.conf and reload asterisk for
+  the changes to take effect.
+
+* For the conference buttons, message waiting indication and automatic three
+  way conferences, you need asterisk CVS-HEAD as of 5/25/2004
+
+* You need flash player versions 7 and up
+
+* You also need to define in your dialplan the conferences in a proper way 
+  and in their own context, as explained in op_server.cfg comments.
+
+* If you plan to use the "Info" box to set the callerid text when
+  transferring or originating a call, you need to modify your dialplan. See
+  extensions.conf.sample
+
+* You also need to be wary, as English is not my first language.
+
+
+Install
+-------
+
+1) Untar de package on a suiteable place, for example /usr/local
+  (if you are reading this you probably already done that)
+
+1) Copy the files in the 'flash' or 'dhtml' subdirectory to a suitable place 
+   on your web server. If your web root is /var/www/html, you can create a 
+   subdirectory 'panel' and copy the files there. 
+
+   There are several ways (index files) to load the flash applet, try them
+   out. You can modify the file help-xx.html files to your liking.
+
+2) Edit op_server.cfg and change the appropriate parameters for your setup. 
+
+   "flash_dir" parameter must be the exact location of the directory where
+   the html and swf files are placed.
+
+    The rest of the parameters are well commented in the cfg file
+
+3) Edit op_buttons.cfg to suit your needs. The file is commented and its
+   self explanatory.
+
+4) Edit op_style.cfg to suit your needs. You can change the button size and
+   colors, icon placement and size, etc. DO NOT modify the variable names,
+   just the value after the equal sign and DO NOT use spaces. With proper
+   adjusting, you can have more than a 100 buttons on the screen.
+
+   You can change the toolbar layout by changing the number after the
+   variable show_???. Each one represents a possible element in the toolbar.
+   A value of 0 disables that element. A number represents the order in the
+   toolbar it will be displayed, number one being the leftmost part of the
+   toolbar. In the example configuration, all the toolbar elements are
+   displayed in correlative order. Eg: if you do not want to display a DEBUG
+   button, set the 'show_btn_debug' to 0. You can translate the text of the
+   toolbar in the corresponding variables.
+
+      --!! Please note !!---------------------------------------------------
+      If you want to transfer an available channel to an already connected
+      call, you have to configure your dialplan correctly and have the
+      context properly defined, if you don't do that you will experience
+      hanged channels and asterisk lockups. Thats because when you redirect
+      a call within the asterisk manager with an incorrect contexts,
+      asterisk does not handle the error gracefully.
+       --!!-----------------------------------------------------------------
+
+
+International Characters
+------------------------
+
+If you want to display foreign characters in button labels, you have to save
+the configuration file with UTF-8 encoding. To convert the file to UTF-8
+utilizing vi and the command line just perform:
+
+vi -c ":wq! ++enc=utf8" op_buttons.cfg
+
+
+Running
+-------
+
+The op_server.pl must run on the same computer as the web server
+
+When started, it writes the file 'variables.txt' to the http directory where
+the flash applet is installed with configuration data. It must have
+permissions to write to that directory.
+
+You can run it daemonized using -d as its command line argument. There are
+some example init scripts in the directory inits
+
+If you want to start the server when the machine starts, you can add a line
+similar to the following to your rc.local file (you have to replace the
+values between '*' with the ones for your system, if you do not want to run
+the op_server.pl as root, just su to that user:
+
+(cd */path/*; su *operator-user* -c */path/*op_server.pl & )
+
+Or better yet, use one of the init scripts provided.
+
+
+Security
+--------
+
+Its not meant to be secure. You should take provisions yourself, like
+limiting who can connect by means of .htaccess files, firewall rules, etc.
+There is basic encryption for messages sent from the server to the client,
+and the security code is sent with MD5. It will hide sensitive information
+from the casual observer, but its not strong enough to send credit card
+information. 
+
+
+How to use it
+-------------
+
+Click the HELP button when running the Flash Operator Panel. Experiment.
+Drag icons, move your mouse around. Click and double click when the arrow
+turns into a hand.
+
+
+Support
+-------
+
+For support or submitting bug reports, features requests, etc, please
+subscribe to the mailing list by sending an empty email to
+operator_panel-subscribe at lists.house.com.ar
+
+Donations
+---------
+
+If you like the program, or have feature requests, you can contribute to the
+cause by donating via paypal. Click the donate button on the webpage. You can
+also contact me for custom works, or asterisk consultancy.
+
+Thanks!
+
+
+Credits
+-------
+
+MD5 Algorithm. Copyright:  
+(C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
+
+TEA Encryption algorithm:  
+Copyright (c) 2000, Peter J Billam c/o P J B Computing, www.pjb.com.au

Added: op-panel/branches/upstream/current/RECIPES
===================================================================
--- op-panel/branches/upstream/current/RECIPES	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/RECIPES	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,101 @@
+RECIPE 1
+--------
+Set DND (Do not disturb) from your dialplan and 
+reflect the status on FOP:
+
+# Example on setting DND state from the dialplan
+# *78 Sets DND ON
+# *79 Sets DND OFF
+#
+# This example only sets the dnd db value and
+# signals FOP to display the status on the button
+# you might have to add a check in your stdexten
+# macro to honour the DND status
+
+in extensions.conf:
+
+exten => *78,1,UserEvent(ASTDB|Family: dnd^State: On)
+exten => *78,2,SetVar(temp=${CHANNEL})
+exten => *78,3,Cut(temp=temp,,1)
+exten => *78,4,DBPut(dnd/${temp}=On)
+exten => *78,5,Hangup
+
+exten => *79,1,UserEvent(ASTDB|Family: dnd^State: ^)
+exten => *79,2,SetVar(temp=${CHANNEL})
+exten => *79,3,Cut(temp=temp,,1)
+exten => *79,4,DBDel(dnd/${temp})
+exten => *79,5,Hangup
+
+in op_astdb.cfg:
+[dnd]
+settext=DND: ${value}
+setalpha=70
+
+RECIPE 2
+--------
+How to monitor rxfax. This is just a barebones sample, you can 
+customize it for your needs. You have to Goto to the fax context
+from your dialplan:
+
+in extensions.conf:
+
+exten => fax,1,Goto(rxfax,s,1)
+
+[rxfax]
+exten => s,1,SetVar(FAXFILE=/var/spool/fax/fax-${TIMESTAMP}.tif)
+exten => s,2,SetVar(LOCALSTATIONID=My Company)
+exten => s,3,UserEvent(Newexten|Channel: FAX/FAX-${UNIQUEID}^State: Up^Uniqueid: 1234)
+exten => s,4,rxfax(${FAXFILE})
+exten => s,5,Hangup()
+exten => t,1,Hangup()
+exten => h,1,UserEvent(Hangup|Channel: FAX/FAX-${UNIQUEID}^State: Down^Uniqueid: 1234)
+
+in op_buttons.cfg:
+[FAX/FAX]
+Position=1
+Label="Fax"
+
+
+
+RECIPE 3
+--------
+How to monitor voicemailmain (users entering the voicemail application)
+You have to define a regular extensions that performs a 'Goto' to the
+vmail context (similar to the fax case above)
+
+in extensions.conf:
+
+[vmail]
+exten => s,1,SetLanguage(es)
+exten => s,2,UserEvent(Newexten|Channel: VMAIL/VMAIL-${UNIQUEID}^State: Up^Uniqueid: 4321)
+exten => s,3,VoicemailMain(${CALLERIDNUM}@internos)
+exten => t,1,Hangup
+exten => h,1,NoOp(Hangup en voicemail)
+exten => h,2,UserEvent(Hangup|Channel: VMAIL/VMAIL-${UNIQUEID}^State: Down^Uniqueid: 4321)
+exten => h,3,Hangup
+
+in op_buttons.cfg:
+
+[VMAIL/VMAIL]
+Position=1
+Label="Voicemail"
+
+RECIPE 4
+--------
+Show day/night mode based on an asterisk db value:
+
+in extensions.conf:
+
+exten => 80,1,DBPut(daymode/DAYMODE=Day);
+exten => 80,2,UserEvent(ASTDB|Family: daymode^Channel: daymode^Value: Day)
+exten => 80,3,Hangup
+;
+exten => 81,1,DBPut(daymode/DAYMODE=Night);
+exten => 81,2,UserEvent(ASTDB|Family: daymode^Channel: daymode^Value: Night)
+exten => 81,3,Hangup
+
+in op_astdb.cfg:
+
+[daymode]
+setlabel=${value}
+ 

Added: op-panel/branches/upstream/current/TODO
===================================================================
--- op-panel/branches/upstream/current/TODO	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/TODO	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,8 @@
+* Clean bugs
+* A way to set astdb values from the .swf
+* A way to perform any cli or manager action from the .swf
+* Go to Astricon USA with more help
+* Change user authentication and restrictions methods
+* Get some sleep
+* Make a client in JAVA
+* Make a windows systray client

Added: op-panel/branches/upstream/current/UPGRADE
===================================================================
--- op-panel/branches/upstream/current/UPGRADE	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/UPGRADE	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,555 @@
+Notes on upgrading from an older release
+========================================
+
+o Upgrading from version .25 to .26:
+
+    New DTHML client. The directory structure on the tarball has changed
+    to accommodate the new DHTML client. The former html subdirectory was
+    renamed to flash, and the new client is inside the dhtml subdirectory.
+    
+    The new DHTLM client works in a similar way to the flash client, it has
+    a couple of scripts that read the same config files than the flash 
+    version to draw the buttons. It is not yet complete but it mostly works.
+
+    New parameter in op_style.cfg:
+
+        shake_pixels
+            Sets the number of pixels to shake the icon when ringing
+
+        dimm_noregister_by
+            Ammount of alpha dimm to apply when channel is not registred
+
+        dimm_lagged_by
+            Ammount of alpha dimm to apply when channel is lagged
+
+    New parameters in op_buttons.cfg:
+
+        VoiceMailExt
+            To set the extension at context to use when transferring directly
+            to voicemail
+
+        Background
+            To specify a jpg image to use as button background. You have to
+            set No_rectangle=true on that button for the background to become 
+            active. The .jpg file should be of the same size as the button width
+            and height as specified in op_style.cfg
+
+        Privacy
+            If set to true, it won't display caller id or dialed number info
+            for that button.
+
+o Upgrading from version .24 to .25:
+
+    Queue buttons now must be defined as:
+
+        [QUEUE/SUPPORT]
+
+      With this new syntax, queue names with numbers
+      only as used in AMP will work without collisions.
+
+      You have to rename all queue buttons in your config 
+      file to use the new syntax or they won't work.
+
+    Added some attributes to LEGENDS in op_buttons.cfg:
+
+       URL       
+       TARGET
+       NO_BASE64
+
+       If set, the legend will become an hyperlink to URL at TARGET
+       If NO_BASE64 is set, the text won't be encoded
+
+    Added attributes to any button in op_buttons.cfg:
+
+        URL
+        TARGET
+        
+        If set, it will add an hyperlink to the button label pointing
+        to that URL and opening it inside TARGET.
+
+    Added enable_label_background to op_style.cfg
+
+        This parameter will set the background color to the button label
+        to the same colors as the led. You can use it together with
+        "no_rectangle" in the buttons and Icon=0 and a small width, height
+        and font to fit hundreds of buttons on one screen. I was able to
+        fit 630 buttons (but only for monitoring as you don't have the led
+        or icon to transfer or hangup calls)
+
+    Added dimm (alpha) for noregistered and lagged buttons to op_style.cfg
+
+        dimm_noregister_by=20
+        dimm_lagged_by=60
+
+    Added listen_addr keyword
+      If you want op_server.pl to bind to only one IP address instead of
+      all avaialbe addresses.
+
+    Added manager_port keyword
+
+      If your manager is not running on the default port, you
+      can specify the port now for each connection with this 
+      option. Example:
+
+         manager_port  = 5039
+
+    Added support for astmanproxy
+
+      In op_server.cfg you have to defined the astmanproxy host & port 
+      (the ip address where astmanproxy is listening) & server (the
+      same ip or name you use in astmanproxy.conf). If you 
+      monitor more than one asterisk server trough astmanproxy, you 
+      will have to enumerate them using the astmanproxy_server keyword.
+      Example:
+
+        astmanproxy_host   = 127.0.0.1
+        astmanproxy_port   = 1234
+        astmanproxy_server = 192.168.10.1
+        astmanproxy_server = 192.168.10.2
+
+    Added buttons for MEETME participants. Just specify more
+    than one position for a meetme button and they will show
+    meetme participants indiviually as they join or leave the
+    conference.
+
+    Added [QUEUEAGENT] buttons. They will be taken by static
+    or dynamic queue members automatically.
+
+    Added buttons for QUEUE positions. Just specify more than
+    one position for the button and they will show each queue
+    position instead of a queue summary
+ 
+
+o Upgrading from version .23 to .24:
+
+    Nothing new, just a bug fix release in op_server.pl
+
+o Upgrading from version .22 to .23:
+
+    Client and server must be upgraded or it will not work well.
+
+    Internationalization support: 
+
+       Parameter ADDED to op_server.cfg:
+
+           language
+
+       To set the language to use in the general section
+       and optionally in every panel context defined.
+
+       The language files are named op_lang_XX.cfg where XX is the 
+       language to use defined in the language option.  Each panel 
+       context might have  a distinct language. The default language 
+       is 'en' (english).
+
+       You can create your own language file. If you do, please
+       send it back to me so I can include it in the tarball.
+       Some strings include variables, they are represented as
+       $1 and $2. You can ommit the variables or use them as you
+       see fit.
+
+       The help file is now called help-XX.html. Be sure to add that file
+       or rename the one you have. Please contribute with translations or 
+       beautifying them if you can.
+
+    Parameters REMOVED from op_style.cfg (they were moved to the language
+    configuration file):
+
+        clid_label
+        detail_title
+        detail_from
+        detail_to
+        detail_duration
+
+    Parameters ADDED to op_style.cfg (to set the button label color, the 
+    button label shadow color, and the clid text color):
+
+        label_font_color = 000000
+        label_shadow_color = FFFFFF
+        clid_font_color = 00DD00
+        timer_font_color = 200070
+
+    New option for LEGENDS in op_buttons.cfg
+
+        font_color = 102030
+
+    Support for command line options. Run op_server.pl with --help to
+    see the available options
+
+
+o Upgrading from version .21 to .22:
+
+    Just replace op_server.pl that has minor bugfixes
+
+o Upgrading from version .20 to .21:
+    New configuration file: op_astdb.cfg used to monitor asterisk
+    db values and change states for a button based on them.
+
+    New option: voicemail_extension parameter in op_server.cfg. 
+    If set, FOP will originate a call to that extension when 
+    double clicking on the MWI icon.
+
+    The PARK buttons are now specified as PARK/XXX
+    instead of PARKXXX to make it more consistent with
+    channel naming conventions. The old name will still
+    work.
+
+    To enable agent_status (displays agent idle
+    time and refresh queue status after each 
+    call). In op_server.cfg:
+
+        agent_status=1
+
+
+    If there is a background.jpg image in the same
+    directory as the swf file, it will be used as
+    the background for the panel. Resolution: 996x600
+
+    The syntax for wildcard buttons has changed, if 
+    you have [SIP/*] change it to [_SIP/.*]
+    The new matching routine allows full regexps to
+    be used. To use regexps buttons start them with
+    an underscore followed by your expression.
+
+    To disable the security code, leave it blank. In
+     op_server.cfg:
+        security_code = ""
+
+    To enable timeout on transfers, you have to set the
+    transfer_timeout paramenter to op_server.cfg
+
+    You can set the reload button to perform an asterisk
+    restart if you set enable_restart to 1 in op_server.cfg
+
+o Upgrading from version .19 to .20:
+
+    You can define the server number of a button in op_buttons.cfg
+    using the 'server' directive. If you leave it empty, it will 
+    default to Server=1
+
+    To monitor more than one asterisk box, just repeat the sequence of
+    connection parameters in op_server.cfg
+
+         ; Server 1
+         manager_host=1.2.3.4
+         manager_user=john
+         manager_secret=doe
+
+         ; Server 2
+         manager_host=1.2.3.5
+         manager_user=mary
+         manager_secret=poppins
+
+    To add text legends, the format is:
+
+        [LEGEND]
+        x=535
+        y=50
+        text=Conferences
+        font_size=32
+        font_family=Arial
+        use_embed_fonts=1
+
+    To add park slot buttons, the format is:
+
+        [PARK701]
+        Position=17
+        Icon=3
+        Extension=700
+        Label="Park 701"
+
+    You can specify the mailbox for a button with the mailbox parameter:
+
+        [SIP/100]
+        Position=1
+        Mailbox=100 at default
+        ...
+
+    The 'old way' still works, by using the combination of Extension and
+    Voicemail_Context. I recommend you to use the new format as it is more
+    flexible (you can monitor a mailbox independant from the extension of
+    that button).
+
+
+    New directives in op_server.cfg
+
+       rename_label_wildcard
+      barge_muted
+      clid_privacy
+      show_ip
+
+o Upgrading from version .18 to .19:
+
+    In op_style.cfg there is a new paramter to confgure the 
+    highlighting color for the buttons:
+
+      btn_highlight_color=ff0000
+
+o Upgrading from version .17 to .18:
+
+    The default .swf client is now the ming port. The new features
+    are available only in the ming port. The flash .swf is included
+    but it was not tested.
+
+    In op_style.cfg there are new parameters (to configure led colors):
+
+      ledcolor_ready
+      ledcolor_busy
+      ledcolor_agent
+
+    The parameter led_color is not used anymore. (It is used by the 
+    flash client only, not the default ming client)
+
+    In op_server.cfg there are new options too (all commented in 
+    op_server.cfg itsef):
+
+      rename_label_agentlogin
+      rename_label_callbacklogin
+      rename_to_agent_name 
+      rename_queue_member
+      change_led_agent   
+      clicktodial_insecure
+
+    It is possible now to draw rectangles, see op_buttons.cfg for 
+    an example.
+
+    If you use click-to-dial, the button used to originate the call
+    must be specified when invoking the .swf file. The parameter used
+    is 'dial'. See index-clicktodial.html for an example.
+
+o Upgrading from version .16 to .17:
+
+    Just replace op_server.pl and your favorite .swf client. Its
+    mostly a bug fix release. The new features do not require 
+    configuration changes.
+
+o Upgrading from version .15 to .16:
+
+    The help window is now a browser windows that loads help.html 
+    (instead of being a flash window that loads the help.txt file)
+    So you need to put a help.html page in the same location as the
+    .swf file.
+
+    There are a couple of new parameters. In op_server.cfg
+
+       poll_voicemail
+
+         Will check for voicemail status every poll_interval seconds.
+         Remeber that poll_interval will also check for sip peers.
+
+       rename_label_agentlogin
+       rename_label_callbacklogin
+
+         Both parameters acomplish the same goal: to rename a button
+         label when an Agent logs in. One of them works with the regular
+         AgentLogin application. The other one with AgentCallbackLogin.
+         For the later, you need to have a button with the same extension
+         and context for the callback for it to work.
+
+    There is also a new parameter in op_style.cfg
+
+        enable_crypto (1 for enable, 0 for disable)
+
+          If you want to encrypt server to client messages, turn this on.
+
+o Upgrading from version .14 to .15:
+
+    The format of the configuration file is different. You have to
+    run ./convert_config_pre_14.pl in order to convert your old
+    configuration files to the new format. The conversion utility
+    must reside in the same directory as the old configuration files:
+
+       op_server.cfg
+       op_style.cfg
+       op_buttons.cfg
+
+    When you run the conversion routine, it will backup your old 
+    configuration files and do its thing. Just in case, backup the
+    files yourself. The conversion program does not have extensive
+    error checking.
+
+    The barge-in functionality has changed also. You no longer need
+    an auto_conference_extension in your dialplan. The panel will 
+    keep track of the conferences itself. You *do* need to add the
+    conference room numbers that must be used for barge-in. The 
+    conversion routine adds the parameter, you have to modify it to
+    suit your needs. The new parameter (in op_server.cfg) is:
+
+        barge_rooms
+
+    It must have at least two rooms defined, with the format:
+    "minor-major". Those rooms must be defined in your extensions.conf
+    under the context defined by conference_context. The extension
+    number must match the meetme room number. See op_server.cfg for
+    an example.
+
+    To authenticate using MD5 to Asterisk Manager you can add the parameter
+    auth_md5=1 in op_server.cfg. It is enabled by default.
+
+    There are new parameter in op_style.cfg: 
+
+        enable_animation: it will animate the phone icons when ringing.
+
+        use_embed_font: lets you choose between embed fonts or system fonts.
+
+        (1 for enable, 0 for disable)
+    
+
+o Upgrading from version .13 to .14:
+   
+    In Asterisk RC1, the IAX naming convention has changed. There are
+    no more brackets in IAX2 channel names. If you run RC1 (try it!)
+    you will have to name your IAX2 channels like:
+
+      IAX2/user
+
+    You will have to rename your op_buttons.cfg if you use IAX2 channels.
+
+    The code for handling the previous naming convention is still there
+    but I have not tested it. It might or might not work.
+
+    There are new elements in op_style that affects the button style:
+
+       arrow_scale
+       arrow_margin_top
+       arrow_margin_left
+
+       The above parameters indicate the size and position of a little
+       arrow that shows the 'direction' of the call. 
+
+       detail_title=Last call details
+       detail_from=From:
+       detail_to=To:
+       detail_duration=Duration:
+
+       These four parameters are for setting the text displayed in the
+       detail box when you double click on the little arrow after a call
+       is made.
+
+       led_color
+
+       The color scheme for the available/busy led.
+         0 for leds green/red. (default)
+         1 for leds grey/green 
+
+       label_shadow
+
+       You can add a shadow to the text label
+         0 for disabling the shadow (default)
+         1 for enabling the shadow
+
+
+    There is a new parameter in op_server.cfg:
+
+      clid_format
+
+        This mask will apply to the callerid field to format the
+        number as you see fit. Every 'x' will be replaced by a number
+        from right to left. Any other char will be preserved. Ex:
+    (xxx) xxx-xxxx
+
+o Upgrading from version .12 to .13:
+
+    For the timer to work, you need to add four new parameters to
+    op_style.cfg
+
+       timer_font_size
+       timer_font_family
+       timer_margin_top
+       timer_margin_left
+
+o Upgrading from version .11 to .12:
+
+    There are 4 new parameters in op_style.cfg for the caller id
+    display on each button.
+
+        clid_font_size
+        clid_font_family
+        clid_margin_top
+        clid_margin_left
+
+o Upgrading from version .10 to .11:
+
+    There are no new parameters in the configuration files. Your .10
+    configuration should work fine with version .11
+
+    The debug level bitmap is now different:
+
+       1   Show Manager Events Received
+       2   Show Commands set to Manager
+       4   Show Flash events Received
+       8   Show events sent to Flash Clients
+       16  1st level Debug on op_server.pl
+       32  2nd level Debug on op_server.pl
+       64  3rd level Debug on op_server.pl
+
+o Upgrading from version .09 to .10:
+
+    There are 2 new parameters in op_style.cfg for a new element
+    in the toolbar (a reload button)
+
+    btn_reload_label
+    show_btn_reload
+
+
+o Upgrading from version .08 to .09:
+
+    The debug level (op_server.cfg) is now a bitmap. Now you have more
+    control of the output produced by debug. The possible values are:
+
+       1   Show Manager Events Received
+       2   Show Commands set to Manager
+       4   1st level debug on op_server.pl
+       8   2nd level debug on op_server.pl
+       16  3rd level debug on op_server.pl
+
+    If you want full debug, set the value to 31 in op_server.cfg
+    If you want to see just the events received and sent, set it to 3 (1+2) 
+
+    The fade matrix for the buttons is slightly different. Its the first
+    step towards a visual button layout configurator.
+
+o Upgrading from version .07 to .08:
+
+    The offset and size of the icons have changed. You will need to adjust
+    your op_style.cfg. Now all the icons are aproximatly the same size and
+    have the same center offset, so the margins and scale parameters will
+    match from icon to icon. New layout configurations should be simpler.
+
+    There are several new parameters in op_style.cfg, related to the  
+    configurability of the toolbar. You have to add them in your current
+    configuration, if you don't do it you will not see any toolbar. The
+    parameters to add are:
+
+        clid_label=Extra Info:
+        security_label=Security Code:
+        btn_help_label=Help
+        btn_log_label=Debug
+        show_security_code=1
+        show_clid_info=2
+        show_status=3
+        show_btn_help=4
+        show_btn_debug=5
+
+    The number in show_xxx represents the order in which it is rendered. If
+    you want to hide an element of the toolbar, set it to 0.
+
+o Upgrading from version .06 to .07:
+
+    There are two new parameters in op_server.cfg:
+
+        auto_conference_extension = 900    
+        conference_context = conferences 
+
+    Add them to your existing configuration file. In op_server.cfg there are
+    also examples of asterisk configuration files to use the 3way auto
+    conferences.
+
+o Upgrading from previous versions:
+
+    There are three new parameters in op_sytle.cfg and a new one in
+    op_buttons.cfg. See CHANGES. Just add those parameters to your current
+    config files, and replace op_server.pl with the new one. The fixed 24
+    buttons flash movie does not support voicemail notifications. There is a
+    new index.html that scales the applet to the size of the browser window.
+    Try it and use the one you like more.

Added: op-panel/branches/upstream/current/dhtml/comunicator.pl
===================================================================
--- op-panel/branches/upstream/current/dhtml/comunicator.pl	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/comunicator.pl	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,1617 @@
+#!/usr/bin/perl -w
+#  Flash Operator Panel.    http://www.asternic.org
+#
+#  Copyright (c) 2004 Nicolas Gudino. All rights reserved.
+#
+#  Nicolas Gudino <nicolas at house.com.ar>
+#
+#  This program is free software, distributed under the terms of
+#  the GNU General Public License.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+#  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+#  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
+#  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+#  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+#  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+#  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use SWF qw(:ALL);
+use SWF::Constants qw(:Text :Button :DisplayItem :Fill);
+
+SWF::setScale(1);
+SWF::useSWFVersion(6);
+my $movie = new SWF::Movie();
+$movie->setDimension(100, 100);
+$movie->setBackground(0xFF, 0xFF, 0xFF);
+$movie->setRate(30);
+$movie->add(new SWF::Action(<<"EndOfActionScript"));
+
+var dummyVar=(getTimer()+random(100000));
+
+if(context != undefined) {
+	context = context.toUpperCase();
+	colaEvento(0,"debug","contexto leido "+context);
+	if(context == "DEFAULT") {	context=""; }
+} else {
+	colaEvento(0,"debug","context undefined");
+	context="";
+}
+
+var archivo = "variables"+context+".txt?rand="+dummyVar;
+
+vr = new LoadVars ();
+
+vr.onLoad = function (success)
+{ 
+	if (success == true) { 
+		colaEvento(0,"debug","Ok al leer "+archivo);
+		nextFrame();
+	} else {
+		colaEvento(0,"debug","Fallo al leer "+archivo);
+		stop();
+	}
+};
+
+vr.load(archivo);
+
+EndOfActionScript
+
+$movie->nextFrame(); 
+$movie->add(new SWF::Action(<<"EndOfActionScript"));
+
+function conecta() {
+	_global.sock = new XMLSocket;
+	_global.sock.onConnect = handleConnect;
+	_global.sock.onClose = handleDisconnect;
+	_global.sock.onXML = handleXML;
+    if(_global.port   == undefined) {
+        _global.port = 4445;
+    }
+    if(_global.server == undefined) {
+	    _global.sock.connect(null, _global.port);
+        _global.server_print = "default";
+    } else {
+	    _global.sock.connect(_global.server, _global.port);
+        _global.server_print = _global.server;
+    }
+}
+
+function handleConnect(connectionStatus){
+
+    if (connectionStatus) {
+		colaEvento(0,"debug","Conectado! con contexto: "+context);
+        _global.reconecta = 0;
+		if(_global.enable_crypto==1) {
+        	envia_comando("contexto", 0, 0);
+		} else {
+        	envia_comando("contexto", 1, 0);
+		}
+		if(restrict != undefined) {
+			envia_comando("restrict",restrict,0);
+		}
+    } else {
+		colaEvento(0,"debug","No pude conectar!");
+        _global.reconecta = 1;
+    }
+}
+
+function handleXML(doc){
+ 	var e = doc.firstChild;
+	if (e != null) {
+		if (e.nodeName == "response") {
+		    var numeroboton = e.attributes.btn; // btn is the button number
+			var comando     = e.attributes.cmd;
+			var textofinal  = e.attributes.data;
+
+			if (_global.key != undefined) {
+				if(_global.enable_crypto == 1) {
+					comando    = decrypt(comando,    _global.key);
+					if (textofinal.length > 0) {
+						textofinal = decrypt(textofinal, _global.key);
+					} 
+				} 
+			} 
+
+
+			var botonparte = numeroboton.split("@");
+			var boton_numero = botonparte[0];
+			var boton_contexto = botonparte[1];
+			var timernumber = 0;
+
+
+			if (boton_contexto == undefined) {
+				boton_contexto = "";
+			}
+			if (_root.context == undefined) {
+				_root.context = "";
+			}
+
+
+			if (comando == "key") {
+				_global.key = textofinal;
+				return;
+			}
+
+			if (comando == "restrict") {
+				_global.restrict = numeroboton;
+                _global.mybutton = numeroboton;
+				var myresa = eval('_root.resaltado'+_global.restrict);
+				myresa._visible = true;
+				return;
+			}
+
+			if (comando == "version") {
+				if(textofinal != _global.swfversion) 
+				{
+					_global.statusline=vr.version_mismatch;
+				} else {
+					_global.statusline="";
+				}
+			}
+
+			if (_root.context == boton_contexto) {
+				colaEvento(boton_numero,comando,textofinal);
+			}
+			// endif root.context
+		}
+		// endif == response
+	}
+	// endiff e != null
+}
+
+function colaEvento(boton_numero,comando,textofinal) {
+
+	if(_global.VersionFlash == "MAC") {
+		// GetURL method for MAC
+		jsQueue.push("javascript: docommand('"+boton_numero+"','"+comando+"','"+textofinal+"')");
+	} else {
+		// FSCommand method for anything else
+		jsQueue.push("newevent;"+boton_numero+"|"+comando+"|"+textofinal);
+	}
+}
+
+
+function handleDisconnect(){
+        delete _global.key;
+        _global.reconecta = 1;
+		colaEvento(0,"debug","Attempt reconnection");
+}
+
+
+Inicia_Variables = function () {
+	_global.jsQueue = new Array();
+	var flashVersion = System.capabilities.version;
+    var datos = flashVersion.split(" ");
+	_global.VersionFlash = datos[0];
+	_global.server = vr.server;
+	_global.port = vr.port;
+	_global.enable_crypto = Number(vr.enable_crypto);
+	if (isNaN(_global.enable_crypto)) {
+		_global.enable_crypto=0;
+	} else {
+		if(_global.enable_crypto != 0) {
+			_global.enable_crypto = 1;
+		}
+	}
+};
+
+
+recarga = function () {
+  	if(_global.restart == 1) {
+		// Send command to restart Asterisk
+		envia_comando("restart","1","1");
+	} else {
+		// Reloads FLASH client
+		delete _global.key;
+		var incontext = context;
+		var inbutton = mybutton;
+		var inrestrict = _global.restrict;
+		var indial = dial;
+		var innohighlight = nohighlight;
+		for (var a in _root) {
+			if (typeof (_root[a]) == "object") {
+				removeMovieClip(_root[a]);
+			}
+			if (typeof (_root[a]) == "movieclip") {
+				removeMovieClip(_root[a]);
+			}
+		}
+		_global.context = incontext;
+		_global.mybutton = inbutton;
+		_global.restrict = inrestrict;
+		_global.dial = indial;
+		_global.nohighlight = inhighlight;
+		stop();
+		gotoAndPlay(1);
+		}
+};
+
+
+_root.onEnterFrame = function() {
+
+		if(_global.jsQueue.length>0) {
+			if(_global.VersionFlash == "MAC") {
+				getURL(jsQueue.shift());
+			} else {
+				var partes = jsQueue.shift().split(";");
+				var comando=partes[0];
+				var params=partes[1];
+				getURL("FSCommand:"+comando,params);
+			}
+		}
+
+};
+
+Timers = function () {
+
+	if (_global.reconecta == 1) {
+		delete setInterval;
+		delete _global.key;
+		recarga();
+		return;
+	}
+};
+
+setInterval(Timers, 10000);
+
+function ExtraeNumeroClip(name) {
+	var destino = "";
+	name = name._name;
+	for (var s = 0; s<name.length; s++) {
+		var c = name.charAt(s);
+		if (c<"0" || c>"9") {
+		} else {
+			destino = destino+""+c;
+		}
+		if (c == ".") {
+			destino = "";
+		}
+	}
+	return destino;
+}
+
+envia_comando = function (comando, origen, destino) {
+	if (comando != "bogus" && comando != "contexto" && comando != "restrict") {
+		if (_global.restrict!=0) {
+			if(comando == "cortar") {
+				origen_number = ExtraeNumeroClip(origen);
+			} else {
+				origen_number = origen;
+			}
+			if(_global.restrict != undefined) {
+			    if (_global.restrict == origen_number ) {
+   			    } else {
+				return;
+			    }
+			} 
+		}
+	}
+	message = new XML();
+	message_data = message.createElement("msg");
+	if (_root.context.length>0) {
+		agrega_contexto = "@"+context;
+	}
+	if (agrega_contexto == undefined) {
+		agrega_contexto = "";
+	}
+	if (_level0.claveinput.secret == undefined) {
+		_level0.claveinput.secret = "";
+	}
+	if (_global.claveingresada == undefined && ( comando != "contexto" && comando != "bogus" && comando != "dial" && comando != "restrict")) {
+		_root.codebox._visible = true;
+		Selection.setFocus(_root.codebox.claveform);
+		_root.codebox.swapDepths(_root.log);
+		return;
+	}
+	// var clave=_level0.claveinput.secret+_global.key;
+	var clave = _global.claveingresada+_global.key;
+	var md5clave = "";
+	var md5clave = calcMD5(clave);
+	if (comando == "contexto" || comando == "restrict") {
+		md5clave = "";
+	}
+	message_data.attributes.data = origen+agrega_contexto+"|"+comando+destino+"|"+md5clave;
+	message.appendChild(message_data);
+	_global.sock.send(message);
+	var clave = "";
+};
+
+function LTrim(str) {
+	var whitespace = new String(" \t\n\r");
+	var s = new String(str);
+	if (whitespace.indexOf(s.charAt(0)) != -1) {
+		var j = 0, i = s.length;
+		while (j<i && whitespace.indexOf(s.charAt(j)) != -1) {
+			j++;
+		}
+		s = s.substring(j, i);
+	}
+	return s;
+}
+
+function RTrim(str) {
+	var whitespace = new String(" \t\n\r");
+	var s = new String(str);
+	if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {
+		var i = s.length-1;
+		// Get length of string
+		while (i>=0 && whitespace.indexOf(s.charAt(i)) != -1) {
+			i--;
+		}
+		s = s.substring(0, i+1);
+	}
+	return s;
+}
+
+function Trim(str) {
+	return RTrim(LTrim(str));
+}
+
+function setDND(obj, item) {
+	var nroboton = ExtraeNumeroClip(obj);
+	envia_comando("dnd", nroboton, nroboton);
+}
+
+function genera_selecttimeout() {
+
+	_global.positionselect = 0;
+	test = attachMovie("option","optionselected", getNextHighestDepth(),  {_x:800, _y:6});
+	test._visible = true;
+	test.legend = "No timeout";
+
+	test.onPress = function() {
+	     _root.despliega_select();
+	};
+
+
+	 for (a=0; a<5; a++) {
+		var b=a+1;
+		if (_global.opcionesTimeout[a] != undefined) {
+
+			testa = attachMovie("option","option"+a, getNextHighestDepth(),  {_x:800, _y:(b*22)+6});
+			testa.legend = _global.opcionesTimeout[a];
+			testa._visible = false;
+
+
+			testa.onRollOver = function() {
+           	 	this.legend = "* "+this.legend;
+        	};
+
+   		 	testa.onRollOut = function() {
+	            this.legend = this.legend.substring(2, this.legend.length);
+    		};
+
+			testa.onPress = function() {
+	            this.legend = this.legend.substring(2, this.legend.length);
+				var posicion = ExtraeNumeroClip(this);
+				_global.timeout_value = _global.opcionesTimeoutSecs[posicion];
+				_root.muestra_selecttimeout(0);
+				_root.selectbox1.gotoAndStop(1);
+				_root.optionselected._visible=true;
+				_root.optionselected.legend = this.legend;
+			};
+		}
+	}
+};
+
+function muestra_selecttimeout(value) {
+	 for (a=0; a<5; a++) {
+	 	var v = eval("_root.option"+a);
+		if(value) {
+			v._visible = true;
+		} else {
+			v._visible = false;
+		}
+	 }
+};
+
+function despliega_select() {
+	_root.optionselected._visible=false;
+	_root.selectbox1.gotoAndStop(2);
+	_root.muestra_selecttimeout(1);
+
+};
+
+function base64_decode(opString) {
+	if ( opString == undefined ) {
+		return;
+	} 
+	var str = opString;
+	var base64s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	var bits, bit1, bit2, bit3, bit4, i = 0;
+	var decOut = "";
+	for (i=0; i<str.length; i += 4) {
+		bit1 = (base64s.indexOf(str.charAt(i)) & 0xff) << 18 ;
+		bit2 = (base64s.indexOf(str.charAt(i+1)) & 0xff) << 12 ;
+		bit3 = (base64s.indexOf(str.charAt(i+2)) & 0xff) << 6 ;
+		bit4 = (base64s.indexOf(str.charAt(i+3)) & 0xff);
+		bits = bit1 | bit2 | bit3 | bit4;
+		decOut += String.fromCharCode((bits & 0xff0000) >> 16, (bits & 0xff00) >> 8, bits & 0xff);
+	}
+	if (str.charCodeAt(i-2) == 61) {
+		return decOut.substring(0, decOut.length-2);
+	} else if (str.charCodeAt(i-1) == 61) {
+		return decOut.substring(0, decOut.length-1);
+	} else {
+		return decOut.substring(0, decOut.length);
+	}
+};
+
+
+
+// MD5 ROUTINE
+/*
+ * Convert a 32-bit number to a hex string with ls-byte first
+ */
+var hex_chr = "0123456789abcdef";
+// 
+// somehow the expression (bitAND(b, c) | bitAND((~b), d)) didn't return coorect results on Mac
+// for: 
+// b&c = a8a20450, ((~b)&d) = 0101c88b, (bitAND(b, c) | bitAND((~b), d)) = a8a20450 <-- !!!
+// looks like the OR is not executed at all.
+//
+// let's try to trick the P-code compiler into working with us... Prayer beads are GO!
+// 
+function bitOR(a, b) {
+	var lsb = (a & 0x1) | (b & 0x1);
+	var msb31 = (a >>> 1) | (b >>> 1);
+	return (msb31 << 1) | lsb;
+}
+//  
+// will bitXOR be the only one working...?
+// Nope. XOR fails too if values with bit31 set are XORed. 
+//
+// Note however that OR (and AND and XOR?!) works alright for the statement
+//   (msb31 << 1) | lsb
+// even if the result of the left-shift operation has bit 31 set.
+// So there might be an extra condition here (Guessmode turned on):
+// Mac Flash fails (OR, AND and XOR) if either one of the input operands has bit31 set
+// *and* both operands have one or more bits both set to 1. In other words: when both
+// input bit-patterns 'overlap'.
+// Stuff to munch on for the MM guys, I guess...
+//
+function bitXOR(a, b) {
+	var lsb = (a & 0x1) ^ (b & 0x1);
+	var msb31 = (a >>> 1) ^ (b >>> 1);
+	return (msb31 << 1) | lsb;
+}
+// 
+// bitwise AND for 32-bit integers. This uses 31 + 1-bit operations internally
+// to work around bug in some AS interpreters. (Mac Flash!)
+// 
+function bitAND(a, b) {
+	var lsb = (a & 0x1) & (b & 0x1);
+	var msb31 = (a >>> 1) & (b >>> 1);
+	return (msb31 << 1) | lsb;
+	// return (a & b);
+}
+// 
+// Add integers, wrapping at 2^32. This uses 16-bit operations internally
+// to work around bugs in some AS interpreters. (Mac Flash!)
+// 
+function addme(x, y) {
+	var lsw = (x & 0xFFFF)+(y & 0xFFFF);
+	var msw = (x >> 16)+(y >> 16)+(lsw >> 16);
+	return (msw << 16) | (lsw & 0xFFFF);
+}
+function rhex(num) {
+	str = "";
+	for (j=0; j<=3; j++) {
+		str += hex_chr.charAt((num >> (j*8+4)) & 0x0F)+hex_chr.charAt((num >> (j*8)) & 0x0F);
+	}
+	return str;
+}
+/*
+ * Convert a string to a sequence of 16-word blocks, stored as an array.
+ * Append padding bits and the length, as described in the MD5 standard.
+ */
+function str2blks_MD5(str) {
+	nblk = ((str.length+8) >> 6)+1;
+	// 1 + (len + 8)/64
+	blks = new Array(nblk*16);
+	for (i=0; i<nblk*16; i++) {
+		blks[i] = 0;
+	}
+	/*
+				Input: 
+				
+				'willi' without the quotes.
+				
+				trace() Output on Intel (and MAC now?):
+				
+				see TXT files: *.Output.txt
+				
+				*/
+	for (i=0; i<str.length; i++) {
+		blks[i >> 2] |= str.charCodeAt(i) << (((str.length*8+i)%4)*8);
+	}
+	blks[i >> 2] |= 0x80 << (((str.length*8+i)%4)*8);
+	var l = str.length*8;
+	blks[nblk*16-2] = (l & 0xFF);
+	blks[nblk*16-2] |= ((l >>> 8) & 0xFF) << 8;
+	blks[nblk*16-2] |= ((l >>> 16) & 0xFF) << 16;
+	blks[nblk*16-2] |= ((l >>> 24) & 0xFF) << 24;
+	return blks;
+}
+/*
+ * Bitwise rotate a 32-bit number to the left
+ */
+function rol(num, cnt) {
+	return (num << cnt) | (num >>> (32-cnt));
+}
+/*
+ * These functions implement the basic operation for each round of the
+ * algorithm.
+ */
+function cmn(q, a, b, x, s, t) {
+	return addme(rol((addme(addme(a, q), addme(x, t))), s), b);
+}
+
+function ff(a, b, c, d, x, s, t) {
+	return cmn(bitOR(bitAND(b, c), bitAND((~b), d)), a, b, x, s, t);
+}
+
+function gg(a, b, c, d, x, s, t) {
+	return cmn(bitOR(bitAND(b, d), bitAND(c, (~d))), a, b, x, s, t);
+}
+
+function hh(a, b, c, d, x, s, t) {
+	return cmn(bitXOR(bitXOR(b, c), d), a, b, x, s, t);
+}
+
+function ii(a, b, c, d, x, s, t) {
+	return cmn(bitXOR(c, bitOR(b, (~d))), a, b, x, s, t);
+}
+/*
+ * Take a string and return the hex representation of its MD5.
+ */
+function calcMD5(str) {
+	x = str2blks_MD5(str);
+	a = 1732584193;
+	b = -271733879;
+	c = -1732584194;
+	d = 271733878;
+	var step;
+	for (i=0; i<x.length; i += 16) {
+		olda = a;
+		oldb = b;
+		oldc = c;
+		oldd = d;
+		step = 0;
+		a = ff(a, b, c, d, x[i+0], 7, -680876936);
+		d = ff(d, a, b, c, x[i+1], 12, -389564586);
+		c = ff(c, d, a, b, x[i+2], 17, 606105819);
+		b = ff(b, c, d, a, x[i+3], 22, -1044525330);
+		a = ff(a, b, c, d, x[i+4], 7, -176418897);
+		d = ff(d, a, b, c, x[i+5], 12, 1200080426);
+		c = ff(c, d, a, b, x[i+6], 17, -1473231341);
+		b = ff(b, c, d, a, x[i+7], 22, -45705983);
+		a = ff(a, b, c, d, x[i+8], 7, 1770035416);
+		d = ff(d, a, b, c, x[i+9], 12, -1958414417);
+		c = ff(c, d, a, b, x[i+10], 17, -42063);
+		b = ff(b, c, d, a, x[i+11], 22, -1990404162);
+		a = ff(a, b, c, d, x[i+12], 7, 1804603682);
+		d = ff(d, a, b, c, x[i+13], 12, -40341101);
+		c = ff(c, d, a, b, x[i+14], 17, -1502002290);
+		b = ff(b, c, d, a, x[i+15], 22, 1236535329);
+		a = gg(a, b, c, d, x[i+1], 5, -165796510);
+		d = gg(d, a, b, c, x[i+6], 9, -1069501632);
+		c = gg(c, d, a, b, x[i+11], 14, 643717713);
+		b = gg(b, c, d, a, x[i+0], 20, -373897302);
+		a = gg(a, b, c, d, x[i+5], 5, -701558691);
+		d = gg(d, a, b, c, x[i+10], 9, 38016083);
+		c = gg(c, d, a, b, x[i+15], 14, -660478335);
+		b = gg(b, c, d, a, x[i+4], 20, -405537848);
+		a = gg(a, b, c, d, x[i+9], 5, 568446438);
+		d = gg(d, a, b, c, x[i+14], 9, -1019803690);
+		c = gg(c, d, a, b, x[i+3], 14, -187363961);
+		b = gg(b, c, d, a, x[i+8], 20, 1163531501);
+		a = gg(a, b, c, d, x[i+13], 5, -1444681467);
+		d = gg(d, a, b, c, x[i+2], 9, -51403784);
+		c = gg(c, d, a, b, x[i+7], 14, 1735328473);
+		b = gg(b, c, d, a, x[i+12], 20, -1926607734);
+		a = hh(a, b, c, d, x[i+5], 4, -378558);
+		d = hh(d, a, b, c, x[i+8], 11, -2022574463);
+		c = hh(c, d, a, b, x[i+11], 16, 1839030562);
+		b = hh(b, c, d, a, x[i+14], 23, -35309556);
+		a = hh(a, b, c, d, x[i+1], 4, -1530992060);
+		d = hh(d, a, b, c, x[i+4], 11, 1272893353);
+		c = hh(c, d, a, b, x[i+7], 16, -155497632);
+		b = hh(b, c, d, a, x[i+10], 23, -1094730640);
+		a = hh(a, b, c, d, x[i+13], 4, 681279174);
+		d = hh(d, a, b, c, x[i+0], 11, -358537222);
+		c = hh(c, d, a, b, x[i+3], 16, -722521979);
+		b = hh(b, c, d, a, x[i+6], 23, 76029189);
+		a = hh(a, b, c, d, x[i+9], 4, -640364487);
+		d = hh(d, a, b, c, x[i+12], 11, -421815835);
+		c = hh(c, d, a, b, x[i+15], 16, 530742520);
+		b = hh(b, c, d, a, x[i+2], 23, -995338651);
+		a = ii(a, b, c, d, x[i+0], 6, -198630844);
+		d = ii(d, a, b, c, x[i+7], 10, 1126891415);
+		c = ii(c, d, a, b, x[i+14], 15, -1416354905);
+		b = ii(b, c, d, a, x[i+5], 21, -57434055);
+		a = ii(a, b, c, d, x[i+12], 6, 1700485571);
+		d = ii(d, a, b, c, x[i+3], 10, -1894986606);
+		c = ii(c, d, a, b, x[i+10], 15, -1051523);
+		b = ii(b, c, d, a, x[i+1], 21, -2054922799);
+		a = ii(a, b, c, d, x[i+8], 6, 1873313359);
+		d = ii(d, a, b, c, x[i+15], 10, -30611744);
+		c = ii(c, d, a, b, x[i+6], 15, -1560198380);
+		b = ii(b, c, d, a, x[i+13], 21, 1309151649);
+		a = ii(a, b, c, d, x[i+4], 6, -145523070);
+		d = ii(d, a, b, c, x[i+11], 10, -1120210379);
+		c = ii(c, d, a, b, x[i+2], 15, 718787259);
+		b = ii(b, c, d, a, x[i+9], 21, -343485551);
+		a = addme(a, olda);
+		b = addme(b, oldb);
+		c = addme(c, oldc);
+		d = addme(d, oldd);
+	}
+	return rhex(a)+rhex(b)+rhex(c)+rhex(d);
+}
+
+
+// TEA2
+
+c2b = new Object();
+c2b['\\000'] = 0;
+c2b["\001"] = 1;
+c2b["\002"] = 2;
+c2b["\003"] = 3;
+c2b["\004"] = 4;
+c2b["\005"] = 5;
+c2b["\006"] = 6;
+c2b["\007"] = 7;
+c2b["\010"] = 8;
+c2b["\011"] = 9;
+c2b["\012"] = 10;
+c2b["\013"] = 11;
+c2b["\014"] = 12;
+c2b["\015"] = 13;
+c2b["\016"] = 14;
+c2b["\017"] = 15;
+c2b["\020"] = 16;
+c2b["\021"] = 17;
+c2b["\022"] = 18;
+c2b["\023"] = 19;
+c2b["\024"] = 20;
+c2b["\025"] = 21;
+c2b["\026"] = 22;
+c2b["\027"] = 23;
+c2b["\030"] = 24;
+c2b["\031"] = 25;
+c2b["\032"] = 26;
+c2b["\033"] = 27;
+c2b["\034"] = 28;
+c2b["\035"] = 29;
+c2b["\036"] = 30;
+c2b["\037"] = 31;
+c2b["\040"] = 32;
+c2b["\041"] = 33;
+c2b['\042'] = 34;
+c2b["\043"] = 35;
+c2b["\044"] = 36;
+c2b["\045"] = 37;
+c2b["\046"] = 38;
+c2b["\047"] = 39;
+c2b["\050"] = 40;
+c2b["\051"] = 41;
+c2b["\052"] = 42;
+c2b["\053"] = 43;
+c2b["\054"] = 44;
+c2b["\055"] = 45;
+c2b["\056"] = 46;
+c2b["\057"] = 47;
+c2b["\060"] = 48;
+c2b["\061"] = 49;
+c2b["\062"] = 50;
+c2b["\063"] = 51;
+c2b["\064"] = 52;
+c2b["\065"] = 53;
+c2b["\066"] = 54;
+c2b["\067"] = 55;
+c2b["\070"] = 56;
+c2b["\071"] = 57;
+c2b["\072"] = 58;
+c2b["\073"] = 59;
+c2b["\074"] = 60;
+c2b["\075"] = 61;
+c2b["\076"] = 62;
+c2b["\077"] = 63;
+c2b["\100"] = 64;
+c2b["\101"] = 65;
+c2b["\102"] = 66;
+c2b["\103"] = 67;
+c2b["\104"] = 68;
+c2b["\105"] = 69;
+c2b["\106"] = 70;
+c2b["\107"] = 71;
+c2b["\110"] = 72;
+c2b["\111"] = 73;
+c2b["\112"] = 74;
+c2b["\113"] = 75;
+c2b["\114"] = 76;
+c2b["\115"] = 77;
+c2b["\116"] = 78;
+c2b["\117"] = 79;
+c2b["\120"] = 80;
+c2b["\121"] = 81;
+c2b["\122"] = 82;
+c2b["\123"] = 83;
+c2b["\124"] = 84;
+c2b["\125"] = 85;
+c2b["\126"] = 86;
+c2b["\127"] = 87;
+c2b["\130"] = 88;
+c2b["\131"] = 89;
+c2b["\132"] = 90;
+c2b["\133"] = 91;
+var pepe="\";
+c2b[pepe] = 92;
+var pepe="]";
+c2b[pepe] = 93;
+c2b["\136"] = 94;
+c2b["\137"] = 95;
+c2b["\140"] = 96;
+c2b["\141"] = 97;
+c2b["\142"] = 98;
+c2b["\143"] = 99;
+c2b["\144"] = 100;
+c2b["\145"] = 101;
+c2b["\146"] = 102;
+c2b["\147"] = 103;
+c2b["\150"] = 104;
+c2b["\151"] = 105;
+c2b["\152"] = 106;
+c2b["\153"] = 107;
+c2b["\154"] = 108;
+c2b["\155"] = 109;
+c2b["\156"] = 110;
+c2b["\157"] = 111;
+c2b["\160"] = 112;
+c2b["\161"] = 113;
+c2b["\162"] = 114;
+c2b["\163"] = 115;
+c2b["\164"] = 116;
+c2b["\165"] = 117;
+c2b["\166"] = 118;
+c2b["\167"] = 119;
+c2b["\170"] = 120;
+c2b["\171"] = 121;
+c2b["\172"] = 122;
+c2b["\173"] = 123;
+c2b["\174"] = 124;
+c2b["\175"] = 125;
+c2b["\176"] = 126;
+c2b["\177"] = 127;
+c2b["\200"] = 128;
+c2b["\201"] = 129;
+c2b["\202"] = 130;
+c2b["\203"] = 131;
+c2b["\204"] = 132;
+c2b["\205"] = 133;
+c2b["\206"] = 134;
+c2b["\207"] = 135;
+c2b["\210"] = 136;
+c2b["\211"] = 137;
+c2b["\212"] = 138;
+c2b["\213"] = 139;
+c2b["\214"] = 140;
+c2b["\215"] = 141;
+c2b["\216"] = 142;
+c2b["\217"] = 143;
+c2b["\220"] = 144;
+c2b["\221"] = 145;
+c2b["\222"] = 146;
+c2b["\223"] = 147;
+c2b["\224"] = 148;
+c2b["\225"] = 149;
+c2b["\226"] = 150;
+c2b["\227"] = 151;
+c2b["\230"] = 152;
+c2b["\231"] = 153;
+c2b["\232"] = 154;
+c2b["\233"] = 155;
+c2b["\234"] = 156;
+c2b["\235"] = 157;
+c2b["\236"] = 158;
+c2b["\237"] = 159;
+c2b["\240"] = 160;
+c2b["\241"] = 161;
+c2b["\242"] = 162;
+c2b["\243"] = 163;
+c2b["\244"] = 164;
+c2b["\245"] = 165;
+c2b["\246"] = 166;
+c2b["\247"] = 167;
+c2b["\250"] = 168;
+c2b["\251"] = 169;
+c2b["\252"] = 170;
+c2b["\253"] = 171;
+c2b["\254"] = 172;
+c2b["\255"] = 173;
+c2b["\256"] = 174;
+c2b["\257"] = 175;
+c2b["\260"] = 176;
+c2b["\261"] = 177;
+c2b["\262"] = 178;
+c2b["\263"] = 179;
+c2b["\264"] = 180;
+c2b["\265"] = 181;
+c2b["\266"] = 182;
+c2b["\267"] = 183;
+c2b["\270"] = 184;
+c2b["\271"] = 185;
+c2b["\272"] = 186;
+c2b["\273"] = 187;
+c2b["\274"] = 188;
+c2b["\275"] = 189;
+c2b["\276"] = 190;
+c2b["\277"] = 191;
+c2b["\300"] = 192;
+c2b["\301"] = 193;
+c2b["\302"] = 194;
+c2b["\303"] = 195;
+c2b["\304"] = 196;
+c2b["\305"] = 197;
+c2b["\306"] = 198;
+c2b["\307"] = 199;
+c2b["\310"] = 200;
+c2b["\311"] = 201;
+c2b["\312"] = 202;
+c2b["\313"] = 203;
+c2b["\314"] = 204;
+c2b["\315"] = 205;
+c2b["\316"] = 206;
+c2b["\317"] = 207;
+c2b["\320"] = 208;
+c2b["\321"] = 209;
+c2b["\322"] = 210;
+c2b["\323"] = 211;
+c2b["\324"] = 212;
+c2b["\325"] = 213;
+c2b["\326"] = 214;
+c2b["\327"] = 215;
+c2b["\330"] = 216;
+c2b["\331"] = 217;
+c2b["\332"] = 218;
+c2b["\333"] = 219;
+c2b["\334"] = 220;
+c2b["\335"] = 221;
+c2b["\336"] = 222;
+c2b["\337"] = 223;
+c2b["\340"] = 224;
+c2b["\341"] = 225;
+c2b["\342"] = 226;
+c2b["\343"] = 227;
+c2b["\344"] = 228;
+c2b["\345"] = 229;
+c2b["\346"] = 230;
+c2b["\347"] = 231;
+c2b["\350"] = 232;
+c2b["\351"] = 233;
+c2b["\352"] = 234;
+c2b["\353"] = 235;
+c2b["\354"] = 236;
+c2b["\355"] = 237;
+c2b["\356"] = 238;
+c2b["\357"] = 239;
+c2b["\360"] = 240;
+c2b["\361"] = 241;
+c2b["\362"] = 242;
+c2b["\363"] = 243;
+c2b["\364"] = 244;
+c2b["\365"] = 245;
+c2b["\366"] = 246;
+c2b["\367"] = 247;
+c2b["\370"] = 248;
+c2b["\371"] = 249;
+c2b["\372"] = 250;
+c2b["\373"] = 251;
+c2b["\374"] = 252;
+c2b["\375"] = 253;
+c2b["\376"] = 254;
+c2b["\377"] = 255;
+b2c = new Object();
+for (b in c2b) {
+	b2c[c2b[b]] = b;
+}
+
+
+// ascii to 6-bit bin to ascii
+a2b = new Object();
+a2b["A"] = 0;
+a2b["B"] = 1;
+a2b["C"] = 2;
+a2b["D"] = 3;
+a2b["E"] = 4;
+a2b["F"] = 5;
+a2b["G"] = 6;
+a2b["H"] = 7;
+a2b["I"] = 8;
+a2b["J"] = 9;
+a2b["K"] = 10;
+a2b["L"] = 11;
+a2b["M"] = 12;
+a2b["N"] = 13;
+a2b["O"] = 14;
+a2b["P"] = 15;
+a2b["Q"] = 16;
+a2b["R"] = 17;
+a2b["S"] = 18;
+a2b["T"] = 19;
+a2b["U"] = 20;
+a2b["V"] = 21;
+a2b["W"] = 22;
+a2b["X"] = 23;
+a2b["Y"] = 24;
+a2b["Z"] = 25;
+a2b["a"] = 26;
+a2b["b"] = 27;
+a2b["c"] = 28;
+a2b["d"] = 29;
+a2b["e"] = 30;
+a2b["f"] = 31;
+a2b["g"] = 32;
+a2b["h"] = 33;
+a2b["i"] = 34;
+a2b["j"] = 35;
+a2b["k"] = 36;
+a2b["l"] = 37;
+a2b["m"] = 38;
+a2b["n"] = 39;
+a2b["o"] = 40;
+a2b["p"] = 41;
+a2b["q"] = 42;
+a2b["r"] = 43;
+a2b["s"] = 44;
+a2b["t"] = 45;
+a2b["u"] = 46;
+a2b["v"] = 47;
+a2b["w"] = 48;
+a2b["x"] = 49;
+a2b["y"] = 50;
+a2b["z"] = 51;
+a2b["0"] = 52;
+a2b["1"] = 53;
+a2b["2"] = 54;
+a2b["3"] = 55;
+a2b["4"] = 56;
+a2b["5"] = 57;
+a2b["6"] = 58;
+a2b["7"] = 59;
+a2b["8"] = 60;
+a2b["9"] = 61;
+a2b["+"] = 62;
+a2b["_"] = 63;
+b2a = new Object();
+for (b in a2b) {
+	b2a[a2b[b]] = ''+b;
+}
+
+function binary2ascii(s) {
+	return bytes2ascii(blocks2bytes(s));
+}
+function binary2str(s) {
+	return bytes2str(blocks2bytes(s));
+}
+function ascii2binary(s) {
+	return bytes2blocks(ascii2bytes(s));
+}
+function str2binary(s) {
+	return bytes2blocks(str2bytes(s));
+}
+function str2bytes(s) {
+	var is = 0;
+	var ls = s.length;
+	var b = new Array();
+	while (1) {
+		if (is>=ls) {
+			break;
+		}
+		var pepe=s.charAt(is);
+		if (c2b[s.charAt(is)] == null) {
+			b[is] = 0xF7;
+		} else {
+			b[is] = c2b[s.charAt(is)];
+		}
+		is++;
+	}
+	return b;
+}
+function bytes2str(b) {
+	var ib = 0;
+	var lb = b.length;
+	var s = '';
+	while (1) {
+		if (ib>=lb) {
+			break;
+		}
+		if (b2c[0xFF & b[ib]]!=undefined) {
+			s += b2c[0xFF & b[ib]];
+		}
+		ib++;
+	}
+	return s;
+}
+function ascii2bytes(a) {
+	var ia = -1;
+	var la = a.length;
+	var ib = 0;
+	var b = new Array();
+	var carry;
+	while (1) {
+		// reads 4 chars and produces 3 bytes
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		b[ib] = a2b[a.charAt(ia)] << 2;
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		carry = a2b[a.charAt(ia)];
+		b[ib] |= carry >>> 4;
+		ib++;
+		carry = 0xF & carry;
+		if (carry == 0 && ia == (la-1)) {
+			return b;
+		}
+		b[ib] = carry << 4;
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		carry = a2b[a.charAt(ia)];
+		b[ib] |= carry >>> 2;
+		ib++;
+		carry = 3 & carry;
+		if (carry == 0 && ia == (la-1)) {
+			return b;
+		}
+		b[ib] = carry << 6;
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		b[ib] |= a2b[a.charAt(ia)];
+		ib++;
+	}
+	return b;
+}
+function bytes2ascii(b) {
+	var ib = 0;
+	var lb = b.length;
+	var s = '';
+	var b1;
+	var b2;
+	var b3;
+	var carry;
+	while (1) {
+		// reads 3 bytes and produces 4 chars
+		if (ib>=lb) {
+			break;
+		}
+		b1 = 0xFF & b[ib];
+		s += b2a[63 & (b1 >>> 2)];
+		carry = 3 & b1;
+		ib++;
+		if (ib>=lb) {
+			s += b2a[carry << 4];
+			break;
+		}
+		b2 = 0xFF & b[ib];
+		s += b2a[(0xF0 & (carry << 4)) | (b2 >>> 4)];
+		carry = 0xF & b2;
+		ib++;
+		if (ib>=lb) {
+			s += b2a[carry << 2];
+			break;
+		}
+		b3 = 0xFF & b[ib];
+		s += b2a[(60 & (carry << 2)) | (b3 >>> 6)]+b2a[63 & b3];
+		ib++;
+		if (ib%36 == 0) {
+			s += "\n";
+		}
+	}
+	return s;
+}
+function bytes2blocks(bytes) {
+	var blocks = new Array();
+	var ibl = 0;
+	var iby = 0;
+	var nby = bytes.length;
+	while (1) {
+		blocks[ibl] = (0xFF & bytes[iby]) << 24;
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		blocks[ibl] |= (0xFF & bytes[iby]) << 16;
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		blocks[ibl] |= (0xFF & bytes[iby]) << 8;
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		blocks[ibl] |= 0xFF & bytes[iby];
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		ibl++;
+	}
+	return blocks;
+}
+function blocks2bytes(blocks) {
+	var bytes = new Array();
+	var iby = 0;
+	var ibl = 0;
+	var nbl = blocks.length;
+	while (1) {
+		if (ibl>=nbl) {
+			break;
+		}
+		bytes[iby] = 0xFF & (blocks[ibl] >>> 24);
+		iby++;
+		bytes[iby] = 0xFF & (blocks[ibl] >>> 16);
+		iby++;
+		bytes[iby] = 0xFF & (blocks[ibl] >>> 8);
+		iby++;
+		bytes[iby] = 0xFF & blocks[ibl];
+		iby++;
+		ibl++;
+	}
+	return bytes;
+}
+function digest_pad(bytearray) {
+	var newarray = new Array();
+	var ina = 0;
+	var iba = 0;
+	var nba = bytearray.length;
+	var npads = 15-(nba%16);
+	newarray[ina] = npads;
+	ina++;
+	while (iba<nba) {
+		newarray[ina] = bytearray[iba];
+		ina++;
+		iba++;
+	}
+	var ip = npads;
+	while (ip>0) {
+		newarray[ina] = 0;
+		ina++;
+		ip--;
+	}
+	return newarray;
+}
+function pad(bytearray) {
+	var newarray = new Array();
+	var ina = 0;
+	var iba = 0;
+	var nba = bytearray.length;
+	var npads = 7-(nba%8);
+	newarray[ina] = (0xF8 & rand_byte()) | (7 & npads);
+	ina++;
+	while (iba<nba) {
+		newarray[ina] = bytearray[iba];
+		ina++;
+		iba++;
+	}
+	var ip = npads;
+	while (ip>0) {
+		newarray[ina] = rand_byte();
+		ina++;
+		ip--;
+	}
+	return newarray;
+}
+function rand_byte() {
+	return Math.floor(256*Math.random());
+	if (!rand_byte_already_called) {
+		var now = new Date();
+		seed = now.milliseconds;
+		rand_byte_already_called = true;
+	}
+	seed = (1029*seed+221591)%1048576;
+	return Math.floor(seed/4096);
+}
+function unpad(bytearray) {
+	var iba = 0;
+	var newarray = new Array();
+	var ina = 0;
+	var npads = 0x7 & bytearray[iba];
+	iba++;
+	var nba = bytearray.length-npads;
+	while (iba<nba) {
+		newarray[ina] = bytearray[iba];
+		ina++;
+		iba++;
+	}
+	return newarray;
+}
+function asciidigest(str) {
+	return binary2ascii(binarydigest(str));
+}
+function binarydigest(str, keystr) {
+	var key = new Array();
+	key[0] = 0x61626364;
+	key[1] = 0x62636465;
+	key[2] = 0x63646566;
+	key[3] = 0x64656667;
+	var c0 = new Array();
+	c0[0] = 0x61626364;
+	c0[1] = 0x62636465;
+	var c1 = new Array();
+	c1 = c0;
+	var v0 = new Array();
+	var v1 = new Array();
+	var swap;
+	var blocks = new Array();
+	blocks = bytes2blocks(digest_pad(str2bytes(str)));
+	var ibl = 0;
+	var nbl = blocks.length;
+	while (1) {
+		if (ibl>=nbl) {
+			break;
+		}
+		v0[0] = blocks[ibl];
+		ibl++;
+		v0[1] = blocks[ibl];
+		ibl++;
+		v1[0] = blocks[ibl];
+		ibl++;
+		v1[1] = blocks[ibl];
+		ibl++;
+		c0 = tea_code(xor_blocks(v0, c0), key);
+		c1 = tea_code(xor_blocks(v1, c1), key);
+		swap = c0[0];
+		c0[0] = c0[1];
+		c0[1] = c1[0];
+		c1[0] = c1[1];
+		c1[1] = swap;
+	}
+	var concat = new Array();
+	concat[0] = c0[0];
+	concat[1] = c0[1];
+	concat[2] = c1[0];
+	concat[3] = c1[1];
+	return concat;
+}
+function encrypt(str, keystr) {
+	var key = new Array();
+	key = binarydigest(keystr);
+	var blocks = new Array();
+	blocks = bytes2blocks(pad(str2bytes(str)));
+	var ibl = 0;
+	var nbl = blocks.length;
+	// Initial Value for CBC mode = "abcdbcde". Retain for interoperability.
+	var c = new Array();
+	c[0] = 0x61626364;
+	c[1] = 0x62636465;
+	var v = new Array();
+	var cblocks = new Array();
+	var icb = 0;
+	while (1) {
+		if (ibl>=nbl) {
+			break;
+		}
+		v[0] = blocks[ibl];
+		ibl++;
+		v[1] = blocks[ibl];
+		ibl++;
+		c = tea_code(xor_blocks(v, c), key);
+		cblocks[icb] = c[0];
+		icb++;
+		cblocks[icb] = c[1];
+		icb++;
+	}
+	return binary2ascii(cblocks);
+}
+function decrypt(ascii, keystr) {
+	var key = new Array();
+	key = binarydigest(keystr);
+	var cblocks = new Array();
+	cblocks = ascii2binary(ascii);
+	var icbl = 0;
+	var ncbl = cblocks.length;
+	var lastc = new Array();
+	lastc[0] = 0x61626364;
+	lastc[1] = 0x62636465;
+	var v = new Array();
+	var c = new Array();
+	var blocks = new Array();
+	var ibl = 0;
+	while (1) {
+		if (icbl>=ncbl) {
+			break;
+		}
+		c[0] = cblocks[icbl];
+		icbl++;
+		c[1] = cblocks[icbl];
+		icbl++;
+		v = xor_blocks(lastc, tea_decode(c, key));
+		blocks[ibl] = v[0];
+		ibl++;
+		blocks[ibl] = v[1];
+		ibl++;
+		lastc[0] = c[0];
+		lastc[1] = c[1];
+	}
+	return bytes2str(unpad(blocks2bytes(blocks)));
+}
+function xor_blocks(blk1, blk2) {
+	var blk = new Array();
+	blk[0] = blk1[0] ^ blk2[0];
+	blk[1] = blk1[1] ^ blk2[1];
+	return blk;
+}
+function tea_code(v, k) {
+	var v0 = v[0];
+	var v1 = v[1];
+	var k0 = k[0];
+	var k1 = k[1];
+	var k2 = k[2];
+	var k3 = k[3];
+	var sum = 0;
+	var n = 32;
+	while (n-->0) {
+		sum -= 1640531527;
+		// TEA magic number 0x9e3779b9 
+		sum = sum | 0;
+		v0 += ((v1 << 4)+k0) ^ (v1+sum) ^ ((v1 >>> 5)+k1);
+		v1 += ((v0 << 4)+k2) ^ (v0+sum) ^ ((v0 >>> 5)+k3);
+	}
+	var w = new Array();
+	w[0] = v0 | 0;
+	w[1] = v1 | 0;
+	return w;
+}
+function tea_decode(v, k) {
+	var v0 = v[0];
+	var v1 = v[1];
+	var k0 = k[0];
+	var k1 = k[1];
+	var k2 = k[2];
+	var k3 = k[3];
+	var sum = 0;
+	var n = 32;
+	sum = -957401312;
+	while (n-->0) {
+		v1 -= ((v0 << 4)+k2) ^ (v0+sum) ^ ((v0 >>> 5)+k3);
+		v0 -= ((v1 << 4)+k0) ^ (v1+sum) ^ ((v1 >>> 5)+k1);
+		sum += 1640531527;
+		sum = sum | 0;
+	}
+	var w = new Array();
+	w[0] = v0 | 0;
+	w[1] = v1 | 0;
+	return w;
+}
+
+Key.addListener(Key);
+
+Key.onKeyDown = function(){
+	var incremento = 1;
+	var tecla = Key.getCode();
+
+	if(tecla == 16) {
+		_global.shift = 1;
+	}
+
+	if(tecla == 40) // DOWN
+	{
+		// Select next button DOWN
+    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+       	dif1 = (_global.rectanguloprendido) % _root.cuantas_filas;
+		incremento = 1;
+		if(dif1 == 0) {
+			// It changed the column, increment it again
+			incremento = incremento - _root.cuantas_filas;
+		}
+        proximo = _global.rectanguloprendido + incremento;
+        var myresa = eval('_root.resaltado'+proximo);
+		if(_global.rectanguloprendido != _global.restrict) {
+        myapaga._visible = false;
+		}
+        myresa._visible = true;
+        _global.rectanguloprendido = proximo;
+        _root.makeStatus(proximo);
+	}
+	if(tecla == 38) // UP
+	{
+		// Select next button UP
+    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+       	dif1 = (_global.rectanguloprendido-1) % _root.cuantas_filas;
+		incremento = -1;
+		if(dif1 == 0) {
+			// It changed the column, increment it again
+			incremento = incremento + _root.cuantas_filas;
+		}
+        proximo = _global.rectanguloprendido + incremento;
+        var myresa = eval('_root.resaltado'+proximo);
+		if(_global.rectanguloprendido != _global.restrict) {
+        myapaga._visible = false;
+		}
+        myresa._visible = true;
+        _global.rectanguloprendido = proximo;
+        _root.makeStatus(proximo);
+	}
+	if(tecla == 37) // LEFT
+	{
+
+		if (_root.superdetails._visible == true) {
+			var tab = _root.superdetails.tab1._currentframe;
+		    if(tab == 2) {
+		        _root.superdetails.tab1.gotoAndStop(1);
+		        _root.superdetails.tab2.gotoAndStop(2);
+		        _root.superdetails.texto = _global.superdetailstexttab1;
+		    } else {
+		        _root.superdetails.tab1.gotoAndStop(2);
+		        _root.superdetails.tab2.gotoAndStop(1);
+		        _root.superdetails.texto = _global.superdetailstexttab2;
+		    }
+		} else {
+			// Select next button on the LEFT
+	    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+	       	incremento = _root.cuantas_filas;
+			diferencia = _global.rectanguloprendido % _root.cuantas_filas;
+	        proximo = _global.rectanguloprendido - incremento;
+
+        	if(proximo < 1) {
+				proximo = ((_root.cuantas_columnas - 1) * _root.cuantas_filas)+diferencia;
+       	 	}
+        	var myresa = eval('_root.resaltado'+proximo);
+			if(_global.rectanguloprendido != _global.restrict) {
+        	myapaga._visible = false;
+			}
+        	myresa._visible = true;
+        	_global.rectanguloprendido = proximo;
+        	_root.makeStatus(proximo);
+		}
+	}
+
+	if(tecla == 39) // RIGHT
+	{
+		if(_root.detail._visible == true) {
+			_root.superdetails._visible = true;
+			_root.detail._visible = false;
+		} else if (_root.superdetails._visible == true) {
+			var tab = _root.superdetails.tab1._currentframe;
+		    if(tab == 2) {
+		        _root.superdetails.tab1.gotoAndStop(1);
+		        _root.superdetails.tab2.gotoAndStop(2);
+		        _root.superdetails.texto = _global.superdetailstexttab1;
+		    } else {
+		        _root.superdetails.tab1.gotoAndStop(2);
+		        _root.superdetails.tab2.gotoAndStop(1);
+		        _root.superdetails.texto = _global.superdetailstexttab2;
+		    }
+		} else {
+			// Select next button on the RIGHT
+	    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+	        total = _root.cuantas_filas * _root.cuantas_columnas;
+        	incremento = _root.cuantas_filas;
+			diferencia = _global.rectanguloprendido % _root.cuantas_filas;
+	        proximo = _global.rectanguloprendido + incremento;
+
+	        if(proximo > total) {
+	            proximo = 1+diferencia-1;
+	        }
+	        var myresa = eval('_root.resaltado'+proximo);
+			if(_global.rectanguloprendido != _global.restrict) {
+	        myapaga._visible = false;
+			}
+	        myresa._visible = true;
+	        _global.rectanguloprendido = proximo;
+	        _root.makeStatus(proximo);
+		}
+	}
+	if(tecla == 9) // TAB
+	{
+		myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+		total = _root.cuantas_filas * _root.cuantas_columnas;
+		if(_global.shift == 1) {
+			incremento = -1;
+		} else {
+			incremento = 1;
+		}
+		proximo = _global.rectanguloprendido + incremento;
+
+	 	if(proximo > total) {
+			proximo = 1;
+		}
+		if(proximo < 1) {
+			proximo = total;
+		}
+		var myresa = eval('_root.resaltado'+proximo);
+		if(_global.rectanguloprendido == _global.restrict) {
+	  	myapaga._visible = false;
+		}
+	   	myresa._visible = true;
+	   	_global.rectanguloprendido = proximo;
+	   	_root.makeStatus(proximo);
+	}
+
+	if(tecla == 27)	// ESC
+	{
+		_root.codebox._visible = false;
+		_root.log._visible = false;
+		_root.detail._visible = false;
+		_root.superdetails._visible = false;
+	}
+
+	if(tecla == 18) // ALT
+	{
+		var myon = _global.rectanguloprendido;
+		if(myon>0) {
+			var myclip = eval('_level0.rectangulo'+myon+'.flecha'+myon);
+			_root.displaydetails(myclip);
+		}
+	}
+
+	if(tecla == 13) // ENTER
+	{
+		if(_root.codebox._visible == true) {
+			// The security code box is visible, sends code and hides it
+			_global.claveingresada = _root.codebox.claveform.text;
+			_root.codebox._visible = false;
+			_root.envia_comando('bogus', 0, 0);
+		} else {
+			// The security code is not visible, open detail windows of
+			// highlighted button
+			var myon = _global.rectanguloprendido;
+			if(myon>0) {
+				var myclip = eval('_level0.rectangulo'+myon+'.flecha'+myon);
+				_root.displaydetails(myclip);
+			}
+		}
+	}
+
+
+};
+
+Key.onKeyUp = function(){
+	var tecla = Key.getCode();
+	if(tecla == 16) {
+		_global.shift = 0;
+	}
+};
+
+Inicia_Variables();
+conecta();
+
+EndOfActionScript
+
+# Saves the movie
+$movie->nextFrame();
+$movie->save("comunicator.swf",9);


Property changes on: op-panel/branches/upstream/current/dhtml/comunicator.pl
___________________________________________________________________
Name: svn:executable
   + 

Added: op-panel/branches/upstream/current/dhtml/css/default.css
===================================================================
--- op-panel/branches/upstream/current/dhtml/css/default.css	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/css/default.css	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,111 @@
+.overlay_dialog img { border: none; }
+.overlay_dialog { background-image: url('../images/overlay.png'); }
+
+/* For PNG transparence in IE !! */
+* html .overlay_dialog {
+	background-color: transparent;
+	back\ground-color: transparent;
+	background-image: none;
+	filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../images/overlay.png", sizingMethod="scale");
+}
+
+.dialog_nw {
+	width: 9px;
+	height: 23px;
+	background: transparent url(../images/top_left.gif) no-repeat 0 0;		
+}
+
+.dialog_n {
+	background: transparent url(../images/top_mid.gif) repeat-x 0 0;	
+	height: 23px;
+	width: 100%;
+}
+
+.dialog_ne {
+	width: 9px;
+	height: 23px;
+	background: transparent url(../images/top_right.gif) no-repeat 0 0;		
+}
+
+.dialog_e {
+	width: 2px;
+	height: 100%;
+	background: transparent url(../images/center_right.gif) repeat-y 0 0;	
+}
+
+.dialog_w {
+	width: 2px;
+	height: 100%;
+	background: transparent url(../images/center_left.gif) repeat-y 0 0;		
+}
+
+.dialog_sw {
+	width: 9px;
+	height: 19px;
+	background: transparent url(../images/bottom_left.gif) no-repeat 0 0;			
+}
+
+.dialog_s {
+	background: transparent url(../images/bottom_mid.gif) repeat-x 0 0;		
+	height: 19px;
+	width: 100%;
+}
+
+.dialog_se {
+	width: 9px;
+	height: 19px;
+	background: transparent url(../images/bottom_right.gif) no-repeat 0 0;			
+}
+
+.dialog_sizer {
+	width: 9px;
+	height: 19px;
+	background: transparent url(../images/sizer.gif) no-repeat 0 0;	
+	cursor:se-resize;	
+}
+
+.dialog_close {
+	width: 14px;
+	height: 14px;
+	background: transparent url(../images/close.gif) no-repeat 0 0;			
+	position:absolute;
+	top:5px;
+	left:8px;
+	cursor:pointer;
+	z-index:2000;
+}
+
+.dialog_title {
+	float:left;
+	height:14px;
+	font-size:12px;
+	text-align:center;
+	width:100%;
+}
+
+.dialog_content {
+	overflow:auto;
+	color: #DDD;
+	font-family: Tahoma, Arial, Sans Serif;
+	font-size: 10px;
+	background-color:#123;
+}
+
+.top_draggable, .bottom_draggable {
+  cursor:move;
+}
+/* DO NOT CHANGE THESE VALUES*/
+.dialog {
+	display: block;
+ 	font-family: Tahoma, Arial, Sans Serif;
+	position: absolute;
+}
+
+.dialog * {
+	margin: 0px;
+	padding:0px;
+}
+
+.dialog table  { border-collapse: collapse; border-spacing: 0; width: 100%; }
+.dialog td, th { padding: 0; }
+

Added: op-panel/branches/upstream/current/dhtml/css/operator.css
===================================================================
--- op-panel/branches/upstream/current/dhtml/css/operator.css	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/css/operator.css	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,113 @@
+body {
+	font-family: verdana, helvetica, sans-serif;
+}
+
+.busy,.free,.agent,.notregistered,.ringing {
+	width: 150px;
+	height: 55px;
+	font-size: 12px;
+    color: #000; 
+	margin: 2px;
+	padding: 2px;
+}
+
+.busy{
+	float: left;
+	background: #ff3300;
+	overflow: hidden;
+}
+.agent{
+	float: left;
+	background: #dfdf33;
+	overflow: hidden;
+}
+.free{
+	float: left;
+	background: #ccffcc;
+	overflow: hidden;
+}
+.ringing{
+	float: left;
+	background: #009999;
+	overflow: hidden;
+	xbackground-image:url("../images/Cartoon_phone.gif");
+    xbackground-repeat:no-repeat;
+}
+.notregistered{
+	float: left;
+	background: #ddd;
+	overflow: hidden;
+}
+
+.mcount {
+   border: 1px solid #000;
+   padding: 0.1em;
+   width: 10em;
+   top: -20px;
+   left: 20px;
+   background: #dfd;
+   position: relative;
+   display: none;
+}
+
+.clid {
+	font-size: 10px;
+}
+
+.phone1 {
+	background-image:url("../images/telephone.png");
+    background-repeat:no-repeat;
+	float: left;
+	width: 20px;
+}
+.phone2 {
+	background-image:url("../images/phone.png");
+    background-repeat:no-repeat;
+	float: left;
+	width: 20px;
+}
+.phone3 {
+	background-image:url("../images/telephone_go.png");
+    background-repeat:no-repeat;
+	float: left;
+	width: 20px;
+}
+.phone4 {
+	background-image:url("../images/phone_sound.png");
+    background-repeat:no-repeat;
+	float: left;
+	width: 20px;
+}
+.phone5 {
+	background-image:url("../images/status_online.png");
+    background-repeat:no-repeat;
+	float: left;
+	width: 20px;
+}
+.phone6 {
+	background-image:url("../images/group.png");
+    background-repeat:no-repeat;
+	float: left;
+	width: 20px;
+}
+.mwi {
+	background-image:url("../images/email.png");
+    background-repeat:no-repeat;
+	visibility: hidden;
+	float: left;
+	width: 20px;
+}
+
+#dhtmltooltip{
+	position: absolute;
+	font-size: 10px;
+	width: 150px;
+	border: 2px solid black;
+	padding: 2px;
+	background-color: lightyellow;
+	visibility: hidden;
+	z-index: 100;
+	/*Remove below line to remove shadow. Below line should always appear last within this CSS*/
+	filter: progid:DXImageTransform.Microsoft.Shadow(color=gray,direction=135);
+}
+

Added: op-panel/branches/upstream/current/dhtml/images/bottom_left.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/bottom_left.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/bottom_mid.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/bottom_mid.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/bottom_right.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/bottom_right.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/bottom_right_resize.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/bottom_right_resize.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/bug.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/bug.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/center_left.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/center_left.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/center_right.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/center_right.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/close.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/close.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/email.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/email.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/group.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/group.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/mail.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/mail.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/overlay.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/overlay.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/phone.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/phone.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/phone_sound.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/phone_sound.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/resize.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/resize.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/sizer.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/sizer.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/status_online.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/status_online.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/telephone.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/telephone.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/telephone_go.png
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/telephone_go.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/top_left.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/top_left.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/top_mid.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/top_mid.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/images/top_right.gif
===================================================================
(Binary files differ)


Property changes on: op-panel/branches/upstream/current/dhtml/images/top_right.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: op-panel/branches/upstream/current/dhtml/index.php
===================================================================
--- op-panel/branches/upstream/current/dhtml/index.php	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/index.php	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,94 @@
+<?
+header("Content-type: text/html; charset=utf-8");
+
+if(isset($_GET['context'])) {
+    $contexto=$_GET['context'];
+    $contexto=strtoupper($contexto);
+    $archivo = "variables$contexto.txt";
+} else {
+    $archivo="variables.txt";
+}
+
+$pepe = file_get_contents($archivo);
+$partes = split("&",$pepe);
+foreach ($partes as $elemento) {
+	$otri = split("=",$elemento);
+	if(substr($otri[0],0,5)=="texto") {
+		$numero = substr($otri[0],5);
+		if($numero > $buttoncount) {$buttoncount = $numero;}
+	}
+}
+?>
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <META HTTP-EQUIV="Expires" CONTENT="Fri, Jun 12 1981 08:20:00 GMT">
+  <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+  <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
+
+  <link href="css/default.css" rel="stylesheet" type="text/css" ></link>
+  <link href="css/operator.css" rel="stylesheet" type="text/css" ></link>
+
+<script language='Javascript'>
+<!--
+function init() {
+	new Ajax.Request('variables.php?context=<?=$contexto?>', {onSuccess:handlerFunc, onFailure:errFunc});
+	loglines = new Array();
+    tiempos   = new Object();
+	tipofree  = new Object();
+	win = new Window('log', {top:10, left:10, width:400, height:250, zIndex: 100, resizable: true, title: "Log", hideEffect: Effect.SwitchOff})
+	win.getContent().innerHTML= "&nbsp;";
+	timerID  = setTimeout("UpdateTimer()", 1000);
+    tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : ""
+};
+-->
+</script>
+
+  <script type="text/javascript" src="js/prototype.js"></script>
+  <script type="text/javascript" src="js/dragdrop.js"></script>
+  <script type="text/javascript" src="js/effects.js"> </script>
+  <script type="text/javascript" src="js/window.js"> </script>
+  <script type="text/javascript" src="js/base64.js"> </script>
+  <script type="text/javascript" src="js/dhtmltooltip.js"> </script>
+  <script type="text/javascript" src="js/scriptaculous"> </script>
+  <script type="text/javascript" src="js/operator.js"> </script>
+
+
+</head>
+
+<body>
+<a href='javascript: win.showCenter();'><img src='images/bug.png' border=0></a>
+<?
+for($a=1;$a<=$buttoncount;$a++)
+{
+$mouseov=" onmouseover='javascript:$(\"mcount$a\").style.display=\"block\";' onmouseout='javascript:$(\"mcount$a\").style.display=\"none\";' ";
+$mouseov1 = " onMouseover=\"ddrivetip(this,'#f0a020', 180)\"; onMouseout=\"hideddrivetip()\" ";
+$mouseov2 = " onMouseover=\"ddrivetip(this,'#f0a020', 180)\"; onMouseout=\"hideddrivetip()\" ";
+echo "<div id=\"boton$a\" class='free' style='display: none;'>\n";
+echo "<span id='label$a'>&nbsp;</span><BR>\n";
+echo "<span id='clid$a' class='clid'>&nbsp;</span><BR>\n";
+echo "<div class='clid' id='tick$a'>&nbsp;</div>";
+echo "<div id='phone$a' class='phone1' $mouseov2>&nbsp;</div>";
+echo "<div id='mwi$a' class='mwi' $mouseov1>&nbsp;</div>";
+echo "</div>\n";
+} 
+?>
+<BR><BR>
+<div id="pa" style='width:100%; clear:both; font-size: 10px;' >
+</div>
+
+<div id="log" style='float: none; font-size: 10px;'>
+</div>
+
+<div align='center'>
+<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="1" height="1" id="operator">
+<param name="allowScriptAccess" value="sameDomain" />
+<param name="movie" value="comunicator.swf?context=<?=$contexto?>" />
+<param name="quality" value="high" />
+<param name="scale" value="noScale" />
+<param name="bgcolor" value="#ffffff" />
+<embed src="comunicator.swf?context=<?=$contexto?>" scale="noScale" quality="high" bgcolor="#ffffff" width="1" height="1" name="operator" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" swLiveConnect="true"/>
+</div>
+<div id="dhtmltooltip"></div>
+</body>
+</html>

Added: op-panel/branches/upstream/current/dhtml/js/base64.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/base64.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/base64.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,154 @@
+var END_OF_INPUT = -1;
+
+var base64Chars = new Array(
+    'A','B','C','D','E','F','G','H',
+    'I','J','K','L','M','N','O','P',
+    'Q','R','S','T','U','V','W','X',
+    'Y','Z','a','b','c','d','e','f',
+    'g','h','i','j','k','l','m','n',
+    'o','p','q','r','s','t','u','v',
+    'w','x','y','z','0','1','2','3',
+    '4','5','6','7','8','9','+','/'
+);
+
+var reverseBase64Chars = new Array();
+for (var i=0; i < base64Chars.length; i++){
+    reverseBase64Chars[base64Chars[i]] = i;
+}
+
+var base64Str;
+var base64Count;
+function setBase64Str(str){
+    base64Str = str;
+    base64Count = 0;
+}
+function readBase64(){    
+    if (!base64Str) return END_OF_INPUT;
+    if (base64Count >= base64Str.length) return END_OF_INPUT;
+    var c = base64Str.charCodeAt(base64Count) & 0xff;
+    base64Count++;
+    return c;
+}
+function encodeBase64(str){
+    setBase64Str(str);
+    var result = '';
+    var inBuffer = new Array(3);
+    var lineCount = 0;
+    var done = false;
+    while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT){
+        inBuffer[1] = readBase64();
+        inBuffer[2] = readBase64();
+        result += (base64Chars[ inBuffer[0] >> 2 ]);
+        if (inBuffer[1] != END_OF_INPUT){
+            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
+            if (inBuffer[2] != END_OF_INPUT){
+                result += (base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
+                result += (base64Chars [inBuffer[2] & 0x3F]);
+            } else {
+                result += (base64Chars [((inBuffer[1] << 2) & 0x3c)]);
+                result += ('=');
+                done = true;
+            }
+        } else {
+            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
+            result += ('=');
+            result += ('=');
+            done = true;
+        }
+        lineCount += 4;
+        if (lineCount >= 76){
+            result += ('\n');
+            lineCount = 0;
+        }
+    }
+    return result;
+}
+function readReverseBase64(){   
+    if (!base64Str) return END_OF_INPUT;
+    while (true){      
+        if (base64Count >= base64Str.length) return END_OF_INPUT;
+        var nextCharacter = base64Str.charAt(base64Count);
+        base64Count++;
+        if (reverseBase64Chars[nextCharacter]){
+            return reverseBase64Chars[nextCharacter];
+        }
+        if (nextCharacter == 'A') return 0;
+    }
+    return END_OF_INPUT;
+}
+
+function ntos(n){
+    n=n.toString(16);
+    if (n.length == 1) n="0"+n;
+    n="%"+n;
+    return unescape(n);
+}
+
+function decodeBase64(str){
+    setBase64Str(str);
+    var result = "";
+    var inBuffer = new Array(4);
+    var done = false;
+    while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
+        && (inBuffer[1] = readReverseBase64()) != END_OF_INPUT){
+        inBuffer[2] = readReverseBase64();
+        inBuffer[3] = readReverseBase64();
+        result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
+        if (inBuffer[2] != END_OF_INPUT){
+            result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
+            if (inBuffer[3] != END_OF_INPUT){
+                result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
+            } else {
+                done = true;
+            }
+        } else {
+            done = true;
+        }
+    }
+    return result;
+}
+
+var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
+function toHex(n){
+    var result = ''
+    var start = true;
+    for (var i=32; i>0;){
+        i-=4;
+        var digit = (n>>i) & 0xf;
+        if (!start || digit != 0){
+            start = false;
+            result += digitArray[digit];
+        }
+    }
+    return (result==''?'0':result);
+}
+
+function pad(str, len, pad){
+    var result = str;
+    for (var i=str.length; i<len; i++){
+        result = pad + result;
+    }
+    return result;
+}
+
+function encodeHex(str){
+    var result = "";
+    for (var i=0; i<str.length; i++){
+        result += pad(toHex(str.charCodeAt(i)&0xff),2,'0');
+    }
+    return result;
+}
+
+function decodeHex(str){
+    str = str.replace(new RegExp("s/[^0-9a-zA-Z]//g"));
+    var result = "";
+    var nextchar = "";
+    for (var i=0; i<str.length; i++){
+        nextchar += str.charAt(i);
+        if (nextchar.length == 2){
+            result += ntos(eval('0x'+nextchar));
+            nextchar = "";
+        }
+    }
+    return result;
+}

Added: op-panel/branches/upstream/current/dhtml/js/builder.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/builder.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/builder.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,101 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// See scriptaculous.js for full license.
+
+var Builder = {
+  NODEMAP: {
+    AREA: 'map',
+    CAPTION: 'table',
+    COL: 'table',
+    COLGROUP: 'table',
+    LEGEND: 'fieldset',
+    OPTGROUP: 'select',
+    OPTION: 'select',
+    PARAM: 'object',
+    TBODY: 'table',
+    TD: 'table',
+    TFOOT: 'table',
+    TH: 'table',
+    THEAD: 'table',
+    TR: 'table'
+  },
+  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+  //       due to a Firefox bug
+  node: function(elementName) {
+    elementName = elementName.toUpperCase();
+    
+    // try innerHTML approach
+    var parentTag = this.NODEMAP[elementName] || 'div';
+    var parentElement = document.createElement(parentTag);
+    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+    } catch(e) {}
+    var element = parentElement.firstChild || null;
+      
+    // see if browser added wrapping tags
+    if(element && (element.tagName != elementName))
+      element = element.getElementsByTagName(elementName)[0];
+    
+    // fallback to createElement approach
+    if(!element) element = document.createElement(elementName);
+    
+    // abort if nothing could be created
+    if(!element) return;
+
+    // attributes (or text)
+    if(arguments[1])
+      if(this._isStringOrNumber(arguments[1]) ||
+        (arguments[1] instanceof Array)) {
+          this._children(element, arguments[1]);
+        } else {
+          var attrs = this._attributes(arguments[1]);
+          if(attrs.length) {
+            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+              parentElement.innerHTML = "<" +elementName + " " +
+                attrs + "></" + elementName + ">";
+            } catch(e) {}
+            element = parentElement.firstChild || null;
+            // workaround firefox 1.0.X bug
+            if(!element) {
+              element = document.createElement(elementName);
+              for(attr in arguments[1]) 
+                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+            }
+            if(element.tagName != elementName)
+              element = parentElement.getElementsByTagName(elementName)[0];
+            }
+        } 
+
+    // text, or array of children
+    if(arguments[2])
+      this._children(element, arguments[2]);
+
+     return element;
+  },
+  _text: function(text) {
+     return document.createTextNode(text);
+  },
+  _attributes: function(attributes) {
+    var attrs = [];
+    for(attribute in attributes)
+      attrs.push((attribute=='className' ? 'class' : attribute) +
+          '="' + attributes[attribute].toString().escapeHTML() + '"');
+    return attrs.join(" ");
+  },
+  _children: function(element, children) {
+    if(typeof children=='object') { // array can hold nodes and text
+      children.flatten().each( function(e) {
+        if(typeof e=='object')
+          element.appendChild(e)
+        else
+          if(Builder._isStringOrNumber(e))
+            element.appendChild(Builder._text(e));
+      });
+    } else
+      if(Builder._isStringOrNumber(children)) 
+         element.appendChild(Builder._text(children));
+  },
+  _isStringOrNumber: function(param) {
+    return(typeof param=='string' || typeof param=='number');
+  }
+}
\ No newline at end of file

Added: op-panel/branches/upstream/current/dhtml/js/controls.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/controls.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/controls.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,815 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+//  Richard Livsey
+//  Rahul Bhargava
+//  Rob Wills
+// 
+// See scriptaculous.js for full license.
+
+// Autocompleter.Base handles all the autocompletion functionality 
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least, 
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method 
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most 
+// useful when one of the tokens is \n (a newline), as it 
+// allows smart autocompletion after linebreaks.
+
+var Autocompleter = {}
+Autocompleter.Base = function() {};
+Autocompleter.Base.prototype = {
+  baseInitialize: function(element, update, options) {
+    this.element     = $(element); 
+    this.update      = $(update);  
+    this.hasFocus    = false; 
+    this.changed     = false; 
+    this.active      = false; 
+    this.index       = 0;     
+    this.entryCount  = 0;
+
+    if (this.setOptions)
+      this.setOptions(options);
+    else
+      this.options = options || {};
+
+    this.options.paramName    = this.options.paramName || this.element.name;
+    this.options.tokens       = this.options.tokens || [];
+    this.options.frequency    = this.options.frequency || 0.4;
+    this.options.minChars     = this.options.minChars || 1;
+    this.options.onShow       = this.options.onShow || 
+    function(element, update){ 
+      if(!update.style.position || update.style.position=='absolute') {
+        update.style.position = 'absolute';
+        Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
+      }
+      Effect.Appear(update,{duration:0.15});
+    };
+    this.options.onHide = this.options.onHide || 
+    function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+    if (typeof(this.options.tokens) == 'string') 
+      this.options.tokens = new Array(this.options.tokens);
+
+    this.observer = null;
+    
+    this.element.setAttribute('autocomplete','off');
+
+    Element.hide(this.update);
+
+    Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
+    Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
+  },
+
+  show: function() {
+    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+    if(!this.iefix && 
+      (navigator.appVersion.indexOf('MSIE')>0) &&
+      (navigator.userAgent.indexOf('Opera')<0) &&
+      (Element.getStyle(this.update, 'position')=='absolute')) {
+      new Insertion.After(this.update, 
+       '<iframe id="' + this.update.id + '_iefix" '+
+       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+      this.iefix = $(this.update.id+'_iefix');
+    }
+    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+  },
+  
+  fixIEOverlapping: function() {
+    Position.clone(this.update, this.iefix);
+    this.iefix.style.zIndex = 1;
+    this.update.style.zIndex = 2;
+    Element.show(this.iefix);
+  },
+
+  hide: function() {
+    this.stopIndicator();
+    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+    if(this.iefix) Element.hide(this.iefix);
+  },
+
+  startIndicator: function() {
+    if(this.options.indicator) Element.show(this.options.indicator);
+  },
+
+  stopIndicator: function() {
+    if(this.options.indicator) Element.hide(this.options.indicator);
+  },
+
+  onKeyPress: function(event) {
+    if(this.active)
+      switch(event.keyCode) {
+       case Event.KEY_TAB:
+       case Event.KEY_RETURN:
+         this.selectEntry();
+         Event.stop(event);
+       case Event.KEY_ESC:
+         this.hide();
+         this.active = false;
+         Event.stop(event);
+         return;
+       case Event.KEY_LEFT:
+       case Event.KEY_RIGHT:
+         return;
+       case Event.KEY_UP:
+         this.markPrevious();
+         this.render();
+         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+         return;
+       case Event.KEY_DOWN:
+         this.markNext();
+         this.render();
+         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+         return;
+      }
+     else 
+       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 
+         (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
+
+    this.changed = true;
+    this.hasFocus = true;
+
+    if(this.observer) clearTimeout(this.observer);
+      this.observer = 
+        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+  },
+
+  activate: function() {
+    this.changed = false;
+    this.hasFocus = true;
+    this.getUpdatedChoices();
+  },
+
+  onHover: function(event) {
+    var element = Event.findElement(event, 'LI');
+    if(this.index != element.autocompleteIndex) 
+    {
+        this.index = element.autocompleteIndex;
+        this.render();
+    }
+    Event.stop(event);
+  },
+  
+  onClick: function(event) {
+    var element = Event.findElement(event, 'LI');
+    this.index = element.autocompleteIndex;
+    this.selectEntry();
+    this.hide();
+  },
+  
+  onBlur: function(event) {
+    // needed to make click events working
+    setTimeout(this.hide.bind(this), 250);
+    this.hasFocus = false;
+    this.active = false;     
+  }, 
+  
+  render: function() {
+    if(this.entryCount > 0) {
+      for (var i = 0; i < this.entryCount; i++)
+        this.index==i ? 
+          Element.addClassName(this.getEntry(i),"selected") : 
+          Element.removeClassName(this.getEntry(i),"selected");
+        
+      if(this.hasFocus) { 
+        this.show();
+        this.active = true;
+      }
+    } else {
+      this.active = false;
+      this.hide();
+    }
+  },
+  
+  markPrevious: function() {
+    if(this.index > 0) this.index--
+      else this.index = this.entryCount-1;
+  },
+  
+  markNext: function() {
+    if(this.index < this.entryCount-1) this.index++
+      else this.index = 0;
+  },
+  
+  getEntry: function(index) {
+    return this.update.firstChild.childNodes[index];
+  },
+  
+  getCurrentEntry: function() {
+    return this.getEntry(this.index);
+  },
+  
+  selectEntry: function() {
+    this.active = false;
+    this.updateElement(this.getCurrentEntry());
+  },
+
+  updateElement: function(selectedElement) {
+    if (this.options.updateElement) {
+      this.options.updateElement(selectedElement);
+      return;
+    }
+    var value = '';
+    if (this.options.select) {
+      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
+      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+    } else
+      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+    
+    var lastTokenPos = this.findLastToken();
+    if (lastTokenPos != -1) {
+      var newValue = this.element.value.substr(0, lastTokenPos + 1);
+      var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
+      if (whitespace)
+        newValue += whitespace[0];
+      this.element.value = newValue + value;
+    } else {
+      this.element.value = value;
+    }
+    this.element.focus();
+    
+    if (this.options.afterUpdateElement)
+      this.options.afterUpdateElement(this.element, selectedElement);
+  },
+
+  updateChoices: function(choices) {
+    if(!this.changed && this.hasFocus) {
+      this.update.innerHTML = choices;
+      Element.cleanWhitespace(this.update);
+      Element.cleanWhitespace(this.update.firstChild);
+
+      if(this.update.firstChild && this.update.firstChild.childNodes) {
+        this.entryCount = 
+          this.update.firstChild.childNodes.length;
+        for (var i = 0; i < this.entryCount; i++) {
+          var entry = this.getEntry(i);
+          entry.autocompleteIndex = i;
+          this.addObservers(entry);
+        }
+      } else { 
+        this.entryCount = 0;
+      }
+
+      this.stopIndicator();
+
+      this.index = 0;
+      this.render();
+    }
+  },
+
+  addObservers: function(element) {
+    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+  },
+
+  onObserverEvent: function() {
+    this.changed = false;   
+    if(this.getToken().length>=this.options.minChars) {
+      this.startIndicator();
+      this.getUpdatedChoices();
+    } else {
+      this.active = false;
+      this.hide();
+    }
+  },
+
+  getToken: function() {
+    var tokenPos = this.findLastToken();
+    if (tokenPos != -1)
+      var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
+    else
+      var ret = this.element.value;
+
+    return /\n/.test(ret) ? '' : ret;
+  },
+
+  findLastToken: function() {
+    var lastTokenPos = -1;
+
+    for (var i=0; i<this.options.tokens.length; i++) {
+      var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
+      if (thisTokenPos > lastTokenPos)
+        lastTokenPos = thisTokenPos;
+    }
+    return lastTokenPos;
+  }
+}
+
+Ajax.Autocompleter = Class.create();
+Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
+  initialize: function(element, update, url, options) {
+    this.baseInitialize(element, update, options);
+    this.options.asynchronous  = true;
+    this.options.onComplete    = this.onComplete.bind(this);
+    this.options.defaultParams = this.options.parameters || null;
+    this.url                   = url;
+  },
+
+  getUpdatedChoices: function() {
+    entry = encodeURIComponent(this.options.paramName) + '=' + 
+      encodeURIComponent(this.getToken());
+
+    this.options.parameters = this.options.callback ?
+      this.options.callback(this.element, entry) : entry;
+
+    if(this.options.defaultParams) 
+      this.options.parameters += '&' + this.options.defaultParams;
+
+    new Ajax.Request(this.url, this.options);
+  },
+
+  onComplete: function(request) {
+    this.updateChoices(request.responseText);
+  }
+
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+//                    text only at the beginning of strings in the 
+//                    autocomplete array. Defaults to true, which will
+//                    match text at the beginning of any *word* in the
+//                    strings in the autocomplete array. If you want to
+//                    search anywhere in the string, additionally set
+//                    the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+//                   a partial match (unlike minChars, which defines
+//                   how many characters are required to do any match
+//                   at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+//                 Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector' 
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create();
+Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
+  initialize: function(element, update, array, options) {
+    this.baseInitialize(element, update, options);
+    this.options.array = array;
+  },
+
+  getUpdatedChoices: function() {
+    this.updateChoices(this.options.selector(this));
+  },
+
+  setOptions: function(options) {
+    this.options = Object.extend({
+      choices: 10,
+      partialSearch: true,
+      partialChars: 2,
+      ignoreCase: true,
+      fullSearch: false,
+      selector: function(instance) {
+        var ret       = []; // Beginning matches
+        var partial   = []; // Inside matches
+        var entry     = instance.getToken();
+        var count     = 0;
+
+        for (var i = 0; i < instance.options.array.length &&  
+          ret.length < instance.options.choices ; i++) { 
+
+          var elem = instance.options.array[i];
+          var foundPos = instance.options.ignoreCase ? 
+            elem.toLowerCase().indexOf(entry.toLowerCase()) : 
+            elem.indexOf(entry);
+
+          while (foundPos != -1) {
+            if (foundPos == 0 && elem.length != entry.length) { 
+              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
+                elem.substr(entry.length) + "</li>");
+              break;
+            } else if (entry.length >= instance.options.partialChars && 
+              instance.options.partialSearch && foundPos != -1) {
+              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+                  foundPos + entry.length) + "</li>");
+                break;
+              }
+            }
+
+            foundPos = instance.options.ignoreCase ? 
+              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
+              elem.indexOf(entry, foundPos + 1);
+
+          }
+        }
+        if (partial.length)
+          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+        return "<ul>" + ret.join('') + "</ul>";
+      }
+    }, options || {});
+  }
+});
+
+// AJAX in-place editor
+//
+// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+  setTimeout(function() {
+    Field.activate(field);
+  }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create();
+Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
+Ajax.InPlaceEditor.prototype = {
+  initialize: function(element, url, options) {
+    this.url = url;
+    this.element = $(element);
+
+    this.options = Object.extend({
+      okButton: true,
+      okText: "ok",
+      cancelLink: true,
+      cancelText: "cancel",
+      savingText: "Saving...",
+      clickToEditText: "Click to edit",
+      okText: "ok",
+      rows: 1,
+      onComplete: function(transport, element) {
+        new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
+      },
+      onFailure: function(transport) {
+        alert("Error communicating with the server: " + transport.responseText.stripTags());
+      },
+      callback: function(form) {
+        return Form.serialize(form);
+      },
+      handleLineBreaks: true,
+      loadingText: 'Loading...',
+      savingClassName: 'inplaceeditor-saving',
+      loadingClassName: 'inplaceeditor-loading',
+      formClassName: 'inplaceeditor-form',
+      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
+      highlightendcolor: "#FFFFFF",
+      externalControl: null,
+      submitOnBlur: false,
+      ajaxOptions: {},
+      evalScripts: false
+    }, options || {});
+
+    if(!this.options.formId && this.element.id) {
+      this.options.formId = this.element.id + "-inplaceeditor";
+      if ($(this.options.formId)) {
+        // there's already a form with that name, don't specify an id
+        this.options.formId = null;
+      }
+    }
+    
+    if (this.options.externalControl) {
+      this.options.externalControl = $(this.options.externalControl);
+    }
+    
+    this.originalBackground = Element.getStyle(this.element, 'background-color');
+    if (!this.originalBackground) {
+      this.originalBackground = "transparent";
+    }
+    
+    this.element.title = this.options.clickToEditText;
+    
+    this.onclickListener = this.enterEditMode.bindAsEventListener(this);
+    this.mouseoverListener = this.enterHover.bindAsEventListener(this);
+    this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
+    Event.observe(this.element, 'click', this.onclickListener);
+    Event.observe(this.element, 'mouseover', this.mouseoverListener);
+    Event.observe(this.element, 'mouseout', this.mouseoutListener);
+    if (this.options.externalControl) {
+      Event.observe(this.options.externalControl, 'click', this.onclickListener);
+      Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
+      Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
+    }
+  },
+  enterEditMode: function(evt) {
+    if (this.saving) return;
+    if (this.editing) return;
+    this.editing = true;
+    this.onEnterEditMode();
+    if (this.options.externalControl) {
+      Element.hide(this.options.externalControl);
+    }
+    Element.hide(this.element);
+    this.createForm();
+    this.element.parentNode.insertBefore(this.form, this.element);
+    Field.scrollFreeActivate(this.editField);
+    // stop the event to avoid a page refresh in Safari
+    if (evt) {
+      Event.stop(evt);
+    }
+    return false;
+  },
+  createForm: function() {
+    this.form = document.createElement("form");
+    this.form.id = this.options.formId;
+    Element.addClassName(this.form, this.options.formClassName)
+    this.form.onsubmit = this.onSubmit.bind(this);
+
+    this.createEditField();
+
+    if (this.options.textarea) {
+      var br = document.createElement("br");
+      this.form.appendChild(br);
+    }
+
+    if (this.options.okButton) {
+      okButton = document.createElement("input");
+      okButton.type = "submit";
+      okButton.value = this.options.okText;
+      okButton.className = 'editor_ok_button';
+      this.form.appendChild(okButton);
+    }
+
+    if (this.options.cancelLink) {
+      cancelLink = document.createElement("a");
+      cancelLink.href = "#";
+      cancelLink.appendChild(document.createTextNode(this.options.cancelText));
+      cancelLink.onclick = this.onclickCancel.bind(this);
+      cancelLink.className = 'editor_cancel';      
+      this.form.appendChild(cancelLink);
+    }
+  },
+  hasHTMLLineBreaks: function(string) {
+    if (!this.options.handleLineBreaks) return false;
+    return string.match(/<br/i) || string.match(/<p>/i);
+  },
+  convertHTMLLineBreaks: function(string) {
+    return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
+  },
+  createEditField: function() {
+    var text;
+    if(this.options.loadTextURL) {
+      text = this.options.loadingText;
+    } else {
+      text = this.getText();
+    }
+
+    var obj = this;
+    
+    if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
+      this.options.textarea = false;
+      var textField = document.createElement("input");
+      textField.obj = this;
+      textField.type = "text";
+      textField.name = "value";
+      textField.value = text;
+      textField.style.backgroundColor = this.options.highlightcolor;
+      textField.className = 'editor_field';
+      var size = this.options.size || this.options.cols || 0;
+      if (size != 0) textField.size = size;
+      if (this.options.submitOnBlur)
+        textField.onblur = this.onSubmit.bind(this);
+      this.editField = textField;
+    } else {
+      this.options.textarea = true;
+      var textArea = document.createElement("textarea");
+      textArea.obj = this;
+      textArea.name = "value";
+      textArea.value = this.convertHTMLLineBreaks(text);
+      textArea.rows = this.options.rows;
+      textArea.cols = this.options.cols || 40;
+      textArea.className = 'editor_field';      
+      if (this.options.submitOnBlur)
+        textArea.onblur = this.onSubmit.bind(this);
+      this.editField = textArea;
+    }
+    
+    if(this.options.loadTextURL) {
+      this.loadExternalText();
+    }
+    this.form.appendChild(this.editField);
+  },
+  getText: function() {
+    return this.element.innerHTML;
+  },
+  loadExternalText: function() {
+    Element.addClassName(this.form, this.options.loadingClassName);
+    this.editField.disabled = true;
+    new Ajax.Request(
+      this.options.loadTextURL,
+      Object.extend({
+        asynchronous: true,
+        onComplete: this.onLoadedExternalText.bind(this)
+      }, this.options.ajaxOptions)
+    );
+  },
+  onLoadedExternalText: function(transport) {
+    Element.removeClassName(this.form, this.options.loadingClassName);
+    this.editField.disabled = false;
+    this.editField.value = transport.responseText.stripTags();
+  },
+  onclickCancel: function() {
+    this.onComplete();
+    this.leaveEditMode();
+    return false;
+  },
+  onFailure: function(transport) {
+    this.options.onFailure(transport);
+    if (this.oldInnerHTML) {
+      this.element.innerHTML = this.oldInnerHTML;
+      this.oldInnerHTML = null;
+    }
+    return false;
+  },
+  onSubmit: function() {
+    // onLoading resets these so we need to save them away for the Ajax call
+    var form = this.form;
+    var value = this.editField.value;
+    
+    // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
+    // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
+    // to be displayed indefinitely
+    this.onLoading();
+    
+    if (this.options.evalScripts) {
+      new Ajax.Request(
+        this.url, Object.extend({
+          parameters: this.options.callback(form, value),
+          onComplete: this.onComplete.bind(this),
+          onFailure: this.onFailure.bind(this),
+          asynchronous:true, 
+          evalScripts:true
+        }, this.options.ajaxOptions));
+    } else  {
+      new Ajax.Updater(
+        { success: this.element,
+          // don't update on failure (this could be an option)
+          failure: null }, 
+        this.url, Object.extend({
+          parameters: this.options.callback(form, value),
+          onComplete: this.onComplete.bind(this),
+          onFailure: this.onFailure.bind(this)
+        }, this.options.ajaxOptions));
+    }
+    // stop the event to avoid a page refresh in Safari
+    if (arguments.length > 1) {
+      Event.stop(arguments[0]);
+    }
+    return false;
+  },
+  onLoading: function() {
+    this.saving = true;
+    this.removeForm();
+    this.leaveHover();
+    this.showSaving();
+  },
+  showSaving: function() {
+    this.oldInnerHTML = this.element.innerHTML;
+    this.element.innerHTML = this.options.savingText;
+    Element.addClassName(this.element, this.options.savingClassName);
+    this.element.style.backgroundColor = this.originalBackground;
+    Element.show(this.element);
+  },
+  removeForm: function() {
+    if(this.form) {
+      if (this.form.parentNode) Element.remove(this.form);
+      this.form = null;
+    }
+  },
+  enterHover: function() {
+    if (this.saving) return;
+    this.element.style.backgroundColor = this.options.highlightcolor;
+    if (this.effect) {
+      this.effect.cancel();
+    }
+    Element.addClassName(this.element, this.options.hoverClassName)
+  },
+  leaveHover: function() {
+    if (this.options.backgroundColor) {
+      this.element.style.backgroundColor = this.oldBackground;
+    }
+    Element.removeClassName(this.element, this.options.hoverClassName)
+    if (this.saving) return;
+    this.effect = new Effect.Highlight(this.element, {
+      startcolor: this.options.highlightcolor,
+      endcolor: this.options.highlightendcolor,
+      restorecolor: this.originalBackground
+    });
+  },
+  leaveEditMode: function() {
+    Element.removeClassName(this.element, this.options.savingClassName);
+    this.removeForm();
+    this.leaveHover();
+    this.element.style.backgroundColor = this.originalBackground;
+    Element.show(this.element);
+    if (this.options.externalControl) {
+      Element.show(this.options.externalControl);
+    }
+    this.editing = false;
+    this.saving = false;
+    this.oldInnerHTML = null;
+    this.onLeaveEditMode();
+  },
+  onComplete: function(transport) {
+    this.leaveEditMode();
+    this.options.onComplete.bind(this)(transport, this.element);
+  },
+  onEnterEditMode: function() {},
+  onLeaveEditMode: function() {},
+  dispose: function() {
+    if (this.oldInnerHTML) {
+      this.element.innerHTML = this.oldInnerHTML;
+    }
+    this.leaveEditMode();
+    Event.stopObserving(this.element, 'click', this.onclickListener);
+    Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
+    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
+    if (this.options.externalControl) {
+      Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
+      Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
+      Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
+    }
+  }
+};
+
+Ajax.InPlaceCollectionEditor = Class.create();
+Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
+Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
+  createEditField: function() {
+    if (!this.cached_selectTag) {
+      var selectTag = document.createElement("select");
+      var collection = this.options.collection || [];
+      var optionTag;
+      collection.each(function(e,i) {
+        optionTag = document.createElement("option");
+        optionTag.value = (e instanceof Array) ? e[0] : e;
+        if(this.options.value==optionTag.value) optionTag.selected = true;
+        optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
+        selectTag.appendChild(optionTag);
+      }.bind(this));
+      this.cached_selectTag = selectTag;
+    }
+
+    this.editField = this.cached_selectTag;
+    if(this.options.loadTextURL) this.loadExternalText();
+    this.form.appendChild(this.editField);
+    this.options.callback = function(form, value) {
+      return "value=" + encodeURIComponent(value);
+    }
+  }
+});
+
+// Delayed observer, like Form.Element.Observer, 
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create();
+Form.Element.DelayedObserver.prototype = {
+  initialize: function(element, delay, callback) {
+    this.delay     = delay || 0.5;
+    this.element   = $(element);
+    this.callback  = callback;
+    this.timer     = null;
+    this.lastValue = $F(this.element); 
+    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+  },
+  delayedListener: function(event) {
+    if(this.lastValue == $F(this.element)) return;
+    if(this.timer) clearTimeout(this.timer);
+    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+    this.lastValue = $F(this.element);
+  },
+  onTimerEvent: function() {
+    this.timer = null;
+    this.callback(this.element, $F(this.element));
+  }
+};

Added: op-panel/branches/upstream/current/dhtml/js/dhtmltooltip.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/dhtmltooltip.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/dhtmltooltip.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,113 @@
+/***********************************************
+* Cool DHTML tooltip script- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
+* This notice MUST stay intact for legal use
+* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code
+***********************************************/
+
+var offsetxpoint=-60 //Customize x offset of tooltip
+var offsetypoint=20 //Customize y offset of tooltip
+var ie=document.all
+var ns6=document.getElementById && !document.all
+var enabletip=false
+if (ie||ns6)
+
+function ietruebody(){
+return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
+}
+
+
+function ExtraeNumero(name) {
+        var destino = "";
+        name = name.id;
+        for (var s = 0; s<name.length; s++) {
+                var c = name.charAt(s);
+                if (c<"0" || c>"9") {
+                } else {
+                        destino = destino+""+c;
+                }
+        }
+        return destino;
+}
+
+function ExtraeNombre(name) {
+        var destino = "";
+        name = name.id;
+        for (var s = 0; s<name.length; s++) {
+                var c = name.charAt(s);
+                if (c<"0" || c>"9") {
+                        destino = destino+""+c;
+                } 
+        }
+        return destino;
+}
+
+
+
+function ddrivetip(element, thecolor, thewidth){
+	if (ns6||ie){
+		if (typeof thewidth!="undefined") tipobj.style.width=thewidth+"px"
+		if (typeof thecolor!="undefined" && thecolor!="") tipobj.style.backgroundColor=thecolor
+
+		var nombre = ExtraeNombre(element);
+		var numero = ExtraeNumero(element);
+
+		if(nombre=="phone") {
+			var dato = info["phone"+numero];
+		}
+		if(nombre=="mwi") {
+			var dato = mwiinfo["mwi"+numero];
+		}
+
+		tipobj.innerHTML=dato;
+
+		if(dato == undefined) {
+			enabletip=false
+		} else {
+			enabletip=true
+		}
+
+
+		return false
+	}
+}
+
+function positiontip(e){
+if (enabletip){
+var curX=(ns6)?e.pageX : event.clientX+ietruebody().scrollLeft;
+var curY=(ns6)?e.pageY : event.clientY+ietruebody().scrollTop;
+//Find out how close the mouse is to the corner of the window
+var rightedge=ie&&!window.opera? ietruebody().clientWidth-event.clientX-offsetxpoint : window.innerWidth-e.clientX-offsetxpoint-20
+var bottomedge=ie&&!window.opera? ietruebody().clientHeight-event.clientY-offsetypoint : window.innerHeight-e.clientY-offsetypoint-20
+
+var leftedge=(offsetxpoint<0)? offsetxpoint*(-1) : -1000
+
+//if the horizontal distance isn't enough to accomodate the width of the context menu
+if (rightedge<tipobj.offsetWidth)
+//move the horizontal position of the menu to the left by it's width
+tipobj.style.left=ie? ietruebody().scrollLeft+event.clientX-tipobj.offsetWidth+"px" : window.pageXOffset+e.clientX-tipobj.offsetWidth+"px"
+else if (curX<leftedge)
+tipobj.style.left="5px"
+else
+//position the horizontal position of the menu where the mouse is positioned
+tipobj.style.left=curX+offsetxpoint+"px"
+
+//same concept with the vertical position
+if (bottomedge<tipobj.offsetHeight)
+tipobj.style.top=ie? ietruebody().scrollTop+event.clientY-tipobj.offsetHeight-offsetypoint+"px" : window.pageYOffset+e.clientY-tipobj.offsetHeight-offsetypoint+"px"
+else
+tipobj.style.top=curY+offsetypoint+"px"
+tipobj.style.visibility="visible"
+}
+}
+
+function hideddrivetip(){
+if (ns6||ie){
+enabletip=false
+tipobj.style.visibility="hidden"
+tipobj.style.left="-1000px"
+tipobj.style.backgroundColor=''
+tipobj.style.width=''
+}
+}
+
+document.onmousemove=positiontip

Added: op-panel/branches/upstream/current/dhtml/js/dragdrop.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/dragdrop.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/dragdrop.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,915 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi at oriontransfer.co.nz)
+// 
+// See scriptaculous.js for full license.
+
+/*--------------------------------------------------------------------------*/
+
+var Droppables = {
+  drops: [],
+
+  remove: function(element) {
+    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+  },
+
+  add: function(element) {
+    element = $(element);
+    var options = Object.extend({
+      greedy:     true,
+      hoverclass: null,
+      tree:       false
+    }, arguments[1] || {});
+
+    // cache containers
+    if(options.containment) {
+      options._containers = [];
+      var containment = options.containment;
+      if((typeof containment == 'object') && 
+        (containment.constructor == Array)) {
+        containment.each( function(c) { options._containers.push($(c)) });
+      } else {
+        options._containers.push($(containment));
+      }
+    }
+    
+    if(options.accept) options.accept = [options.accept].flatten();
+
+    Element.makePositioned(element); // fix IE
+    options.element = element;
+
+    this.drops.push(options);
+  },
+  
+  findDeepestChild: function(drops) {
+    deepest = drops[0];
+      
+    for (i = 1; i < drops.length; ++i)
+      if (Element.isParent(drops[i].element, deepest.element))
+        deepest = drops[i];
+    
+    return deepest;
+  },
+
+  isContained: function(element, drop) {
+    var containmentNode;
+    if(drop.tree) {
+      containmentNode = element.treeNode; 
+    } else {
+      containmentNode = element.parentNode;
+    }
+    return drop._containers.detect(function(c) { return containmentNode == c });
+  },
+  
+  isAffected: function(point, element, drop) {
+    return (
+      (drop.element!=element) &&
+      ((!drop._containers) ||
+        this.isContained(element, drop)) &&
+      ((!drop.accept) ||
+        (Element.classNames(element).detect( 
+          function(v) { return drop.accept.include(v) } ) )) &&
+      Position.within(drop.element, point[0], point[1]) );
+  },
+
+  deactivate: function(drop) {
+    if(drop.hoverclass)
+      Element.removeClassName(drop.element, drop.hoverclass);
+    this.last_active = null;
+  },
+
+  activate: function(drop) {
+    if(drop.hoverclass)
+      Element.addClassName(drop.element, drop.hoverclass);
+    this.last_active = drop;
+  },
+
+  show: function(point, element) {
+    if(!this.drops.length) return;
+    var affected = [];
+    
+    if(this.last_active) this.deactivate(this.last_active);
+    this.drops.each( function(drop) {
+      if(Droppables.isAffected(point, element, drop))
+        affected.push(drop);
+    });
+        
+    if(affected.length>0) {
+      drop = Droppables.findDeepestChild(affected);
+      Position.within(drop.element, point[0], point[1]);
+      if(drop.onHover)
+        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+      
+      Droppables.activate(drop);
+    }
+  },
+
+  fire: function(event, element) {
+    if(!this.last_active) return;
+    Position.prepare();
+
+    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+      if (this.last_active.onDrop) 
+        this.last_active.onDrop(element, this.last_active.element, event);
+  },
+
+  reset: function() {
+    if(this.last_active)
+      this.deactivate(this.last_active);
+  }
+}
+
+var Draggables = {
+  drags: [],
+  observers: [],
+  
+  register: function(draggable) {
+    if(this.drags.length == 0) {
+      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+      this.eventKeypress  = this.keyPress.bindAsEventListener(this);
+      
+      Event.observe(document, "mouseup", this.eventMouseUp);
+      Event.observe(document, "mousemove", this.eventMouseMove);
+      Event.observe(document, "keypress", this.eventKeypress);
+    }
+    this.drags.push(draggable);
+  },
+  
+  unregister: function(draggable) {
+    this.drags = this.drags.reject(function(d) { return d==draggable });
+    if(this.drags.length == 0) {
+      Event.stopObserving(document, "mouseup", this.eventMouseUp);
+      Event.stopObserving(document, "mousemove", this.eventMouseMove);
+      Event.stopObserving(document, "keypress", this.eventKeypress);
+    }
+  },
+  
+  activate: function(draggable) {
+    window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+    this.activeDraggable = draggable;
+  },
+  
+  deactivate: function() {
+    this.activeDraggable = null;
+  },
+  
+  updateDrag: function(event) {
+    if(!this.activeDraggable) return;
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    // Mozilla-based browsers fire successive mousemove events with
+    // the same coordinates, prevent needless redrawing (moz bug?)
+    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+    this._lastPointer = pointer;
+    this.activeDraggable.updateDrag(event, pointer);
+  },
+  
+  endDrag: function(event) {
+    if(!this.activeDraggable) return;
+    this._lastPointer = null;
+    this.activeDraggable.endDrag(event);
+    this.activeDraggable = null;
+  },
+  
+  keyPress: function(event) {
+    if(this.activeDraggable)
+      this.activeDraggable.keyPress(event);
+  },
+  
+  addObserver: function(observer) {
+    this.observers.push(observer);
+    this._cacheObserverCallbacks();
+  },
+  
+  removeObserver: function(element) {  // element instead of observer fixes mem leaks
+    this.observers = this.observers.reject( function(o) { return o.element==element });
+    this._cacheObserverCallbacks();
+  },
+  
+  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
+    if(this[eventName+'Count'] > 0)
+      this.observers.each( function(o) {
+        if(o[eventName]) o[eventName](eventName, draggable, event);
+      });
+  },
+  
+  _cacheObserverCallbacks: function() {
+    ['onStart','onEnd','onDrag'].each( function(eventName) {
+      Draggables[eventName+'Count'] = Draggables.observers.select(
+        function(o) { return o[eventName]; }
+      ).length;
+    });
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create();
+Draggable.prototype = {
+  initialize: function(element) {
+    var options = Object.extend({
+      handle: false,
+      starteffect: function(element) {
+        element._opacity = Element.getOpacity(element); 
+        new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); 
+      },
+      reverteffect: function(element, top_offset, left_offset) {
+        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur});
+      },
+      endeffect: function(element) {
+        var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0
+        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity}); 
+      },
+      zindex: 1000,
+      revert: false,
+      scroll: false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      snap: false   // false, or xy or [x,y] or function(x,y){ return [x,y] }
+    }, arguments[1] || {});
+
+    this.element = $(element);
+    
+    if(options.handle && (typeof options.handle == 'string')) {
+      var h = Element.childrenWithClassName(this.element, options.handle, true);
+      if(h.length>0) this.handle = h[0];
+    }
+    if(!this.handle) this.handle = $(options.handle);
+    if(!this.handle) this.handle = this.element;
+    
+    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML)
+      options.scroll = $(options.scroll);
+
+    Element.makePositioned(this.element); // fix IE    
+
+    this.delta    = this.currentDelta();
+    this.options  = options;
+    this.dragging = false;   
+
+    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+    Event.observe(this.handle, "mousedown", this.eventMouseDown);
+    
+    Draggables.register(this);
+  },
+  
+  destroy: function() {
+    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+    Draggables.unregister(this);
+  },
+  
+  currentDelta: function() {
+    return([
+      parseInt(Element.getStyle(this.element,'left') || '0'),
+      parseInt(Element.getStyle(this.element,'top') || '0')]);
+  },
+  
+  initDrag: function(event) {
+    if(Event.isLeftClick(event)) {    
+      // abort on form elements, fixes a Firefox issue
+      var src = Event.element(event);
+      if(src.tagName && (
+        src.tagName=='INPUT' ||
+        src.tagName=='SELECT' ||
+        src.tagName=='OPTION' ||
+        src.tagName=='BUTTON' ||
+        src.tagName=='TEXTAREA')) return;
+        
+      if(this.element._revert) {
+        this.element._revert.cancel();
+        this.element._revert = null;
+      }
+      
+      var pointer = [Event.pointerX(event), Event.pointerY(event)];
+      var pos     = Position.cumulativeOffset(this.element);
+      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+      
+      Draggables.activate(this);
+      Event.stop(event);
+    }
+  },
+  
+  startDrag: function(event) {
+    this.dragging = true;
+    
+    if(this.options.zindex) {
+      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+      this.element.style.zIndex = this.options.zindex;
+    }
+    
+    if(this.options.ghosting) {
+      this._clone = this.element.cloneNode(true);
+      Position.absolutize(this.element);
+      this.element.parentNode.insertBefore(this._clone, this.element);
+    }
+    
+    if(this.options.scroll) {
+      if (this.options.scroll == window) {
+        var where = this._getWindowScroll(this.options.scroll);
+        this.originalScrollLeft = where.left;
+        this.originalScrollTop = where.top;
+      } else {
+        this.originalScrollLeft = this.options.scroll.scrollLeft;
+        this.originalScrollTop = this.options.scroll.scrollTop;
+      }
+    }
+    
+    Draggables.notify('onStart', this, event);
+    if(this.options.starteffect) this.options.starteffect(this.element);
+  },
+  
+  updateDrag: function(event, pointer) {
+    if(!this.dragging) this.startDrag(event);
+    Position.prepare();
+    Droppables.show(pointer, this.element);
+    Draggables.notify('onDrag', this, event);
+    this.draw(pointer);
+    if(this.options.change) this.options.change(this);
+    
+    if(this.options.scroll) {
+      this.stopScrolling();
+      
+      var p;
+      if (this.options.scroll == window) {
+        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+      } else {
+        p = Position.page(this.options.scroll);
+        p[0] += this.options.scroll.scrollLeft;
+        p[1] += this.options.scroll.scrollTop;
+        p.push(p[0]+this.options.scroll.offsetWidth);
+        p.push(p[1]+this.options.scroll.offsetHeight);
+      }
+      var speed = [0,0];
+      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+      this.startScrolling(speed);
+    }
+    
+    // fix AppleWebKit rendering
+    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+    
+    Event.stop(event);
+  },
+  
+  finishDrag: function(event, success) {
+    this.dragging = false;
+
+    if(this.options.ghosting) {
+      Position.relativize(this.element);
+      Element.remove(this._clone);
+      this._clone = null;
+    }
+
+    if(success) Droppables.fire(event, this.element);
+    Draggables.notify('onEnd', this, event);
+
+    var revert = this.options.revert;
+    if(revert && typeof revert == 'function') revert = revert(this.element);
+    
+    var d = this.currentDelta();
+    if(revert && this.options.reverteffect) {
+      this.options.reverteffect(this.element, 
+        d[1]-this.delta[1], d[0]-this.delta[0]);
+    } else {
+      this.delta = d;
+    }
+
+    if(this.options.zindex)
+      this.element.style.zIndex = this.originalZ;
+
+    if(this.options.endeffect) 
+      this.options.endeffect(this.element);
+
+    Draggables.deactivate(this);
+    Droppables.reset();
+  },
+  
+  keyPress: function(event) {
+    if(event.keyCode!=Event.KEY_ESC) return;
+    this.finishDrag(event, false);
+    Event.stop(event);
+  },
+  
+  endDrag: function(event) {
+    if(!this.dragging) return;
+    this.stopScrolling();
+    this.finishDrag(event, true);
+    Event.stop(event);
+  },
+  
+  draw: function(point) {
+    var pos = Position.cumulativeOffset(this.element);
+    var d = this.currentDelta();
+    pos[0] -= d[0]; pos[1] -= d[1];
+    
+    if(this.options.scroll && (this.options.scroll != window)) {
+      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+    }
+    
+    var p = [0,1].map(function(i){ 
+      return (point[i]-pos[i]-this.offset[i]) 
+    }.bind(this));
+    
+    if(this.options.snap) {
+      if(typeof this.options.snap == 'function') {
+        p = this.options.snap(p[0],p[1],this);
+      } else {
+      if(this.options.snap instanceof Array) {
+        p = p.map( function(v, i) {
+          return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
+      } else {
+        p = p.map( function(v) {
+          return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
+      }
+    }}
+    
+    var style = this.element.style;
+    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+      style.left = p[0] + "px";
+    if((!this.options.constraint) || (this.options.constraint=='vertical'))
+      style.top  = p[1] + "px";
+    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+  },
+  
+  stopScrolling: function() {
+    if(this.scrollInterval) {
+      clearInterval(this.scrollInterval);
+      this.scrollInterval = null;
+      Draggables._lastScrollPointer = null;
+    }
+  },
+  
+  startScrolling: function(speed) {
+    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+    this.lastScrolled = new Date();
+    this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+  },
+  
+  scroll: function() {
+    var current = new Date();
+    var delta = current - this.lastScrolled;
+    this.lastScrolled = current;
+    if(this.options.scroll == window) {
+      with (this._getWindowScroll(this.options.scroll)) {
+        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+          var d = delta / 1000;
+          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+        }
+      }
+    } else {
+      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000;
+    }
+    
+    Position.prepare();
+    Droppables.show(Draggables._lastPointer, this.element);
+    Draggables.notify('onDrag', this);
+    Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+    Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+    Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+    if (Draggables._lastScrollPointer[0] < 0)
+      Draggables._lastScrollPointer[0] = 0;
+    if (Draggables._lastScrollPointer[1] < 0)
+      Draggables._lastScrollPointer[1] = 0;
+    this.draw(Draggables._lastScrollPointer);
+    
+    if(this.options.change) this.options.change(this);
+  },
+  
+  _getWindowScroll: function(w) {
+    var T, L, W, H;
+    with (w.document) {
+      if (w.document.documentElement && documentElement.scrollTop) {
+        T = documentElement.scrollTop;
+        L = documentElement.scrollLeft;
+      } else if (w.document.body) {
+        T = body.scrollTop;
+        L = body.scrollLeft;
+      }
+      if (w.innerWidth) {
+        W = w.innerWidth;
+        H = w.innerHeight;
+      } else if (w.document.documentElement && documentElement.clientWidth) {
+        W = documentElement.clientWidth;
+        H = documentElement.clientHeight;
+      } else {
+        W = body.offsetWidth;
+        H = body.offsetHeight
+      }
+    }
+    return { top: T, left: L, width: W, height: H };
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create();
+SortableObserver.prototype = {
+  initialize: function(element, observer) {
+    this.element   = $(element);
+    this.observer  = observer;
+    this.lastValue = Sortable.serialize(this.element);
+  },
+  
+  onStart: function() {
+    this.lastValue = Sortable.serialize(this.element);
+  },
+  
+  onEnd: function() {
+    Sortable.unmark();
+    if(this.lastValue != Sortable.serialize(this.element))
+      this.observer(this.element)
+  }
+}
+
+var Sortable = {
+  sortables: {},
+  
+  _findRootElement: function(element) {
+    while (element.tagName != "BODY") {  
+      if(element.id && Sortable.sortables[element.id]) return element;
+      element = element.parentNode;
+    }
+  },
+
+  options: function(element) {
+    element = Sortable._findRootElement($(element));
+    if(!element) return;
+    return Sortable.sortables[element.id];
+  },
+  
+  destroy: function(element){
+    var s = Sortable.options(element);
+    
+    if(s) {
+      Draggables.removeObserver(s.element);
+      s.droppables.each(function(d){ Droppables.remove(d) });
+      s.draggables.invoke('destroy');
+      
+      delete Sortable.sortables[s.element.id];
+    }
+  },
+
+  create: function(element) {
+    element = $(element);
+    var options = Object.extend({ 
+      element:     element,
+      tag:         'li',       // assumes li children, override with tag: 'tagname'
+      dropOnEmpty: false,
+      tree:        false,
+      treeTag:     'ul',
+      overlap:     'vertical', // one of 'vertical', 'horizontal'
+      constraint:  'vertical', // one of 'vertical', 'horizontal', false
+      containment: element,    // also takes array of elements (or id's); or false
+      handle:      false,      // or a CSS class
+      only:        false,
+      hoverclass:  null,
+      ghosting:    false,
+      scroll:      false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      format:      /^[^_]*_(.*)$/,
+      onChange:    Prototype.emptyFunction,
+      onUpdate:    Prototype.emptyFunction
+    }, arguments[1] || {});
+
+    // clear any old sortable with same element
+    this.destroy(element);
+
+    // build options for the draggables
+    var options_for_draggable = {
+      revert:      true,
+      scroll:      options.scroll,
+      scrollSpeed: options.scrollSpeed,
+      scrollSensitivity: options.scrollSensitivity,
+      ghosting:    options.ghosting,
+      constraint:  options.constraint,
+      handle:      options.handle };
+
+    if(options.starteffect)
+      options_for_draggable.starteffect = options.starteffect;
+
+    if(options.reverteffect)
+      options_for_draggable.reverteffect = options.reverteffect;
+    else
+      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+        element.style.top  = 0;
+        element.style.left = 0;
+      };
+
+    if(options.endeffect)
+      options_for_draggable.endeffect = options.endeffect;
+
+    if(options.zindex)
+      options_for_draggable.zindex = options.zindex;
+
+    // build options for the droppables  
+    var options_for_droppable = {
+      overlap:     options.overlap,
+      containment: options.containment,
+      tree:        options.tree,
+      hoverclass:  options.hoverclass,
+      onHover:     Sortable.onHover
+      //greedy:      !options.dropOnEmpty
+    }
+    
+    var options_for_tree = {
+      onHover:      Sortable.onEmptyHover,
+      overlap:      options.overlap,
+      containment:  options.containment,
+      hoverclass:   options.hoverclass
+    }
+
+    // fix for gecko engine
+    Element.cleanWhitespace(element); 
+
+    options.draggables = [];
+    options.droppables = [];
+
+    // drop on empty handling
+    if(options.dropOnEmpty || options.tree) {
+      Droppables.add(element, options_for_tree);
+      options.droppables.push(element);
+    }
+
+    (this.findElements(element, options) || []).each( function(e) {
+      // handles are per-draggable
+      var handle = options.handle ? 
+        Element.childrenWithClassName(e, options.handle)[0] : e;    
+      options.draggables.push(
+        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+      Droppables.add(e, options_for_droppable);
+      if(options.tree) e.treeNode = element;
+      options.droppables.push(e);      
+    });
+    
+    if(options.tree) {
+      (Sortable.findTreeElements(element, options) || []).each( function(e) {
+        Droppables.add(e, options_for_tree);
+        e.treeNode = element;
+        options.droppables.push(e);
+      });
+    }
+
+    // keep reference
+    this.sortables[element.id] = options;
+
+    // for onupdate
+    Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+  },
+
+  // return all suitable-for-sortable elements in a guaranteed order
+  findElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.tag);
+  },
+  
+  findTreeElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.treeTag);
+  },
+
+  onHover: function(element, dropon, overlap) {
+    if(Element.isParent(dropon, element)) return;
+
+    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+      return;
+    } else if(overlap>0.5) {
+      Sortable.mark(dropon, 'before');
+      if(dropon.previousSibling != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, dropon);
+        if(dropon.parentNode!=oldParentNode) 
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    } else {
+      Sortable.mark(dropon, 'after');
+      var nextElement = dropon.nextSibling || null;
+      if(nextElement != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, nextElement);
+        if(dropon.parentNode!=oldParentNode) 
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    }
+  },
+  
+  onEmptyHover: function(element, dropon, overlap) {
+    var oldParentNode = element.parentNode;
+    var droponOptions = Sortable.options(dropon);
+        
+    if(!Element.isParent(dropon, element)) {
+      var index;
+      
+      var children = Sortable.findElements(dropon, {tag: droponOptions.tag});
+      var child = null;
+            
+      if(children) {
+        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+        
+        for (index = 0; index < children.length; index += 1) {
+          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+            offset -= Element.offsetSize (children[index], droponOptions.overlap);
+          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+            child = index + 1 < children.length ? children[index + 1] : null;
+            break;
+          } else {
+            child = children[index];
+            break;
+          }
+        }
+      }
+      
+      dropon.insertBefore(element, child);
+      
+      Sortable.options(oldParentNode).onChange(element);
+      droponOptions.onChange(element);
+    }
+  },
+
+  unmark: function() {
+    if(Sortable._marker) Element.hide(Sortable._marker);
+  },
+
+  mark: function(dropon, position) {
+    // mark on ghosting only
+    var sortable = Sortable.options(dropon.parentNode);
+    if(sortable && !sortable.ghosting) return; 
+
+    if(!Sortable._marker) {
+      Sortable._marker = $('dropmarker') || document.createElement('DIV');
+      Element.hide(Sortable._marker);
+      Element.addClassName(Sortable._marker, 'dropmarker');
+      Sortable._marker.style.position = 'absolute';
+      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+    }    
+    var offsets = Position.cumulativeOffset(dropon);
+    Sortable._marker.style.left = offsets[0] + 'px';
+    Sortable._marker.style.top = offsets[1] + 'px';
+    
+    if(position=='after')
+      if(sortable.overlap == 'horizontal') 
+        Sortable._marker.style.left = (offsets[0]+dropon.clientWidth) + 'px';
+      else
+        Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px';
+    
+    Element.show(Sortable._marker);
+  },
+  
+  _tree: function(element, options, parent) {
+    var children = Sortable.findElements(element, options) || [];
+  
+    for (var i = 0; i < children.length; ++i) {
+      var match = children[i].id.match(options.format);
+
+      if (!match) continue;
+      
+      var child = {
+        id: encodeURIComponent(match ? match[1] : null),
+        element: element,
+        parent: parent,
+        children: new Array,
+        position: parent.children.length,
+        container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase())
+      }
+      
+      /* Get the element containing the children and recurse over it */
+      if (child.container)
+        this._tree(child.container, options, child)
+      
+      parent.children.push (child);
+    }
+
+    return parent; 
+  },
+
+  /* Finds the first element of the given tag type within a parent element.
+    Used for finding the first LI[ST] within a L[IST]I[TEM].*/
+  _findChildrenElement: function (element, containerTag) {
+    if (element && element.hasChildNodes)
+      for (var i = 0; i < element.childNodes.length; ++i)
+        if (element.childNodes[i].tagName == containerTag)
+          return element.childNodes[i];
+  
+    return null;
+  },
+
+  tree: function(element) {
+    element = $(element);
+    var sortableOptions = this.options(element);
+    var options = Object.extend({
+      tag: sortableOptions.tag,
+      treeTag: sortableOptions.treeTag,
+      only: sortableOptions.only,
+      name: element.id,
+      format: sortableOptions.format
+    }, arguments[1] || {});
+    
+    var root = {
+      id: null,
+      parent: null,
+      children: new Array,
+      container: element,
+      position: 0
+    }
+    
+    return Sortable._tree (element, options, root);
+  },
+
+  /* Construct a [i] index for a particular node */
+  _constructIndex: function(node) {
+    var index = '';
+    do {
+      if (node.id) index = '[' + node.position + ']' + index;
+    } while ((node = node.parent) != null);
+    return index;
+  },
+
+  sequence: function(element) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[1] || {});
+    
+    return $(this.findElements(element, options) || []).map( function(item) {
+      return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+    });
+  },
+
+  setSequence: function(element, new_sequence) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[2] || {});
+    
+    var nodeMap = {};
+    this.findElements(element, options).each( function(n) {
+        if (n.id.match(options.format))
+            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+        n.parentNode.removeChild(n);
+    });
+   
+    new_sequence.each(function(ident) {
+      var n = nodeMap[ident];
+      if (n) {
+        n[1].appendChild(n[0]);
+        delete nodeMap[ident];
+      }
+    });
+  },
+  
+  serialize: function(element) {
+    element = $(element);
+    var options = Object.extend(Sortable.options(element), arguments[1] || {});
+    var name = encodeURIComponent(
+      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+    
+    if (options.tree) {
+      return Sortable.tree(element, arguments[1]).children.map( function (item) {
+        return [name + Sortable._constructIndex(item) + "=" + 
+                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+      }).flatten().join('&');
+    } else {
+      return Sortable.sequence(element, arguments[1]).map( function(item) {
+        return name + "[]=" + encodeURIComponent(item);
+      }).join('&');
+    }
+  }
+}
+
+/* Returns true if child is contained within element */
+Element.isParent = function(child, element) {
+  if (!child.parentNode || child == element) return false;
+
+  if (child.parentNode == element) return true;
+
+  return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {    
+  if(!element.hasChildNodes()) return null;
+  tagName = tagName.toUpperCase();
+  if(only) only = [only].flatten();
+  var elements = [];
+  $A(element.childNodes).each( function(e) {
+    if(e.tagName && e.tagName.toUpperCase()==tagName &&
+      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+        elements.push(e);
+    if(recursive) {
+      var grandchildren = Element.findChildren(e, only, recursive, tagName);
+      if(grandchildren) elements.push(grandchildren);
+    }
+  });
+
+  return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+  if (type == 'vertical' || type == 'height')
+    return element.offsetHeight;
+  else
+    return element.offsetWidth;
+}
\ No newline at end of file

Added: op-panel/branches/upstream/current/dhtml/js/effects.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/effects.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/effects.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,958 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+//  Justin Palmer (http://encytemedia.com/)
+//  Mark Pilgrim (http://diveintomark.org/)
+//  Martin Bialasinki
+// 
+// See scriptaculous.js for full license.  
+
+// converts rgb() and #xxx to #xxxxxx format,  
+// returns self (or first argument) if not convertable  
+String.prototype.parseColor = function() {  
+  var color = '#';  
+  if(this.slice(0,4) == 'rgb(') {  
+    var cols = this.slice(4,this.length-1).split(',');  
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
+  } else {  
+    if(this.slice(0,1) == '#') {  
+      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
+      if(this.length==7) color = this.toLowerCase();  
+    }  
+  }  
+  return(color.length==7 ? color : (arguments[0] || this));  
+}
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+  }).flatten().join('');
+}
+
+Element.collectTextNodesIgnoreClass = function(element, className) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
+        Element.collectTextNodesIgnoreClass(node, className) : ''));
+  }).flatten().join('');
+}
+
+Element.setContentZoom = function(element, percent) {
+  element = $(element);  
+  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
+  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+}
+
+Element.getOpacity = function(element){  
+  var opacity;
+  if (opacity = Element.getStyle(element, 'opacity'))  
+    return parseFloat(opacity);  
+  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
+    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
+  return 1.0;  
+}
+
+Element.setOpacity = function(element, value){  
+  element= $(element);  
+  if (value == 1){
+    Element.setStyle(element, { opacity: 
+      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
+      0.999999 : null });
+    if(/MSIE/.test(navigator.userAgent))  
+      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
+  } else {  
+    if(value < 0.00001) value = 0;  
+    Element.setStyle(element, {opacity: value});
+    if(/MSIE/.test(navigator.userAgent))  
+     Element.setStyle(element, 
+       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
+                 'alpha(opacity='+value*100+')' });  
+  }
+}  
+ 
+Element.getInlineOpacity = function(element){  
+  return $(element).style.opacity || '';
+}  
+
+Element.childrenWithClassName = function(element, className, findFirst) {
+  var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)");
+  var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { 
+    return (c.className && c.className.match(classNameRegExp));
+  });
+  if(!results) results = [];
+  return results;
+}
+
+Element.forceRerendering = function(element) {
+  try {
+    element = $(element);
+    var n = document.createTextNode(' ');
+    element.appendChild(n);
+    element.removeChild(n);
+  } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Array.prototype.call = function() {
+  var args = arguments;
+  this.each(function(f){ f.apply(this, args) });
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+  tagifyText: function(element) {
+    var tagifyStyle = 'position:relative';
+    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
+    element = $(element);
+    $A(element.childNodes).each( function(child) {
+      if(child.nodeType==3) {
+        child.nodeValue.toArray().each( function(character) {
+          element.insertBefore(
+            Builder.node('span',{style: tagifyStyle},
+              character == ' ' ? String.fromCharCode(160) : character), 
+              child);
+        });
+        Element.remove(child);
+      }
+    });
+  },
+  multiple: function(element, effect) {
+    var elements;
+    if(((typeof element == 'object') || 
+        (typeof element == 'function')) && 
+       (element.length))
+      elements = element;
+    else
+      elements = $(element).childNodes;
+      
+    var options = Object.extend({
+      speed: 0.1,
+      delay: 0.0
+    }, arguments[2] || {});
+    var masterDelay = options.delay;
+
+    $A(elements).each( function(element, index) {
+      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+    });
+  },
+  PAIRS: {
+    'slide':  ['SlideDown','SlideUp'],
+    'blind':  ['BlindDown','BlindUp'],
+    'appear': ['Appear','Fade']
+  },
+  toggle: function(element, effect) {
+    element = $(element);
+    effect = (effect || 'appear').toLowerCase();
+    var options = Object.extend({
+      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+    }, arguments[2] || {});
+    Effect[element.visible() ? 
+      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+  }
+};
+
+var Effect2 = Effect; // deprecated
+
+/* ------------- transitions ------------- */
+
+Effect.Transitions = {}
+
+Effect.Transitions.linear = function(pos) {
+  return pos;
+}
+Effect.Transitions.sinoidal = function(pos) {
+  return (-Math.cos(pos*Math.PI)/2) + 0.5;
+}
+Effect.Transitions.reverse  = function(pos) {
+  return 1-pos;
+}
+Effect.Transitions.flicker = function(pos) {
+  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+}
+Effect.Transitions.wobble = function(pos) {
+  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+}
+Effect.Transitions.pulse = function(pos) {
+  return (Math.floor(pos*10) % 2 == 0 ? 
+    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
+}
+Effect.Transitions.none = function(pos) {
+  return 0;
+}
+Effect.Transitions.full = function(pos) {
+  return 1;
+}
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create();
+Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
+  initialize: function() {
+    this.effects  = [];
+    this.interval = null;
+  },
+  _each: function(iterator) {
+    this.effects._each(iterator);
+  },
+  add: function(effect) {
+    var timestamp = new Date().getTime();
+    
+    var position = (typeof effect.options.queue == 'string') ? 
+      effect.options.queue : effect.options.queue.position;
+    
+    switch(position) {
+      case 'front':
+        // move unstarted effects after this effect  
+        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+            e.startOn  += effect.finishOn;
+            e.finishOn += effect.finishOn;
+          });
+        break;
+      case 'end':
+        // start effect after last queued effect has finished
+        timestamp = this.effects.pluck('finishOn').max() || timestamp;
+        break;
+    }
+    
+    effect.startOn  += timestamp;
+    effect.finishOn += timestamp;
+
+    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+      this.effects.push(effect);
+    
+    if(!this.interval) 
+      this.interval = setInterval(this.loop.bind(this), 40);
+  },
+  remove: function(effect) {
+    this.effects = this.effects.reject(function(e) { return e==effect });
+    if(this.effects.length == 0) {
+      clearInterval(this.interval);
+      this.interval = null;
+    }
+  },
+  loop: function() {
+    var timePos = new Date().getTime();
+    this.effects.invoke('loop', timePos);
+  }
+});
+
+Effect.Queues = {
+  instances: $H(),
+  get: function(queueName) {
+    if(typeof queueName != 'string') return queueName;
+    
+    if(!this.instances[queueName])
+      this.instances[queueName] = new Effect.ScopedQueue();
+      
+    return this.instances[queueName];
+  }
+}
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.DefaultOptions = {
+  transition: Effect.Transitions.sinoidal,
+  duration:   1.0,   // seconds
+  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
+  sync:       false, // true for combining
+  from:       0.0,
+  to:         1.0,
+  delay:      0.0,
+  queue:      'parallel'
+}
+
+Effect.Base = function() {};
+Effect.Base.prototype = {
+  position: null,
+  start: function(options) {
+    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
+    this.currentFrame = 0;
+    this.state        = 'idle';
+    this.startOn      = this.options.delay*1000;
+    this.finishOn     = this.startOn + (this.options.duration*1000);
+    this.event('beforeStart');
+    if(!this.options.sync)
+      Effect.Queues.get(typeof this.options.queue == 'string' ? 
+        'global' : this.options.queue.scope).add(this);
+  },
+  loop: function(timePos) {
+    if(timePos >= this.startOn) {
+      if(timePos >= this.finishOn) {
+        this.render(1.0);
+        this.cancel();
+        this.event('beforeFinish');
+        if(this.finish) this.finish(); 
+        this.event('afterFinish');
+        return;  
+      }
+      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
+      var frame = Math.round(pos * this.options.fps * this.options.duration);
+      if(frame > this.currentFrame) {
+        this.render(pos);
+        this.currentFrame = frame;
+      }
+    }
+  },
+  render: function(pos) {
+    if(this.state == 'idle') {
+      this.state = 'running';
+      this.event('beforeSetup');
+      if(this.setup) this.setup();
+      this.event('afterSetup');
+    }
+    if(this.state == 'running') {
+      if(this.options.transition) pos = this.options.transition(pos);
+      pos *= (this.options.to-this.options.from);
+      pos += this.options.from;
+      this.position = pos;
+      this.event('beforeUpdate');
+      if(this.update) this.update(pos);
+      this.event('afterUpdate');
+    }
+  },
+  cancel: function() {
+    if(!this.options.sync)
+      Effect.Queues.get(typeof this.options.queue == 'string' ? 
+        'global' : this.options.queue.scope).remove(this);
+    this.state = 'finished';
+  },
+  event: function(eventName) {
+    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+    if(this.options[eventName]) this.options[eventName](this);
+  },
+  inspect: function() {
+    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
+  }
+}
+
+Effect.Parallel = Class.create();
+Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
+  initialize: function(effects) {
+    this.effects = effects || [];
+    this.start(arguments[1]);
+  },
+  update: function(position) {
+    this.effects.invoke('render', position);
+  },
+  finish: function(position) {
+    this.effects.each( function(effect) {
+      effect.render(1.0);
+      effect.cancel();
+      effect.event('beforeFinish');
+      if(effect.finish) effect.finish(position);
+      effect.event('afterFinish');
+    });
+  }
+});
+
+Effect.Opacity = Class.create();
+Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    // make this work on IE on elements without 'layout'
+    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
+      this.element.setStyle({zoom: 1});
+    var options = Object.extend({
+      from: this.element.getOpacity() || 0.0,
+      to:   1.0
+    }, arguments[1] || {});
+    this.start(options);
+  },
+  update: function(position) {
+    this.element.setOpacity(position);
+  }
+});
+
+Effect.Move = Class.create();
+Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    var options = Object.extend({
+      x:    0,
+      y:    0,
+      mode: 'relative'
+    }, arguments[1] || {});
+    this.start(options);
+  },
+  setup: function() {
+    // Bug in Opera: Opera returns the "real" position of a static element or
+    // relative element that does not have top/left explicitly set.
+    // ==> Always set top and left for position relative elements in your stylesheets 
+    // (to 0 if you do not need them) 
+    this.element.makePositioned();
+    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
+    if(this.options.mode == 'absolute') {
+      // absolute movement, so we need to calc deltaX and deltaY
+      this.options.x = this.options.x - this.originalLeft;
+      this.options.y = this.options.y - this.originalTop;
+    }
+  },
+  update: function(position) {
+    this.element.setStyle({
+      left: this.options.x  * position + this.originalLeft + 'px',
+      top:  this.options.y  * position + this.originalTop  + 'px'
+    });
+  }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+  return new Effect.Move(element, 
+    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
+};
+
+Effect.Scale = Class.create();
+Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
+  initialize: function(element, percent) {
+    this.element = $(element)
+    var options = Object.extend({
+      scaleX: true,
+      scaleY: true,
+      scaleContent: true,
+      scaleFromCenter: false,
+      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
+      scaleFrom: 100.0,
+      scaleTo:   percent
+    }, arguments[2] || {});
+    this.start(options);
+  },
+  setup: function() {
+    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+    this.elementPositioning = this.element.getStyle('position');
+    
+    this.originalStyle = {};
+    ['top','left','width','height','fontSize'].each( function(k) {
+      this.originalStyle[k] = this.element.style[k];
+    }.bind(this));
+      
+    this.originalTop  = this.element.offsetTop;
+    this.originalLeft = this.element.offsetLeft;
+    
+    var fontSize = this.element.getStyle('font-size') || '100%';
+    ['em','px','%'].each( function(fontSizeType) {
+      if(fontSize.indexOf(fontSizeType)>0) {
+        this.fontSize     = parseFloat(fontSize);
+        this.fontSizeType = fontSizeType;
+      }
+    }.bind(this));
+    
+    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+    
+    this.dims = null;
+    if(this.options.scaleMode=='box')
+      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+    if(/^content/.test(this.options.scaleMode))
+      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+    if(!this.dims)
+      this.dims = [this.options.scaleMode.originalHeight,
+                   this.options.scaleMode.originalWidth];
+  },
+  update: function(position) {
+    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+    if(this.options.scaleContent && this.fontSize)
+      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+  },
+  finish: function(position) {
+    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+  },
+  setDimensions: function(height, width) {
+    var d = {};
+    if(this.options.scaleX) d.width = width + 'px';
+    if(this.options.scaleY) d.height = height + 'px';
+    if(this.options.scaleFromCenter) {
+      var topd  = (height - this.dims[0])/2;
+      var leftd = (width  - this.dims[1])/2;
+      if(this.elementPositioning == 'absolute') {
+        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
+        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+      } else {
+        if(this.options.scaleY) d.top = -topd + 'px';
+        if(this.options.scaleX) d.left = -leftd + 'px';
+      }
+    }
+    this.element.setStyle(d);
+  }
+});
+
+Effect.Highlight = Class.create();
+Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
+    this.start(options);
+  },
+  setup: function() {
+    // Prevent executing on elements not in the layout flow
+    if(this.element.getStyle('display')=='none') { this.cancel(); return; }
+    // Disable background image during the effect
+    this.oldStyle = {
+      backgroundImage: this.element.getStyle('background-image') };
+    this.element.setStyle({backgroundImage: 'none'});
+    if(!this.options.endcolor)
+      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+    if(!this.options.restorecolor)
+      this.options.restorecolor = this.element.getStyle('background-color');
+    // init color calculations
+    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+  },
+  update: function(position) {
+    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
+  },
+  finish: function() {
+    this.element.setStyle(Object.extend(this.oldStyle, {
+      backgroundColor: this.options.restorecolor
+    }));
+  }
+});
+
+Effect.ScrollTo = Class.create();
+Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    this.start(arguments[1] || {});
+  },
+  setup: function() {
+    Position.prepare();
+    var offsets = Position.cumulativeOffset(this.element);
+    if(this.options.offset) offsets[1] += this.options.offset;
+    var max = window.innerHeight ? 
+      window.height - window.innerHeight :
+      document.body.scrollHeight - 
+        (document.documentElement.clientHeight ? 
+          document.documentElement.clientHeight : document.body.clientHeight);
+    this.scrollStart = Position.deltaY;
+    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
+  },
+  update: function(position) {
+    Position.prepare();
+    window.scrollTo(Position.deltaX, 
+      this.scrollStart + (position*this.delta));
+  }
+});
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  var options = Object.extend({
+  from: element.getOpacity() || 1.0,
+  to:   0.0,
+  afterFinishInternal: function(effect) { 
+    if(effect.options.to!=0) return;
+    effect.element.hide();
+    effect.element.setStyle({opacity: oldOpacity}); 
+  }}, arguments[1] || {});
+  return new Effect.Opacity(element,options);
+}
+
+Effect.Appear = function(element) {
+  element = $(element);
+  var options = Object.extend({
+  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+  to:   1.0,
+  // force Safari to render floated elements properly
+  afterFinishInternal: function(effect) {
+    effect.element.forceRerendering();
+  },
+  beforeSetup: function(effect) {
+    effect.element.setOpacity(effect.options.from);
+    effect.element.show(); 
+  }}, arguments[1] || {});
+  return new Effect.Opacity(element,options);
+}
+
+Effect.Puff = function(element) {
+  element = $(element);
+  var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') };
+  return new Effect.Parallel(
+   [ new Effect.Scale(element, 200, 
+      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
+     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
+     Object.extend({ duration: 1.0, 
+      beforeSetupInternal: function(effect) {
+        effect.effects[0].element.setStyle({position: 'absolute'}); },
+      afterFinishInternal: function(effect) {
+         effect.effects[0].element.hide();
+         effect.effects[0].element.setStyle(oldStyle); }
+     }, arguments[1] || {})
+   );
+}
+
+Effect.BlindUp = function(element) {
+  element = $(element);
+  element.makeClipping();
+  return new Effect.Scale(element, 0, 
+    Object.extend({ scaleContent: false, 
+      scaleX: false, 
+      restoreAfterFinish: true,
+      afterFinishInternal: function(effect) {
+        effect.element.hide();
+        effect.element.undoClipping();
+      } 
+    }, arguments[1] || {})
+  );
+}
+
+Effect.BlindDown = function(element) {
+  element = $(element);
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, 
+    Object.extend({ scaleContent: false, 
+      scaleX: false,
+      scaleFrom: 0,
+      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+      restoreAfterFinish: true,
+      afterSetup: function(effect) {
+        effect.element.makeClipping();
+        effect.element.setStyle({height: '0px'});
+        effect.element.show(); 
+      },  
+      afterFinishInternal: function(effect) {
+        effect.element.undoClipping();
+      }
+    }, arguments[1] || {})
+  );
+}
+
+Effect.SwitchOff = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  return new Effect.Appear(element, { 
+    duration: 0.4,
+    from: 0,
+    transition: Effect.Transitions.flicker,
+    afterFinishInternal: function(effect) {
+      new Effect.Scale(effect.element, 1, { 
+        duration: 0.3, scaleFromCenter: true,
+        scaleX: false, scaleContent: false, restoreAfterFinish: true,
+        beforeSetup: function(effect) { 
+          effect.element.makePositioned();
+          effect.element.makeClipping();
+        },
+        afterFinishInternal: function(effect) {
+          effect.element.hide();
+          effect.element.undoClipping();
+          effect.element.undoPositioned();
+          effect.element.setStyle({opacity: oldOpacity});
+        }
+      })
+    }
+  });
+}
+
+Effect.DropOut = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left'),
+    opacity: element.getInlineOpacity() };
+  return new Effect.Parallel(
+    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
+      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+    Object.extend(
+      { duration: 0.5,
+        beforeSetup: function(effect) {
+          effect.effects[0].element.makePositioned(); 
+        },
+        afterFinishInternal: function(effect) {
+          effect.effects[0].element.hide();
+          effect.effects[0].element.undoPositioned();
+          effect.effects[0].element.setStyle(oldStyle);
+        } 
+      }, arguments[1] || {}));
+}
+
+Effect.Shake = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left') };
+    return new Effect.Move(element, 
+      { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+        effect.element.undoPositioned();
+        effect.element.setStyle(oldStyle);
+  }}) }}) }}) }}) }}) }});
+}
+
+Effect.SlideDown = function(element) {
+  element = $(element);
+  element.cleanWhitespace();
+  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, Object.extend({ 
+    scaleContent: false, 
+    scaleX: false, 
+    scaleFrom: window.opera ? 0 : 1,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makePositioned();
+      effect.element.firstChild.makePositioned();
+      if(window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping();
+      effect.element.setStyle({height: '0px'});
+      effect.element.show(); },
+    afterUpdateInternal: function(effect) {
+      effect.element.firstChild.setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.undoClipping(); 
+      // IE will crash if child is undoPositioned first
+      if(/MSIE/.test(navigator.userAgent)){
+        effect.element.undoPositioned();
+        effect.element.firstChild.undoPositioned();
+      }else{
+        effect.element.firstChild.undoPositioned();
+        effect.element.undoPositioned();
+      }
+      effect.element.firstChild.setStyle({bottom: oldInnerBottom}); }
+    }, arguments[1] || {})
+  );
+}
+  
+Effect.SlideUp = function(element) {
+  element = $(element);
+  element.cleanWhitespace();
+  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
+  return new Effect.Scale(element, window.opera ? 0 : 1,
+   Object.extend({ scaleContent: false, 
+    scaleX: false, 
+    scaleMode: 'box',
+    scaleFrom: 100,
+    restoreAfterFinish: true,
+    beforeStartInternal: function(effect) {
+      effect.element.makePositioned();
+      effect.element.firstChild.makePositioned();
+      if(window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping();
+      effect.element.show(); },  
+    afterUpdateInternal: function(effect) {
+      effect.element.firstChild.setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); },
+    afterFinishInternal: function(effect) {
+      effect.element.hide();
+      effect.element.undoClipping();
+      effect.element.firstChild.undoPositioned();
+      effect.element.undoPositioned();
+      effect.element.setStyle({bottom: oldInnerBottom}); }
+   }, arguments[1] || {})
+  );
+}
+
+// Bug in opera makes the TD containing this element expand for a instance after finish 
+Effect.Squish = function(element) {
+  return new Effect.Scale(element, window.opera ? 1 : 0, 
+    { restoreAfterFinish: true,
+      beforeSetup: function(effect) {
+        effect.element.makeClipping(effect.element); },  
+      afterFinishInternal: function(effect) {
+        effect.element.hide(effect.element); 
+        effect.element.undoClipping(effect.element); }
+  });
+}
+
+Effect.Grow = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.full
+  }, arguments[1] || {});
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();    
+  var initialMoveX, initialMoveY;
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      initialMoveX = initialMoveY = moveX = moveY = 0; 
+      break;
+    case 'top-right':
+      initialMoveX = dims.width;
+      initialMoveY = moveY = 0;
+      moveX = -dims.width;
+      break;
+    case 'bottom-left':
+      initialMoveX = moveX = 0;
+      initialMoveY = dims.height;
+      moveY = -dims.height;
+      break;
+    case 'bottom-right':
+      initialMoveX = dims.width;
+      initialMoveY = dims.height;
+      moveX = -dims.width;
+      moveY = -dims.height;
+      break;
+    case 'center':
+      initialMoveX = dims.width / 2;
+      initialMoveY = dims.height / 2;
+      moveX = -dims.width / 2;
+      moveY = -dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Move(element, {
+    x: initialMoveX,
+    y: initialMoveY,
+    duration: 0.01, 
+    beforeSetup: function(effect) {
+      effect.element.hide();
+      effect.element.makeClipping();
+      effect.element.makePositioned();
+    },
+    afterFinishInternal: function(effect) {
+      new Effect.Parallel(
+        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+          new Effect.Scale(effect.element, 100, {
+            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
+            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+        ], Object.extend({
+             beforeSetup: function(effect) {
+               effect.effects[0].element.setStyle({height: '0px'});
+               effect.effects[0].element.show(); 
+             },
+             afterFinishInternal: function(effect) {
+               effect.effects[0].element.undoClipping();
+               effect.effects[0].element.undoPositioned();
+               effect.effects[0].element.setStyle(oldStyle); 
+             }
+           }, options)
+      )
+    }
+  });
+}
+
+Effect.Shrink = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.none
+  }, arguments[1] || {});
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      moveX = moveY = 0;
+      break;
+    case 'top-right':
+      moveX = dims.width;
+      moveY = 0;
+      break;
+    case 'bottom-left':
+      moveX = 0;
+      moveY = dims.height;
+      break;
+    case 'bottom-right':
+      moveX = dims.width;
+      moveY = dims.height;
+      break;
+    case 'center':  
+      moveX = dims.width / 2;
+      moveY = dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Parallel(
+    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+    ], Object.extend({            
+         beforeStartInternal: function(effect) {
+           effect.effects[0].element.makePositioned();
+           effect.effects[0].element.makeClipping(); },
+         afterFinishInternal: function(effect) {
+           effect.effects[0].element.hide();
+           effect.effects[0].element.undoClipping();
+           effect.effects[0].element.undoPositioned();
+           effect.effects[0].element.setStyle(oldStyle); }
+       }, options)
+  );
+}
+
+Effect.Pulsate = function(element) {
+  element = $(element);
+  var options    = arguments[1] || {};
+  var oldOpacity = element.getInlineOpacity();
+  var transition = options.transition || Effect.Transitions.sinoidal;
+  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
+  reverser.bind(transition);
+  return new Effect.Opacity(element, 
+    Object.extend(Object.extend({  duration: 3.0, from: 0,
+      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+    }, options), {transition: reverser}));
+}
+
+Effect.Fold = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height };
+  Element.makeClipping(element);
+  return new Effect.Scale(element, 5, Object.extend({   
+    scaleContent: false,
+    scaleX: false,
+    afterFinishInternal: function(effect) {
+    new Effect.Scale(element, 1, { 
+      scaleContent: false, 
+      scaleY: false,
+      afterFinishInternal: function(effect) {
+        effect.element.hide();
+        effect.element.undoClipping(); 
+        effect.element.setStyle(oldStyle);
+      } });
+  }}, arguments[1] || {}));
+};
+
+['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
+ 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( 
+  function(f) { Element.Methods[f] = Element[f]; }
+);
+
+Element.Methods.visualEffect = function(element, effect, options) {
+  s = effect.gsub(/_/, '-').camelize();
+  effect_class = s.charAt(0).toUpperCase() + s.substring(1);
+  new Effect[effect_class](element, options);
+  return $(element);
+};
+
+Element.addMethods();
\ No newline at end of file

Added: op-panel/branches/upstream/current/dhtml/js/operator.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/operator.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/operator.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,221 @@
+info  = new Object();
+mwiinfo  = new Object();
+Event.observe(window, 'load', init, false);
+
+function operator_DoFSCommand(command, args) {
+	if(command == "newevent") {
+		newevent(args);
+	}
+}
+
+// Hook for Internet Explorer
+if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
+    document.write('<SCRIPT LANGUAGE=VBScript\> \n');
+    document.write('on error resume next \n');
+    document.write('Sub operator_FSCommand(ByVal command, ByVal args)\n');
+    document.write('  call operator_DoFSCommand(command, args)\n');
+    document.write('end sub\n');
+    document.write('</SCRIPT\> \n');
+}
+
+function toObject (texto) {
+    var pairs = texto.split('&');
+    return pairs.inject({}, function(params, pairString) {
+      var pair = pairString.split('=');
+      params[pair[0]] = pair[1];
+      return params;
+    });
+}
+
+var handlerFunc = function(t) {
+    var query = t.responseText;
+	var queryObj = toObject(query);
+	for (var i in queryObj)
+	{
+		if(i.indexOf("texto")==0) {
+			var numero = i.substr(5);
+			var label = document.getElementById("label"+numero);
+			var boton = document.getElementById("boton"+numero);
+			var texto = queryObj[i];
+			label.innerHTML=texto;
+			boton.style.display='block';
+		}
+		if(i.indexOf("icono")==0) {
+			var numero = i.substr(5);
+			var iconphone = document.getElementById("phone"+numero);
+			var texto = queryObj[i];
+			iconphone.className="phone"+texto;
+		}
+	}
+}
+
+var errFunc = function(t) {
+    alert('Error ' + t.status + ' -- ' + t.statusText);
+}
+
+function UpdateTimer() {
+
+   if(timerID) {
+      clearTimeout(timerID);
+   }
+
+   for(var i in tiempos ){
+	   var   tick = document.getElementById("tick"+i);
+   	   var   tDate = new Date();
+	   var   elapsedTime = tDate.getTime() - tiempos[i];
+
+       // hours
+       var hours = parseInt(elapsedTime/3600000);
+       var remaining = elapsedTime-(hours*3600000);
+       // minutes
+       var minutes = parseInt(remaining/60000);
+       remaining = remaining-(minutes*60000);
+       // seconds
+       var seconds = parseInt(remaining/1000);
+
+	   if (hours < 0)  { hours   = Math.abs(hours) }
+	   if (minutes < 0){ minutes = Math.abs(minutes) }
+	   if (seconds < 0){ seconds = Math.abs(seconds) }
+	   if (hours  <10) { hours   = "0"+hours;   }
+	   if (minutes<10) { minutes = "0"+minutes; }
+	   if (seconds<10) { seconds = "0"+seconds; }
+
+       var texto = "" + hours + ":" + minutes + ":" + seconds;
+       tick.innerHTML=texto;
+   }
+
+   timerID = setTimeout("UpdateTimer()", 1000);
+}
+
+function debug(texto)
+{
+    loglines.push(texto);
+    if (loglines.length>35) {
+		loglines.shift();
+    }   
+	var textofinal = ""; 
+	for(a=0;a<35;a++) {
+		textofinal = textofinal + loglines[a] + "<BR>";
+		
+	}       
+	win.getContent().innerHTML=textofinal;
+}
+
+function newevent(params) {
+	var partes = params.split("|");
+	docommand(partes[0],partes[1],partes[2]);
+}
+
+function replace(string,text,by) {
+// Replaces text with by in string
+    var strLength = string.length, txtLength = text.length;
+    if ((strLength == 0) || (txtLength == 0)) return string;
+
+    var i = string.indexOf(text);
+    if ((!i) && (text != string.substring(0,txtLength))) return string;
+    if (i == -1) return string;
+
+    var newstr = string.substring(0,i) + by;
+
+    if (i+txtLength < strLength)
+        newstr += replace(string.substring(i+txtLength,strLength),text,by);
+
+    return newstr;
+}
+
+
+function docommand(nro,comando,texto) { 
+
+	var boton = document.getElementById("boton"+nro);
+	var clid  = document.getElementById("clid"+nro);
+	var mwi   = document.getElementById("mwi"+nro);
+	var mcount= document.getElementById("mcount"+nro);
+
+	debug(nro+","+comando+"="+texto);
+
+	if(comando=="state") {
+		if(texto=="busy") {
+			boton.className="busy";
+		}
+		if(texto=="free") {
+			if(tipofree[nro] == undefined) {
+				tipofree[nro]="free";
+				boton.className="free";
+			} else {
+				boton.className=tipofree[nro];			
+			}
+		}
+	}
+
+	if(comando ==  "settext") {
+		clid.innerHTML=texto;
+	}
+
+	if(comando.match(/^info/)) {
+		var cola = comando.substring(4);
+        var textodecode = decodeBase64(texto);
+        var i = textodecode.indexOf("\n");
+		textodecode = replace(textodecode,'\n','<BR>');
+		info["phone"+nro]=textodecode;
+    }
+
+	if(comando == "settimer") {
+
+		var tick  = document.getElementById("tick"+nro);
+		var partes = texto.split("@");
+		var seconds = partes[0];
+		var type = partes[1];
+
+		var sDate = new Date();
+		if(type=="UP" || type =="IDLE") {
+			tiempos[nro] = sDate.getTime() - parseInt(seconds) * 1000;
+		}
+		if(type=="STOP") {
+			delete tiempos[nro];
+			tick.innerHTML="&nbsp;";
+		}
+	}
+
+	if(comando.indexOf("ocupado")>=0) {
+		boton.className="busy";
+		clid.innerHTML=texto;
+	}
+	if(comando == "corto") {
+		if(tipofree[nro] == undefined) {
+			tipofree[nro]="free";
+			boton.className="free";
+		} else {
+			boton.className=tipofree[nro];			
+		}
+		clid.innerHTML="&nbsp;";
+	}
+	if(comando=="ringing") {
+		boton.className="ringing";
+		clid.innerHTML=texto;
+		new Effect.Pulsate(boton);
+	}
+	if(comando=="noregistrado") {
+		boton.className="notregistered";
+		clid.innerHTML="";
+	}
+	if(comando.indexOf("changelabel1")>=0) {
+		if(texto=="original") {	
+			tipofree[nro]='free';
+		} else {
+			tipofree[nro]='agent';
+		}
+		boton.className=tipofree[nro];
+	}
+	if(comando == "voicemail") {
+		if(texto=="1") {
+			mwi.style.visibility='visible';
+		} else {
+			mwi.style.visibility='hidden';
+		}
+	}
+	if(comando == "voicemailcount") {
+		mwiinfo["mwi"+nro]=texto;
+	}
+
+}
+

Added: op-panel/branches/upstream/current/dhtml/js/prototype.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/prototype.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/prototype.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,2006 @@
+/*  Prototype JavaScript framework, version 1.5.0_rc0
+ *  (c) 2005 Sam Stephenson <sam at 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.5.0_rc0',
+  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 (var 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;
+      }
+    }
+  }
+}
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += (replacement(match) || '').toString();
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = count === undefined ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return this;
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = truncation === undefined ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : this;
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  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(function(script) { return eval(script) });
+  },
+
+  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(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (typeof replacement == 'function') return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+}
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern  = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    return this.template.gsub(this.pattern, function(match) {
+      var before = match[1];
+      if (before == '\\') return match[2];
+      return before + (object[match[3]] || '').toString();
+    });
+  }
+}
+
+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 (result == undefined || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value < result)
+        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) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  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);
+
+if (!Array.prototype._reverse)
+  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 && 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();
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  }
+});
+var Hash = {
+  _each: function(iterator) {
+    for (var 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 XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || 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,
+      contentType:  'application/x-www-form-urlencoded',
+      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,
+       'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
+
+    if (this.options.method == 'post') {
+      requestHeaders.push('Content-type', this.options.contentType);
+
+      /* 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);
+  }
+});
+function $() {
+  var results = [], element;
+  for (var i = 0; i < arguments.length; i++) {
+    element = arguments[i];
+    if (typeof element == 'string')
+      element = document.getElementById(element);
+    results.push(Element.extend(element));
+  }
+  return results.length < 2 ? results[0] : results;
+}
+
+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(Element.extend(child));
+    return elements;
+  });
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element)
+  var Element = new Object();
+
+Element.extend = function(element) {
+  if (!element) return;
+  if (_nativeExtensions) return element;
+
+  if (!element._extended && element.tagName && element != window) {
+    var methods = Element.Methods, cache = Element.extend.cache;
+    for (property in methods) {
+      var value = methods[property];
+      if (typeof value == 'function')
+        element[property] = cache.findOrStore(value);
+    }
+  }
+
+  element._extended = true;
+  return element;
+}
+
+Element.extend.cache = {
+  findOrStore: function(value) {
+    return this[value] = this[value] || function() {
+      return value.apply(null, [this].concat($A(arguments)));
+    }
+  }
+}
+
+Element.Methods = {
+  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);
+  },
+
+  replace: function(element, html) {
+    element = $(element);
+    if (element.outerHTML) {
+      element.outerHTML = html.stripScripts();
+    } else {
+      var range = element.ownerDocument.createRange();
+      range.selectNodeContents(element);
+      element.parentNode.replaceChild(
+        range.createContextualFragment(html.stripScripts()), element);
+    }
+    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*$/);
+  },
+
+  childOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+    return false;
+  },
+
+  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 (var 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;
+  }
+}
+
+Object.extend(Element, Element.Methods);
+
+var _nativeExtensions = false;
+
+if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+  var HTMLElement = {}
+  HTMLElement.prototype = document.createElement('div').__proto__;
+}
+
+Element.addMethods = function(methods) {
+  Object.extend(Element.Methods, methods || {});
+
+  if(typeof HTMLElement != 'undefined') {
+    var methods = Element.Methods, cache = Element.extend.cache;
+    for (property in methods) {
+      var value = methods[property];
+      if (typeof value == 'function')
+        HTMLElement.prototype[property] = cache.findOrStore(value);
+    }
+    _nativeExtensions = true;
+  }
+}
+
+Element.addMethods();
+
+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) {
+        var tagName = this.element.tagName.toLowerCase();
+        if (tagName == 'tbody' || tagName == 'tr') {
+          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 Selector = Class.create();
+Selector.prototype = {
+  initialize: function(expression) {
+    this.params = {classNames: []};
+    this.expression = expression.toString().strip();
+    this.parseExpression();
+    this.compileMatcher();
+  },
+
+  parseExpression: function() {
+    function abort(message) { throw 'Parse error in selector: ' + message; }
+
+    if (this.expression == '')  abort('empty expression');
+
+    var params = this.params, expr = this.expression, match, modifier, clause, rest;
+    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
+      params.attributes = params.attributes || [];
+      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
+      expr = match[1];
+    }
+
+    if (expr == '*') return this.params.wildcard = true;
+
+    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
+      modifier = match[1], clause = match[2], rest = match[3];
+      switch (modifier) {
+        case '#':       params.id = clause; break;
+        case '.':       params.classNames.push(clause); break;
+        case '':
+        case undefined: params.tagName = clause.toUpperCase(); break;
+        default:        abort(expr.inspect());
+      }
+      expr = rest;
+    }
+
+    if (expr.length > 0) abort(expr.inspect());
+  },
+
+  buildMatchExpression: function() {
+    var params = this.params, conditions = [], clause;
+
+    if (params.wildcard)
+      conditions.push('true');
+    if (clause = params.id)
+      conditions.push('element.id == ' + clause.inspect());
+    if (clause = params.tagName)
+      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
+    if ((clause = params.classNames).length > 0)
+      for (var i = 0; i < clause.length; i++)
+        conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
+    if (clause = params.attributes) {
+      clause.each(function(attribute) {
+        var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
+        var splitValueBy = function(delimiter) {
+          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
+        }
+
+        switch (attribute.operator) {
+          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
+          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
+          case '|=':      conditions.push(
+                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
+                          ); break;
+          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
+          case '':
+          case undefined: conditions.push(value + ' != null'); break;
+          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
+        }
+      });
+    }
+
+    return conditions.join(' && ');
+  },
+
+  compileMatcher: function() {
+    this.match = new Function('element', 'if (!element.tagName) return false; \
+      return ' + this.buildMatchExpression());
+  },
+
+  findElements: function(scope) {
+    var element;
+
+    if (element = $(this.params.id))
+      if (this.match(element))
+        if (!scope || Element.childOf(element, scope))
+          return [element];
+
+    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+
+    var results = [];
+    for (var i = 0; i < scope.length; i++)
+      if (this.match(element = scope[i]))
+        results.push(Element.extend(element));
+
+    return results;
+  },
+
+  toString: function() {
+    return this.expression;
+  }
+}
+
+function $$() {
+  return $A(arguments).map(function(expression) {
+    return expression.strip().split(/\s+/).inject([null], function(results, expr) {
+      var selector = new Selector(expr);
+      return results.map(selector.findElements.bind(selector)).flatten();
+    });
+  }).flatten();
+}
+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 (var 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 || opt.text;
+    }
+    return [element.name, value];
+  },
+
+  selectMany: function(element) {
+    var value = [];
+    for (var i = 0; i < element.length; i++) {
+      var opt = element.options[i];
+      if (opt.selected)
+        value.push(opt.value || opt.text);
+    }
+    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 */
+if (navigator.appVersion.match(/\bMSIE\b/))
+  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

Added: op-panel/branches/upstream/current/dhtml/js/scriptaculous.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/scriptaculous.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/scriptaculous.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,47 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var Scriptaculous = {
+  Version: '1.6.1',
+  require: function(libraryName) {
+    // inserting via DOM fails in Safari 2.0, so brute force approach
+    document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
+  },
+  load: function() {
+    if((typeof Prototype=='undefined') || 
+       (typeof Element == 'undefined') || 
+       (typeof Element.Methods=='undefined') ||
+       parseFloat(Prototype.Version.split(".")[0] + "." +
+                  Prototype.Version.split(".")[1]) < 1.5)
+       throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");
+    
+    $A(document.getElementsByTagName("script")).findAll( function(s) {
+      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+    }).each( function(s) {
+      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+      var includes = s.src.match(/\?.*load=([a-z,]*)/);
+      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
+       function(include) { Scriptaculous.require(path+include+'.js') });
+    });
+  }
+}
+
+Scriptaculous.load();
\ No newline at end of file

Added: op-panel/branches/upstream/current/dhtml/js/slider.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/slider.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/slider.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,283 @@
+// Copyright (c) 2005 Marty Haught, Thomas Fuchs 
+//
+// See http://script.aculo.us for more info
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if(!Control) var Control = {};
+Control.Slider = Class.create();
+
+// options:
+//  axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+//  onChange(value)
+//  onSlide(value)
+Control.Slider.prototype = {
+  initialize: function(handle, track, options) {
+    var slider = this;
+    
+    if(handle instanceof Array) {
+      this.handles = handle.collect( function(e) { return $(e) });
+    } else {
+      this.handles = [$(handle)];
+    }
+    
+    this.track   = $(track);
+    this.options = options || {};
+
+    this.axis      = this.options.axis || 'horizontal';
+    this.increment = this.options.increment || 1;
+    this.step      = parseInt(this.options.step || '1');
+    this.range     = this.options.range || $R(0,1);
+    
+    this.value     = 0; // assure backwards compat
+    this.values    = this.handles.map( function() { return 0 });
+    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+    this.options.startSpan = $(this.options.startSpan || null);
+    this.options.endSpan   = $(this.options.endSpan || null);
+
+    this.restricted = this.options.restricted || false;
+
+    this.maximum   = this.options.maximum || this.range.end;
+    this.minimum   = this.options.minimum || this.range.start;
+
+    // Will be used to align the handle onto the track, if necessary
+    this.alignX = parseInt(this.options.alignX || '0');
+    this.alignY = parseInt(this.options.alignY || '0');
+    
+    this.trackLength = this.maximumOffset() - this.minimumOffset();
+    this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth;
+
+    this.active   = false;
+    this.dragging = false;
+    this.disabled = false;
+
+    if(this.options.disabled) this.setDisabled();
+
+    // Allowed values array
+    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+    if(this.allowedValues) {
+      this.minimum = this.allowedValues.min();
+      this.maximum = this.allowedValues.max();
+    }
+
+    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+    this.eventMouseMove = this.update.bindAsEventListener(this);
+
+    // Initialize handles in reverse (make sure first handle is active)
+    this.handles.each( function(h,i) {
+      i = slider.handles.length-1-i;
+      slider.setValue(parseFloat(
+        (slider.options.sliderValue instanceof Array ? 
+          slider.options.sliderValue[i] : slider.options.sliderValue) || 
+         slider.range.start), i);
+      Element.makePositioned(h); // fix IE
+      Event.observe(h, "mousedown", slider.eventMouseDown);
+    });
+    
+    Event.observe(this.track, "mousedown", this.eventMouseDown);
+    Event.observe(document, "mouseup", this.eventMouseUp);
+    Event.observe(document, "mousemove", this.eventMouseMove);
+    
+    this.initialized = true;
+  },
+  dispose: function() {
+    var slider = this;    
+    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+    Event.stopObserving(document, "mouseup", this.eventMouseUp);
+    Event.stopObserving(document, "mousemove", this.eventMouseMove);
+    this.handles.each( function(h) {
+      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+    });
+  },
+  setDisabled: function(){
+    this.disabled = true;
+  },
+  setEnabled: function(){
+    this.disabled = false;
+  },  
+  getNearestValue: function(value){
+    if(this.allowedValues){
+      if(value >= this.allowedValues.max()) return(this.allowedValues.max());
+      if(value <= this.allowedValues.min()) return(this.allowedValues.min());
+      
+      var offset = Math.abs(this.allowedValues[0] - value);
+      var newValue = this.allowedValues[0];
+      this.allowedValues.each( function(v) {
+        var currentOffset = Math.abs(v - value);
+        if(currentOffset <= offset){
+          newValue = v;
+          offset = currentOffset;
+        } 
+      });
+      return newValue;
+    }
+    if(value > this.range.end) return this.range.end;
+    if(value < this.range.start) return this.range.start;
+    return value;
+  },
+  setValue: function(sliderValue, handleIdx){
+    if(!this.active) {
+      this.activeHandle    = this.handles[handleIdx];
+      this.activeHandleIdx = handleIdx;
+      this.updateStyles();
+    }
+    handleIdx = handleIdx || this.activeHandleIdx || 0;
+    if(this.initialized && this.restricted) {
+      if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+        sliderValue = this.values[handleIdx-1];
+      if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+        sliderValue = this.values[handleIdx+1];
+    }
+    sliderValue = this.getNearestValue(sliderValue);
+    this.values[handleIdx] = sliderValue;
+    this.value = this.values[0]; // assure backwards compat
+    
+    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
+      this.translateToPx(sliderValue);
+    
+    this.drawSpans();
+    if(!this.dragging || !this.event) this.updateFinished();
+  },
+  setValueBy: function(delta, handleIdx) {
+    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
+      handleIdx || this.activeHandleIdx || 0);
+  },
+  translateToPx: function(value) {
+    return Math.round(
+      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
+      (value - this.range.start)) + "px";
+  },
+  translateToValue: function(offset) {
+    return ((offset/(this.trackLength-this.handleLength) * 
+      (this.range.end-this.range.start)) + this.range.start);
+  },
+  getRange: function(range) {
+    var v = this.values.sortBy(Prototype.K); 
+    range = range || 0;
+    return $R(v[range],v[range+1]);
+  },
+  minimumOffset: function(){
+    return(this.isVertical() ? this.alignY : this.alignX);
+  },
+  maximumOffset: function(){
+    return(this.isVertical() ?
+      this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX);
+  },  
+  isVertical:  function(){
+    return (this.axis == 'vertical');
+  },
+  drawSpans: function() {
+    var slider = this;
+    if(this.spans)
+      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+    if(this.options.startSpan)
+      this.setSpan(this.options.startSpan,
+        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+    if(this.options.endSpan)
+      this.setSpan(this.options.endSpan, 
+        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+  },
+  setSpan: function(span, range) {
+    if(this.isVertical()) {
+      span.style.top = this.translateToPx(range.start);
+      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+    } else {
+      span.style.left = this.translateToPx(range.start);
+      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+    }
+  },
+  updateStyles: function() {
+    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+    Element.addClassName(this.activeHandle, 'selected');
+  },
+  startDrag: function(event) {
+    if(Event.isLeftClick(event)) {
+      if(!this.disabled){
+        this.active = true;
+        
+        var handle = Event.element(event);
+        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
+        if(handle==this.track) {
+          var offsets  = Position.cumulativeOffset(this.track); 
+          this.event = event;
+          this.setValue(this.translateToValue( 
+           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+          ));
+          var offsets  = Position.cumulativeOffset(this.activeHandle);
+          this.offsetX = (pointer[0] - offsets[0]);
+          this.offsetY = (pointer[1] - offsets[1]);
+        } else {
+          // find the handle (prevents issues with Safari)
+          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
+            handle = handle.parentNode;
+        
+          this.activeHandle    = handle;
+          this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+          this.updateStyles();
+        
+          var offsets  = Position.cumulativeOffset(this.activeHandle);
+          this.offsetX = (pointer[0] - offsets[0]);
+          this.offsetY = (pointer[1] - offsets[1]);
+        }
+      }
+      Event.stop(event);
+    }
+  },
+  update: function(event) {
+   if(this.active) {
+      if(!this.dragging) this.dragging = true;
+      this.draw(event);
+      // fix AppleWebKit rendering
+      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+      Event.stop(event);
+   }
+  },
+  draw: function(event) {
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    var offsets = Position.cumulativeOffset(this.track);
+    pointer[0] -= this.offsetX + offsets[0];
+    pointer[1] -= this.offsetY + offsets[1];
+    this.event = event;
+    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+    if(this.initialized && this.options.onSlide)
+      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+  },
+  endDrag: function(event) {
+    if(this.active && this.dragging) {
+      this.finishDrag(event, true);
+      Event.stop(event);
+    }
+    this.active = false;
+    this.dragging = false;
+  },  
+  finishDrag: function(event, success) {
+    this.active = false;
+    this.dragging = false;
+    this.updateFinished();
+  },
+  updateFinished: function() {
+    if(this.initialized && this.options.onChange) 
+      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+    this.event = null;
+  }
+}
\ No newline at end of file

Added: op-panel/branches/upstream/current/dhtml/js/window.js
===================================================================
--- op-panel/branches/upstream/current/dhtml/js/window.js	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/js/window.js	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,860 @@
+// Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// VERSION 0.70
+
+var Window = Class.create();
+Window.prototype = {
+	// Constructor
+	// Available parameters : className, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, resizable, zIndex, opacity, 
+	//                        hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, relativeTo, draggable, closable, parent
+	initialize: function(id, parameters) {
+		this.hasEffectLib = String.prototype.parseColor != null
+		this.minWidth = parameters.minWidth || 100;
+		this.minHeight = parameters.minHeight || 100;
+		this.maxWidth = parameters.maxWidth;
+		this.maxHeight = parameters.maxHeight;
+		this.showEffect = parameters.showEffect || (this.hasEffectLib ? Effect.Appear : Element.show)
+		this.hideEffect = parameters.hideEffect || (this.hasEffectLib ? Effect.Fade : Element.hide)
+		
+		this.showEffectOptions = parameters.showEffectOptions || parameters.effectOptions;
+		this.hideEffectOptions = parameters.hideEffectOptions || parameters.effectOptions;
+		this.draggable = parameters.draggable != null ? parameters.draggable : true;
+		
+		var resizable = parameters.resizable != null ? parameters.resizable : true;
+		var closable = parameters.closable != null ? parameters.closable : true;
+		var className = parameters.className != null ? parameters.className : "dialog";
+		this.className = className;
+		
+		var parent = parameters.parent || document.getElementsByTagName("body").item(0);
+			
+		this.element = this.createWindow(id, className, parent, resizable, closable, parameters.title, parameters.url);
+		this.isIFrame = parameters.url != null;
+		
+		// Bind event listener
+    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+  	this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+  	this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+  	this.eventKeyPress = this.keyPress.bindAsEventListener(this);
+
+		this.topbar = $(this.element.id + "_top");
+		this.bottombar = $(this.element.id + "_bottom");
+		
+		if (this.draggable)  {
+  		Event.observe(this.topbar, "mousedown", this.eventMouseDown);
+  		Event.observe(this.bottombar, "mousedown", this.eventMouseDown);
+			Element.addClassName(this.bottombar, "bottom_draggable")
+			Element.addClassName(this.topbar, "top_draggable")
+    }		
+    
+		var offset = [0,0];
+		if (resizable) {
+			this.sizer = $(this.element.id + "_sizer");
+    	Event.observe(this.sizer, "mousedown", this.eventMouseDown);
+    }	
+		var width = parseFloat(parameters.width) || 200;
+		var height = parseFloat(parameters.height) || 200;
+
+		if (parameters.left != null) {
+			Element.setStyle(this.element,{left: parseFloat(parameters.left) + offset[0] + 'px'});
+			this.useLeft = true;
+		}
+
+		if (parameters.right != null) {
+			Element.setStyle(this.element,{right: parseFloat(parameters.right) + 'px'});
+			this.useLeft = false;
+		}
+
+		if (parameters.top != null) {
+			Element.setStyle(this.element,{top: parseFloat(parameters.top) + 'px'});
+			this.useTop = true;
+		}
+
+		if (parameters.bottom != null) {
+			Element.setStyle(this.element,{bottom: parseFloat(parameters.bottom) + 'px'});			
+			this.useTop = false;
+		}
+
+		this.setSize(width, height);
+
+		if (parameters.opacity)
+			this.setOpacity(parameters.opacity);
+		if (parameters.zIndex)
+			this.setZIndex(parameters.zIndex)
+
+		this.destroyOnClose = false;
+
+    this._getWindowBorderSize()
+		Windows.register(this);	    
+  },
+  
+  _getWindowBorderSize: function() {
+    // Hack to get real window border size!!
+    var div = this._createHiddenDiv(this.className + "_n")
+		this.heightN = Element.getDimensions(div).height;		
+		div.parentNode.removeChild(div)
+
+    var div = this._createHiddenDiv(this.className + "_s")
+		this.heightS = Element.getDimensions(div).height;		
+		div.parentNode.removeChild(div)
+
+    var div = this._createHiddenDiv(this.className + "_e")
+		this.widthE = Element.getDimensions(div).width;		
+		div.parentNode.removeChild(div)
+
+    var div = this._createHiddenDiv(this.className + "_w")
+		this.widthW = Element.getDimensions(div).width;
+		div.parentNode.removeChild(div)
+  },
+ 
+  _createHiddenDiv: function(className) {
+    var objBody = document.getElementsByTagName("body").item(0);
+    var win = document.createElement("div");
+		win.setAttribute('id', this.element.id+ "_tmp");
+		win.className = className;
+		win.style.display = 'none'
+		win.innerHTML = ''
+		objBody.insertBefore(win, objBody.firstChild)   
+		return win
+  },
+  
+	// Destructor
+ 	destroy: function() {
+		Windows.notify("onDestroy", this);
+  	Event.stopObserving(this.topbar, "mousedown", this.eventMouseDown);
+  	Event.stopObserving(this.bottombar, "mousedown", this.eventMouseDown);
+		if (this.sizer)
+    		Event.stopObserving(this.sizer, "mousedown", this.eventMouseDown);
+
+		var objBody = document.getElementsByTagName("body").item(0);
+		objBody.removeChild(this.element);
+
+		Windows.unregister(this);	    
+	},
+  	
+	// Sets window deleagte, should have functions: "canClose(window)" 
+	setDelegate: function(delegate) {
+		this.delegate = delegate
+	},
+	
+	// Gets current window delegate
+	getDelegate: function() {
+		return this.delegate;
+	},
+	
+	// Gets window content
+	getContent: function () {
+		return $(this.element.id + "_content");
+	},
+	
+	// Sets the content with an element id
+	setContent: function(id, autoresize, autoposition) {
+		var d = null;
+		var p = null;
+
+		if (autoresize) 
+			d = Element.getDimensions(id);
+		if (autoposition) 
+			p = Position.cumulativeOffset($(id));
+
+		var content = this.getContent()
+		content.appendChild($(id));
+		
+		if (autoresize) 
+			this.setSize(d.width, d.height);
+		if (autoposition) 
+		  this.setLocation(p[1] - this.heightN, p[0] - this.widthW);	  
+	},
+	
+	setCookie: function(name, expires, path, domain, secure) {
+		name = name || this.element.id;
+		this.cookie = [name, expires, path, domain, secure];
+		
+		// Get cookie
+		var value = WindowUtilities.getCookie(name)
+		// If exists
+		if (value) {
+			var values = value.split(',')
+			var x = values[0].split(':')
+			var y = values[1].split(':')
+
+			this.setSize(parseFloat(values[2]), parseFloat(values[3]));
+
+			Element.setStyle(this.element, x[0] == "l" ? {left: x[1]} : {right: x[1]});
+			Element.setStyle(this.element, y[0] == "t" ? {top: y[1]} : {bottom: y[1]});
+		}
+	},
+	
+	// Gets window ID
+	getId: function() {
+		return this.element.id;
+	},
+	
+	// Detroys itself when closing 
+	setDestroyOnClose: function() {
+		this.destroyOnClose = true;
+	},
+	
+	// initDrag event
+	initDrag: function(event) {
+		// Get pointer X,Y
+  	this.pointer = [Event.pointerX(event), Event.pointerY(event)];
+		this.doResize = false;
+		
+		// Check if click on close button, 
+		var closeButton = $(this.getId() + '_close');
+		if (closeButton && Position.within(closeButton, this.pointer[0], this.pointer[1])) {
+			return;
+		}
+		// Check if click on sizer
+		if (this.sizer && Position.within(this.sizer, this.pointer[0], this.pointer[1])) {
+			this.doResize = true;
+    	this.widthOrg = this.width;
+    	this.heightOrg = this.height;
+    	this.bottomOrg = parseFloat(Element.getStyle(this.element, 'bottom'));
+    	this.rightOrg = parseFloat(Element.getStyle(this.element, 'right'));
+			Windows.notify("onStartResize", this);
+		}
+		else 
+			Windows.notify("onStartMove", this);
+		
+		// Register global event to capture mouseUp and mouseMove
+		Event.observe(document, "mouseup", this.eventMouseUp);
+  	Event.observe(document, "mousemove", this.eventMouseMove);
+		
+		// Add an invisible div to keep catching mouse event over the iframe
+		if (this.isIFrame) {
+			var objBody = document.getElementsByTagName("body").item(0);
+			var div = document.createElement("div");
+			div.style.position = "absolute";
+			div.style.top = this.heightN + "px";
+			div.style.bottom = this.widthW + "px";
+			div.style.zIndex = Windows.maxZIndex;			
+			div.style.width = this.width + "px";
+			div.style.height = this.height + "px";
+			this.element.appendChild(div);
+			this.tmpDiv = div;			
+		}
+		this.toFront();
+      	Event.stop(event);
+  	},
+
+    // updateDrag event
+  	updateDrag: function(event) {
+	   	var pointer = [Event.pointerX(event), Event.pointerY(event)];    
+  		var dx = pointer[0] - this.pointer[0];
+  		var dy = pointer[1] - this.pointer[1];
+  		
+  		// Resize case, update width/height
+  		if (this.doResize) {
+  			var width = this.widthOrg
+  			var height = this.heightOrg;
+  			width += dx;
+  			height += dy;
+  			
+  			this.setSize(width, height);
+  			
+        dx = this.width - this.widthOrg
+        dy = this.height - this.heightOrg
+  			
+			  // Check if it's a right position, update it to keep upper-left corner at the same position
+  			if (! this.useLeft) 
+  				Element.setStyle(this.element,{right: (this.rightOrg -dx) + 'px'});
+  			// Check if it's a bottom position, update it to keep upper-left corner at the same position
+  			if (! this.useTop) 
+  				Element.setStyle(this.element,{bottom: (this.bottomOrg -dy) + 'px'});
+  		}
+  		// Move case, update top/left
+  		else {
+  		  this.pointer = pointer;
+    		
+  			if (this.useLeft) {
+    			var left = Element.getStyle(this.element, 'left');
+  				left = parseFloat(left) + dx;
+  				Element.setStyle(this.element,{left: left + 'px'});
+  			}	else {
+  				var right = Element.getStyle(this.element, 'right');
+  				right = parseFloat(right) - dx;
+  				Element.setStyle(this.element,{right: right + 'px'});
+  			}
+			
+  			if (this.useTop) {
+    			var top = Element.getStyle(this.element, 'top');
+  				top = parseFloat(top) + dy;
+  				Element.setStyle(this.element,{top: top + 'px'});
+  			} else {
+  				var bottom = Element.getStyle(this.element, 'bottom');
+  				bottom = parseFloat(bottom) - dy;
+  				Element.setStyle(this.element,{bottom: bottom + 'px'});
+  			}
+  		}
+  		if (this.iefix) 
+  			this._fixIEOverlapping(); 
+      Event.stop(event);
+  	},
+
+	 // endDrag callback
+ 	endDrag: function(event) {
+		if (this.doResize)
+			Windows.notify("onEndResize", this);
+		else
+			Windows.notify("onEndMove", this);
+		
+		// Release event observing
+		Event.stopObserving(document, "mouseup", this.eventMouseUp);
+    Event.stopObserving(document, "mousemove", this.eventMouseMove);
+
+		// Remove temporary div
+		if (this.isIFrame) {
+			this.tmpDiv.parentNode.removeChild(this.tmpDiv);
+			this.tmpDiv = null;
+		}
+		// Store new location/size
+		if (this.cookie) {
+			var value = "";
+			if (this.useLeft)
+				value += "l:" + Element.getStyle(this.element.id, 'left')
+			else
+				value += "r:" + Element.getStyle(this.element.id, 'right')
+			if (this.useTop)
+				value += ",t:" + Element.getStyle(this.element.id, 'top')
+			else
+				value += ",b:" + Element.getStyle(this.element.id, 'bottom')
+			value += "," + this.width;
+			value += "," + this.height;
+			WindowUtilities.setCookie(value, this.cookie)
+		}
+    Event.stop(event);
+  },
+
+	keyPress: function(event) {
+		//Dialog.cancelCallback();
+	},
+	
+	// Creates HTML window code
+	createWindow: function(id, className, parent, resizable, closable, title, url) {
+		win = document.createElement("div");
+		win.setAttribute('id', id);
+		win.className = "dialog";
+	 	if (!title)
+			title = "&nbsp;";
+
+		var content;
+		if (url)
+			content= "<IFRAME id=\"" + id + "_content\" SRC=\"" + url + "\" > </IFRAME>";
+		else
+			content ="<DIV id=\"" + id + "_content\" class=\"" +className + "_content\"> </DIV>";
+
+		win.innerHTML = "\
+		<div class='"+ className +"_close' id='"+ id +"_close' onclick='Windows.close(\""+ id +"\")'> </div>\
+		<table id='"+ id +"_header'>\
+			<tr id='"+ id +"_row1'>\
+				<td>\
+					<table>\
+						<tr>\
+							<td id='"+ id +"_nw' class='"+ className +"_nw'><div class='"+ className +"_nw'> </td>\
+							<td class='"+ className +"_n'  valign='middle'><div  id='"+ id +"_top' class='"+ className +"_title'>"+ title +"</div></td>\
+							<td class='"+ className +"_ne'> <div class='"+ className +"_ne'></td>\
+						</tr>\
+					</table>\
+				</td>\
+			</tr>\
+			<tr id='"+ id +"_row2'>\
+				<td>\
+					<table>\
+						<tr>\
+							<td class='"+ className +"_w'><div class='"+ className +"_w'> </div></td>\
+							<td class='"+ className +"_content'>"+ content +"</td>\
+							<td class='"+ className +"_e'><div class='"+ className +"_e'> </div></td>\
+						</tr>\
+					</table>\
+				</td>\
+			</tr>\
+			<tr id='"+ id +"_row3'>\
+				<td>\
+					<table>\
+						<tr>\
+							<td class='"+ className +"_sw' id='"+ id +"_sw'><div class='"+ className +"_sw'> </td>\
+							<td class='"+ className +"_s'><div  id='"+ id +"_bottom' class='"+ className +"_s'> </div></td>\
+							<td class='"+ className +"_se'>"+ (resizable  ? "<div id='"+ id + "_sizer' class='"+ className +"_sizer'></div>" : "<div class='"+ className +"_se'></div>") +"</td>\
+						</tr>\
+					</table>\
+				</td>\
+			</tr>\
+		</table>\
+		";
+		Element.hide(win);
+		parent.insertBefore(win, parent.firstChild);
+		
+		if (!closable)
+		  Element.hide(id +"_close")
+    
+		return win;
+	},
+	
+	// Sets window location
+	setLocation: function(top, left) {
+		Element.setStyle(this.element,{top: top + 'px'});
+		Element.setStyle(this.element,{left: left + 'px'});
+	},
+		
+	// Sets window size
+	setSize: function(width, height) {    
+		// Check min and max size
+		if (width < this.minWidth)
+			width = this.minWidth;
+
+		if (height < this.minHeight)
+			height = this.minHeight;
+			
+		if (this.maxHeight && height > this.maxHeight)
+			height = this.maxHeight;
+
+		if (this.maxWidth && width > this.maxWidth)
+			width = this.maxWidth;
+
+		this.width = width;
+		this.height = height;
+		
+		Element.setStyle(this.element,{width: width + 'px'});
+		Element.setStyle(this.element,{height: height + 'px'});
+
+		// Update content height
+		var content = $(this.element.id + '_content')
+		Element.setStyle(content,{height: height  + 'px'});
+		Element.setStyle(content,{width: width  + 'px'});
+	},
+	
+	// Brings window to front
+	toFront: function() {
+		windows = document.getElementsByClassName("dialog");
+		var maxIndex= 0;
+		for (var i = 0; i<windows.length; i++){
+			if (maxIndex < parseFloat(windows[i].style.zIndex))
+				maxIndex = windows[i].style.zIndex;
+		}
+		this.element.style.zIndex = parseFloat(maxIndex) +1;
+	},
+	
+	// Displays window modal state or not
+	show: function(modal) {
+		if (modal) {
+			WindowUtilities.disableScreen(this.className);
+			this.modal = true;			
+			this.setZIndex(Windows.maxZIndex + 20);
+			Windows.unsetOverflow(this);
+			Event.observe(document, "keypress", this.eventKeyPress);	      	
+		}
+			
+		this.setSize(this.width, this.height);
+		if (this.showEffectOptions )
+			this.showEffect(this.element, this.showEffectOptions);	
+		else
+			this.showEffect(this.element);	
+		this._checkIEOverlapping();
+	},
+	
+	// Displays window modal state or not at the center of the page
+	showCenter: function(modal) {
+		this.setSize(this.width, this.height);
+		this.center();
+		
+		this.show(modal);
+	},
+	
+	center: function() {
+		var arrayPageSize = WindowUtilities.getPageSize();
+		var arrayPageScroll = WindowUtilities.getPageScroll();
+
+		this.element.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - this.height) / 2) + 'px');
+		this.element.style.left = (((arrayPageSize[0] - this.width) / 2) + 'px');	
+	},
+	
+	// Hides window
+	hide: function() {
+		if (this.modal) {
+			WindowUtilities.enableScreen();
+			Windows.resetOverflow();
+			Event.stopObserving(document, "keypress", this.eventKeyPress);
+			
+		}
+		// To avoid bug on scrolling bar
+		Element.setStyle(this.getContent(), {overflow: "hidden"});
+	
+		if (this.hideEffectOptions)
+			this.hideEffect(this.element, this.hideEffectOptions);	
+		else
+			this.hideEffect(this.element);	
+	 	if(this.iefix) 
+			Element.hide(this.iefix);
+		
+	},
+
+	_checkIEOverlapping: function() {
+    if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (navigator.userAgent.indexOf('Opera')<0) && (Element.getStyle(this.element, 'position')=='absolute')) {
+        new Insertion.After(this.element.id, '<iframe id="' + this.element.id + '_iefix" '+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+        this.iefix = $(this.element.id+'_iefix');
+    }
+    if(this.iefix) 
+			setTimeout(this._fixIEOverlapping.bind(this), 50);
+	},
+
+	_fixIEOverlapping: function() {
+	    Position.clone(this.element, this.iefix);
+	    this.iefix.style.zIndex = this.element.style.zIndex - 1;
+	    Element.show(this.iefix);
+	},
+
+	setOpacity: function(opacity) {
+		if (Element.setOpacity)
+			Element.setOpacity(this.element, opacity);
+	},
+	
+	setZIndex: function(zindex) {
+		Element.setStyle(this.element,{zIndex: zindex});
+		Windows.updateZindex(zindex, this);
+	}
+};
+
+// Windows containers, register all page windows
+var Windows = {
+  windows: [],
+  observers: [],
+
+  maxZIndex: 0,
+
+  addObserver: function(observer) {
+    this.observers.push(observer);
+  },
+  
+  removeObserver: function(observer) {  
+    this.observers = this.observers.reject( function(o) { return o==observer });
+  },
+  
+  notify: function(eventName, win) {  //  onStartResize(), onEndResize(), onStartMove(), onEndMove(), onClose(), onDestroy()
+    this.observers.each( function(o) {if(o[eventName]) o[eventName](eventName, win);});
+  },
+
+  // Gets window from its id
+  getWindow: function(id) {
+	  return this.windows.detect(function(d) { return d.getId() ==id });
+  },
+
+  // Registers a new window (called by Windows constructor)
+  register: function(win) {
+    this.windows.push(win);
+  },
+  
+  // Unregisters a window (called by Windows destructor)
+  unregister: function(win) {
+    this.windows = this.windows.reject(function(d) { return d==win });
+  }, 
+
+  // Closes a window with its id
+  close: function(id) {
+  	win = this.getWindow(id);
+  	// Asks delegate if exists
+  	if (win.getDelegate() && ! win.getDelegate().canClose(win)) 
+  		return;
+	
+      if (win) {
+  			this.notify("onClose", win);
+  			win.hide();
+    		if (win.destroyOnClose)  
+    			win.destroy();
+  	}
+  },
+
+  unsetOverflow: function(except) {		
+  	this.windows.each(function(d) { d.oldOverflow = Element.getStyle(d.getContent(), "overflow") || "auto" ; Element.setStyle(d.getContent(), {overflow: "hidden"}) });
+  	if (except && except.oldOverflow)
+  		Element.setStyle(except.getContent(), {overflow: except.oldOverflow});
+  },
+
+  resetOverflow: function() {
+	  this.windows.each(function(d) { if (d.oldOverflow) Element.setStyle(d.getContent(), {overflow: d.oldOverflow}) });
+  },
+
+  updateZindex: function(zindex, win) {
+  	if (zindex > this.maxZIndex)
+  		this.maxZIndex = zindex;
+    }
+};
+
+var Dialog = {
+ 	win: null,
+
+	confirm: function(message, parameters) {
+		var okLabel = parameters && parameters.okLabel ? parameters.okLabel : "Ok";
+		var cancelLabel = parameters && parameters.cancelLabel ? parameters.cancelLabel : "Cancel";
+		var windowParam = parameters  ? parameters.windowParameters : {};
+		windowParam.className = windowParam.className || "alert";
+
+		var content = "\
+			<div class='" + windowParam.className + "_message'>" + message  + "</div>\
+				<div class='" + windowParam.className + "_buttons'>\
+					<input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()'/>\
+					<input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()'/>\
+				</div>\
+		";
+		return this.openDialog(content, parameters)
+	},
+	
+	alert: function(message, parameters) {
+		var okLabel = parameters && parameters.okLabel ? parameters.okLabel : "Ok";
+
+		var windowParam = parameters ? parameters.windowParameters : {};
+		windowParam.className = windowParam.className || "alert";
+
+		var content = "\
+			<div class='" + windowParam.className + "_message'>" + message  + "</div>\
+				<div class='" + windowParam.className + "_buttons'>\
+					<input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()'/>\
+				</div>\
+		";
+		return this.openDialog(content, parameters)
+	},
+	
+	openDialog: function(content, parameters) {
+		// remove old dialog
+		if (this.win) 
+			this.win.destroy();
+
+		var windowParam = parameters ? parameters.windowParameters : {};
+		windowParam.resizable = windowParam.resizable || false;
+		windowParam.effectOptions = {duration: 1};
+
+		this.win = new Window('modal_dialog', windowParam);
+		this.win.getContent().innerHTML = content;
+		this.win.showCenter(true);	
+		
+		this.win.cancelCallback = parameters.cancel;
+		this.win.okCallback = parameters.ok;
+		
+		this.eventResize = this.recenter.bindAsEventListener(this);
+  	Event.observe(window, "resize", this.eventResize);
+  	Event.observe(window, "scroll", this.eventResize);
+
+		return this.win;		
+	},
+	
+	okCallback: function() {
+		this.win.hide();
+		Event.stopObserving(window, "resize", this.eventResize);
+		Event.stopObserving(window, "scroll", this.eventResize);
+      	
+		if (this.win.okCallback)
+			this.win.okCallback(this.win);
+	},
+
+	cancelCallback: function() {
+		this.win.hide();
+		Event.stopObserving(window, "resize", this.eventResize);
+		Event.stopObserving(window, "scroll", this.eventResize);
+		
+		if (this.win.cancelCallback)
+			this.win.cancelCallback(win);
+	},
+
+	recenter: function(event) {
+		var arrayPageSize = WindowUtilities.getPageSize();
+
+		// set height of Overlay to take up whole page and show
+		$('overlay_modal').style.height = (arrayPageSize[1] + 'px');
+		
+		this.win.center();
+	}
+}
+/*
+	Based on Lightbox JS: Fullsize Image Overlays 
+	by Lokesh Dhakar - http://www.huddletogether.com
+
+	For more information on this script, visit:
+	http://huddletogether.com/projects/lightbox/
+
+	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
+	(basically, do anything you want, just leave my name and link)
+*/
+
+var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";
+
+//
+// getPageScroll()
+// Returns array with x,y page scroll values.
+// Core code from - quirksmode.org
+//
+var WindowUtilities = {
+ 	getPageScroll :function() {
+		var yScroll;
+
+		if (self.pageYOffset) {
+			yScroll = self.pageYOffset;
+		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
+			yScroll = document.documentElement.scrollTop;
+		} else if (document.body) {// all other Explorers
+			yScroll = document.body.scrollTop;
+		}
+
+		arrayPageScroll = new Array('',yScroll) 
+		return arrayPageScroll;
+	},
+
+	// getPageSize()
+	// Returns array with page width, height and window width, height
+	// Core code from - quirksmode.org
+	// Edit for Firefox by pHaez
+	getPageSize: function(){
+		var xScroll, yScroll;
+	
+		if (window.innerHeight && window.scrollMaxY) {	
+			xScroll = document.body.scrollWidth;
+			yScroll = window.innerHeight + window.scrollMaxY;
+		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
+			xScroll = document.body.scrollWidth;
+			yScroll = document.body.scrollHeight;
+		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
+			xScroll = document.body.offsetWidth;
+			yScroll = document.body.offsetHeight;
+		}
+	
+		var windowWidth, windowHeight;
+		if (self.innerHeight) {	// all except Explorer
+			windowWidth = self.innerWidth;
+			windowHeight = self.innerHeight;
+		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
+			windowWidth = document.documentElement.clientWidth;
+			windowHeight = document.documentElement.clientHeight;
+		} else if (document.body) { // other Explorers
+			windowWidth = document.body.clientWidth;
+			windowHeight = document.body.clientHeight;
+		}	
+	
+		// for small pages with total height less then height of the viewport
+		if(yScroll < windowHeight){
+			pageHeight = windowHeight;
+		} else { 
+			pageHeight = yScroll;
+		}
+
+		// for small pages with total width less then width of the viewport
+		if(xScroll < windowWidth){	
+			pageWidth = windowWidth;
+		} else {
+			pageWidth = xScroll;
+		}
+
+		arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
+		return arrayPageSize;
+	},
+
+ 	disableScreen: function(className) {
+		WindowUtilities.initLightbox(className);
+		var objBody = document.getElementsByTagName("body").item(0);
+
+		// prep objects
+	 	var objOverlay = $('overlay_modal');
+
+		var arrayPageSize = WindowUtilities.getPageSize();
+
+		// Hide select boxes as they will 'peek' through the image in IE
+		if (isIE) {
+			selects = document.getElementsByTagName("select");
+		    for (var i = 0; i != selects.length; i++) {
+		    	selects[i].style.visibility = "hidden";
+		    }
+		}	
+	
+		// set height of Overlay to take up whole page and show
+		objOverlay.style.height = (arrayPageSize[1] + 'px');
+		objOverlay.style.display = 'block';	
+	},
+
+ 	enableScreen: function() {
+	 	var objOverlay = $('overlay_modal');
+		if (objOverlay) {
+			// hide lightbox and overlay
+			objOverlay.style.display = 'none';
+
+			// make select boxes visible
+			if (isIE) {
+				selects = document.getElementsByTagName("select");
+			    for (var i = 0; i != selects.length; i++) {
+					selects[i].style.visibility = "visible";
+				}
+			}
+			objOverlay.parentNode.removeChild(objOverlay);
+		}
+	},
+
+	// initLightbox()
+	// Function runs on window load, going through link tags looking for rel="lightbox".
+	// These links receive onclick events that enable the lightbox display for their targets.
+	// The function also inserts html markup at the top of the page which will be used as a
+	// container for the overlay pattern and the inline image.
+	initLightbox: function(className) {
+		// Already done, just update zIndex
+		if ($('overlay_modal')) {
+			Element.setStyle('overlay_modal', {zIndex: Windows.maxZIndex + 10});
+		}
+		// create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
+		else {
+			var objBody = document.getElementsByTagName("body").item(0);
+			var objOverlay = document.createElement("div");
+			objOverlay.setAttribute('id', 'overlay_modal');
+			objOverlay.className = "overlay_" + className
+			objOverlay.style.display = 'none';
+			objOverlay.style.position = 'absolute';
+			objOverlay.style.top = '0';
+			objOverlay.style.left = '0';
+			objOverlay.style.zIndex = Windows.maxZIndex + 10;
+		 	objOverlay.style.width = '100%';
+
+			objBody.insertBefore(objOverlay, objBody.firstChild);
+		}
+	},
+	
+	setCookie: function(value, parameters) {
+    document.cookie= parameters[0] + "=" + escape(value) +
+      ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") +
+      ((parameters[2]) ? "; path=" + parameters[2] : "") +
+      ((parameters[3]) ? "; domain=" + parameters[3] : "") +
+      ((parameters[4]) ? "; secure" : "");
+  },
+
+  getCookie: function(name) {
+    var dc = document.cookie;
+    var prefix = name + "=";
+    var begin = dc.indexOf("; " + prefix);
+    if (begin == -1) {
+      begin = dc.indexOf(prefix);
+      if (begin != 0) return null;
+    } else {
+      begin += 2;
+    }
+    var end = document.cookie.indexOf(";", begin);
+    if (end == -1) {
+      end = dc.length;
+    }
+    return unescape(dc.substring(begin + prefix.length, end));
+  }
+}
+
+

Added: op-panel/branches/upstream/current/dhtml/variables.php
===================================================================
--- op-panel/branches/upstream/current/dhtml/variables.php	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/dhtml/variables.php	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,29 @@
+<?
+header("Content-type: text/html; charset=utf-8");
+
+if(isset($_GET['context'])) {
+	$contexto=$_GET['context'];
+	$contexto=strtoupper($contexto);
+	$archivo = "variables$contexto.txt";
+} else {
+    $archivo="variables.txt";
+}
+
+$pepe = file_get_contents($archivo);
+$partes = split("&",$pepe);
+foreach ($partes as $elemento) {
+	$otri = split("=",$elemento);
+	if(substr($otri[0],0,5)=="texto") {
+		$numero = substr($otri[0],5);
+		if($numero > $maxnumero) {$maxnumero = $numero;}
+		$printresponse.="$otri[0]=$otri[1]&";
+	}
+	if(substr($otri[0],0,4)=="icon") {
+		$printresponse.="$otri[0]=$otri[1]&";
+	}
+}
+$printresponse.="maxnumero=$maxnumero";
+
+echo $printresponse;
+?>
+

Added: op-panel/branches/upstream/current/extensions.conf.sample
===================================================================
--- op-panel/branches/upstream/current/extensions.conf.sample	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/extensions.conf.sample	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,46 @@
+#
+# Example entry for setting a callerid text comming 
+# from the flash operator panel
+# You have to modify line 1 and 3 to match the channel
+# name for that extension: temp=clid should remain untouched.
+#
+# If the variable does not exist in the database
+# (if was not set by the operator panel) the line
+# 1 jumps to priority n+101, to perform a normal
+# dial without setting the CallerIDName
+
+exten => 11,1,DBget(temp=clid/SIP/11)
+exten => 11,2,SetCIDName(${temp})
+exten => 11,3,DBdel(clid/SIP/11)   
+exten => 11,4,Dial(SIP/11,30,TrH)
+exten => 11,5,Hangup
+
+; gets here if there was not 'info' provided
+exten => 11,102,Dial(SIP/11,30,TrH)
+
+; busy from the dial
+exten => 11,105,Busy
+exten => 11,203,Busy
+
+
+# Example on setting DND state from the dialplan
+# *78 Sets DND ON
+# *79 Sets DND OFF
+#
+# This example only sets the dnd db value and
+# signals FOP to display the status on the button
+# you might have to add a check in your stdext
+# macro to honour the DND status
+
+exten => *78,1,UserEvent(ASTDB|Family: dnd^State: On)
+exten => *78,2,SetVar(temp=${CHANNEL})
+exten => *78,3,Cut(temp=temp,,1)
+exten => *78,4,DBPut(dnd/${temp}=On)
+exten => *78,5,Hangup
+
+exten => *79,1,UserEvent(ASTDB|Family: dnd^State: ^)
+exten => *79,2,SetVar(temp=${CHANNEL})
+exten => *79,3,Cut(temp=temp,,1)
+exten => *79,4,DBDel(dnd/${temp})
+exten => *79,5,Hangup
+

Added: op-panel/branches/upstream/current/flash/help_de.html
===================================================================
--- op-panel/branches/upstream/current/flash/help_de.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/help_de.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,26 @@
+<html>
+<body>
+Ausführung von Aktionen:<BR>
+<ul>
+<li>Anrufe transferieren: durch Ziehen des Telefon-Icons auf den gewünschten Ziel-Teilnehmer
+<BR>
+<BR>
+<li>Anrufe beenden: Doppelklick auf den roten Button
+<BR>
+<BR>
+<li>Anruf initiieren: durch Ziehen eines verfügbaren Teilnehmers auf den gewünschten Ziel-Teilnehmer
+<BR>
+<BR>
+<li>Konferenzanrufe:  Sie können eine dritte Person zu einem bestehenden Telefonat hinzufügen, indem Sie einen verfügbaren Teilnehmer auf einen der bereits verbundenen Teilnehmer ziehen.
+<BR>
+<BR>
+<li>Stumm-/Lautschaltung von MeetMe-Mitgliedern: Doppelklick auf das Pfeil-Icon des Teilnehmers
+<BR>
+<BR>
+<li>Informationen zum letzten Anruf abrufen: Doppelklick auf das Pfeil-Icon des Teilnehmers
+<BR>
+<BR>
+</ul>
+Sie können auch Zusatzinformationen in die Infobox schreiben, bevor Sie Anrufe transferieren oder initiieren. Wenn in der Infobox Text eingegeben wurde, dann wird er als Caller-ID-Text für einen transferierten oder initiierten Anruf genutzt, z.B: "555-1212 Bob Jones/IBM"
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/help_en.html
===================================================================
--- op-panel/branches/upstream/current/flash/help_en.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/help_en.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,26 @@
+<html>
+<body>
+How to perform actions:<BR>
+<ul>
+<li> Transfer calls: by dragging the phone icon to the destination you want
+<BR>
+<BR>
+<li>Hangup calls: by double clikcing on the red button
+<BR>
+<BR>
+<li>Originate calls: by dragging an available extension to an available destination
+<BR>
+<BR>
+<li>Conference calls:  You can add a third person to an existing conversation by dragging an available extension to a leg of an already connected call.
+<BR>
+<BR>
+<li>Mute/Unmute meetme members: just double click on the arrow of a meetme participant
+<BR>
+<BR>
+<li>Get information about last call: double click on the arrow of an available button
+<BR>
+<BR>
+</ul>
+You can also write additional information in the Info box before transferring or originating a call. If text is entered in the Info box, it will be used as the Caller ID text for any originated or transferred calls.e.g. "555-1212 Bob Jones/IBM"
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/help_es.html
===================================================================
--- op-panel/branches/upstream/current/flash/help_es.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/help_es.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,28 @@
+<html>
+<body>
+Como realizar acciones:<BR>
+<ul>
+<li>Transferir llamados: arrastre y suelte el telefono hacia la extension de destino
+<BR>
+<BR>
+<li>Cortar llamados: pinche dos veces sobre el óvalo rojo
+<BR>
+<BR>
+<li>Originar llamados: arrastre el ícono de una extensión libre hacia su destino
+<BR>
+<BR>
+<li>Irrumpir en un llamado:  Puede agregar una tercer persona a una conversación en curso arrastrando el ícono del teléfono hacia cualquiera de los botones de la conversación en curso. Los tres serán puestos en una conferencia.
+<BR>
+<BR>
+<li>Enmudecer/desenmudecer participantes de una conferencia: pinche sobre la flecha pequeña de un botón
+<BR>
+<BR>
+<li>Obtener información sobre el último llamado: pinche dos veces sobre la flecha de un botón inactivo
+<BR>
+<BR>
+</ul>
+Puede mandar información adicional al realizar transferencias usando el campo textual del callerid. Para ello, escriba el texto que desee en el casillero y luego realice la transferencia. 
+<BR><BR>
+Puede determinar el tiempo máximo de un llamado configurando el 
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/help_fr.html
===================================================================
--- op-panel/branches/upstream/current/flash/help_fr.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/help_fr.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,20 @@
+<html>
+<body>
+	Vous pouvez réaliser les opérations suivantes:<br>
+<ul>
+	<li> Transférer les appels en déplacant l'icône vers la nouvelle destination
+	<br><br></li>
+	<li> Racrocher en double-cliquant sur le bouton rouge
+	<br><br></li>
+	<li> Initier des appels en déplacant l'icône vers la destination
+	<br><br></li>
+	<li>Gérer les conférences: ajouter des participants en déplacant l'icône vers la salle de conférence
+	<br><br></li>
+	<li>Mute/Unmute un participant d'une conférence en double cliquant sur la flèche
+	<br><br></li>
+	<li>Lire les informations sur le dernier appel en double-cliquant sur la flèche
+	<br><br></li>
+</ul>
+Vous pouvez aussi entrer un texte dans la boîte Info avant de transférer ou d'initier un appel; ce texte constituera alors l'identifiant de l'appelant (<i>Caller ID</i>) pour les appels ou transfert suivants.
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/help_it.html
===================================================================
--- op-panel/branches/upstream/current/flash/help_it.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/help_it.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,26 @@
+<html>
+<body>
+Istruzioni:<BR>
+<ul>
+<li>Trasferimento di una Chiamata: Trascinare l'icona del Telefono sulla destinazione desiderata.
+<BR>
+<BR>
+<li>Terminare Chiamata: Cliccare due volte sul pulsante Rosso.
+<BR>
+<BR>
+<li>Effettuare una Chiamata: Trascinare l'icona di una estensione disponibile su una Destinazione.
+<BR>
+<BR>
+<li>Conferenze: Tu puoi aggiungere persone ad una conferenza Attiva semplicemente trascinando l'icona di una Telefono dentro l'estensione della Conferenza.
+<BR>
+<BR>
+<li>Attivare o Sospendere l'audio per le Persone nel Meetme: Per fare questo devi cliccare due volte la Freccetta sul partecipante del meetme.
+<BR>
+<BR>
+<li>Informazioni sulle ultime chiamate: Clicca due volte la freccetta sull'estensione desiderata.
+<BR>
+<BR>
+</ul>
+PS: Prima di trasferire una chiamta puoi anche scrivere delle informazioni nel INFO-BOX, quello che hai digitato verra' trasmesso alla persona chiamata. Esempio: 555-1212 Bob Jones/IBM
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/help_se.html
===================================================================
--- op-panel/branches/upstream/current/flash/help_se.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/help_se.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,26 @@
+<html>
+<body>
+<b>Hur man anv&auml;nder Flash Operator Panel:</b><BR>
+<ul>
+<li> <b>Flytta samtal:</b> genom att dra telefonikonen till den anknytning du vill
+<BR>
+<BR>
+<li><b>L&auml;gg p&aring samtal:</b> genom att dubbelklicka p&aing; den r&ouml;da knappen
+<BR>
+<BR>
+<li><b>Skapa samtal:</b> genom att dra en tillg&auml;nglig anknytning till en tillg&auml;nglig mottagare
+<BR>
+<BR>
+<li><b>Konferenssamtal:</b> Du kan l&auml;gga till en tredje person till en existerande konversation genom att dra en tillg&auml;nglig anknytning till ett ben av det redan kopplade samtalet.
+<BR>
+<BR>
+<li><b>St&auml;ng av/p&aring; mikrofonen f&ouml;r MeetMe medlemmar:</b> bara att dubbelklicka p&aring; pilen hos en MeetMe deltagare.
+<BR>
+<BR>
+<li><b>Visa information om senaste samtalet:</b> dubbelklicka p&aring; pilen p&aring; en tillg&auml;nglig knapp
+<BR>
+<BR>
+</ul>
+Du kan ocks&aring; skriva extra information i Infoboxen f&ouml;re samtalskoppling eller skapande av samtal. Om text skrivs in i Infoboxen kommer den att anv&auml;ndas som CID (nummerpresentation) f&ouml;r samtalet, till exempel: "0877878787 Daniel Nylander"
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/index-clicktodial.html
===================================================================
--- op-panel/branches/upstream/current/flash/index-clicktodial.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/index-clicktodial.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,77 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+  <link rel="stylesheet" href="styles.css" media="screen" />
+  <META HTTP-EQUIV="Expires" CONTENT="Fri, Jun 12 1981 08:20:00 GMT">
+  <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+  <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
+
+
+<SCRIPT LANGUAGE="JavaScript"> 
+<!--  
+var movieName = "operator_panel";
+
+function thisMovie(movieName) {
+  // If you want to run this from another frame, change window or document 
+  // for the appropiate reference, like parent.frame[1].window[movieName] 
+  if (navigator.appName.indexOf ("Microsoft") !=-1) {
+    return window[movieName]
+  } else {
+    return document[movieName]
+  }
+}
+
+function movieIsLoaded (theMovie) {
+  if (typeof(theMovie) != "undefined") {
+    return theMovie.PercentLoaded() == 100;
+  } else {
+    return false;
+  }
+}
+
+
+function sendnumber(telefono) {
+  if (movieIsLoaded(thisMovie(movieName))) {
+        thisMovie(movieName).TGotoFrame("_level0/numdial",10); // Erase previous number
+        for(a=0;a<telefono.length;a++) {
+            var frame= telefono.charAt(a);
+            if(!isNaN(frame)) {
+            thisMovie(movieName).TGotoFrame("_level0/numdial",frame); // Add digit to number
+            thisMovie(movieName).TGotoFrame("_level0/numdial",12);    // next digit
+            }
+        }
+        thisMovie(movieName).TGotoFrame("_level0/numdial",11); // Dial current number
+  }
+}
+
+
+</script>
+
+</head>
+<body>
+
+<!--
+To enable click to dial, you have to specify the dial parameter after each
+appearance of operator_panel.swf below. You can specify the button number
+as this example, or the channel name, like
+
+operator_panel.swf?dial=SIP/john
+
+When a dial order is received from javascript, it will use that channel
+to originate the call. It only works for channels for the 1st server
+(if you are monitoring multiple servers).
+-->
+
+<div align='center'>
+<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="990" height="600" id="operator_panel">
+<param name="allowScriptAccess" value="sameDomain" />
+<param name="movie" value="operator_panel.swf?dial=7" />
+<param name="quality" value="high" />
+<param name="bgcolor" value="#ffffff" />
+<embed src="operator_panel.swf?dial=7" quality="high" bgcolor="#ffffff" width=990" height="600" name="operator_panel" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
+</div>
+
+<a href="#" onclick="sendnumber('18005555555'); return false;">Dial 1-800-555-5555</a>
+
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/index-crm.html
===================================================================
--- op-panel/branches/upstream/current/flash/index-crm.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/index-crm.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,40 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Asterisk Flash Operator Panel</title>
+<style>
+<!--
+html,body {
+	margin: 0;
+	padding: 0;
+	height: 100%;
+	width: 100%;
+}
+
+-->
+</style>
+</head>
+<body bgcolor="#ffffff">
+<!--
+
+This is an example on how to call the swf file when using the integration
+with CRM software. You have to append some variables at the end of every
+appearance of operator_panel.swf.
+
+This page sets:
+
+mybutton=1
+url=mypage.php
+target=bottom
+
+-->
+<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="100%" height="100%" id="operator_panel" align="left">
+<param name="allowScriptAccess" value="sameDomain" />
+<param name="movie" value="operator_panel.swf?mybutton=1&url=mypage.php&target=bottom" />
+<param name="quality" value="high" />
+<param name="bgcolor" value="#ffffff" />
+<param name="scale" value="exactfit" />
+<embed src="operator_panel.swf?mybutton=1&url=mypage.php&target=bottom" quality="high" scale="exactfit" bgcolor="#ffffff" width="100%" height="100%" name="operator_panel" align="left" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
+</object>
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/index-fixed.html
===================================================================
--- op-panel/branches/upstream/current/flash/index-fixed.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/index-fixed.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<META HTTP-EQUIV="Expires" CONTENT="Fri, Jun 12 1981 08:20:00 GMT">
+<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Asterisk Flash Operator Panel</title>
+</head>
+<body bgcolor="#ffffff" style="margin-top: 0px; margin-left: 0px">
+<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="996" height="600" id="operator_panel3" align="middle">
+<param name="allowScriptAccess" value="sameDomain" />
+<param name="movie" value="operator_panel.swf" />
+<param name="quality" value="high" />
+<param name="bgcolor" value="#ffffff" />
+<embed src="operator_panel.swf" quality="high" bgcolor="#ffffff" width="996" height="600" name="operator_panel3" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
+</object>
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/index-restrict.html
===================================================================
--- op-panel/branches/upstream/current/flash/index-restrict.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/index-restrict.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,37 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Asterisk Flash Operator Panel</title>
+<style>
+<!--
+html,body {
+	margin: 0;
+	padding: 0;
+	height: 100%;
+	width: 100%;
+}
+
+-->
+</style>
+</head>
+<body bgcolor="#ffffff">
+<!--
+
+This is an example on how to restrict the drag and drop commands
+(transfers and originations) to just one button: just append
+
+?restrict=btnnumber
+
+after every appeareance of operator_panel.swf
+
+-->
+<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="100%" height="100%" id="operator_panel" align="left">
+<param name="allowScriptAccess" value="sameDomain" />
+<param name="movie" value="operator_panel.swf?restrict=1" />
+<param name="quality" value="high" />
+<param name="bgcolor" value="#ffffff" />
+<param name="scale" value="exactfit" />
+<embed src="operator_panel.swf?restrict=1" quality="high" scale="exactfit" bgcolor="#ffffff" width="100%" height="100%" name="operator_panel" align="left" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
+</object>
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/index.html
===================================================================
--- op-panel/branches/upstream/current/flash/index.html	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/index.html	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Asterisk Flash Operator Panel</title>
+<style>
+<!--
+html,body {
+	margin: 0;
+	padding: 0;
+	height: 100%;
+	width: 100%;
+}
+
+-->
+</style>
+</head>
+<body bgcolor="#ffffff">
+<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="100%" height="100%" id="operator_panel" align="left">
+<param name="allowScriptAccess" value="sameDomain" />
+<param name="movie" value="operator_panel.swf" />
+<param name="quality" value="high" />
+<param name="bgcolor" value="#ffffff" />
+<param name="scale" value="exactfit" />
+<embed src="operator_panel.swf" quality="high" scale="exactfit" bgcolor="#ffffff" width="100%" height="100%" name="operator_panel" align="left" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
+</object>
+</body>
+</html>

Added: op-panel/branches/upstream/current/flash/mypage.php
===================================================================
--- op-panel/branches/upstream/current/flash/mypage.php	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/flash/mypage.php	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,21 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+</head>
+<body>
+<?
+if(!isset($_GET['clid'])) {
+     echo "No caller ID provided<BR>";
+} else {
+     echo "Caller id is: ".$_GET['clid']."<BR>";
+}
+
+if(!isset($_GET['clidname'])) {
+     echo "No caller ID Name provided<BR>";
+} else {
+	 echo "Your clid name: ".base64_decode($_GET['clidname'])."<BR>";
+}
+
+?>
+</body>
+</html>

Added: op-panel/branches/upstream/current/init/op_panel_debian.sh
===================================================================
--- op-panel/branches/upstream/current/init/op_panel_debian.sh	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/init/op_panel_debian.sh	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,78 @@
+#! /bin/sh
+#
+# skeleton	example file to build /etc/init.d/ scripts.
+#		This file should be used to construct scripts for /etc/init.d.
+#
+# Author:	Miquel van Smoorenburg <miquels at cistron.nl>.
+#		Ian Murdock <imurdock at gnu.ai.mit.edu>.
+#
+#		You may remove the "Author" lines above and replace them
+#		with your own name if you copy and modify this script.
+#
+# Version:	@(#)skeleton  1.9.4  21-Mar-2004  miquels at cistron.nl
+#
+
+set -e
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/local/operator/bin/op_server.pl
+NAME=op_panel
+DESC="Flash Operator Panel"
+
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+OPTIONS="-d -p $PIDFILE"
+
+# Gracefully exit if the package has been removed.
+test -x $DAEMON || exit 0
+
+# Read config file if it is present.
+#if [ -r /etc/default/$NAME ]
+#then
+#	. /etc/default/$NAME
+#fi
+
+case "$1" in
+  start)
+	echo -n "Starting $DESC: $NAME"
+	start-stop-daemon --start --pidfile $PIDFILE --startas $DAEMON -- $OPTIONS 
+	echo "."
+	;;
+  stop)
+	echo -n "Stopping $DESC: $NAME"
+	start-stop-daemon --stop --pidfile $PIDFILE
+	echo "."
+	;;
+  reload)
+	
+	#	If the daemon can reload its config files on the fly
+	#	for example by sending it SIGHUP, do it here.
+	#
+	#	If the daemon responds to changes in its config file
+	#	directly anyway, make this a do-nothing entry.
+	#
+	 echo -n "Reloading $DESC configuration..."
+	 start-stop-daemon --stop --pidfile $PIDFILE --signal HUP
+	 echo "done."
+  ;;
+  restart|force-reload)
+	#
+	#	If the "reload" option is implemented, move the "force-reload"
+	#	option to the "reload" entry above. If not, "force-reload" is
+	#	just the same as "restart".
+	#
+	echo -n "Restarting $DESC: $NAME"
+	start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON
+	sleep 1
+	start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON -- $OPTIONS
+	echo "."
+	;;
+  *)
+	# echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
+	exit 1
+	;;
+esac
+
+exit 0

Added: op-panel/branches/upstream/current/init/op_panel_redhat.sh
===================================================================
--- op-panel/branches/upstream/current/init/op_panel_redhat.sh	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/init/op_panel_redhat.sh	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# chkconfig: 2345 99 15
+# description: Flash Operator Panel 
+# processname: op_server.pl
+
+# source function library
+. /etc/rc.d/init.d/functions
+
+DAEMON=/usr/local/operator/op_server.pl
+OPTIONS=-d
+RETVAL=0
+
+case "$1" in
+  start)
+	echo -n "Starting Flash Operator Panel: "
+	daemon $DAEMON $OPTIONS
+	RETVAL=$?
+	echo
+	[ $RETVAL -eq 0 ] && touch /var/lock/subsys/op_server.pl
+	;;
+  stop)
+	echo -n "Shutting dows Flash Operator Panel: "
+	killproc op_server.pl
+	RETVAL=$?
+
+	echo
+	[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/op_server.pl
+	;;
+  restart)
+	$0 stop
+	$0 start
+	RETVAL=$?
+	;;
+  reload)
+	echo -n "Reloading Flash Operator Panel configuration: "
+	killproc op_server.pl -HUP
+	RETVAL=$?
+	echo
+	;;
+  status)
+	status op_server.pl
+	RETVAL=$?
+	;;
+  *)
+	echo "Usage: op_panel {start|stop|status|restart|reload}"
+	exit 1
+esac
+
+exit $RETVAL
+

Added: op-panel/branches/upstream/current/init/op_panel_suse.sh
===================================================================
--- op-panel/branches/upstream/current/init/op_panel_suse.sh	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/init/op_panel_suse.sh	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,162 @@
+#!/bin/bash
+#
+# /etc/init.d/fop
+#
+# LSB compliant service control script; see http://www.linuxbase.org/spec/
+#
+# System startup script for daemon spamd
+#
+### BEGIN INIT INFO
+# Provides: fop
+# Required-Start:
+# Required-Stop:
+# Default-Start:  3 5
+# Default-Stop:   0 1 2 6
+# Description:    Start Flash Operator Panel
+### END INIT INFO
+#
+# Note on Required-Start: It does specify the init script ordering,
+# not real dependencies. Depencies have to be handled by admin
+# resp. the configuration tools (s)he uses.
+
+# Source SuSE config (if still necessary, most info has been moved)
+test -r /etc/rc.config && . /etc/rc.config
+
+# Check for missing binaries (stale symlinks should not happen)
+FOP_BIN=/usr/local/fop/op_server.pl
+
+# Check for existence of needed config file and read it
+#
+# Later, we may want to make startup behaviour (user ID, firewalling, ...)
+# configurable, as there are security implications (read README.spamd).
+#FOP_CONFIG=/etc/sysconfig/fop
+#test -r $FOP_CONFIG || exit 6
+#. $FOP_CONFIG
+
+test -x $FOP_BIN || exit 5
+
+# Shell functions sourced from /etc/rc.status:
+#      rc_check         check and set local and overall rc status
+#      rc_status        check and set local and overall rc status
+#      rc_status -v     ditto but be verbose in local rc status
+#      rc_status -v -r  ditto and clear the local rc status
+#      rc_failed        set local and overall rc status to failed
+#      rc_failed <num>  set local and overall rc status to <num><num>
+#      rc_reset         clear local rc status (overall remains)
+#      rc_exit          exit appropriate to overall rc status
+#      rc_active        checks whether a service is activated by symlinks
+. /etc/rc.status
+
+
+FOP_ARGS="-d -p /var/run/fop.pid"
+
+# First reset status of this service
+rc_reset
+
+# Return values acc. to LSB for all commands but status:
+# 0 - success
+# 1 - generic or unspecified error
+# 2 - invalid or excess argument(s)
+# 3 - unimplemented feature (e.g. "reload")
+# 4 - insufficient privilege
+# 5 - program is not installed
+# 6 - program is not configured
+# 7 - program is not running
+#
+# Note that starting an already running service, stopping
+# or restarting a not-running service as well as the restart
+# with force-reload (in case signalling is not supported) are
+# considered a success.
+
+case "$1" in
+    start)
+        echo -n "Starting Flash Operator Panel server "
+        ## Start daemon with startproc(8). If this fails
+        ## the echo return value is set appropriate.
+
+        # NOTE: startproc returns 0, even if service is
+        # already running to match LSB spec.
+        startproc -p /var/run/fop.pid $FOP_BIN $FOP_ARGS
+
+        # Remember status and be verbose
+        rc_status -v
+        ;;
+    stop)
+        echo -n "Shutting down op_server.pl "
+        ## Stop daemon with killproc(8) and if this fails
+        ## set echo the echo return value.
+
+        killproc -p /var/run/fop.pid -TERM $FOP_BIN
+
+        # Remember status and be verbose
+        rc_status -v
+        ;;
+    try-restart)
+        ## Stop the service and if this succeeds (i.e. the
+        ## service was running before), start it again.
+        ## Note: try-restart is not (yet) part of LSB (as of 0.7.5)
+        $0 status >/dev/null &&  $0 restart
+
+        # Remember status and be quiet
+        rc_status
+        ;;
+    restart)
+        ## Stop the service and regardless of whether it was
+        ## running or not, start it again.
+        $0 stop
+        $0 start
+
+        # Remember status and be quiet
+        rc_status
+        ;;
+    force-reload)
+        ## Signal the daemon to reload its config. Most daemons
+        ## do this on signal 1 (SIGHUP).
+        ## If it does not support it, restart.
+
+        echo -n "Reload service op_server.pl "
+        ## if it supports it:
+        killproc -HUP $FOP_BIN
+        touch /var/run/fop.pid
+        rc_status -v
+
+        ## Otherwise:
+        #$0 stop  &&  $0 start
+        #rc_status
+        ;;
+    reload)
+        ## Like force-reload, but if daemon does not support
+        ## signalling, do nothing (!)
+
+        # If it supports signalling:
+        echo -n "Reload service op_server.pl "
+        killproc -HUP $FOP_BIN
+        touch /var/run/fop.pid
+        rc_status -v
+
+        ## Otherwise if it does not support reload:
+        #rc_failed 3
+        #rc_status -v
+        ;;
+    status)
+        echo -n "Checking for service fop "
+        ## Check status with checkproc(8), if process is running
+        ## checkproc will return with exit status 0.
+
+        # Return value is slightly different for the status command:
+        # 0 - service running
+        # 1 - service dead, but /var/run/  pid  file exists
+        # 2 - service dead, but /var/lock/ lock file exists
+        # 3 - service not running
+
+        # NOTE: checkproc returns LSB compliant status values.
+        checkproc $FOP_BIN
+        rc_status -v
+        ;;
+    *)
+        echo "Usage: $0 {start|stop|status|try-restart|restart|reload}"
+        exit 1
+        ;;
+esac
+rc_exit
+

Added: op-panel/branches/upstream/current/ming-source/README
===================================================================
--- op-panel/branches/upstream/current/ming-source/README	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/ming-source/README	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,8 @@
+I used MING from CVS as of 10/5/2004
+
+You can find instructions and a ming perl mini howto at:
+
+http://todbot.com/ming
+
+My thanks to Tod E. Kurt for his advice and help for
+porting the client to Ming.

Added: op-panel/branches/upstream/current/ming-source/operator_panel.pl
===================================================================
--- op-panel/branches/upstream/current/ming-source/operator_panel.pl	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/ming-source/operator_panel.pl	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,11239 @@
+#!/usr/bin/perl -w
+#  Flash Operator Panel.    http://www.asternic.org
+#
+#  Copyright (c) 2004 Nicolas Gudino. All rights reserved.
+#
+#  Nicolas Gudino <nicolas at house.com.ar>
+#
+#  This program is free software, distributed under the terms of
+#  the GNU General Public License.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+#  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+#  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
+#  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+#  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+#  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+#  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use SWF qw(:ALL);
+use SWF::Constants qw(:Text :Button :DisplayItem :Fill);
+
+SWF::setScale(2);
+SWF::useSWFVersion(7);
+my $movie = new SWF::Movie();
+$movie->setDimension(9960, 6000);
+$movie->setBackground(0xFF, 0xFF, 0xFF);
+$movie->setRate(20);
+
+
+
+$fuente="fonts/Arial.fdb";
+$fuente_nombre="Arial";
+
+sub maketextfield {
+	$name = shift;
+	$font = shift;
+	$str  = shift;
+	
+	$txtfield = new SWF::TextField( SWFTEXTFIELD_MULTILINE | SWFTEXTFIELD_WORDWRAP | SWFTEXTFIELD_USEFONT );
+	$txtfield->setHeight(254);	
+	$txtfield->setBounds(200,30);
+	$txtfield->setName($name);
+	$txtfield->setColor(0x00, 0x00, 0x00);
+	$txtfield->setFont(new SWF::Font($font));
+	$txtfield->addChars("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x100\x101\x102\x103\x104\x105\x106\x107\x108\x109\x110\x111\x112\x113\x114\x115\x116\x116\x118\x119\x11a\x11b\x11c\x11d\x11e\x11f\x120\x121\x122\x123\x124\x125\x126\x127\x128\x129\x12a\x12b\x12c\x12d\x12e\x12f\x130\x131\x132\x133\x134\x135\x136\x137\x138\x139\x13a\x13b\x13c\x13d\x13e\x13f\x140\x141\x142\x143\x144\x145\x146\x147\x148\x149\x14a\x14b\x14c\x14d\x14e\x14f\x150\x151\x152\x153\x154\x155\x156\x157\x158\x159\x15a\x15b\x15c\x15d\x15e\x15f\x160\x161\x162\x163\x164\x165\x166\x167\x168\x169\x16a\x16b\x16c\x16d\x16e\x16f\x170\x171\x172\x173\x174\x175\x176\x177\x178\x179\x17a\x17b\x17c\x17d\x17e\x17f\x180\x181\x182\x183\x184\x185\x186\x187\x188\x189\x18a\x18b\x18c\x18d\x18e\x18f\x190\x191\x192\x193\x194\x195\x196\x197\x198\x199\x19a\x19b\x19c\x19d\x19e\x19f\x1a0\x1a1\x1a2\x1a3\x1a4\x1a5\x1a6\x1a7\x1a8\x1a9\x1aa\x1ab\x1ac\x1ad\x1ae\x1af\x1b0\x1b1\x1b2\x1b3\x1b4\x1b5\x1b6\x1b7\x1b8\x1b9\x1ba\x1bb\x1bc\x1bd\x1be\x1bf\x1c0\x1c1\x1c2\x1c3\x1c4\x1c5\x1c6\x1c7\x1c8\x1c9\x1ca\x1cb\x1cc\x1cd\x1ce\x1cf\x1d0\x1d1\x1d2\x1d3\x1d4\x1d5\x1d6\x1d7\x1d8\x1d9\x1da\x1db\x1dc\x1dd\x1de\x1df\x1e0\x1e1\x1e2\x1e3\x1e4\x1e5\x1e6\x1e7\x1e8\x1e9\x1ea\x1eb\x1ec\x1ed\x1ee\x1ef\x1f0\x1f1\x1f2\x1f3\x1f4\x1f5\x1f6\x1f7\x1f8\x1f9\x1fa\x1fb\x1fc\x1fd\x1fe\x1ff\x200\x201\x202\x203\x204\x205\x206\x207\x208\x209\x20a\x20b\x20c\x20d\x20e\x20f\x210\x211\x212\x213\x214\x215\x216\x217\x218\x219\x21a\x21b\x21c\x21d\x21e\x21f\x220\x221\x222\x223\x224\x225\x226\x227\x228\x229\x22a\x22b\x22c\x22d\x22e\x22f\x230\x231\x232\x233\x234\x235\x236\x237\x238\x239\x23a\x23b\x23c\x23d\x23e\x23f\x240\x241\x242\x243\x244\x245\x246\x247\x248\x249\x24a\x24b\x24c\x24d\x24e\x24f\x250\x251\x252\x253\x254\x255\x256\x257\x258\x259\x25a\x25b\x25c\x25d\x25e\x25f\x260\x261\x262\x263\x264\x265\x266\x267\x268\x269\x26a\x26b\x26c\x26d\x26e\x26f\x270\x271\x272\x273\x274\x275\x276\x277\x278\x279\x27a\x27b\x27c\x27d\x27e\x27f\x280\x281\x282\x283\x284\x285\x286\x287\x288\x289\x28a\x28b\x28c\x28d\x28e\x28f\x290\x291\x292\x293\x294\x295\x296\x297\x298\x299\x29a\x29b\x29c\x29d\x29e\x29f\x2a0\x2a1\x2a2\x2a3\x2a4\x2a5\x2a6\x2a7\x2a8\x2a9\x2aa\x2ab\x2ac\x2ad\x2ae\x2af\x2b0\x2b1\x2b2\x2b3\x2b4\x2b5\x2b6\x2b7\x2b8\x2b9");
+	$txtfield->addString($str);
+	return $txtfield;
+}
+
+$txtv = maketextfield("txtv",$fuente,"Nico");
+$txt=$movie->add($txtv);
+$txt->moveTo(-2400,-2800);
+#$txt->moveTo(10,10);
+$txt->setName("textoload");
+
+#################################################
+## SELECT TIMEOUT BOX
+#################################################
+$dropbox1 = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(5600, 0);
+$s1->setRightFill(0xf2, 0xf2, 0xf6);
+#$s1->setLine(1, 0xbe, 0xbe, 0xbe);
+$s1->drawLine(0, 3400);
+$s1->drawLine(-5600, 0);
+#$s1->setLine(1, 0xf2, 0xf2, 0xf6);
+$s1->drawLine(0, -3400);
+$s1->drawLine(5600, 0);
+
+### MovieClip 2 ###
+$s2 = new SWF::MovieClip();  # 1 frames
+$s2->add($s1);
+$s2->nextFrame();  # end of clip frame 1 
+
+$i1 = $dropbox1->add($s2);
+#$i1->scaleTo(0.714279, 0.105881);
+$i1->scaleTo(0.328, 0.0635);
+$i1->setName('bg');
+
+### Shape 3 ###
+# Scroll DOWN #
+$s3 = new SWF::Shape();
+$s3->movePenTo(320, 0);
+$s3->setRightFill(0x6f, 0x7f, 0x7f);
+$s3->setLine(1, 0xbe, 0xbe, 0xbe);
+$s3->drawLine(0, 340);
+$s3->drawLine(-320, 0);
+$s3->setLine(0,0,0,0);
+$s3->drawLine(0, -340);
+$s3->drawLine(320, 0);
+$s3->setLeftFill();
+$s3->setRightFill();
+$s3->setLine(0,0,0,0);
+$s3->movePenTo(160, 220);
+$s3->setRightFill(0x7f, 0x7f, 0x7f);
+$s3->drawLine(-80, -80);
+$s3->drawLine(160, 0);
+$s3->drawLine(-80, 80);
+### MovieClip 4 ###
+$s4 = new SWF::MovieClip();  # 1 frames
+$s4->add($s3);
+
+$s4->add(new SWF::Action("
+this.onPress = function() {
+	if(_parent._currentframe == 1) {
+		_root.despliega_select();
+	} else {
+		var incremento = 1;
+		var cuantashay = _global.opcionesTimeout.length;
+		cuantashay = cuantashay - 4;
+		if (_global.positionselect < cuantashay) {
+			for(a=0;a<5;a++) {
+				var indice = a + _global.positionselect;
+				if (_global.opcionesTimeout[indice] != undefined) {
+					_root['option'+a].legend = _global.opcionesTimeout[indice];
+					incremento = 1;
+				} else {
+					incremento = 0;
+				}
+			}
+		_global.positionselect=_global.positionselect+incremento;
+		}
+	}
+};
+
+"));
+$s4->nextFrame();  # end of clip frame 1 
+### END SCROLL DOWN #####
+
+
+#### SCROLL UP ######
+### Shape 5 ###
+$s5 = new SWF::Shape();
+$s5->movePenTo(320, 0);
+$s5->setRightFill(0x6f, 0x7f, 0x7f);
+$s5->setLine(1, 0xbe, 0xbe, 0xbe);
+$s5->drawLine(0, 340);
+$s5->drawLine(-320, 0);
+$s5->setLine(0,0,0,0);
+$s5->drawLine(0, -340);
+$s5->drawLine(320, 0);
+$s5->setLeftFill();
+$s5->setRightFill();
+$s5->setLine(0,0,0,0);
+$s5->movePenTo(160, 140);
+$s5->setRightFill(0x7f, 0x7f, 0x7f);
+$s5->drawLine(-80, 80);
+$s5->drawLine(160, 0);
+$s5->drawLine(-80, -80);
+### MovieClip 6 ###
+$s6 = new SWF::MovieClip();  # 1 frames
+$s6->add($s5);
+$s6->add(new SWF::Action("
+this.onPress = function() {
+        var incremento = 1;
+        if (_global.positionselect > 0) {
+            for(a=0;a<5;a++) {
+                var indice = a + _global.positionselect - 1;
+                if (_global.opcionesTimeout[indice] != undefined) {
+                    _root['option'+a].legend = _global.opcionesTimeout[indice];
+                    incremento = -1;
+                } else {
+                    incremento = 0;
+                }
+            }
+        _global.positionselect=_global.positionselect+incremento;
+        }
+};
+
+"));
+$s6->nextFrame();  # end of clip frame 1
+##### END SCROLL UP ######
+
+$i3 = $dropbox1->add($s4);
+$i3->moveTo(1640, 10);
+$i3->scaleTo(0.6, 0.6);
+$i3->setName('ScrollDown');
+
+$dropbox1->nextFrame();  # end of frame 1
+$dropbox1->remove($i3);
+
+$i1 = $dropbox1->add($s2);
+$i1->scaleTo(0.328, 0.4);
+$i1->setName('bg');
+$i3 = $dropbox1->add($s4);
+$i3->moveTo(1640,1160);
+$i3->scaleTo(0.6, 0.6);
+$i3->setName('ScrollDown');
+
+
+$i3 = $dropbox1->add($s6);
+$i3->moveTo(1640, 10);
+$i3->scaleTo(0.6, 0.6);
+$i3->setName('ScrollUp');
+
+$option = new SWF::MovieClip();
+$i3 = $option->add($s2);
+$i3->scaleTo(0.29, 0.0635);
+$i3->setName('bg');
+
+$font_general = new SWF::Font($fuente);  
+
+$s8 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_USEFONT | SWFTEXTFIELD_NOSELECT );
+$s8->setBounds(1411, 398);
+$s8->setFont($font_general);
+#$s8->setFont(new SWF::Font("_sans"));
+$s8->setHeight(180);
+$s8->setColor(0x00, 0x00, 0x00, 0xff);
+$s8->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s8->setName('legend');
+$s8->addString('Select Timeout');
+
+$i3 = $option->add($s8);
+$i3->moveTo(70,10);
+
+$option->nextFrame();
+$dropbox1->nextFrame();  # end of frame 2
+##################################################
+# END SELECT TIMEOUT BOX
+##################################################
+
+## MovieCLIP progress graphic
+##
+$progressclip = new SWF::Sprite();
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(140, -53);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(140, -62);
+$s2->drawLine(-40, -70);
+$s2->drawLine(-124, 91);
+$s2->drawCurve(16, 19, 8, 22);
+$s2->movePenTo(95, -115);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s2->setRightFill();
+#$s2->setLine(0,255,255,255);
+$s2->drawLine(90, -125);
+$s2->drawLine(-70, -40);
+$s2->drawLine(-62, 140);
+$s2->drawLine(42, 25);
+$s2->movePenTo(40, -300);
+$s2->setLeftFill(0xff, 0xff, 0xff);
+$s2->setRightFill();
+#$s2->setLine(0,255,255,255);
+$s2->drawLine(-80, 0);
+$s2->drawLine(16, 152);
+$s2->drawLine(23, -1);
+$s2->drawLine(26, 2);
+$s2->drawLine(15, -153);
+$s2->movePenTo(148, -24);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s2->setRightFill();
+#$s2->setLine(0,255,255,255);
+$s2->drawLine(2, 24);
+$s2->drawLine(-2, 25);
+$s2->drawLine(152, 15);
+$s2->drawLine(0, -80);
+$s2->drawLine(-152, 16);
+$s2->movePenTo(280, 115);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(-140, -62);
+$s2->drawCurve(-8, 22, -16, 20);
+$s2->drawLine(124, 90);
+$s2->drawLine(40, -70);
+$s2->movePenTo(53, 141);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(62, 139);
+$s2->drawLine(70, -40);
+$s2->drawLine(-90, -124);
+$s2->drawLine(-42, 25);
+$s2->movePenTo(25, 149);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(-26, 2);
+$s2->drawLine(-23, -2);
+$s2->drawLine(-16, 151);
+$s2->drawLine(80, 0);
+$s2->drawLine(-15, -151);
+$s2->movePenTo(-239, -185);
+$s2->setLeftFill();
+$s2->setRightFill(0xff, 0xff, 0xff, 0xcc);
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(123, 90);
+$s2->drawCurve(-17, 19, -8, 23);
+$s2->drawLine(-138, -62);
+$s2->drawLine(40, -70);
+$s2->movePenTo(-53, -140);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(-62, -140);
+$s2->drawLine(-70, 40);
+$s2->drawLine(90, 124);
+$s2->drawCurve(19, -16, 23, -8);
+$s2->movePenTo(-148, -24);
+$s2->setLeftFill();
+$s2->setRightFill(0xff, 0xff, 0xff, 0xc0);
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(-2, 24);
+$s2->drawLine(2, 25);
+$s2->drawLine(-152, 15);
+$s2->drawLine(0, -80);
+$s2->drawLine(152, 16);
+$s2->movePenTo(-141, 53);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(-138, 62);
+$s2->drawLine(40, 70);
+$s2->drawLine(123, -89);
+$s2->drawLine(-25, -43);
+$s2->movePenTo(-95, 117);
+$s2->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s2->setRightFill();
+#$s2->setLine(0,0,0,0);
+$s2->drawLine(-90, 123);
+$s2->drawLine(70, 40);
+$s2->drawLine(62, -138);
+$s2->drawCurve(-23, -9, -19, -16);
+
+### Shape 3 ###
+$s3 = new SWF::Shape();
+$s3->movePenTo(116, -94);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawCurve(16, 19, 8, 22);
+$s3->drawLine(140, -62);
+$s3->drawLine(-40, -70);
+$s3->drawLine(-124, 90);
+$s3->drawLine(0, 1);
+$s3->movePenTo(185, -240);
+$s3->setLeftFill(0xff, 0xff, 0xff);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-69, -40);
+$s3->drawLine(-63, 140);
+$s3->drawLine(42, 25);
+$s3->drawLine(90, -125);
+$s3->movePenTo(40, -300);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-80, 0);
+$s3->drawLine(16, 152);
+$s3->drawLine(23, -1);
+$s3->drawLine(25, 2);
+$s3->drawLine(16, -153);
+$s3->movePenTo(148, -24);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(2, 24);
+$s3->drawLine(-2, 24);
+$s3->drawLine(152, 16);
+$s3->drawLine(1, -80);
+$s3->drawLine(-153, 16);
+$s3->movePenTo(280, 116);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-140, -63);
+$s3->drawCurve(-8, 22, -16, 20);
+$s3->drawLine(124, 90);
+$s3->drawLine(40, -69);
+$s3->movePenTo(95, 116);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-41, 25);
+$s3->drawLine(62, 139);
+$s3->drawLine(69, -40);
+$s3->drawLine(-90, -124);
+$s3->movePenTo(40, 300);
+$s3->setLeftFill();
+$s3->setRightFill(0xff, 0xff, 0xff, 0x8d);
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-80, 0);
+$s3->drawLine(16, -151);
+$s3->drawLine(23, 2);
+$s3->drawLine(25, -2);
+$s3->drawLine(16, 151);
+$s3->movePenTo(-240, -184);
+$s3->setLeftFill();
+$s3->setRightFill(0xff, 0xff, 0xff, 0xc0);
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(124, 89);
+$s3->drawCurve(-17, 19, -8, 23);
+$s3->drawLine(-139, -62);
+$s3->drawLine(40, -69);
+$s3->movePenTo(-52, -140);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-63, -140);
+$s3->drawLine(-69, 40);
+$s3->drawLine(89, 124);
+$s3->drawCurve(19, -16, 23, -8);
+$s3->drawLine(1, 0);
+$s3->movePenTo(-148, -24);
+$s3->setLeftFill();
+$s3->setRightFill(0xff, 0xff, 0xff, 0xb3);
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-2, 24);
+$s3->drawLine(2, 24);
+$s3->drawLine(-151, 16);
+$s3->drawLine(0, -80);
+$s3->drawLine(151, 16);
+$s3->movePenTo(-141, 53);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-139, 62);
+$s3->drawLine(40, 70);
+$s3->drawLine(124, -89);
+$s3->drawLine(-25, -43);
+$s3->movePenTo(-95, 117);
+$s3->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s3->setRightFill();
+#$s3->setLine(0,0,0,0);
+$s3->drawLine(-89, 123);
+$s3->drawLine(69, 40);
+$s3->drawLine(62, -138);
+$s3->drawCurve(-23, -9, -19, -16);
+
+### Shape 4 ###
+$s4 = new SWF::Shape();
+$s4->movePenTo(25, -147);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(16, -153);
+$s4->drawLine(-81, 0);
+$s4->drawLine(16, 152);
+$s4->drawLine(23, -1);
+$s4->drawLine(25, 2);
+$s4->drawLine(1, 0);
+$s4->movePenTo(116, -94);
+$s4->setLeftFill(0xff, 0xff, 0xff);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawCurve(16, 19, 8, 22);
+$s4->drawLine(0, 1);
+$s4->drawLine(140, -63);
+$s4->drawLine(-40, -69);
+$s4->drawLine(-124, 89);
+$s4->drawLine(0, 1);
+$s4->movePenTo(185, -240);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-69, -40);
+$s4->drawLine(-63, 140);
+$s4->drawLine(41, 25);
+$s4->drawLine(91, -125);
+$s4->movePenTo(148, -24);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(2, 24);
+$s4->drawLine(-2, 24);
+$s4->drawLine(152, 16);
+$s4->drawLine(0, -80);
+$s4->drawLine(-152, 16);
+$s4->movePenTo(280, 116);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-140, -63);
+$s4->drawCurve(-8, 22, -16, 20);
+$s4->drawLine(124, 90);
+$s4->drawLine(40, -69);
+$s4->movePenTo(95, 116);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-41, 25);
+$s4->drawLine(-1, 0);
+$s4->drawLine(63, 139);
+$s4->drawLine(69, -40);
+$s4->drawLine(-90, -124);
+$s4->movePenTo(24, 149);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-25, 2);
+$s4->drawLine(-23, -2);
+$s4->drawLine(-16, 151);
+$s4->drawLine(81, 0);
+$s4->drawLine(-16, -151);
+$s4->drawLine(-1, 0);
+$s4->movePenTo(-239, -184);
+$s4->setLeftFill();
+$s4->setRightFill(0xff, 0xff, 0xff, 0xb3);
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(123, 89);
+$s4->drawCurve(-17, 19, -8, 23);
+$s4->drawLine(-138, -62);
+$s4->drawLine(40, -69);
+$s4->movePenTo(-53, -140);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-62, -140);
+$s4->drawLine(-69, 40);
+$s4->drawLine(89, 124);
+$s4->drawCurve(19, -16, 23, -8);
+$s4->movePenTo(-148, -24);
+$s4->setLeftFill();
+$s4->setRightFill(0xff, 0xff, 0xff, 0xa6);
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-2, 24);
+$s4->drawLine(2, 24);
+$s4->drawLine(0, 1);
+$s4->drawLine(-152, 15);
+$s4->drawLine(0, -80);
+$s4->drawLine(152, 16);
+$s4->movePenTo(-141, 53);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-139, 63);
+$s4->drawLine(40, 69);
+$s4->drawLine(124, -89);
+$s4->drawLine(-25, -43);
+$s4->movePenTo(-95, 117);
+$s4->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s4->setRightFill();
+#$s4->setLine(0,0,0,0);
+$s4->drawLine(-89, 123);
+$s4->drawLine(69, 40);
+$s4->drawLine(62, -138);
+$s4->drawCurve(-23, -9, -19, -16);
+
+### Shape 5 ###
+$s5 = new SWF::Shape();
+$s5->movePenTo(25, -147);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(15, -153);
+$s5->drawLine(-80, 0);
+$s5->drawLine(16, 152);
+$s5->drawLine(23, -1);
+$s5->drawLine(25, 2);
+$s5->drawLine(1, 0);
+$s5->movePenTo(95, -115);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(90, -124);
+$s5->drawLine(-69, -41);
+$s5->drawLine(-63, 140);
+$s5->drawLine(41, 25);
+$s5->drawLine(1, 0);
+$s5->movePenTo(140, -53);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(140, -62);
+$s5->drawLine(-40, -69);
+$s5->drawLine(-124, 89);
+$s5->drawLine(0, 1);
+$s5->drawLine(24, 41);
+$s5->movePenTo(148, -24);
+$s5->setLeftFill(0xff, 0xff, 0xff);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(2, 24);
+$s5->drawLine(-2, 24);
+$s5->drawLine(0, 1);
+$s5->drawLine(152, 15);
+$s5->drawLine(0, -80);
+$s5->drawLine(-152, 16);
+$s5->movePenTo(280, 115);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(-140, -62);
+$s5->drawCurve(-8, 22, -16, 20);
+$s5->drawLine(124, 90);
+$s5->drawLine(40, -70);
+$s5->movePenTo(95, 116);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(-41, 25);
+$s5->drawLine(62, 139);
+$s5->drawLine(69, -40);
+$s5->drawLine(-90, -124);
+$s5->movePenTo(24, 149);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(-25, 2);
+$s5->drawLine(-23, -2);
+$s5->drawLine(-16, 151);
+$s5->drawLine(80, 0);
+$s5->drawLine(-15, -151);
+$s5->drawLine(-1, 0);
+$s5->movePenTo(-239, -185);
+$s5->setLeftFill();
+$s5->setRightFill(0xff, 0xff, 0xff, 0xa6);
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(123, 90);
+$s5->drawCurve(-17, 19, -8, 23);
+$s5->drawLine(-139, -62);
+$s5->drawLine(41, -70);
+$s5->movePenTo(-52, -140);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(-63, -139);
+$s5->drawLine(-69, 40);
+$s5->drawLine(89, 123);
+$s5->drawCurve(19, -16, 23, -8);
+$s5->drawLine(1, 0);
+$s5->movePenTo(-148, -24);
+$s5->setLeftFill();
+$s5->setRightFill(0xff, 0xff, 0xff, 0x99);
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(-2, 24);
+$s5->drawLine(2, 24);
+$s5->drawLine(0, 1);
+$s5->drawLine(-152, 15);
+$s5->drawLine(0, -80);
+$s5->drawLine(152, 16);
+$s5->movePenTo(-141, 53);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawLine(-138, 62);
+$s5->drawLine(40, 70);
+$s5->drawLine(123, -89);
+$s5->drawLine(-25, -43);
+$s5->movePenTo(-53, 142);
+$s5->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s5->setRightFill();
+#$s5->setLine(0,0,0,0);
+$s5->drawCurve(-23, -9, -19, -16);
+$s5->drawLine(-89, 123);
+$s5->drawLine(69, 40);
+$s5->drawLine(62, -138);
+
+### Shape 6 ###
+$s6 = new SWF::Shape();
+$s6->movePenTo(25, -147);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(15, -152);
+$s6->drawLine(-80, 0);
+$s6->drawLine(16, 151);
+$s6->drawLine(23, -1);
+$s6->drawLine(25, 2);
+$s6->drawLine(1, 0);
+$s6->movePenTo(95, -115);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(90, -125);
+$s6->drawLine(-69, -40);
+$s6->drawLine(-63, 140);
+$s6->drawLine(41, 25);
+$s6->drawLine(1, 0);
+$s6->movePenTo(140, -52);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(140, -63);
+$s6->drawLine(-40, -69);
+$s6->drawLine(-124, 89);
+$s6->drawLine(0, 1);
+$s6->drawLine(24, 41);
+$s6->drawLine(0, 1);
+$s6->movePenTo(148, -24);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(2, 24);
+$s6->drawLine(-2, 24);
+$s6->drawLine(152, 16);
+$s6->drawLine(0, -80);
+$s6->drawLine(-152, 16);
+$s6->movePenTo(280, 116);
+$s6->setLeftFill(0xff, 0xff, 0xff);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-140, -63);
+$s6->drawCurve(-8, 22, -16, 20);
+$s6->drawLine(124, 90);
+$s6->drawLine(40, -69);
+$s6->movePenTo(95, 116);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-41, 25);
+$s6->drawLine(62, 139);
+$s6->drawLine(69, -40);
+$s6->drawLine(-90, -124);
+$s6->movePenTo(24, 149);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-25, 2);
+$s6->drawLine(-23, -2);
+$s6->drawLine(-16, 151);
+$s6->drawLine(80, 0);
+$s6->drawLine(-15, -151);
+$s6->drawLine(-1, 0);
+$s6->movePenTo(-240, -184);
+$s6->setLeftFill();
+$s6->setRightFill(0xff, 0xff, 0xff, 0x99);
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(124, 89);
+$s6->drawCurve(-17, 19, -8, 23);
+$s6->drawLine(-139, -62);
+$s6->drawLine(40, -69);
+$s6->movePenTo(-52, -140);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-63, -140);
+$s6->drawLine(-69, 40);
+$s6->drawLine(89, 124);
+$s6->drawCurve(19, -16, 23, -8);
+$s6->drawLine(1, 0);
+$s6->movePenTo(-148, -24);
+$s6->setLeftFill();
+$s6->setRightFill(0xff, 0xff, 0xff, 0x8d);
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-2, 24);
+$s6->drawLine(2, 24);
+$s6->drawLine(-151, 16);
+$s6->drawLine(0, -80);
+$s6->drawLine(151, 16);
+$s6->movePenTo(-95, 117);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-89, 123);
+$s6->drawLine(69, 40);
+$s6->drawLine(62, -138);
+$s6->drawCurve(-23, -9, -19, -16);
+$s6->movePenTo(-141, 54);
+$s6->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s6->setRightFill();
+#$s6->setLine(0,0,0,0);
+$s6->drawLine(-139, 62);
+$s6->drawLine(41, 69);
+$s6->drawLine(123, -89);
+$s6->drawLine(-25, -42);
+
+### Shape 7 ###
+$s7 = new SWF::Shape();
+$s7->movePenTo(25, -147);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(16, -153);
+$s7->drawLine(-81, 0);
+$s7->drawLine(16, 152);
+$s7->drawLine(23, -1);
+$s7->drawLine(25, 2);
+$s7->drawLine(1, 0);
+$s7->movePenTo(95, -115);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(90, -124);
+$s7->drawLine(-70, -40);
+$s7->drawLine(-62, 139);
+$s7->drawLine(41, 25);
+$s7->drawLine(1, 0);
+$s7->movePenTo(140, -52);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(140, -63);
+$s7->drawLine(-40, -69);
+$s7->drawLine(-124, 90);
+$s7->drawLine(24, 41);
+$s7->drawLine(0, 1);
+$s7->movePenTo(300, -40);
+$s7->setLeftFill();
+$s7->setRightFill(0xff, 0xff, 0xff, 0xcc);
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(0, 81);
+$s7->drawLine(-152, -16);
+$s7->drawLine(0, -1);
+$s7->drawLine(2, -24);
+$s7->drawLine(-2, -24);
+$s7->drawLine(152, -16);
+$s7->movePenTo(280, 116);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(-140, -63);
+$s7->drawCurve(-8, 22, -16, 20);
+$s7->drawLine(124, 90);
+$s7->drawLine(40, -69);
+$s7->movePenTo(95, 116);
+$s7->setLeftFill(0xff, 0xff, 0xff);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(-41, 25);
+$s7->drawLine(-1, 0);
+$s7->drawLine(63, 139);
+$s7->drawLine(69, -40);
+$s7->drawLine(-90, -124);
+$s7->movePenTo(24, 149);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(-25, 2);
+$s7->drawLine(-23, -2);
+$s7->drawLine(-16, 151);
+$s7->drawLine(81, 0);
+$s7->drawLine(-16, -151);
+$s7->drawLine(-1, 0);
+$s7->movePenTo(-239, -184);
+$s7->setLeftFill();
+$s7->setRightFill(0xff, 0xff, 0xff, 0x8d);
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(123, 89);
+$s7->drawCurve(-17, 19, -8, 23);
+$s7->drawLine(-138, -62);
+$s7->drawLine(40, -69);
+$s7->movePenTo(-53, -140);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(-62, -140);
+$s7->drawLine(-69, 40);
+$s7->drawLine(89, 124);
+$s7->drawCurve(19, -16, 23, -8);
+$s7->movePenTo(-300, -40);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(0, 81);
+$s7->drawLine(152, -16);
+$s7->drawLine(0, -1);
+$s7->drawLine(-2, -24);
+$s7->drawLine(2, -24);
+$s7->drawLine(-152, -16);
+$s7->movePenTo(-141, 53);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawLine(-139, 63);
+$s7->drawLine(40, 69);
+$s7->drawLine(124, -89);
+$s7->drawLine(-25, -43);
+$s7->movePenTo(-53, 142);
+$s7->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s7->setRightFill();
+#$s7->setLine(0,0,0,0);
+$s7->drawCurve(-23, -9, -19, -16);
+$s7->drawLine(-89, 123);
+$s7->drawLine(69, 40);
+$s7->drawLine(62, -138);
+
+### Shape 8 ###
+$s8 = new SWF::Shape();
+$s8->movePenTo(25, -147);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(15, -153);
+$s8->drawLine(-80, 0);
+$s8->drawLine(16, 152);
+$s8->drawLine(23, -1);
+$s8->drawLine(25, 2);
+$s8->drawLine(1, 0);
+$s8->movePenTo(95, -115);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(90, -124);
+$s8->drawLine(-69, -41);
+$s8->drawLine(-63, 140);
+$s8->drawLine(41, 25);
+$s8->drawLine(1, 0);
+$s8->movePenTo(140, -52);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(140, -63);
+$s8->drawLine(-40, -69);
+$s8->drawLine(-124, 90);
+$s8->drawLine(24, 41);
+$s8->drawLine(0, 1);
+$s8->movePenTo(300, -40);
+$s8->setLeftFill();
+$s8->setRightFill(0xff, 0xff, 0xff, 0xc0);
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(0, 80);
+$s8->drawLine(-152, -15);
+$s8->drawLine(0, -1);
+$s8->drawLine(2, -24);
+$s8->drawLine(-2, -24);
+$s8->drawLine(152, -16);
+$s8->movePenTo(240, 185);
+$s8->setLeftFill();
+$s8->setRightFill(0xff, 0xff, 0xff, 0xcc);
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(-124, -90);
+$s8->drawCurve(16, -20, 8, -22);
+$s8->drawLine(140, 63);
+$s8->drawLine(-40, 69);
+$s8->movePenTo(95, 116);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(-41, 25);
+$s8->drawLine(62, 139);
+$s8->drawLine(69, -40);
+$s8->drawLine(-90, -124);
+$s8->movePenTo(24, 149);
+$s8->setLeftFill(0xff, 0xff, 0xff);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(-25, 2);
+$s8->drawLine(-23, -2);
+$s8->drawLine(-16, 151);
+$s8->drawLine(80, 0);
+$s8->drawLine(-15, -151);
+$s8->drawLine(-1, 0);
+$s8->movePenTo(-280, -115);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(139, 62);
+$s8->drawCurve(8, -23, 17, -19);
+$s8->drawLine(-124, -89);
+$s8->drawLine(-40, 69);
+$s8->movePenTo(-52, -140);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(-63, -139);
+$s8->drawLine(-69, 40);
+$s8->drawLine(89, 123);
+$s8->drawCurve(19, -16, 23, -8);
+$s8->drawLine(1, 0);
+$s8->movePenTo(-300, -40);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(0, 80);
+$s8->drawLine(152, -15);
+$s8->drawLine(0, -1);
+$s8->drawLine(-2, -24);
+$s8->drawLine(2, -24);
+$s8->drawLine(-152, -16);
+$s8->movePenTo(-140, 54);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawLine(-140, 62);
+$s8->drawLine(40, 69);
+$s8->drawLine(124, -89);
+$s8->drawCurve(-17, -20, -7, -22);
+$s8->movePenTo(-53, 142);
+$s8->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s8->setRightFill();
+#$s8->setLine(0,0,0,0);
+$s8->drawCurve(-23, -9, -19, -16);
+$s8->drawLine(-89, 123);
+$s8->drawLine(69, 40);
+$s8->drawLine(62, -138);
+
+### Shape 9 ###
+$s9 = new SWF::Shape();
+$s9->movePenTo(25, -147);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(15, -152);
+$s9->drawLine(-80, 0);
+$s9->drawLine(16, 151);
+$s9->drawLine(23, -1);
+$s9->drawLine(25, 2);
+$s9->drawLine(1, 0);
+$s9->movePenTo(95, -115);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(90, -125);
+$s9->drawLine(-69, -40);
+$s9->drawLine(-63, 140);
+$s9->drawLine(41, 25);
+$s9->drawLine(1, 0);
+$s9->movePenTo(140, -52);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(140, -63);
+$s9->drawLine(-40, -69);
+$s9->drawLine(-124, 89);
+$s9->drawLine(0, 1);
+$s9->drawLine(24, 41);
+$s9->drawLine(0, 1);
+$s9->movePenTo(300, -40);
+$s9->setLeftFill();
+$s9->setRightFill(0xff, 0xff, 0xff, 0xb3);
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(0, 80);
+$s9->drawLine(-152, -15);
+$s9->drawLine(0, -1);
+$s9->drawLine(2, -24);
+$s9->drawLine(-2, -24);
+$s9->drawLine(152, -16);
+$s9->movePenTo(240, 185);
+$s9->setLeftFill();
+$s9->setRightFill(0xff, 0xff, 0xff, 0xc0);
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(-124, -90);
+$s9->drawCurve(16, -20, 8, -22);
+$s9->drawLine(140, 63);
+$s9->drawLine(-40, 69);
+$s9->movePenTo(95, 116);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(-41, 25);
+$s9->drawLine(-1, 0);
+$s9->drawLine(62, 139);
+$s9->drawLine(70, -40);
+$s9->drawLine(-90, -124);
+$s9->movePenTo(24, 149);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(-25, 2);
+$s9->drawLine(-23, -2);
+$s9->drawLine(-16, 151);
+$s9->drawLine(80, 0);
+$s9->drawLine(-15, -151);
+$s9->drawLine(-1, 0);
+$s9->movePenTo(-280, -115);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(139, 62);
+$s9->drawCurve(8, -23, 17, -19);
+$s9->drawLine(-124, -89);
+$s9->drawLine(-40, 69);
+$s9->movePenTo(-53, -140);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(-62, -140);
+$s9->drawLine(-70, 41);
+$s9->drawLine(90, 123);
+$s9->drawCurve(19, -16, 23, -8);
+$s9->movePenTo(-300, -40);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(0, 80);
+$s9->drawLine(152, -15);
+$s9->drawLine(0, -1);
+$s9->drawLine(-2, -24);
+$s9->drawLine(2, -24);
+$s9->drawLine(-152, -16);
+$s9->movePenTo(-95, 117);
+$s9->setLeftFill(0xff, 0xff, 0xff);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(-89, 123);
+$s9->drawLine(69, 40);
+$s9->drawLine(62, -138);
+$s9->drawCurve(-23, -9, -19, -16);
+$s9->movePenTo(-141, 54);
+$s9->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s9->setRightFill();
+#$s9->setLine(0,0,0,0);
+$s9->drawLine(-139, 62);
+$s9->drawLine(41, 69);
+$s9->drawLine(123, -89);
+$s9->drawLine(-25, -42);
+
+### Shape 10 ###
+$s10 = new SWF::Shape();
+$s10->movePenTo(95, -115);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(90, -124);
+$s10->drawLine(-70, -40);
+$s10->drawLine(-62, 139);
+$s10->drawLine(41, 25);
+$s10->drawLine(1, 0);
+$s10->movePenTo(140, -52);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(140, -63);
+$s10->drawLine(-40, -69);
+$s10->drawLine(-124, 90);
+$s10->drawLine(24, 41);
+$s10->drawLine(0, 1);
+$s10->movePenTo(300, -40);
+$s10->setLeftFill();
+$s10->setRightFill(0xff, 0xff, 0xff, 0xa6);
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(0, 81);
+$s10->drawLine(-152, -16);
+$s10->drawLine(0, -1);
+$s10->drawLine(2, -24);
+$s10->drawLine(-2, -24);
+$s10->drawLine(152, -16);
+$s10->movePenTo(40, -300);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(-80, 0);
+$s10->drawLine(16, 152);
+$s10->drawLine(23, -1);
+$s10->drawLine(25, 2);
+$s10->drawLine(16, -153);
+$s10->movePenTo(240, 185);
+$s10->setLeftFill();
+$s10->setRightFill(0xff, 0xff, 0xff, 0xb3);
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(-124, -90);
+$s10->drawCurve(16, -20, 8, -22);
+$s10->drawLine(140, 62);
+$s10->drawLine(-40, 70);
+$s10->movePenTo(95, 116);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(-41, 25);
+$s10->drawLine(-1, 0);
+$s10->drawLine(63, 139);
+$s10->drawLine(69, -40);
+$s10->drawLine(-90, -124);
+$s10->movePenTo(24, 149);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(-25, 2);
+$s10->drawLine(-23, -2);
+$s10->drawLine(-16, 151);
+$s10->drawLine(80, 0);
+$s10->drawLine(-15, -151);
+$s10->drawLine(-1, 0);
+$s10->movePenTo(-280, -115);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(139, 62);
+$s10->drawCurve(8, -23, 16, -19);
+$s10->drawLine(-123, -89);
+$s10->drawLine(-40, 69);
+$s10->movePenTo(-53, -140);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(-62, -140);
+$s10->drawLine(-69, 40);
+$s10->drawLine(89, 124);
+$s10->drawCurve(19, -16, 23, -8);
+$s10->movePenTo(-300, -40);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(0, 81);
+$s10->drawLine(152, -16);
+$s10->drawLine(0, -1);
+$s10->drawLine(-2, -24);
+$s10->drawLine(2, -24);
+$s10->drawLine(-152, -16);
+$s10->movePenTo(-141, 53);
+$s10->setLeftFill(0xff, 0xff, 0xff);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawLine(-139, 63);
+$s10->drawLine(40, 69);
+$s10->drawLine(124, -89);
+$s10->drawLine(-25, -43);
+$s10->movePenTo(-53, 142);
+$s10->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s10->setRightFill();
+#$s10->setLine(0,0,0,0);
+$s10->drawCurve(-23, -9, -19, -16);
+$s10->drawLine(-89, 123);
+$s10->drawLine(69, 40);
+$s10->drawLine(62, -138);
+
+### Shape 11 ###
+$s11 = new SWF::Shape();
+$s11->movePenTo(25, -147);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(15, -153);
+$s11->drawLine(-80, 0);
+$s11->drawLine(16, 152);
+$s11->drawLine(23, -1);
+$s11->drawLine(25, 2);
+$s11->drawLine(1, 0);
+$s11->movePenTo(95, -115);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(90, -125);
+$s11->drawLine(-70, -40);
+$s11->drawLine(-62, 140);
+$s11->drawLine(41, 25);
+$s11->drawLine(1, 0);
+$s11->movePenTo(140, -52);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0x8d);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(140, -63);
+$s11->drawLine(-40, -69);
+$s11->drawLine(-124, 90);
+$s11->drawLine(24, 41);
+$s11->drawLine(0, 1);
+$s11->movePenTo(300, -40);
+$s11->setLeftFill();
+$s11->setRightFill(0xff, 0xff, 0xff, 0x99);
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(0, 80);
+$s11->drawLine(-152, -15);
+$s11->drawLine(0, -1);
+$s11->drawLine(2, -24);
+$s11->drawLine(-2, -24);
+$s11->drawLine(152, -16);
+$s11->movePenTo(240, 185);
+$s11->setLeftFill();
+$s11->setRightFill(0xff, 0xff, 0xff, 0xa6);
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(-124, -90);
+$s11->drawCurve(16, -20, 8, -22);
+$s11->drawLine(140, 63);
+$s11->drawLine(-40, 69);
+$s11->movePenTo(53, 141);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(62, 139);
+$s11->drawLine(70, -40);
+$s11->drawLine(-90, -124);
+$s11->drawLine(-41, 25);
+$s11->drawLine(-1, 0);
+$s11->movePenTo(24, 149);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(-25, 2);
+$s11->drawLine(-23, -2);
+$s11->drawLine(-16, 151);
+$s11->drawLine(80, 0);
+$s11->drawLine(-15, -151);
+$s11->drawLine(-1, 0);
+$s11->movePenTo(-280, -115);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(139, 62);
+$s11->drawCurve(8, -23, 17, -19);
+$s11->drawLine(-124, -89);
+$s11->drawLine(-40, 69);
+$s11->movePenTo(-53, -140);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(-62, -140);
+$s11->drawLine(-69, 40);
+$s11->drawLine(89, 124);
+$s11->drawCurve(19, -16, 23, -8);
+$s11->movePenTo(-300, -40);
+$s11->setLeftFill(0xff, 0xff, 0xff);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(0, 80);
+$s11->drawLine(152, -15);
+$s11->drawLine(0, -1);
+$s11->drawLine(-2, -24);
+$s11->drawLine(2, -24);
+$s11->drawLine(-152, -16);
+$s11->movePenTo(-95, 117);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(-90, 123);
+$s11->drawLine(70, 40);
+$s11->drawLine(62, -138);
+$s11->drawCurve(-23, -9, -19, -16);
+$s11->movePenTo(-140, 54);
+$s11->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s11->setRightFill();
+#$s11->setLine(0,0,0,0);
+$s11->drawLine(-140, 62);
+$s11->drawLine(40, 69);
+$s11->drawLine(124, -89);
+$s11->drawCurve(-17, -20, -7, -22);
+
+### Shape 12 ###
+$s12 = new SWF::Shape();
+$s12->movePenTo(95, -115);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(90, -125);
+$s12->drawLine(-69, -40);
+$s12->drawLine(-63, 140);
+$s12->drawLine(41, 25);
+$s12->drawLine(1, 0);
+$s12->movePenTo(140, -53);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(140, -62);
+$s12->drawLine(-40, -70);
+$s12->drawLine(-124, 90);
+$s12->drawLine(0, 1);
+$s12->drawLine(24, 41);
+$s12->movePenTo(300, -40);
+$s12->setLeftFill();
+$s12->setRightFill(0xff, 0xff, 0xff, 0x8d);
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(0, 80);
+$s12->drawLine(-152, -15);
+$s12->drawLine(0, -1);
+$s12->drawLine(2, -24);
+$s12->drawLine(-2, -24);
+$s12->drawLine(152, -16);
+$s12->movePenTo(40, -300);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-80, 0);
+$s12->drawLine(16, 152);
+$s12->drawLine(23, -1);
+$s12->drawLine(25, 2);
+$s12->drawLine(16, -153);
+$s12->movePenTo(240, 185);
+$s12->setLeftFill();
+$s12->setRightFill(0xff, 0xff, 0xff, 0x99);
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-124, -90);
+$s12->drawCurve(16, -20, 8, -22);
+$s12->drawLine(140, 63);
+$s12->drawLine(-40, 69);
+$s12->movePenTo(95, 116);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-41, 25);
+$s12->drawLine(-1, 0);
+$s12->drawLine(62, 139);
+$s12->drawLine(70, -40);
+$s12->drawLine(-90, -124);
+$s12->movePenTo(40, 300);
+$s12->setLeftFill();
+$s12->setRightFill(0xff, 0xff, 0xff, 0xb3);
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-80, 0);
+$s12->drawLine(16, -151);
+$s12->drawLine(23, 2);
+$s12->drawLine(25, -2);
+$s12->drawLine(16, 151);
+$s12->movePenTo(-280, -115);
+$s12->setLeftFill(0xff, 0xff, 0xff);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(139, 62);
+$s12->drawCurve(8, -23, 17, -19);
+$s12->drawLine(-124, -89);
+$s12->drawLine(-40, 69);
+$s12->movePenTo(-53, -140);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-62, -140);
+$s12->drawLine(-70, 41);
+$s12->drawLine(90, 123);
+$s12->drawCurve(19, -16, 23, -8);
+$s12->movePenTo(-300, -40);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(0, 80);
+$s12->drawLine(152, -15);
+$s12->drawLine(0, -1);
+$s12->drawLine(-2, -24);
+$s12->drawLine(2, -24);
+$s12->drawLine(-152, -16);
+$s12->movePenTo(-95, 117);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-89, 123);
+$s12->drawLine(69, 40);
+$s12->drawLine(62, -138);
+$s12->drawCurve(-23, -9, -19, -16);
+$s12->movePenTo(-141, 53);
+$s12->setLeftFill(0xff, 0xff, 0xff, 0xcc);
+$s12->setRightFill();
+#$s12->setLine(0,0,0,0);
+$s12->drawLine(-139, 62);
+$s12->drawLine(40, 70);
+$s12->drawLine(124, -89);
+$s12->drawLine(-25, -43);
+
+### Shape 13 ###
+$s13 = new SWF::Shape();
+$s13->movePenTo(140, -52);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0x73);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(140, -63);
+$s13->drawLine(-40, -69);
+$s13->drawLine(-124, 89);
+$s13->drawLine(0, 1);
+$s13->drawLine(24, 41);
+$s13->drawLine(0, 1);
+$s13->movePenTo(94, -115);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0x66);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(91, -125);
+$s13->drawLine(-69, -40);
+$s13->drawLine(-63, 140);
+$s13->drawLine(41, 25);
+$s13->movePenTo(148, -24);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0x80);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(2, 24);
+$s13->drawLine(-2, 24);
+$s13->drawLine(152, 16);
+$s13->drawLine(0, -80);
+$s13->drawLine(-152, 16);
+$s13->movePenTo(40, -300);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0x5a);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-80, 0);
+$s13->drawLine(16, 152);
+$s13->drawLine(23, -1);
+$s13->drawLine(25, 2);
+$s13->drawLine(16, -153);
+$s13->movePenTo(240, 185);
+$s13->setLeftFill();
+$s13->setRightFill(0xff, 0xff, 0xff, 0x8d);
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-124, -90);
+$s13->drawCurve(16, -20, 8, -22);
+$s13->drawLine(140, 62);
+$s13->drawLine(-40, 70);
+$s13->movePenTo(95, 116);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0x99);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-41, 25);
+$s13->drawLine(-1, 0);
+$s13->drawLine(63, 139);
+$s13->drawLine(69, -40);
+$s13->drawLine(-90, -124);
+$s13->movePenTo(24, 149);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0xa6);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-25, 2);
+$s13->drawLine(-23, -2);
+$s13->drawLine(-16, 151);
+$s13->drawLine(80, 0);
+$s13->drawLine(-15, -151);
+$s13->drawLine(-1, 0);
+$s13->movePenTo(-280, -115);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0xe6);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(139, 62);
+$s13->drawCurve(8, -23, 16, -19);
+$s13->drawLine(-123, -89);
+$s13->drawLine(-40, 69);
+$s13->movePenTo(-53, -140);
+$s13->setLeftFill(0xff, 0xff, 0xff);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-62, -140);
+$s13->drawLine(-69, 40);
+$s13->drawLine(89, 124);
+$s13->drawCurve(19, -16, 23, -8);
+$s13->movePenTo(-148, -24);
+$s13->setLeftFill();
+$s13->setRightFill(0xff, 0xff, 0xff, 0xcc);
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-2, 24);
+$s13->drawLine(2, 24);
+$s13->drawLine(0, 1);
+$s13->drawLine(-152, 15);
+$s13->drawLine(0, -80);
+$s13->drawLine(152, 16);
+$s13->movePenTo(-95, 117);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0xb3);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-89, 123);
+$s13->drawLine(69, 40);
+$s13->drawLine(62, -138);
+$s13->drawCurve(-23, -9, -19, -16);
+$s13->movePenTo(-141, 53);
+$s13->setLeftFill(0xff, 0xff, 0xff, 0xc0);
+$s13->setRightFill();
+#$s13->setLine(0,0,0,0);
+$s13->drawLine(-139, 63);
+$s13->drawLine(40, 69);
+$s13->drawLine(124, -89);
+$s13->drawLine(-25, -43);
+
+### MovieClip 1 ###
+$s1 = new SWF::MovieClip();  # 14 frames
+$s1->add(new SWF::Action("
+this.gotoAndPlay(random(12) + 1);
+;
+
+"));
+$j1 = $s1->add($s2);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 1 
+
+$s1->nextFrame();  # end of clip frame 2 
+
+$s1->remove($j1);
+$j1 = $s1->add($s3);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 3 
+
+$s1->remove($j1);
+$j1 = $s1->add($s4);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 4 
+
+$s1->remove($j1);
+$j1 = $s1->add($s5);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 5 
+
+$s1->remove($j1);
+$j1 = $s1->add($s6);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 6 
+
+$s1->remove($j1);
+$j1 = $s1->add($s7);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 7 
+
+$s1->remove($j1);
+$j1 = $s1->add($s8);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 8 
+
+$s1->remove($j1);
+$j1 = $s1->add($s9);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 9 
+
+$s1->remove($j1);
+$j1 = $s1->add($s10);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 10 
+
+$s1->remove($j1);
+$j1 = $s1->add($s11);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 11 
+
+$s1->remove($j1);
+$j1 = $s1->add($s12);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 12 
+
+$s1->remove($j1);
+$j1 = $s1->add($s13);
+$j1->multColor(1.000000, 1.000000, 1.000000);
+$j1->addColor(0x00, 0x00, 0x00);
+$s1->nextFrame();  # end of clip frame 13 
+
+$s1->add(new SWF::Action("
+this.gotoAndPlay(2);
+;
+
+"));
+$s1->nextFrame();  # end of clip frame 14 
+
+$s14 = new SWF::MovieClip();  # 1 frames
+$j1 = $s14->add($s1);
+$j1->scaleTo(0.666672);
+$j1->moveTo(200, 200);
+$j1->multColor(0.000000, 0.000000, 0.000000);
+$j1->addColor(0x81, 0xac, 0xdb);
+$s14->nextFrame();  # end of clip frame 1 
+
+
+$i1 = $progressclip->add($s14);
+$i1->moveTo(20, 20);
+$i1->multColor(1.000000, 1.000000, 1.000000);
+$i1->addColor(0x00, 0x00, 0x00);
+$progressclip->nextFrame();  # end of frame 1
+
+
+$i1 = $movie->add($progressclip);
+$i1->scaleTo(0.5); 
+$i1->moveTo(4700,2550);
+$movie->nextFrame();
+$movie->nextFrame();
+$movie->nextFrame();
+
+
+$movie->add(new SWF::Action(<<ENDSCRIPT
+
+//System.useCodePage();
+
+fmtLoad = new TextFormat();
+fmtLoad.size = 20;
+fmtLoad.font = "$fuente_nombre";
+fmtLoad.color = "0x3240da";
+
+_root.createTextField('preload',getNextHighestDepth(),500,252,400,100);
+_root.preload.setNewTextFormat(fmtLoad);   
+with (_root['preload']) {
+	border = false;
+	embedFonts = true;
+}
+
+createEmptyMovieClip("fondo",-15000);
+fondo.createEmptyMovieClip("mihijo",0);
+loadMovie("background.jpg", fondo.mihijo);
+fondo._visible = true;
+fondo._x = 1;
+fondo._y = 1;
+_root.textoload._visible=false;
+
+if (fondo.mihijo.getBytesLoaded() == fondo.mihijo.getBytesTotal() && fonto.mihijo.getBytesLoaded() > 4) {
+		_root.preload.text="background";
+}
+
+
+var totalTotal  = _root.getBytesTotal() + fondo.mihijo.getBytesTotal();
+var totalLoaded = _root.getBytesLoaded() + fondo.mihijo.getBytesLoaded();
+
+
+if (totalLoaded < totalTotal){
+	var percent = Math.floor(totalLoaded*100/totalTotal);
+	//_root.preload.text=percent+ "% ";
+	prevFrame();
+ 	play();
+} else {
+	_root.preload.text="";
+	nextFrame();
+}
+
+ENDSCRIPT
+));
+$movie->nextFrame( );
+$movie->remove($i1);
+
+$movie->add(new SWF::Action(<<"EndOfActionScript"));
+
+_root.createEmptyMovieClip("soundHolder", -14345);
+_root.soundHolder.mySound = new Sound(_root.soundHolder);
+//_root.soundHolder.mySound.loadSound("pepe.mp3", true);
+//_root.soundHolder.mySound.stop();
+
+dummyVar=(getTimer()+random(100000));
+
+if(context != undefined) {
+	context = context.toUpperCase();
+	if(context == "DEFAULT") {	context=""; }
+} else {
+	context="";
+}
+
+if(nohighlight != undefined) {
+    _global.nohighlight = Number(nohighlight);
+} else {
+    _global.nohighlight = 0;
+}
+
+if(mybutton != undefined) {
+    mybutton = Number(mybutton);
+}
+
+if(restrict != undefined) {
+	_global.restrict = restrict;
+} else {
+	delete _global.restrict;
+}
+
+if(dial != undefined) {
+//	dial = Number(dial);
+	dial = dial;
+	_root.logea("dial "+dial);
+} else {
+	dial = 0;
+}
+
+var archivo = "variables"+context+".txt?aldope="+dummyVar;
+
+vr = new LoadVars ();
+
+vr.onLoad = function (success)
+{ 
+	if (success == true) { 
+		nextFrame();
+	} else { 
+			with (_root['preload']) {
+			    text = "Couldn't load "+archivo;
+				errorconfiguration=1;
+			    multiline = true;
+				wordWrap = true;
+//			    border = true;
+//				prevFrame();
+			}
+		stop();
+	}
+};
+
+vr.load(archivo);
+
+EndOfActionScript
+
+$movie->nextFrame();
+
+#$font_general = new SWF::Font($fuente);  
+
+# Ventana INPUT del security code
+$codebox = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$g = new SWF::Gradient();
+$g->addEntry(0.000000, 0xff, 0xff, 0xff);
+$g->addEntry(0.015686, 0xe2, 0xe2, 0xe2);
+$g->addEntry(0.964706, 0x9d, 0x9d, 0x9d);
+$g->addEntry(1.000000, 0x5a, 0x5a, 0x5a);
+$f2 = $s1->addFill($g, SWFFILL_LINEAR_GRADIENT);
+$f2->scaleTo(0.24, 0.24);
+$f2->moveTo(-35, 37);
+$s1->movePenTo(2074, -1915);
+$s1->setLeftFill(0x66, 0x66, 0x66, 0x39);
+$s1->setLine(20, 0xc5, 0xc5, 0xc5, 0x39);
+$s1->drawCurve(-29, -31, -41, 0);
+$s1->drawLine(-3939, 0);
+$s1->drawCurve(-41, 0, -30, 31);
+$s1->drawCurve(-29, 32, 0, 44);
+$s1->drawLine(0, 3945);
+$s1->drawCurve(0, 44, 29, 31);
+$s1->drawCurve(30, 33, 41, 0);
+$s1->drawLine(3939, 0);
+$s1->drawCurve(41, 0, 29, -33);
+$s1->drawCurve(30, -31, 0, -44);
+$s1->drawLine(0, -3945);
+$s1->drawCurve(0, -44, -30, -32);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(2005, -2023);
+$s1->setLeftFill($f2);
+$s1->setLine(20, 0x66, 0x66, 0x66);
+$s1->drawCurve(-29, -31, -41, 0);
+$s1->drawLine(-3939, 0);
+$s1->drawCurve(-41, 0, -30, 31);
+$s1->drawCurve(-29, 33, 0, 44);
+$s1->drawLine(0, 3966);
+$s1->drawCurve(0, 44, 29, 32);
+$s1->drawCurve(30, 32, 41, 0);
+$s1->drawLine(3939, 0);
+$s1->drawCurve(41, 0, 29, -32);
+$s1->drawCurve(30, -32, 0, -44);
+$s1->drawLine(0, -3966);
+$s1->drawCurve(0, -44, -30, -33);
+
+### MovieClip 2 ###
+$s2 = new SWF::MovieClip();  # 1 frames
+$s2->add($s1);
+$s2->nextFrame();  # end of clip frame 1 
+
+
+$i1 = $codebox->add($s2);
+$i1->scaleTo(1.427750, 0.540558);
+$i1->moveTo(5509, 3957);
+$i1->setName('inputCode');
+
+### Shape 3 ###
+$s3 = new SWF::Shape();
+$s3->movePenTo(3094, 4290);
+$s3->setRightFill(0xcc, 0xcc, 0xcc);
+$s3->setLine(20, 0x99, 0x99, 0x99);
+$s3->drawLine(0, -580);
+$s3->drawLine(4713, 0);
+$s3->setLine(20, 0xcc, 0xcc, 0xcc);
+$s3->drawLine(0, 580);
+$s3->drawLine(-4713, 0);
+$i4 = $codebox->add($s3);
+
+$s5 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_MULTILINE | SWFTEXTFIELD_NOSELECT | SWFTEXTFIELD_USEFONT );
+$s5->setBounds(5650, 653);
+$s5->setFont($font_general);
+$s5->setHeight(320);
+$s5->setColor(0x00, 0x00, 0x00, 0xff);
+$s5->align(SWFTEXTFIELD_ALIGN_CENTER);
+$s5->setName('title');
+$s5->addString('Please enter the security code:');
+$i5 = $codebox->add($s5);
+$i5->moveTo(2704, 3067);
+
+$s6 = new SWF::TextField( SWFTEXTFIELD_PASSWORD | SWFTEXTFIELD_USEFONT );
+$s6->setBounds(4579, 398);
+$s6->setFont($font_general);
+$s6->setHeight(320);
+$s6->setColor(0x00, 0x00, 0x00, 0xff);
+$s6->align(SWFTEXTFIELD_ALIGN_LEFT);
+$i6 = $codebox->add($s6);
+$i6->moveTo(3189, 3821);
+$i6->setName('claveform');
+
+### Shape 7 ###
+$s7 = new SWF::Shape();
+$s7->movePenTo(-500, 200);
+$s7->setRightFill(0xcc, 0xcc, 0xcc);
+$s7->setLine(20, 0x99, 0x99, 0x99);
+$s7->drawLine(0, -400);
+$s7->drawLine(1000, 0);
+$s7->setLine(20, 0x00, 0x00, 0x00);
+$s7->drawLine(0, 400);
+$s7->drawLine(-1000, 0);
+
+$s8 = new SWF::Text;
+$s8->setFont($font_general);
+$s8->setHeight(280);
+$s8->setColor(0x00, 0x00, 0x33, 0xff);
+$s8->moveTo(-180,100);
+$s8->addString('OK');
+
+### Shape 9 ###
+$s9 = new SWF::Shape();
+$s9->movePenTo(-500, 200);
+$s9->setRightFill(0xcc, 0xcc, 0xcc);
+$s9->setLine(20, 0x99, 0x99, 0x99);
+$s9->drawLine(0, -400);
+$s9->drawLine(1000, 0);
+$s9->setLine(20, 0x00, 0x00, 0x00);
+$s9->drawLine(0, 400);
+$s9->drawLine(-1000, 0);
+
+$s11 = new SWF::Shape();
+$s11->movePenTo(500, -200);
+$s11->setRightFill(0xcc, 0xcc, 0xcc);
+$s11->setLine(20, 0x99, 0x99, 0x99);
+$s11->drawLine(0, 400);
+$s11->drawLine(-1000, 0);
+$s11->setLine(20, 0x00, 0x00, 0x00);
+$s11->drawLine(0, -400);
+$s11->drawLine(1000, 0);
+
+
+### Button2 13 ###
+$s13 = new SWF::Button();
+$s13->addShape($s7, SWFBUTTON_UP);
+$s13->addShape($s8, SWFBUTTON_UP);
+$s13->addShape($s9, SWFBUTTON_OVER);
+$s13->addShape($s8, SWFBUTTON_OVER);
+$s13->addShape($s11, SWFBUTTON_HIT | SWFBUTTON_DOWN);
+$s13->addShape($s8, SWFBUTTON_HIT | SWFBUTTON_DOWN);
+$a = new SWF::Action("
+_global.claveingresada = this.claveform.text;
+_root.LocalSave('auth','clave',_global.claveingresada);
+this._visible = false;
+_root.envia_comando('bogus', 0, 0);
+;
+");
+$s13->addAction($a, SWFBUTTON_MOUSEUP);
+
+$i7 = $codebox->add($s13);
+$i7->moveTo(5454, 4725);
+
+### Shape 14 ###
+$s14 = new SWF::Shape();
+$s14->movePenTo(228, -228);
+$s14->setRightFill(0x99, 0x99, 0x99);
+$s14->setLine(20, 0x00, 0x00, 0x00);
+$s14->drawLine(0, 456);
+$s14->drawLine(-456, 0);
+$s14->setLine(20, 0xcc, 0xcc, 0xcc);
+$s14->drawLine(0, -456);
+$s14->drawLine(456, 0);
+$s14->setLeftFill();
+$s14->setRightFill();
+$s14->movePenTo(120, 132);
+$s14->setLine(60, 0xcc, 0xcc, 0xcc);
+$s14->drawLine(-120, -117);
+$s14->drawLine(-112, 121);
+$s14->movePenTo(-120, -102);
+$s14->drawLine(120, 117);
+$s14->drawLine(112, -120);
+$s14->setLeftFill();
+$s14->setRightFill();
+$s14->movePenTo(120, 102);
+$s14->setLine(60, 0x00, 0x00, 0x00);
+$s14->drawLine(-120, -117);
+$s14->drawLine(-112, 121);
+$s14->movePenTo(-120, -132);
+$s14->drawLine(120, 117);
+$s14->drawLine(112, -120);
+
+### Shape 15 ###
+$s15 = new SWF::Shape();
+$s15->movePenTo(228, -228);
+$s15->setRightFill(0x99, 0x99, 0x99);
+$s15->setLine(20, 0x00, 0x00, 0x00);
+$s15->drawLine(0, 456);
+$s15->drawLine(-456, 0);
+$s15->setLine(20, 0xcc, 0xcc, 0xcc);
+$s15->drawLine(0, -456);
+$s15->drawLine(456, 0);
+$s15->setLeftFill();
+$s15->setRightFill();
+$s15->movePenTo(120, 132);
+$s15->setLine(60, 0xcc, 0xcc, 0xcc);
+$s15->drawLine(-120, -117);
+$s15->drawLine(-112, 121);
+$s15->movePenTo(-120, -102);
+$s15->drawLine(120, 117);
+$s15->drawLine(112, -120);
+$s15->setLeftFill();
+$s15->setRightFill();
+$s15->movePenTo(120, 102);
+$s15->setLine(60, 0x00, 0x00, 0x00);
+$s15->drawLine(-120, -117);
+$s15->drawLine(-112, 121);
+$s15->movePenTo(-120, -132);
+$s15->drawLine(120, 117);
+$s15->drawLine(112, -120);
+
+### Shape 16 ###
+$s16 = new SWF::Shape();
+$s16->movePenTo(228, -228);
+$s16->setRightFill(0x99, 0x99, 0x99);
+$s16->setLine(20, 0x00, 0x00, 0x00);
+$s16->drawLine(0, 456);
+$s16->drawLine(-456, 0);
+$s16->setLine(20, 0xcc, 0xcc, 0xcc);
+$s16->drawLine(0, -456);
+$s16->drawLine(456, 0);
+$s16->setLeftFill();
+$s16->setRightFill();
+$s16->movePenTo(120, 132);
+$s16->setLine(60, 0xcc, 0xcc, 0xcc);
+$s16->drawLine(-120, -117);
+$s16->drawLine(-112, 121);
+$s16->movePenTo(-120, -102);
+$s16->drawLine(120, 117);
+$s16->drawLine(112, -120);
+$s16->setLeftFill();
+$s16->setRightFill();
+$s16->movePenTo(122, 120);
+$s16->setLine(60, 0x00, 0x00, 0x00);
+$s16->drawLine(-120, -117);
+$s16->drawLine(-112, 121);
+$s16->movePenTo(-118, -114);
+$s16->drawLine(120, 117);
+$s16->drawLine(112, -120);
+
+### Button2 17 ###
+$s17 = new SWF::Button();
+$s17->addShape($s14, SWFBUTTON_UP);
+$s17->addShape($s15, SWFBUTTON_OVER);
+$s17->addShape($s16, SWFBUTTON_DOWN);
+$s17->addShape($s16, SWFBUTTON_HIT);
+$a = new SWF::Action("
+this._visible = false;
+");
+$s17->addAction($a, SWFBUTTON_MOUSEUP);
+$i10 = $codebox->add($s17);
+$i10->scaleTo(0.657883);
+$i10->moveTo(8118, 3100);
+
+
+$codebox->nextFrame();  # end of frame 1
+
+# FIN DE Ventana INPUT del security code
+
+$i1=$movie->add($codebox);
+$i1->scaleTo(0.5);
+$i1->setDepth(101);
+$i1->moveTo(2400,500);
+$i1->setName("codebox");
+
+$fin = $movie->add($dropbox1);    # XXXX
+$fin->setName("selectbox1");      
+$fin->moveTo(8000,60);
+#
+# Number Dialer Catcher
+#
+# We can control movie playback from javascript, but just
+# the frame number. This bogus movieclip sets a global variable
+# with the number constructed from javascript while setting
+# the frame of the movieclip.
+#
+$numdial = new SWF::Sprite();
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="0";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 1
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="1";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 2
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="2";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 3
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="3";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 4
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="4";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 5
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="5";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 6
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="6";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 7
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="7";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 8
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="8";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 9
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar+="9";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 10
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	_global.numero_a_discar="";
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 11
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	if(_root.dial!=0) {
+		_root.logea("Dial Number "+_global.numero_a_discar);
+		_root.logea("Restrict "+_global.restrict);
+		_root.logea("Dialing from "+_root.dial);
+		if(_global.restrict != undefined)
+		{
+			_root.envia_comando("dial",_global.restrict,_global.numero_a_discar);
+		} else {
+			_root.envia_comando("dial",_root.dial,_global.numero_a_discar);
+		}
+	} else {
+		_root.logea("Dial not defined in index.html "+numero_a_discar);
+	}
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 13
+$numdial->add(new SWF::Action(<<"EndOfActionScript"));
+	stop();
+EndOfActionScript
+$numdial->nextFrame(); # End Frame 13
+
+$i1 = $movie->add($numdial);
+$i1->moveTo(-2000,-2000);
+$i1->setName("numdial");
+
+
+
+
+# Detail Window movieclip
+
+$detail_window = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$g = new SWF::Gradient();
+$g->addEntry(0.000000, 0xff, 0xff, 0xff);
+$g->addEntry(0.015686, 0xe2, 0xe2, 0xe2);
+$g->addEntry(0.964706, 0x9d, 0x9d, 0x9d);
+$g->addEntry(1.000000, 0x5a, 0x5a, 0x5a);
+$f2 = $s1->addFill($g, SWFFILL_LINEAR_GRADIENT);
+$f2->scaleTo(0.24, 0.24);
+$f2->moveTo(-35, 37);
+$s1->movePenTo(2074, -1915);
+$s1->setLeftFill(0x66, 0x66, 0x66, 0x39);
+$s1->setLine(20, 0xc5, 0xc5, 0xc5, 0x39);
+$s1->drawCurve(-29, -31, -41, 0);
+$s1->drawLine(-3939, 0);
+$s1->drawCurve(-41, 0, -30, 31);
+$s1->drawCurve(-29, 32, 0, 44);
+$s1->drawLine(0, 3945);
+$s1->drawCurve(0, 44, 29, 31);
+$s1->drawCurve(30, 33, 41, 0);
+$s1->drawLine(3939, 0);
+$s1->drawCurve(41, 0, 29, -33);
+$s1->drawCurve(30, -31, 0, -44);
+$s1->drawLine(0, -3945);
+$s1->drawCurve(0, -44, -30, -32);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->setLine(0,0,0,0);
+$s1->movePenTo(2005, -2023);
+$s1->setLeftFill($f2);
+$s1->setLine(20, 0x66, 0x66, 0x66);
+$s1->drawCurve(-29, -31, -41, 0);
+$s1->drawLine(-3939, 0);
+$s1->drawCurve(-41, 0, -30, 31);
+$s1->drawCurve(-29, 33, 0, 44);
+$s1->drawLine(0, 3966);
+$s1->drawCurve(0, 44, 29, 32);
+$s1->drawCurve(30, 32, 41, 0);
+$s1->drawLine(3939, 0);
+$s1->drawCurve(41, 0, 29, -32);
+$s1->drawCurve(30, -32, 0, -44);
+$s1->drawLine(0, -3966);
+$s1->drawCurve(0, -44, -30, -33);
+
+$s3 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_USEFONT );
+$s3->setBounds(3112, 377);
+$s3->setFont($font_general);
+$s3->setHeight(280);
+$s3->setColor(0x33, 0x33, 0x33, 0xff);
+$s3->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s3->setName('title');
+$s3->addString('Last call details:');
+
+$s5 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_USEFONT );
+$s5->setBounds(907, 330);
+$s5->setFont($font_general);
+$s5->setHeight(260);
+$s5->setColor(0x33, 0x33, 0x33, 0xff);
+$s5->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s5->setName('label');
+$s5->addString('From:');
+
+$s6 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_USEFONT );
+$s6->setBounds(1097, 330);
+$s6->setFont($font_general);
+$s6->setHeight(260);
+$s6->setColor(0x33, 0x33, 0x33, 0xff);
+$s6->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s6->setName('duration_label');
+$s6->addString('Duration:');
+
+$s7 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_USEFONT );
+$s7->setBounds(2517, 330);
+$s7->setFont($font_general);
+$s7->setHeight(260);
+$s7->setColor(0x33, 0x33, 0x33, 0xff);
+$s7->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s7->setName('clid');
+
+$s8 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_USEFONT );
+$s8->setBounds(2116, 330);
+$s8->setFont($font_general);
+$s8->setHeight(260);
+$s8->setColor(0x33, 0x33, 0x33, 0xff);
+$s8->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s8->setName('duration');
+
+### Shape 9 ###
+$s9 = new SWF::Shape();
+$s9->movePenTo(142, -141);
+$s9->setRightFill(0x33, 0x33, 0x33);
+$s9->drawCurve(58, 58, 0, 83);
+$s9->drawCurve(0, 83, -58, 59);
+$s9->drawCurve(-59, 58, -83, 0);
+$s9->drawCurve(-83, 0, -58, -58);
+$s9->drawCurve(-59, -59, 0, -83);
+$s9->drawCurve(0, -83, 59, -58);
+$s9->drawCurve(58, -59, 83, 0);
+$s9->drawCurve(83, 0, 59, 59);
+$s9->setLeftFill();
+$s9->setRightFill();
+$s9->setLine(0,0,0,0);
+$s9->movePenTo(-43, -137);
+$s9->setRightFill(0xff, 0xff, 0xff);
+$s9->drawLine(192, 136);
+$s9->drawLine(-192, 139);
+$s9->drawLine(0, -67);
+$s9->drawLine(-66, -1);
+$s9->drawLine(0, -143);
+$s9->drawLine(66, 0);
+$s9->drawLine(0, -64);
+
+### Button2 10 ###
+$s10 = new SWF::Button();
+$s10->addShape($s9, SWFBUTTON_HIT | SWFBUTTON_DOWN | SWFBUTTON_OVER | SWFBUTTON_UP);
+$a = new SWF::Action("
+_root.superdetails._visible = true;
+_root.detail._visible = false;
+//_root.superdetails.tab1.gotoAndStop(1);
+//_root.superdetails.tab2.gotoAndStop(2); 
+
+				if(_global.superdetailstexttab1 == undefined) {
+					_global.superdetailstexttab1 = 'no data';
+				}
+				if(_global.superdetailstexttab1 == 'no data') {
+					_root.superdetails.tab1.gotoAndStop(2);
+					_root.superdetails.tab2.gotoAndStop(1);
+				    _root.superdetails.texto = _global.superdetailstexttab2;
+				} else {
+					_root.superdetails.tab1.gotoAndStop(1);
+					_root.superdetails.tab2.gotoAndStop(2);
+				    _root.superdetails.texto = _global.superdetailstexttab1;
+				}
+");
+$s10->addAction($a, SWFBUTTON_MOUSEUP);
+
+### Shape 11 ###
+$s11 = new SWF::Shape();
+$s11->movePenTo(228, -228);
+$s11->setRightFill(0x99, 0x99, 0x99);
+$s11->setLine(20, 0x00, 0x00, 0x00);
+$s11->drawLine(0, 456);
+$s11->drawLine(-456, 0);
+$s11->setLine(20, 0xcc, 0xcc, 0xcc);
+$s11->drawLine(0, -456);
+$s11->drawLine(456, 0);
+$s11->setLeftFill();
+$s11->setRightFill();
+$s11->setLine(0,0,0,0);
+$s11->movePenTo(120, 132);
+$s11->setLine(60, 0xcc, 0xcc, 0xcc);
+$s11->drawLine(-120, -117);
+$s11->drawLine(-112, 121);
+$s11->movePenTo(-120, -102);
+$s11->drawLine(120, 117);
+$s11->drawLine(112, -120);
+$s11->setLeftFill();
+$s11->setRightFill();
+$s11->setLine(0,0,0,0);
+$s11->movePenTo(120, 102);
+$s11->setLine(60, 0x00, 0x00, 0x00);
+$s11->drawLine(-120, -117);
+$s11->drawLine(-112, 121);
+$s11->movePenTo(-120, -132);
+$s11->drawLine(120, 117);
+$s11->drawLine(112, -120);
+
+### Shape 12 ###
+$s12 = new SWF::Shape();
+$s12->movePenTo(228, -228);
+$s12->setRightFill(0x99, 0x99, 0x99);
+$s12->setLine(20, 0x00, 0x00, 0x00);
+$s12->drawLine(0, 456);
+$s12->drawLine(-456, 0);
+$s12->setLine(20, 0xcc, 0xcc, 0xcc);
+$s12->drawLine(0, -456);
+$s12->drawLine(456, 0);
+$s12->setLeftFill();
+$s12->setRightFill();
+$s12->setLine(0,0,0,0);
+$s12->movePenTo(120, 132);
+$s12->setLine(60, 0xcc, 0xcc, 0xcc);
+$s12->drawLine(-120, -117);
+$s12->drawLine(-112, 121);
+$s12->movePenTo(-120, -102);
+$s12->drawLine(120, 117);
+$s12->drawLine(112, -120);
+$s12->setLeftFill();
+$s12->setRightFill();
+$s12->setLine(0,0,0,0);
+$s12->movePenTo(120, 102);
+$s12->setLine(60, 0x00, 0x00, 0x00);
+$s12->drawLine(-120, -117);
+$s12->drawLine(-112, 121);
+$s12->movePenTo(-120, -132);
+$s12->drawLine(120, 117);
+$s12->drawLine(112, -120);
+
+### Shape 13 ###
+$s13 = new SWF::Shape();
+$s13->movePenTo(228, -228);
+$s13->setRightFill(0x99, 0x99, 0x99);
+$s13->setLine(20, 0x00, 0x00, 0x00);
+$s13->drawLine(0, 456);
+$s13->drawLine(-456, 0);
+$s13->setLine(20, 0xcc, 0xcc, 0xcc);
+$s13->drawLine(0, -456);
+$s13->drawLine(456, 0);
+$s13->setLeftFill();
+$s13->setRightFill();
+$s13->setLine(0,0,0,0);
+$s13->movePenTo(120, 132);
+$s13->setLine(60, 0xcc, 0xcc, 0xcc);
+$s13->drawLine(-120, -117);
+$s13->drawLine(-112, 121);
+$s13->movePenTo(-120, -102);
+$s13->drawLine(120, 117);
+$s13->drawLine(112, -120);
+$s13->setLeftFill();
+$s13->setRightFill();
+$s13->setLine(0,0,0,0);
+$s13->movePenTo(122, 120);
+$s13->setLine(60, 0x00, 0x00, 0x00);
+$s13->drawLine(-120, -117);
+$s13->drawLine(-112, 121);
+$s13->movePenTo(-118, -114);
+$s13->drawLine(120, 117);
+$s13->drawLine(112, -120);
+
+### Button2 14 ###
+$s14 = new SWF::Button();
+$s14->addShape($s11, SWFBUTTON_UP);
+$s14->addShape($s12, SWFBUTTON_OVER);
+$s14->addShape($s13, SWFBUTTON_DOWN);
+$s14->addShape($s13, SWFBUTTON_HIT);
+$a = new SWF::Action("
+_root.detail._visible = false;
+this._visible = false;
+_root.superdetails._visible = false;
+
+");
+$s14->addAction($a, SWFBUTTON_MOUSEUP);
+
+$j2 = $detail_window->add($s1);
+$j2->scaleTo(0.950256, 0.391327);
+$j2->moveTo(2036, 737);
+$j3 = $detail_window->add($s3);
+$j3->moveTo(163, 37);
+$j4 = $detail_window->add($s5);
+$j4->moveTo(207, 523);
+$j5 = $detail_window->add($s6);
+$j5->moveTo(207, 979);
+$j6 = $detail_window->add($s7);
+$j6->moveTo(1402, 526);
+$j7 = $detail_window->add($s8);
+$j7->moveTo(1404, 995);
+$j8 = $detail_window->add($s10);
+$j8->scaleTo(0.800003);
+$j8->moveTo(3746, 1267);
+$j11 = $detail_window->add($s14);
+$j11->scaleTo(0.561401);
+$j11->moveTo(3720, 180);
+$detail_window->nextFrame();  # end of clip frame 1 
+
+$i1=$movie->add($detail_window);
+$i1->scaleTo(0.5);
+$i1->setName("detail");
+
+
+
+#  Superdetail window
+$superdetails = new SWF::Sprite();
+$s1 = new SWF::Shape();
+$g = new SWF::Gradient();
+$g->addEntry(0.000000, 0xff, 0xff, 0xff);
+$g->addEntry(0.015686, 0xe2, 0xe2, 0xe2);
+$g->addEntry(0.964706, 0x9d, 0x9d, 0x9d);
+$g->addEntry(1.000000, 0x5a, 0x5a, 0x5a);
+$f2 = $s1->addFill($g, SWFFILL_LINEAR_GRADIENT);
+$f2->scaleTo(0.25, 0.25);
+$f2->moveTo(-35, 37);
+$s1->movePenTo(2074, -1915);
+$s1->setLeftFill(0x66, 0x66, 0x66, 0x39);
+$s1->setLine(20, 0xc5, 0xc5, 0xc5, 0x39);
+$s1->drawCurve(-29, -31, -41, 0);
+$s1->drawLine(-3939, 0);
+$s1->drawCurve(-41, 0, -30, 31);
+$s1->drawCurve(-29, 32, 0, 44);
+$s1->drawLine(0, 3945);
+$s1->drawCurve(0, 44, 29, 31);
+$s1->drawCurve(30, 33, 41, 0);
+$s1->drawLine(3939, 0);
+$s1->drawCurve(41, 0, 29, -33);
+$s1->drawCurve(30, -31, 0, -44);
+$s1->drawLine(0, -3945);
+$s1->drawCurve(0, -44, -30, -32);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->setLine(0,0,0,0);
+$s1->movePenTo(2005, -2023);
+$s1->setLeftFill($f2);
+$s1->setLine(20, 0x66, 0x66, 0x66);
+$s1->drawCurve(-29, -31, -41, 0);
+$s1->drawLine(-3939, 0);
+$s1->drawCurve(-41, 0, -30, 31);
+$s1->drawCurve(-29, 33, 0, 44);
+$s1->drawLine(0, 3966);
+$s1->drawCurve(0, 44, 29, 32);
+$s1->drawCurve(30, 32, 41, 0);
+$s1->drawLine(3939, 0);
+$s1->drawCurve(41, 0, 29, -32);
+$s1->drawCurve(30, -32, 0, -44);
+$s1->drawLine(0, -3966);
+$s1->drawCurve(0, -44, -30, -33);
+
+$s3 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_MULTILINE | SWFTEXTFIELD_USEFONT );
+$s3->setBounds(4939, 4740);
+$s3->setFont($font_general);
+$s3->setHeight(260);
+$s3->setColor(0x00, 0x00, 0x00, 0xff);
+$s3->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s3->setName('texto');
+
+### Shape 4 ###
+$s4 = new SWF::Shape();
+$s4->movePenTo(228, -228);
+$s4->setRightFill(0x99, 0x99, 0x99);
+$s4->setLine(20, 0x00, 0x00, 0x00);
+$s4->drawLine(0, 456);
+$s4->drawLine(-456, 0);
+$s4->setLine(20, 0xcc, 0xcc, 0xcc);
+$s4->drawLine(0, -456);
+$s4->drawLine(456, 0);
+$s4->setLeftFill();
+$s4->setRightFill();
+$s4->setLine(0,0,0,0);
+$s4->movePenTo(120, 132);
+$s4->setLine(60, 0xcc, 0xcc, 0xcc);
+$s4->drawLine(-120, -117);
+$s4->drawLine(-112, 121);
+$s4->movePenTo(-120, -102);
+$s4->drawLine(120, 117);
+$s4->drawLine(112, -120);
+$s4->setLeftFill();
+$s4->setRightFill();
+$s4->setLine(0,0,0,0);
+$s4->movePenTo(120, 102);
+$s4->setLine(60, 0x00, 0x00, 0x00);
+$s4->drawLine(-120, -117);
+$s4->drawLine(-112, 121);
+$s4->movePenTo(-120, -132);
+$s4->drawLine(120, 117);
+$s4->drawLine(112, -120);
+
+### Shape 5 ###
+$s5 = new SWF::Shape();
+$s5->movePenTo(228, -228);
+$s5->setRightFill(0x99, 0x99, 0x99);
+$s5->setLine(20, 0x00, 0x00, 0x00);
+$s5->drawLine(0, 456);
+$s5->drawLine(-456, 0);
+$s5->setLine(20, 0xcc, 0xcc, 0xcc);
+$s5->drawLine(0, -456);
+$s5->drawLine(456, 0);
+$s5->setLeftFill();
+$s5->setRightFill();
+$s5->setLine(0,0,0,0);
+$s5->movePenTo(120, 132);
+$s5->setLine(60, 0xcc, 0xcc, 0xcc);
+$s5->drawLine(-120, -117);
+$s5->drawLine(-112, 121);
+$s5->movePenTo(-120, -102);
+$s5->drawLine(120, 117);
+$s5->drawLine(112, -120);
+$s5->setLeftFill();
+$s5->setRightFill();
+$s5->setLine(0,0,0,0);
+$s5->movePenTo(120, 102);
+$s5->setLine(60, 0x00, 0x00, 0x00);
+$s5->drawLine(-120, -117);
+$s5->drawLine(-112, 121);
+$s5->movePenTo(-120, -132);
+$s5->drawLine(120, 117);
+$s5->drawLine(112, -120);
+
+### Shape 6 ###
+$s6 = new SWF::Shape();
+$s6->movePenTo(228, -228);
+$s6->setRightFill(0x99, 0x99, 0x99);
+$s6->setLine(20, 0x00, 0x00, 0x00);
+$s6->drawLine(0, 456);
+$s6->drawLine(-456, 0);
+$s6->setLine(20, 0xcc, 0xcc, 0xcc);
+$s6->drawLine(0, -456);
+$s6->drawLine(456, 0);
+$s6->setLeftFill();
+$s6->setRightFill();
+$s6->setLine(0,0,0,0);
+$s6->movePenTo(120, 132);
+$s6->setLine(60, 0xcc, 0xcc, 0xcc);
+$s6->drawLine(-120, -117);
+$s6->drawLine(-112, 121);
+$s6->movePenTo(-120, -102);
+$s6->drawLine(120, 117);
+$s6->drawLine(112, -120);
+$s6->setLeftFill();
+$s6->setRightFill();
+$s6->setLine(0,0,0,0);
+$s6->movePenTo(122, 120);
+$s6->setLine(60, 0x00, 0x00, 0x00);
+$s6->drawLine(-120, -117);
+$s6->drawLine(-112, 121);
+$s6->movePenTo(-118, -114);
+$s6->drawLine(120, 117);
+$s6->drawLine(112, -120);
+
+### Button2 7 ###
+$s7 = new SWF::Button();
+$s7->addShape($s4, SWFBUTTON_UP);
+$s7->addShape($s5, SWFBUTTON_OVER);
+$s7->addShape($s6, SWFBUTTON_DOWN);
+$s7->addShape($s6, SWFBUTTON_HIT);
+$a = new SWF::Action("
+this._visible = false;
+_root.detail._visible = false;
+
+");
+$s7->addAction($a, SWFBUTTON_MOUSEUP);
+
+
+$s8 = new SWF::Shape();
+$s8->movePenTo(228, -228);
+$s8->setRightFill(0xdd, 0xdd, 0xdd);
+$s8->setLine(40, 0xdd, 0xdd, 0xdd);
+$s8->drawLine(-1640, 0);
+$s8->setLine(40, 0x00, 0x00, 0x00);
+$s8->drawLine(0, -600);
+$s8->setLine(40, 0x00, 0x00, 0x00);
+$s8->drawLine(1640, 0);
+$s8->setLine(40, 0x00, 0x00, 0x00);
+$s8->drawLine(0, 600);
+
+$s8b = new SWF::Shape();
+$s8b->movePenTo(228, -228);
+$s8b->setRightFill(0xdd, 0xdd, 0xdd);
+$s8b->setLine(40, 0x00, 0x00, 0x00);
+$s8b->drawLine(-1640, 0);
+$s8b->setLine(40, 0x00, 0x00, 0x00);
+$s8b->drawLine(0, -600);
+$s8b->setLine(40, 0x00, 0x00, 0x00);
+$s8b->drawLine(1640, 0);
+$s8b->setLine(40, 0x00, 0x00, 0x00);
+$s8b->drawLine(0, 600);
+
+$s8a = new SWF::Action("
+stop();
+onRelease = function() {
+	var tab = this._name.substring(3,4);
+	if(tab == 1) {
+		gotoAndStop(1);
+		_parent.tab2.gotoAndStop(2);
+		_parent.texto = _global.superdetailstexttab1;
+	} else {
+		gotoAndStop(1);
+		_parent.tab1.gotoAndStop(2);
+		_parent.texto = _global.superdetailstexttab2;
+	}
+};
+
+");
+
+
+$fs3 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_NOSELECT | SWFTEXTFIELD_USEFONT );
+$fs3->setBounds(939, 200);
+$fs3->setName('titlefs3');
+$fs3->setFont($font_general);
+$fs3->setHeight(220);
+$fs3->setColor(0x00, 0x00, 0x00, 0xff);
+$fs3->align(SWFTEXTFIELD_ALIGN_LEFT);
+$fs3->addString('Queue');
+
+$fs2 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_NOSELECT | SWFTEXTFIELD_USEFONT );
+$fs2->setBounds(939, 200);
+$fs2->setName('titlefs2');
+$fs2->setFont($font_general);
+$fs2->setHeight(220);
+$fs2->setColor(0x00, 0x00, 0x00, 0xff);
+$fs2->align(SWFTEXTFIELD_ALIGN_LEFT);
+$fs2->addString('Call');
+
+$sptab = new SWF::Sprite();
+$sptab->add($s8);
+$sptab->add($s8a);
+$sptab->nextFrame();
+$sptab->add($s8b);
+$sptab->add($s8a);
+$sptab->nextFrame();
+
+
+$s9 = new SWF::Shape();
+$s9->movePenTo(1, 1);
+$s9->setRightFill(0xdd, 0xdd, 0xdd);
+$s9->setLine(40, 0x00, 0x00, 0x00);
+$s9->drawLine(-8000, 0);
+$s9->setLine(40, 0x00, 0x00, 0x00);
+$s9->drawLine(0, -7700);
+$s9->setLine(40, 0x00, 0x00, 0x00);
+$s9->drawLine(8000, 0);
+$s9->setLine(40, 0x00, 0x00, 0x00);
+$s9->drawLine(0, 7700);
+
+
+
+
+$j2 = $superdetails->add($s1);
+$j2->scaleTo(1.349503, 1.391388);
+
+$j5 = $superdetails->add($s9);
+$j5->scaleTo(0.657898);
+$j5->moveTo(2565, 2700);
+
+$j5 = $superdetails->add($sptab);
+$j5->scaleTo(0.657898);
+$j5->moveTo(-1740, -2214);
+$j5->setName("tab1");
+
+$j5 = $superdetails->add($sptab);
+$j5->scaleTo(0.657898);
+$j5->moveTo(-620, -2214);
+$j5->setName("tab2");
+
+$j3 = $superdetails->add($s3);
+$j3->moveTo(-2540, -2200);
+$j3->setName('textos');
+
+$j4 = $superdetails->add($s7);
+$j4->scaleTo(0.657898);
+$j4->moveTo(2472, -2610);
+
+$ia = $superdetails->add($fs2);
+$ia->moveTo(-2580,-2680);
+
+$ia = $superdetails->add($fs3);
+$ia->moveTo(-1460,-2680);
+
+$superdetails->nextFrame();  # end of clip frame 1 
+
+$i1 = $movie->add($superdetails);
+$i1->scaleTo(0.5);
+$i1->setName("superdetails");
+$i1->moveTo(4900,3000);
+
+
+
+$ventana_debug = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(120, -120);
+$s1->setRightFill(0x99, 0xcc, 0xcc, 0x03);
+$s1->drawLine(0, 240);
+$s1->drawLine(-240, 0);
+$s1->drawLine(0, -240);
+$s1->drawLine(240, 0);
+
+### Button2 3 ###
+$s3 = new SWF::Button();
+$s3->addShape($s1, SWFBUTTON_HIT | SWFBUTTON_DOWN | SWFBUTTON_OVER | SWFBUTTON_UP);
+$a = new SWF::Action("
+beginDrag(this, 0);
+var este = this.getDepth();
+var aquel = _level0.codebox.getDepth();
+
+if(aquel > este)
+{
+  swapDepths(_level0.codebox);
+  ;
+}
+
+");
+$s3->addAction($a, SWFBUTTON_MOUSEDOWN);
+$a = new SWF::Action("
+endDrag();
+
+");
+$s3->addAction($a, SWFBUTTON_MOUSEUPOUTSIDE | SWFBUTTON_MOUSEUP);
+
+### Shape 4 ###
+$s4 = new SWF::Shape();
+$g = new SWF::Gradient();
+$g->addEntry(0.000000, 0xff, 0xff, 0xff);
+$g->addEntry(0.015686, 0xe2, 0xe2, 0xe2);
+$g->addEntry(0.964706, 0x9d, 0x9d, 0x9d);
+$g->addEntry(1.000000, 0x5a, 0x5a, 0x5a);
+$f2 = $s4->addFill($g, SWFFILL_LINEAR_GRADIENT);
+$f2->scaleTo(0.25, 0.25);
+$f2->moveTo(-35, 37);
+$s4->movePenTo(2074, -1915);
+$s4->setLeftFill(0x66, 0x66, 0x66, 0x39);
+$s4->setLine(20, 0xc5, 0xc5, 0xc5, 0x39);
+$s4->drawCurve(-29, -31, -41, 0);
+$s4->drawLine(-3939, 0);
+$s4->drawCurve(-41, 0, -30, 31);
+$s4->drawCurve(-29, 32, 0, 44);
+$s4->drawLine(0, 3945);
+$s4->drawCurve(0, 44, 29, 31);
+$s4->drawCurve(30, 33, 41, 0);
+$s4->drawLine(3939, 0);
+$s4->drawCurve(41, 0, 29, -33);
+$s4->drawCurve(30, -31, 0, -44);
+$s4->drawLine(0, -3945);
+$s4->drawCurve(0, -44, -30, -32);
+$s4->setLeftFill();
+$s4->setRightFill();
+$s4->setLine(0,0,0,0);
+$s4->movePenTo(2005, -2023);
+$s4->setLeftFill($f2);
+$s4->setLine(20, 0x66, 0x66, 0x66);
+$s4->drawCurve(-29, -31, -41, 0);
+$s4->drawLine(-3939, 0);
+$s4->drawCurve(-41, 0, -30, 31);
+$s4->drawCurve(-29, 33, 0, 44);
+$s4->drawLine(0, 3966);
+$s4->drawCurve(0, 44, 29, 32);
+$s4->drawCurve(30, 32, 41, 0);
+$s4->drawLine(3939, 0);
+$s4->drawCurve(41, 0, 29, -32);
+$s4->drawCurve(30, -32, 0, -44);
+$s4->drawLine(0, -3966);
+$s4->drawCurve(0, -44, -30, -33);
+
+$s6 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_NOSELECT | SWFTEXTFIELD_USEFONT );
+$s6->setBounds(8104, 398);
+$s6->setFont($font_general);
+$s6->setHeight(320);
+$s6->setColor(0x00, 0x00, 0x00, 0xff);
+$s6->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s6->setName("title");
+$s6->addString('Debug Window');
+
+### Shape 7 ###
+$s7 = new SWF::Shape();
+$s7->movePenTo(228, -228);
+$s7->setRightFill(0x99, 0x99, 0x99);
+$s7->setLine(20, 0x00, 0x00, 0x00);
+$s7->drawLine(0, 456);
+$s7->drawLine(-456, 0);
+$s7->setLine(20, 0xcc, 0xcc, 0xcc);
+$s7->drawLine(0, -456);
+$s7->drawLine(456, 0);
+$s7->setLeftFill();
+$s7->setRightFill();
+$s7->setLine(0,0,0,0);
+$s7->movePenTo(120, 132);
+$s7->setLine(60, 0xcc, 0xcc, 0xcc);
+$s7->drawLine(-120, -117);
+$s7->drawLine(-112, 121);
+$s7->movePenTo(-120, -102);
+$s7->drawLine(120, 117);
+$s7->drawLine(112, -120);
+$s7->setLeftFill();
+$s7->setRightFill();
+$s7->setLine(0,0,0,0);
+$s7->movePenTo(120, 102);
+$s7->setLine(60, 0x00, 0x00, 0x00);
+$s7->drawLine(-120, -117);
+$s7->drawLine(-112, 121);
+$s7->movePenTo(-120, -132);
+$s7->drawLine(120, 117);
+$s7->drawLine(112, -120);
+
+### Shape 8 ###
+$s8 = new SWF::Shape();
+$s8->movePenTo(228, -228);
+$s8->setRightFill(0x99, 0x99, 0x99);
+$s8->setLine(20, 0x00, 0x00, 0x00);
+$s8->drawLine(0, 456);
+$s8->drawLine(-456, 0);
+$s8->setLine(20, 0xcc, 0xcc, 0xcc);
+$s8->drawLine(0, -456);
+$s8->drawLine(456, 0);
+$s8->setLeftFill();
+$s8->setRightFill();
+$s8->setLine(0,0,0,0);
+$s8->movePenTo(120, 132);
+$s8->setLine(60, 0xcc, 0xcc, 0xcc);
+$s8->drawLine(-120, -117);
+$s8->drawLine(-112, 121);
+$s8->movePenTo(-120, -102);
+$s8->drawLine(120, 117);
+$s8->drawLine(112, -120);
+$s8->setLeftFill();
+$s8->setRightFill();
+$s8->setLine(0,0,0,0);
+$s8->movePenTo(120, 102);
+$s8->setLine(60, 0x00, 0x00, 0x00);
+$s8->drawLine(-120, -117);
+$s8->drawLine(-112, 121);
+$s8->movePenTo(-120, -132);
+$s8->drawLine(120, 117);
+$s8->drawLine(112, -120);
+
+### Shape 9 ###
+$s9 = new SWF::Shape();
+$s9->movePenTo(228, -228);
+$s9->setRightFill(0x99, 0x99, 0x99);
+$s9->setLine(20, 0x00, 0x00, 0x00);
+$s9->drawLine(0, 456);
+$s9->drawLine(-456, 0);
+$s9->setLine(20, 0xcc, 0xcc, 0xcc);
+$s9->drawLine(0, -456);
+$s9->drawLine(456, 0);
+$s9->setLeftFill();
+$s9->setRightFill();
+$s9->setLine(0,0,0,0);
+$s9->movePenTo(120, 132);
+$s9->setLine(60, 0xcc, 0xcc, 0xcc);
+$s9->drawLine(-120, -117);
+$s9->drawLine(-112, 121);
+$s9->movePenTo(-120, -102);
+$s9->drawLine(120, 117);
+$s9->drawLine(112, -120);
+$s9->setLeftFill();
+$s9->setRightFill();
+$s9->setLine(0,0,0,0);
+$s9->movePenTo(122, 120);
+$s9->setLine(60, 0x00, 0x00, 0x00);
+$s9->drawLine(-120, -117);
+$s9->drawLine(-112, 121);
+$s9->movePenTo(-118, -114);
+$s9->drawLine(120, 117);
+$s9->drawLine(112, -120);
+
+### Button2 10 ###
+$s10 = new SWF::Button();
+$s10->addShape($s7, SWFBUTTON_UP);
+$s10->addShape($s8, SWFBUTTON_OVER);
+$s10->addShape($s9, SWFBUTTON_DOWN);
+$s10->addShape($s9, SWFBUTTON_HIT);
+$a = new SWF::Action("
+this._visible = false;
+
+");
+$s10->addAction($a, SWFBUTTON_MOUSEUP);
+
+### Shape 11 ###
+$s11 = new SWF::Shape();
+$s11->movePenTo(3825, -1782);
+$s11->setRightFill(0xf0, 0xf0, 0xf0);
+$s11->setLine(20, 0x66, 0x66, 0x66);
+$s11->drawLine(0, 3620);
+$s11->drawLine(-8158, 0);
+$s11->drawLine(0, -3620);
+$s11->drawLine(8158, 0);
+
+$s13 = new SWF::TextField(SWFTEXTFIELD_NOEDIT | SWFTEXTFIELD_MULTILINE | SWFTEXTFIELD_USEFONT );
+$s13->setBounds(8000, 3606);
+$s13->setFont($font_general);
+$s13->setHeight(320);
+$s13->setColor(0x00, 0x00, 0x00, 0xff);
+$s13->align(SWFTEXTFIELD_ALIGN_LEFT);
+$s13->setRightMargin(80);
+$s13->setIndentation(40);
+$s13->setName('logcontent');
+
+### MovieClip 14 ###
+$j2 = $ventana_debug->add($s4);
+$j2->scaleTo(2.121078, 1.087326);
+$j2->moveTo(0, -87);
+$j3 = $ventana_debug->add($s3);
+$j3->scaleTo(34.419983, 1.277756);
+$j3->moveTo(-233, -2030);
+$j5 = $ventana_debug->add($s6);
+$j5->moveTo(-4323, -2220);
+$j5->setName('title');
+$j6 = $ventana_debug->add($s10);
+$j6->scaleTo(0.657898);
+$j6->moveTo(4015, -2031);
+$ventana_debug->add($s11);
+$j11 = $ventana_debug->add($s13);
+#$j11->scaleTo(1.289948, 0.945129); 
+#$j11->scaleTo(1.2, 0.9);
+$j11->moveTo(-4281, -1710);
+$j11->setName('Field1');
+$ventana_debug->nextFrame();  # end of ventana_debug 
+
+####################################################
+
+
+$i1=$movie->add($ventana_debug);
+$i1->scaleTo(0.5);
+$i1->setDepth(100);
+$i1->moveTo(5000,2500);
+$i1->setName("log");
+
+
+
+
+
+$ledcolor = new SWF::Sprite();
+$s1 = new SWF::Shape();
+$s1->movePenTo(524, 125);
+$s1->setLeftFill(255, 0x00, 0x00);
+$s1->drawCurve(-112, -86, -125, 0);
+$s1->drawCurve(-127, 0, -66, 86);
+$s1->drawLine(-21, 33);
+$s1->drawCurve(-38, 76, 27, 99);
+$s1->drawLine(11, 35);
+$s1->drawCurve(37, 99, 96, 73);
+$s1->drawLine(13, 10);
+$s1->drawCurve(107, 75, 118, 1);
+$s1->drawCurve(118, -1, 65, -75);
+$s1->drawLine(9, -10);
+$s1->drawCurve(66, -86, -33, -121);
+$s1->drawCurve(-33, -122, -112, -86);
+$i1 = $ledcolor->add($s1);
+$i1->scaleTo(0.5);
+$i1->moveTo(-185, -174);
+$ledcolor->nextFrame();  # end of frame 1
+
+
+$ledsombra = new SWF::Sprite();
+$s2 = new SWF::Shape();
+$s2->movePenTo(216, -124);
+$s2->setRightFill(0x00, 0x00, 0x00, 0x32);
+$s2->drawCurve(30, 58, -21, 78);
+$s2->drawLine(-8, 25);
+$s2->drawCurve(-26, 71, -68, 52);
+$s2->drawLine(-1, 1);
+$s2->drawLine(-8, 6);
+$s2->drawCurve(-77, 54, -84, 0);
+$s2->drawCurve(-94, -1, -50, -60);
+$s2->drawLine(-6, -6);
+$s2->drawLine(0, -2);
+$s2->drawCurve(-54, -68, 25, -95);
+$s2->drawCurve(23, -87, 80, -62);
+$s2->drawCurve(80, -62, 90, 1);
+$s2->drawCurve(99, -1, 52, 70);
+$s2->drawLine(0, 1);
+$s2->drawLine(18, 27);
+$s2->movePenTo(191, -146);
+$s2->setLeftFill(0x00, 0x00, 0x00, 0x32);
+$s2->setRightFill(0x00, 0x00, 0x00, 0x65);
+$s2->drawLine(16, 25);
+$s2->drawCurve(29, 57, -20, 74);
+$s2->drawLine(-7, 24);
+$s2->drawCurve(-26, 68, -66, 51);
+$s2->drawLine(0, 1);
+$s2->drawCurve(-5, 2, -4, 4);
+$s2->drawCurve(-73, 52, -82, 0);
+$s2->drawCurve(-89, -1, -49, -57);
+$s2->drawLine(-4, -7);
+$s2->drawLine(-1, -1);
+$s2->drawCurve(-52, -64, 25, -91);
+$s2->drawCurve(22, -85, 78, -59);
+$s2->drawCurve(77, -60, 87, 1);
+$s2->drawCurve(95, -1, 49, 66);
+$s2->drawLine(0, 1);
+$s2->movePenTo(184, -141);
+$s2->setLeftFill(0x00, 0x00, 0x00, 0x65);
+$s2->setRightFill(0x00, 0x00, 0x00, 0x98);
+$s2->drawLine(15, 25);
+$s2->drawCurve(28, 53, -19, 71);
+$s2->drawLine(-8, 23);
+$s2->drawLine(0, -1);
+$s2->drawCurve(-24, 67, -64, 49);
+$s2->drawLine(-9, 7);
+$s2->drawCurve(-71, 50, -79, 0);
+$s2->drawCurve(-85, -1, -46, -54);
+$s2->drawLine(-5, -6);
+$s2->drawLine(-1, -1);
+$s2->drawCurve(-48, -61, 24, -87);
+$s2->drawCurve(21, -81, 75, -58);
+$s2->drawCurve(75, -58, 84, 1);
+$s2->drawCurve(89, -1, 48, 62);
+$s2->drawLine(0, 1);
+$s2->movePenTo(177, -135);
+$s2->setLeftFill(0x00, 0x00, 0x00, 0x98);
+$s2->setRightFill(0x00, 0x00, 0x00, 0xcb);
+$s2->drawLine(14, 22);
+$s2->drawCurve(26, 52, -18, 66);
+$s2->drawLine(-7, 23);
+$s2->drawCurve(-24, 63, -61, 48);
+$s2->drawLine(-9, 6);
+$s2->drawCurve(-69, 49, -76, 0);
+$s2->drawCurve(-80, -1, -43, -51);
+$s2->drawLine(-6, -6);
+$s2->drawLine(-1, 0);
+$s2->drawCurve(-45, -59, 22, -81);
+$s2->drawCurve(21, -79, 73, -56);
+$s2->drawCurve(72, -56, 81, 1);
+$s2->drawCurve(85, -1, 45, 59);
+$s2->drawLine(0, 1);
+$s2->movePenTo(183, -108);
+$s2->setLeftFill(0x00, 0x00, 0x00, 0xcb);
+$s2->setRightFill(0x00, 0x00, 0x00);
+$s2->drawCurve(24, 47, -17, 63);
+$s2->drawLine(-6, 22);
+$s2->drawCurve(-23, 62, -60, 46);
+$s2->drawLine(-8, 5);
+$s2->drawCurve(-66, 48, -74, 0);
+$s2->drawCurve(-76, 0, -41, -49);
+$s2->drawLine(-5, -6);
+$s2->drawLine(-1, 0);
+$s2->drawCurve(-42, -55, 21, -77);
+$s2->drawCurve(21, -77, 70, -53);
+$s2->drawCurve(69, -54, 78, 1);
+$s2->drawCurve(80, -1, 43, 56);
+$s2->drawLine(13, 22);
+$i2 = $ledsombra->add($s2);
+#$i2->scaleTo(1.574982, -1.574982);
+$i2->scaleTo(0.72, -0.72);
+$i2->rotateTo(-180);
+#$i2->moveTo(369, 348);
+#$i2->moveTo(185, 174);
+$i2->multColor(1.000000, 1.000000, 1.000000, 0.351562);
+$i2->addColor(0x00, 0x00, 0x00);
+$ledsombra->nextFrame();
+
+$ledbrillo = new SWF::Sprite();
+$s4 = new SWF::Shape();
+$g = new SWF::Gradient();
+$g->addEntry(0.368627, 0x00, 0x00, 0x00, 0x00);
+$g->addEntry(0.913725, 0x00, 0x00, 0x00, 0x99);
+$f1 = $s4->addFill($g, SWFFILL_RADIAL_GRADIENT);
+$f1->skewXTo(0.234316);
+$f1->scaleTo(0.06, -0.06);
+$f1->rotateTo(165.488144);
+$f1->moveTo(383, 415);
+$g = new SWF::Gradient();
+$g->addEntry(0.000000, 0xff, 0xff, 0xff);
+$g->addEntry(0.282353, 0xff, 0xff, 0xff, 0x8d);
+$g->addEntry(1.000000, 0xff, 0xff, 0xff, 0x00);
+$f2 = $s4->addFill($g, SWFFILL_RADIAL_GRADIENT);
+$f2->skewXTo(0.234808);
+$f2->scaleTo(0.030644, -0.027754);
+$f2->rotateTo(165.465546);
+$f2->moveTo(405, 500);
+$g = new SWF::Gradient();
+$g->addEntry(0.196078, 0xff, 0xff, 0xff);
+$g->addEntry(0.921569, 0xff, 0xff, 0xff, 0x00);
+$f3 = $s4->addFill($g, SWFFILL_RADIAL_GRADIENT);
+$f3->skewXTo(0.103049);
+$f3->scaleTo(0.015, -0.009);
+$f3->rotateTo(170.450867);
+$f3->moveTo(291, 115);
+$s4->movePenTo(669, 336);
+$s4->setRightFill($f1);
+$s4->drawCurve(-34, -124, -113, -85);
+$s4->drawCurve(-110, -86, -126, 0);
+$s4->drawCurve(-126, 0, -67, 86);
+$s4->drawCurve(-66, 85, 34, 124);
+$s4->drawCurve(32, 119, 112, 88);
+$s4->drawCurve(113, 85, 126, 0);
+$s4->drawCurve(126, 0, 65, -85);
+$s4->drawCurve(65, -88, -31, -119);
+$s4->setLeftFill();
+$s4->setRightFill();
+#brillo grande inferior
+$s4->movePenTo(286, 41);
+$s4->setRightFill($f2);
+$s4->drawCurve(-126, -2, -65, 88);
+$s4->drawCurve(-65, 85, 31, 122);
+$s4->drawCurve(34, 121, 110, 86);
+$s4->drawCurve(113, 85, 126, 0);
+$s4->drawCurve(126, 0, 65, -85);
+$s4->drawCurve(67, -86, -33, -121);
+$s4->drawCurve(-32, -122, -112, -85);
+$s4->drawCurve(-113, -88, -126, 2);
+$s4->setLeftFill();
+$s4->setRightFill();
+# brillo superior
+$s4->movePenTo(184, 57);
+$s4->setRightFill($f3);
+$s4->drawCurve(-32, 24, 9, 34);
+$s4->drawCurve(9, 34, 45, 23);
+$s4->drawCurve(45, 25, 53, 0);
+$s4->drawCurve(54, 0, 32, -25);
+$s4->drawCurve(32, -23, -10, -34);
+$s4->drawCurve(-8, -34, -45, -24);
+$s4->drawCurve(-45, -24, -54, 0);
+$s4->drawCurve(-53, 0, -32, 24);
+$i6 = $ledbrillo->add($s4);
+$i6->scaleTo(0.5);
+$i6->moveTo(-185, -174);
+$ledbrillo->nextFrame();  
+
+
+# Icons movieclips
+
+####### Arrow
+
+my $fle = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(5642, 3859);
+$s1->setRightFill(0x33, 0x33, 0x33);
+$s1->drawCurve(58, 58, 0, 83);
+$s1->drawCurve(0, 83, -58, 59);
+$s1->drawCurve(-59, 58, -83, 0);
+$s1->drawCurve(-83, 0, -58, -58);
+$s1->drawCurve(-59, -59, 0, -83);
+$s1->drawCurve(0, -83, 59, -58);
+$s1->drawCurve(58, -59, 83, 0);
+$s1->drawCurve(83, 0, 59, 59);
+$s1->movePenTo(5543, 3930);
+$s1->setLeftFill(0x33, 0x33, 0x33);
+$s1->setRightFill(0xff, 0xff, 0xff);
+$s1->drawLine(66, 0);
+$s1->drawLine(0, 144);
+$s1->drawLine(-66, -1);
+$s1->drawLine(0, 65);
+$s1->drawLine(-191, -136);
+$s1->drawLine(191, -139);
+$s1->drawLine(0, 67);
+$i1 = $fle->add($s1);
+$i1->moveTo(-2750,-2000);
+$i1->scaleTo(0.5);
+$fle->nextFrame();  # end of frame 1
+$fle->remove($i1);
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(5500, 3800);
+$s2->setRightFill(0x33, 0x33, 0x33);
+$s2->drawCurve(83, 0, 59, 59);
+$s2->drawCurve(58, 58, 0, 83);
+$s2->drawCurve(0, 83, -58, 59);
+$s2->drawCurve(-59, 58, -83, 0);
+$s2->drawCurve(-83, 0, -58, -58);
+$s2->drawCurve(-59, -59, 0, -83);
+$s2->drawCurve(0, -83, 59, -58);
+$s2->drawCurve(58, -59, 83, 0);
+$s2->movePenTo(5457, 3927);
+$s2->setLeftFill(0x33, 0x33, 0x33);
+$s2->setRightFill(0xff, 0xff, 0xff);
+$s2->drawLine(0, -64);
+$s2->drawLine(192, 136);
+$s2->drawLine(-192, 139);
+$s2->drawLine(0, -67);
+$s2->drawLine(-66, -1);
+$s2->drawLine(0, -143);
+$s2->drawLine(66, 0);
+$i1 = $fle->add($s2);
+$i1->moveTo(-2750,-2000);
+$i1->scaleTo(0.5);
+$fle->nextFrame();  # end of frame 2
+$fle->remove($i1);
+
+### Shape 3 ###
+$s3 = new SWF::Shape();
+$s3->movePenTo(5500, 3800);
+$s3->setRightFill(0x33, 0x33, 0x33);
+$s3->drawCurve(83, 0, 59, 59);
+$s3->drawCurve(58, 58, 0, 83);
+$s3->drawCurve(0, 83, -58, 59);
+$s3->drawCurve(-59, 58, -83, 0);
+$s3->drawCurve(-83, 0, -58, -58);
+$s3->drawCurve(-59, -59, 0, -83);
+$s3->drawCurve(0, -83, 59, -58);
+$s3->drawCurve(58, -59, 83, 0);
+$s3->movePenTo(5574, 3891);
+$s3->setLeftFill(0x33, 0x33, 0x33);
+$s3->setRightFill(0xff, 0xff, 0xff);
+$s3->drawLine(-1, 66);
+$s3->drawLine(65, 0);
+$s3->drawLine(-136, 192);
+$s3->drawLine(-139, -192);
+$s3->drawLine(67, 0);
+$s3->drawLine(0, -66);
+$s3->drawLine(144, 0);
+$i1 = $fle->add($s3);
+$i1->moveTo(-2750,-2000);
+$i1->scaleTo(0.5);
+$fle->nextFrame();  # end of frame 3
+$fle->remove($i1);
+
+
+
+
+
+
+# Icon 3 Shape
+my $s_icon2 = new SWF::Shape();
+$s_icon2->movePenTo(3339, 2660);
+$s_icon2->setRightFill(0xcc, 0xcc, 0xcc, 0x00);
+$s_icon2->drawLine(-6639, 0);
+$s_icon2->drawLine(0,     -5340);
+$s_icon2->drawLine(6639,  0);
+$s_icon2->drawLine(0,     5340);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(2622, -2528);
+$s_icon2->setLeftFill(0x00, 0x00, 0x00);
+$s_icon2->drawCurve(-129, -82, -182, -26);
+$s_icon2->drawLine(-329, -25);
+$s_icon2->drawCurve(-648, -45,  -912, 195);
+$s_icon2->drawCurve(-744, 158,  -633, 349);
+$s_icon2->drawCurve(-748, 412,  -329, 551);
+$s_icon2->drawCurve(-141, 237,  -51,  287);
+$s_icon2->drawCurve(-53,  294,  58,   257);
+$s_icon2->drawCurve(62,   279,  180,  170);
+$s_icon2->drawCurve(200,  189,  319,  26);
+$s_icon2->drawCurve(216,  17,   238,  -98);
+$s_icon2->drawCurve(235,  -96,  173,  -175);
+$s_icon2->drawCurve(184,  -185, 55,   -214);
+$s_icon2->drawCurve(61,   -239, -116, -229);
+$s_icon2->drawCurve(-52,  -105, -126, -100);
+$s_icon2->drawCurve(-62,  -49,  -166, -106);
+$s_icon2->drawCurve(-3,   282,  -101, 178);
+$s_icon2->drawCurve(-125, 220,  -251, 0);
+$s_icon2->drawCurve(111,  -550, 272,  -330);
+$s_icon2->drawCurve(277,  -329, 620,  -295);
+$s_icon2->drawCurve(993,  -472, 807,  -4);
+$s_icon2->drawCurve(-80,  192,  -228, 70);
+$s_icon2->drawCurve(-106, 32,   -335, 29);
+$s_icon2->drawCurve(-279, 25,   -118, 70);
+$s_icon2->drawCurve(-172, 104,  -2,   258);
+$s_icon2->drawCurve(-51,  5,    -120, 41);
+$s_icon2->drawCurve(-110, 39,   -59,  -2);
+$s_icon2->drawCurve(-69,  -4,   -107, -35);
+$s_icon2->drawLine(-170, -51);
+$s_icon2->drawCurve(-196, -41, -128, 171);
+$s_icon2->drawCurve(-95,  129, 38,   131);
+$s_icon2->drawCurve(28,   96,  120,  135);
+$s_icon2->drawLine(203, 230);
+$s_icon2->drawCurve(103, 137, 3,    119);
+$s_icon2->drawCurve(4,   185, -112, 228);
+$s_icon2->drawCurve(-69, 140, -157, 226);
+$s_icon2->drawLine(-125, 142);
+$s_icon2->drawCurve(-84,  96,   -4,   62);
+$s_icon2->drawCurve(-2,   71,   112,  115);
+$s_icon2->drawCurve(60,   62,   107,  92);
+$s_icon2->drawCurve(600,  600,  500,  150);
+$s_icon2->drawCurve(831,  245,  809,  -555);
+$s_icon2->drawCurve(237,  -169, 36,   -34);
+$s_icon2->drawCurve(152,  -145, -45,  -132);
+$s_icon2->drawCurve(-160, 62,   -299, 191);
+$s_icon2->drawCurve(-296, 188,  -165, 62);
+$s_icon2->drawCurve(-374, 141,  -411, -83);
+$s_icon2->drawCurve(-389, -79,  -326, -256);
+$s_icon2->drawCurve(-108, -86,  -212, -211);
+$s_icon2->drawCurve(-202, -200, -118, -89);
+$s_icon2->drawLine(0, -20);
+$s_icon2->drawCurve(183,  -140, 118,  -250);
+$s_icon2->drawCurve(115,  -245, 11,   -262);
+$s_icon2->drawCurve(12,   -278, -114, -206);
+$s_icon2->drawCurve(-126, -229, -259, -89);
+$s_icon2->drawCurve(62,   -182, 144,  -25);
+$s_icon2->drawCurve(148,  -25,  106,  172);
+$s_icon2->drawCurve(124,  -21,  161,  -65);
+$s_icon2->drawCurve(187,  -75,  68,   -73);
+$s_icon2->drawCurve(37,   -39,  30,   -107);
+$s_icon2->drawCurve(32,   -118, 27,   -39);
+$s_icon2->drawCurve(88,   -134, 149,  2);
+$s_icon2->drawCurve(145,  3,    92,   126);
+$s_icon2->drawCurve(154,  -44,  210,  -119);
+$s_icon2->drawCurve(241,  -136, 68,   -108);
+$s_icon2->drawCurve(30,   -49,  16,   -93);
+$s_icon2->drawLine(21, -151);
+$s_icon2->drawCurve(-666, 0,    -553, 127);
+$s_icon2->drawCurve(-597, 137,  -544, 302);
+$s_icon2->drawCurve(-689, 377,  -228, 437);
+$s_icon2->drawCurve(-183, 355,  0,    704);
+$s_icon2->drawCurve(369,  0,    209,  -219);
+$s_icon2->drawCurve(181,  -192, 81,   -388);
+$s_icon2->drawCurve(213,  220,  -59,  276);
+$s_icon2->drawCurve(-53,  246,  -237, 183);
+$s_icon2->drawCurve(-238, 184,  -270, -1);
+$s_icon2->drawCurve(-302, -2,   -198, -247);
+$s_icon2->drawCurve(-232, -292, 179,  -487);
+$s_icon2->drawCurve(141,  -381, 296,  -316);
+$s_icon2->drawCurve(363,  -387, 717,  -320);
+$s_icon2->drawCurve(1330, -603, 950,  93);
+$s_icon2->drawCurve(243,  22,   222,  130);
+$s_icon2->drawCurve(220,  128,  130,  192);
+$s_icon2->drawCurve(138,  204,  -4,   219);
+$s_icon2->drawCurve(-5,   242,  -181, 217);
+$s_icon2->drawCurve(-82,  99,   -151, 23);
+$s_icon2->drawCurve(-138, 21,   -158, -47);
+$s_icon2->drawCurve(-155, -46,  -114, -93);
+$s_icon2->drawCurve(-122, -99,  -33,  -118);
+$s_icon2->drawCurve(-17,  -55,  31,   -76);
+$s_icon2->drawLine(56, -129);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(53,  265,  224,  122);
+$s_icon2->drawCurve(215, 117,  268,  -64);
+$s_icon2->drawCurve(-38, -177, -122, -27);
+$s_icon2->drawLine(-126, -17);
+$s_icon2->drawCurve(-86,  -12,  -68,  -34);
+$s_icon2->drawCurve(-217, -105, -63,  -288);
+$s_icon2->drawCurve(-320, 171,  54,   289);
+$s_icon2->drawCurve(43,   235,  263,  245);
+$s_icon2->drawCurve(-32,  -19,  -244, -117);
+$s_icon2->drawCurve(-173, -83,  -85,  -75);
+$s_icon2->drawCurve(-45,  -38,  -98,  -166);
+$s_icon2->drawCurve(-79,  -133, -104, -36);
+$s_icon2->drawCurve(-165, -56,  -79,  193);
+$s_icon2->drawCurve(-32,  79,   1,    87);
+$s_icon2->drawCurve(0,    89,   35,   55);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(26,  -54,  24, -26);
+$s_icon2->drawCurve(112, -131, 75, 74);
+$s_icon2->drawLine(63, 87);
+$s_icon2->drawCurve(43, 67, 30, 29);
+$s_icon2->drawCurve(35, 37, 81, 34);
+$s_icon2->drawLine(131, 53);
+$s_icon2->drawCurve(1018, 508, 332,  841);
+$s_icon2->drawCurve(107,  286, 33,   129);
+$s_icon2->drawCurve(69,   266, -46,  159);
+$s_icon2->drawCurve(-39,  133, -133, 137);
+$s_icon2->drawCurve(-61,  63,  -180, 150);
+$s_icon2->drawCurve(-374, 306, -372, 148);
+$s_icon2->drawCurve(-452, 179, -402, -76);
+$s_icon2->drawCurve(-469, -88, -484, -377);
+$s_icon2->drawLine(-405, -339);
+$s_icon2->drawCurve(-254, -217, -168, -119);
+$s_icon2->drawCurve(-80,  281,  251,  280);
+$s_icon2->drawCurve(88,   99,   154,  125);
+$s_icon2->drawLine(247, 198);
+$s_icon2->drawCurve(536,  454,  708,  42);
+$s_icon2->drawCurve(699,  41,   597,  -374);
+$s_icon2->drawCurve(223,  -143, 283,  -294);
+$s_icon2->drawCurve(357,  -370, 117,  -99);
+$s_icon2->drawCurve(-95,  -688, -323, -580);
+$s_icon2->drawCurve(-372, -668, -550, -263);
+$s_icon2->drawLine(179, 13);
+$s_icon2->drawLine(184, 26);
+$s_icon2->drawCurve(224,  25,   129,  -78);
+$s_icon2->drawCurve(208,  -128, 96,   -235);
+$s_icon2->drawCurve(88,   -215, -23,  -261);
+$s_icon2->drawCurve(-21,  -252, -117, -218);
+$s_icon2->drawCurve(-121, -225, -186, -119);
+$s_icon2->movePenTo(-782, -2506);
+$s_icon2->drawCurve(-149, -33, -83,  -2);
+$s_icon2->drawCurve(-259, -6,  -25,  266);
+$s_icon2->drawCurve(-290, -76, -185, 73);
+$s_icon2->drawCurve(-225, 89,  0,    294);
+$s_icon2->drawCurve(-141, -25, -128, 24);
+$s_icon2->drawCurve(-129, 24,  -80,  69);
+$s_icon2->drawCurve(-187, 161, 165,  287);
+$s_icon2->drawLine(-230, 10);
+$s_icon2->drawCurve(-136, 18,  -71, 65);
+$s_icon2->drawCurve(-126, 109, 28,  183);
+$s_icon2->drawCurve(28,   181, 147, 74);
+$s_icon2->drawLine(0, 20);
+$s_icon2->drawCurve(-194, 18,  -117, 128);
+$s_icon2->drawCurve(-106, 116, -3,   155);
+$s_icon2->drawCurve(-2,   157, 103,  106);
+$s_icon2->drawCurve(116,  118, 203,  1);
+$s_icon2->drawLine(0, 20);
+$s_icon2->drawCurve(-208, 97,  -38, 224);
+$s_icon2->drawCurve(-40,  230, 186, 139);
+$s_icon2->drawCurve(74,   54,  107, 12);
+$s_icon2->drawCurve(35,   4,   164, 0);
+$s_icon2->drawLine(-60, 137);
+$s_icon2->drawCurve(-28,  79,   11,  64);
+$s_icon2->drawCurve(29,   212,  260, 95);
+$s_icon2->drawCurve(212,  77,   236, -28);
+$s_icon2->drawCurve(179,  -21,  199, -113);
+$s_icon2->drawCurve(41,   -23,  301, -199);
+$s_icon2->drawCurve(-117, -134, -83, 14);
+$s_icon2->drawCurve(-75,  15,   -83, 46);
+$s_icon2->drawLine(-138, 86);
+$s_icon2->drawCurve(-173, 108, -151, -15);
+$s_icon2->drawCurve(-126, -12, -90,  -60);
+$s_icon2->drawCurve(-86,  -57, -28,  -82);
+$s_icon2->drawCurve(-30,  -85, 40,   -84);
+$s_icon2->drawCurve(43,   -92, 117,  -68);
+$s_icon2->drawLine(0, -20);
+$s_icon2->drawCurve(-701, 0,    91,  -340);
+$s_icon2->drawCurve(24,   -81,  83,  -89);
+$s_icon2->drawCurve(100,  -97,  43,  -53);
+$s_icon2->drawCurve(-151, -41,  -72, -29);
+$s_icon2->drawCurve(-123, -49,  -64, -84);
+$s_icon2->drawCurve(-149, -193, 200, -133);
+$s_icon2->drawCurve(161,  -107, 218, -3);
+$s_icon2->drawLine(0, -20);
+$s_icon2->drawCurve(-72,  -45,  -65, -75);
+$s_icon2->drawCurve(-215, -237, 221, -118);
+$s_icon2->drawCurve(159,  -85,  292, 0);
+$s_icon2->drawLine(-82, -164);
+$s_icon2->drawCurve(-50, -100, -2,  -76);
+$s_icon2->drawCurve(-2,  -184, 225, -21);
+$s_icon2->drawLine(351, 25);
+$s_icon2->drawCurve(-50,  -142, -4,  -38);
+$s_icon2->drawCurve(-19,  -292, 267, 5);
+$s_icon2->drawCurve(148,  2,    298, 85);
+$s_icon2->drawCurve(-113, -272, 214, -40);
+$s_icon2->drawCurve(100,  -19,  319, 51);
+$s_icon2->drawLine(40,   -120);
+$s_icon2->drawLine(-224, -45);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(2838, -1701);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawCurve(-9,   -387, -364, -223);
+$s_icon2->drawCurve(-310, -190, -413, 0);
+$s_icon2->drawCurve(-688, 0,    -717, 217);
+$s_icon2->drawCurve(-699, 212,  -596, 377);
+$s_icon2->drawCurve(-609, 384,  -171, 390);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(317,  -418, 522, -307);
+$s_icon2->drawCurve(396,  -235, 625, -224);
+$s_icon2->drawCurve(782,  -281, 518, -12);
+$s_icon2->drawCurve(1039, -30,  257, 547);
+$s_icon2->drawCurve(64,   137,  0,   323);
+$s_icon2->drawCurve(33,   -55,  5,   -80);
+$s_icon2->drawCurve(3,    -35,  -5,  -110);
+$s_icon2->movePenTo(-598, -2341);
+$s_icon2->drawCurve(-225, -62, -86, -5);
+$s_icon2->drawCurve(-200, -11, -49, 138);
+$s_icon2->drawLine(520, 40);
+$s_icon2->drawLine(40,  -100);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1782, -2181);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawCurve(-965, 4,   -1075, 586);
+$s_icon2->drawCurve(-670, 361, -210,  489);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(385, -610, 887, -381);
+$s_icon2->drawCurve(806, -347, 802, -2);
+$s_icon2->drawLine(20, -100);
+$s_icon2->movePenTo(-1669, -2135);
+$s_icon2->drawCurve(-97,  52,   -32,  102);
+$s_icon2->drawCurve(154,  -93,  165,  20);
+$s_icon2->drawCurve(126,  15,   195,  98);
+$s_icon2->drawCurve(-23,  -101, -91,  -64);
+$s_icon2->drawCurve(-85,  -59,  -111, -9);
+$s_icon2->drawCurve(-113, -8,   -88,  47);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1822, -1981);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawLine(-640, 380);
+$s_icon2->drawCurve(-51, -103, -88, -29);
+$s_icon2->drawCurve(-79, -25,  -90, 37);
+$s_icon2->drawCurve(-85, 35,   -65, 76);
+$s_icon2->drawCurve(-66, 79,   -16, 90);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(49,  -114, 94,  -53);
+$s_icon2->drawCurve(104, -59,  113, 52);
+$s_icon2->drawCurve(28,  15,   55,  46);
+$s_icon2->drawCurve(53,  38,   44,  -2);
+$s_icon2->drawCurve(69,  -4,   117, -80);
+$s_icon2->drawLine(174, -123);
+$s_icon2->drawLine(171, -101);
+$s_icon2->drawCurve(104, -75, -15, -80);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(-2338, -1501);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(83,  -105, 157, -8);
+$s_icon2->drawCurve(86,  -4,   194, 37);
+$s_icon2->drawCurve(-31, -85,  -86, -36);
+$s_icon2->drawCurve(-78, -34,  -96, 16);
+$s_icon2->drawCurve(-96, 16,   -68, 56);
+$s_icon2->drawCurve(-74, 61,   -11, 86);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1782, -1661);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawLine(-100, 220);
+$s_icon2->drawLine(20,   0);
+$s_icon2->drawLine(80,   -100);
+$s_icon2->drawCurve(45,   260,  236,  116);
+$s_icon2->drawCurve(218,  108,  261,  -64);
+$s_icon2->drawCurve(-29,  -71,  -184, -32);
+$s_icon2->drawCurve(-229, -40,  -38,  -21);
+$s_icon2->drawCurve(-95,  -50,  -69,  -119);
+$s_icon2->drawCurve(-69,  -140, -47,  -67);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(-2598, -1361);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawLine(100,  0);
+$s_icon2->drawLine(-100, -220);
+$s_icon2->drawLine(0,    220);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1242, -1541);
+$s_icon2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon2->drawLine(-60, 40);
+$s_icon2->drawLine(120, 240);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(-80, -280);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1982, -861);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawCurve(181,  126,  206,  18);
+$s_icon2->drawCurve(235,  20,   154,  -144);
+$s_icon2->drawCurve(131,  -130, -7,   -90);
+$s_icon2->drawCurve(-188, 202,  -230, 24);
+$s_icon2->drawCurve(-132, 14,   -350, -60);
+$s_icon2->drawLine(0, 20);
+$s_icon2->movePenTo(722, -1241);
+$s_icon2->drawLine(20,   180);
+$s_icon2->drawLine(40,   0);
+$s_icon2->drawLine(40,   -120);
+$s_icon2->drawLine(-100, -60);
+$s_icon2->movePenTo(-595, -849);
+$s_icon2->drawCurve(41,  83,  106, 120);
+$s_icon2->drawCurve(131, 148, 36,  52);
+$s_icon2->drawCurve(84,  122, 19,  123);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(48,   -216, -203, -264);
+$s_icon2->drawCurve(-252, -280, -73,  -140);
+$s_icon2->drawCurve(-17,  132,  60,   120);
+$s_icon2->movePenTo(-2778, -901);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(73,  -138, 162, -29);
+$s_icon2->drawCurve(99,  -17,  206, 24);
+$s_icon2->drawCurve(-55, -80,  -91, -23);
+$s_icon2->drawCurve(-84, -21,  -92, 30);
+$s_icon2->drawCurve(-89, 30,   -65, 66);
+$s_icon2->drawCurve(-68, 71,   -16, 87);
+$s_icon2->movePenTo(-2858, -721);
+$s_icon2->drawLine(-200, -280);
+$s_icon2->drawCurve(-47, 325, 247, -25);
+$s_icon2->drawLine(0, -20);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1102, -795);
+$s_icon2->setLeftFill(0x00, 0x00, 0x00);
+$s_icon2->drawCurve(-299, 24,  -163, 104);
+$s_icon2->drawCurve(-189, 120, -83,  266);
+$s_icon2->drawCurve(-82,  264, 53,   286);
+$s_icon2->drawCurve(51,   274, 161,  235);
+$s_icon2->drawCurve(163,  237, 236,  137);
+$s_icon2->drawCurve(251,  146, 281,  0);
+$s_icon2->drawLine(340, -16);
+$s_icon2->drawCurve(185,  -36,  108,  -128);
+$s_icon2->drawCurve(216,  -256, -19,  -343);
+$s_icon2->drawCurve(-18,  -315, -203, -281);
+$s_icon2->drawCurve(-203, -282, -294, -119);
+$s_icon2->drawCurve(-320, -129, -312, 119);
+$s_icon2->drawCurve(-213, 81,   -41,  294);
+$s_icon2->drawCurve(-37,  261,  107,  210);
+$s_icon2->drawCurve(236,  471,  668,  49);
+$s_icon2->drawLine(-60, -260);
+$s_icon2->drawCurve(-204, -19,  -180, -124);
+$s_icon2->drawCurve(-195, -133, -55,  -184);
+$s_icon2->drawCurve(-69,  -228, 153,  -170);
+$s_icon2->drawCurve(156,  -172, 234,  64);
+$s_icon2->drawCurve(164,  47,   156,  173);
+$s_icon2->drawCurve(152,  168,  76,   212);
+$s_icon2->drawCurve(81,   226,  -43,  182);
+$s_icon2->drawCurve(-48,  206,  -202, 98);
+$s_icon2->drawCurve(-171, 82,   -325, -75);
+$s_icon2->drawCurve(-207, -47,  -189, -174);
+$s_icon2->drawCurve(-184, -168, -102, -227);
+$s_icon2->drawCurve(-108, -238, 23,   -218);
+$s_icon2->drawCurve(26,   -242, 184,  -162);
+$s_icon2->drawCurve(156,  -140, 223,  -12);
+$s_icon2->drawCurve(98,   -5,   320,  41);
+$s_icon2->drawCurve(-32,  -107, -152, -45);
+$s_icon2->drawCurve(-119, -34,  -137, 12);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(997, -640);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawCurve(-267, 49,   -108, 250);
+$s_icon2->drawCurve(225,  -156, 192,  -34);
+$s_icon2->drawCurve(159,  -28,  304,  38);
+$s_icon2->drawLine(0, -100);
+$s_icon2->drawCurve(-345, -48, -160, 29);
+$s_icon2->movePenTo(-838, -601);
+$s_icon2->drawLine(-20, -180);
+$s_icon2->drawLine(0,   180);
+$s_icon2->drawLine(20,  0);
+$s_icon2->movePenTo(-698, -661);
+$s_icon2->drawLine(140, 480);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawCurve(41, -332, -201, -148);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(1422, -641);
+$s_icon2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon2->drawLine(0,   20);
+$s_icon2->drawLine(60,  0);
+$s_icon2->drawLine(-60, -20);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(-2978, -361);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawLine(20, 0);
+$s_icon2->drawCurve(148,  -149, 272,  29);
+$s_icon2->drawCurve(-113, -105, -147, 35);
+$s_icon2->drawCurve(-151, 36,   -29,  154);
+$s_icon2->movePenTo(-878, -581);
+$s_icon2->drawLine(0,   60);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(-20, -60);
+$s_icon2->movePenTo(-1498, -561);
+$s_icon2->drawLine(-80, 799);
+$s_icon2->drawCurve(587,  0,   113,  -379);
+$s_icon2->drawCurve(-189, 151, -116, 54);
+$s_icon2->drawCurve(-157, 74,  -198, 0);
+$s_icon2->drawLine(40, -699);
+$s_icon2->setLeftFill();
+$s_icon2->setRightFill();
+$s_icon2->movePenTo(3262, 1358);
+$s_icon2->setLeftFill(0xb8, 0xb8, 0xd9);
+$s_icon2->drawCurve(-86,  165,  -193, 189);
+$s_icon2->drawCurve(-112, 109,  -229, 187);
+$s_icon2->drawCurve(-629, 502,  -708, 55);
+$s_icon2->drawCurve(-743, 57,   -640, -458);
+$s_icon2->drawCurve(-197, -141, -249, -270);
+$s_icon2->drawCurve(-333, -360, -81,  -75);
+$s_icon2->drawCurve(-13,  109,  53,   89);
+$s_icon2->drawCurve(21,   35,   112,  127);
+$s_icon2->drawCurve(276,  313,  351,  260);
+$s_icon2->drawCurve(645,  481,  791,  -73);
+$s_icon2->drawCurve(742,  -68,  638,  -523);
+$s_icon2->drawCurve(253,  -204, 108,  -111);
+$s_icon2->drawCurve(210,  -217, 33,   -178);
+$s_icon2->drawLine(-20, 0);
+$s_icon2->movePenTo(1002, -141);
+$s_icon2->drawCurve(217,  -130, 198,  37);
+$s_icon2->drawCurve(176,  34,   142,  160);
+$s_icon2->drawCurve(128,  145,  73,   217);
+$s_icon2->drawCurve(70,   210,  -4,   206);
+$s_icon2->drawCurve(122,  -229, -122, -321);
+$s_icon2->drawCurve(-115, -301, -225, -148);
+$s_icon2->drawCurve(-182, -119, -191, 20);
+$s_icon2->drawCurve(-212, 22,   -75,  197);
+$s_icon2->movePenTo(715, 67);
+$s_icon2->drawCurve(-9,  -110, -24,  -58);
+$s_icon2->drawCurve(-37, 463,  266,  293);
+$s_icon2->drawCurve(261, 287,  470,  36);
+$s_icon2->drawCurve(-21, -95,  -230, -77);
+$s_icon2->drawLine(-185, -61);
+$s_icon2->drawCurve(-99,  -37,  -45, -37);
+$s_icon2->drawCurve(-261, -203, -63, -230);
+$s_icon2->drawCurve(-13,  -46,  -10, -125);
+$s_icon2->movePenTo(302, -101);
+$s_icon2->drawCurve(-83,  436,  216,  406);
+$s_icon2->drawCurve(216,  409,  411,  174);
+$s_icon2->drawCurve(281,  122,  321,  -39);
+$s_icon2->drawCurve(375,  -45,  103,  -264);
+$s_icon2->drawCurve(-223, 155,  -254, 35);
+$s_icon2->drawCurve(-241, 33,   -238, -79);
+$s_icon2->drawCurve(-233, -78,  -192, -171);
+$s_icon2->drawCurve(-196, -173, -120, -242);
+$s_icon2->drawCurve(-59,  -117, -21,  -227);
+$s_icon2->drawCurve(-24,  -239, -39,  -96);
+$s_icon2->movePenTo(-2258, -441);
+$s_icon2->drawLine(0,   140);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(-20, -140);
+$s_icon2->movePenTo(-2278, -201);
+$s_icon2->drawCurve(0,   568,  246, 224);
+$s_icon2->drawCurve(166, 146,  238, 49);
+$s_icon2->drawCurve(227, 47,   234, -52);
+$s_icon2->drawCurve(237, -54,  174, -140);
+$s_icon2->drawCurve(188, -151, 70,  -218);
+$s_icon2->drawLine(-20, 0);
+$s_icon2->drawCurve(-128, 172,  -184, 124);
+$s_icon2->drawCurve(-189, 127,  -204, 47);
+$s_icon2->drawCurve(-472, 109,  -320, -339);
+$s_icon2->drawCurve(-109, -115, -53,  -204);
+$s_icon2->drawLine(-41, -169);
+$s_icon2->drawCurve(-27, -100, -33, -71);
+$s_icon2->movePenTo(-3318, -281);
+$s_icon2->drawCurve(-27, 225, 136, 145);
+$s_icon2->drawCurve(147, 158, 204, -129);
+$s_icon2->drawLine(0, -20);
+$s_icon2->drawCurve(-188, -5,  -105, -110);
+$s_icon2->drawCurve(-31,  -34, -136, -230);
+$s_icon2->movePenTo(-2722, 231);
+$s_icon2->drawCurve(-60, 81, -16, 106);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(220, -240);
+$s_icon2->drawCurve(-89, -49, -75, 102);
+$s_icon2->movePenTo(-3138, 518);
+$s_icon2->drawCurve(0,    134, 17,   70);
+$s_icon2->drawCurve(26,   104, 77,   65);
+$s_icon2->drawCurve(96,   85,  141,  10);
+$s_icon2->drawCurve(159,  11,  44,   -119);
+$s_icon2->drawCurve(-222, 0,   -117, -85);
+$s_icon2->drawCurve(-87,  -64, -134, -211);
+$s_icon2->movePenTo(-2398, 998);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(180, -160);
+$s_icon2->drawCurve(-80, -32, -56, 57);
+$s_icon2->drawCurve(-46, 47,  -18, 88);
+$s_icon2->movePenTo(-598, -21);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(-20, -60);
+$s_icon2->drawLine(0,   60);
+$s_icon2->movePenTo(-578, -161);
+$s_icon2->drawLine(0,   60);
+$s_icon2->drawLine(20,  0);
+$s_icon2->drawLine(-20, -60);
+$s_icon2->movePenTo(-168, 562);
+$s_icon2->drawCurve(94, -131, -24, -93);
+$s_icon2->drawLine(-260, 380);
+$s_icon2->drawLine(20,   20);
+$s_icon2->drawCurve(101, -81, 69, -95);
+$s_icon2->movePenTo(-698, 818);
+$s_icon2->drawLine(-60, 60);
+$s_icon2->drawLine(0,   20);
+$s_icon2->drawCurve(307, 308,  131, 122);
+$s_icon2->drawCurve(265, 244,  228, 154);
+$s_icon2->drawCurve(599, 403,  570, -75);
+$s_icon2->drawCurve(309, -39,  351, -191);
+$s_icon2->drawCurve(294, -154, 122, -85);
+$s_icon2->drawCurve(275, -191, 9,   -156);
+$s_icon2->drawLine(-390, 293);
+$s_icon2->drawCurve(-232, 175,  -178, 85);
+$s_icon2->drawCurve(-430, 205,  -467, -64);
+$s_icon2->drawCurve(-434, -60,  -409, -284);
+$s_icon2->drawCurve(-184, -127, -256, -250);
+$s_icon2->drawCurve(-315, -306, -105, -87);
+$s_icon2->movePenTo(-1658, 1431);
+$s_icon2->drawCurve(-313, 133,  -261, -74);
+$s_icon2->drawCurve(-262, -75,  -184, -277);
+$s_icon2->drawCurve(0,    267,  181,  123);
+$s_icon2->drawCurve(158,  107,  265,  -18);
+$s_icon2->drawCurve(240,  -17,  240,  -109);
+$s_icon2->drawCurve(239,  -109, 117,  -144);
+$s_icon2->drawCurve(-86,  -8,   -129, 78);
+$s_icon2->drawLine(-205, 123);
+$s_icon2->movePenTo(-898, 1298);
+$s_icon2->drawLine(-20, -60);
+$s_icon2->drawLine(0,   60);
+$s_icon2->drawLine(20,  0);
+
+# icon3 Movieclip
+my $i_icon2 = new SWF::Sprite();
+my $item    = $i_icon2->add($s_icon2);
+$item->scaleTo(0.5);
+$i_icon2->nextFrame();
+
+# icon1 Shapes
+my $s_icon1 = new SWF::Shape();
+$s_icon1->movePenTo(6960, 2721);
+$s_icon1->setLeftFill(0xab, 0x97, 0xfd);
+$s_icon1->setRightFill(0x01, 0x01, 0x01);
+$s_icon1->drawCurve(-210, 0,    -370, -108);
+$s_icon1->drawCurve(-397, -117, -183, -12);
+$s_icon1->drawCurve(-191, -13,  -375, 85);
+$s_icon1->drawCurve(-367, 83,   -187, -18);
+$s_icon1->drawCurve(-80,  -8,   -114, -61);
+$s_icon1->drawCurve(-142, -76,  -44,  -15);
+$s_icon1->drawCurve(-17,  176,  7,    76);
+$s_icon1->drawCurve(13,   135,  80,   93);
+$s_icon1->drawCurve(70,   80,   122,  54);
+$s_icon1->drawCurve(120,  52,   130,  9);
+$s_icon1->drawCurve(309,  19,   106,  -214);
+$s_icon1->drawCurve(-302, 0,    -158, -220);
+$s_icon1->drawCurve(64,   -12,  125,  24);
+$s_icon1->drawCurve(127,  24,   64,   -10);
+$s_icon1->drawCurve(45,   -7,   102,  -38);
+$s_icon1->drawCurve(93,   -34,  60,   -4);
+$s_icon1->drawCurve(228,  -17,  308,  73);
+$s_icon1->drawCurve(177,  42,   347,  102);
+$s_icon1->drawLine(343, 97);
+$s_icon1->drawCurve(193,  67,   117,  99);
+$s_icon1->drawCurve(91,   75,   54,   126);
+$s_icon1->drawCurve(24,   54,   51,   174);
+$s_icon1->drawCurve(41,   141,  45,   72);
+$s_icon1->drawCurve(66,   103,  115,  49);
+$s_icon1->drawCurve(356,  155,  280,  -58);
+$s_icon1->drawCurve(334,  -69,  90,   -368);
+$s_icon1->drawCurve(31,   -119, -31,  -141);
+$s_icon1->drawCurve(-226, 104,  -217, -10);
+$s_icon1->drawCurve(-189, -10,  -248, -104);
+$s_icon1->drawLine(0, -40);
+$s_icon1->drawCurve(68, -13, 102, 16);
+$s_icon1->drawLine(179, 32);
+$s_icon1->drawCurve(223,  38,   121,  -90);
+$s_icon1->drawCurve(262,  -193, -276, -280);
+$s_icon1->drawCurve(-161, -164, -318, -170);
+$s_icon1->drawCurve(-330, -173, -454, -126);
+$s_icon1->drawLine(-816, -194);
+$s_icon1->drawCurve(-357, -91, -179, -40);
+$s_icon1->drawCurve(-311, -70, -233, -2);
+$s_icon1->drawCurve(-268, 0,   -168, 30);
+$s_icon1->drawCurve(-229, 42,  -175, 111);
+$s_icon1->drawCurve(-112, 68,  -41,  105);
+$s_icon1->drawCurve(-46,  117, 75,   103);
+$s_icon1->drawCurve(142,  191, 288,  -44);
+$s_icon1->drawCurve(81,   -12, 163,  -46);
+$s_icon1->drawCurve(159,  -45, 71,   -10);
+$s_icon1->drawCurve(256,  -37, 349,  65);
+$s_icon1->drawLine(595, 142);
+$s_icon1->drawCurve(179, 44, 67, 25);
+$s_icon1->drawCurve(146, 53, 68, 78);
+$s_icon1->movePenTo(8890, 3055);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->setRightFill();
+$s_icon1->drawLine(-184, -161);
+$s_icon1->drawCurve(-44,  -46,  -92,  -148);
+$s_icon1->drawCurve(-79,  -126, -75,  -60);
+$s_icon1->drawCurve(-365, -300, -771, -257);
+$s_icon1->drawCurve(-573, -192, -402, -78);
+$s_icon1->drawCurve(-544, -105, -461, 45);
+$s_icon1->drawCurve(-503, 48,   -237, 96);
+$s_icon1->drawCurve(-60,  23,   -111, 68);
+$s_icon1->drawCurve(-111, 67,   -58,  22);
+$s_icon1->drawCurve(-40,  15,   -82,  3);
+$s_icon1->drawCurve(-82,  3,    -40,  15);
+$s_icon1->drawCurve(-53,  20,   -119, 105);
+$s_icon1->drawCurve(-107, 94,   -71,  11);
+$s_icon1->drawCurve(-56,  9,    -118, -51);
+$s_icon1->drawCurve(-129, -61,  -43,  -17);
+$s_icon1->drawCurve(-527, -190, -273, 164);
+$s_icon1->drawCurve(-188, 109,  28,   283);
+$s_icon1->drawCurve(13,   121,  53,   108);
+$s_icon1->drawCurve(54,   110,  80,   59);
+$s_icon1->drawCurve(258,  187,  355,  -123);
+$s_icon1->drawCurve(333,  -116, 174,  -288);
+$s_icon1->drawCurve(-23,  128,  -126, 169);
+$s_icon1->drawCurve(-70,  95,   -141, 168);
+$s_icon1->drawCurve(-405, 538,  -135, 304);
+$s_icon1->drawCurve(-244, 549,  214,  409);
+$s_icon1->drawCurve(103,  203,  218,  138);
+$s_icon1->drawCurve(114,  73,   315,  136);
+$s_icon1->drawLine(980, 430);
+$s_icon1->drawCurve(1131, 483,  649, 193);
+$s_icon1->drawCurve(888,  261,  572, -261);
+$s_icon1->drawCurve(214,  -102, 246, -247);
+$s_icon1->drawLine(400, -427);
+$s_icon1->drawLine(377, -387);
+$s_icon1->drawCurve(216, -246, 67, -207);
+$s_icon1->drawCurve(46,  -139, 10, -207);
+$s_icon1->drawLine(7, -354);
+$s_icon1->drawCurve(16, -277, -3,  -138);
+$s_icon1->drawCurve(-6, -239, -77, -166);
+$s_icon1->drawLine(-27, -51);
+$s_icon1->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawLine(14, 85);
+$s_icon1->drawCurve(23,    232,  -120, 314);
+$s_icon1->drawCurve(-250,  661,  -643, 925);
+$s_icon1->drawCurve(-183,  258,  -82,  85);
+$s_icon1->drawCurve(-159,  165,  -206, 66);
+$s_icon1->drawCurve(-309,  97,   -361, -54);
+$s_icon1->drawCurve(-207,  -31,  -443, -136);
+$s_icon1->drawCurve(-1336, -403, -844, -343);
+$s_icon1->drawCurve(-396,  -159, -159, -91);
+$s_icon1->drawCurve(-296,  -170, -149, -234);
+$s_icon1->drawCurve(-275,  -428, 295,  -570);
+$s_icon1->drawCurve(100,   -194, 198,  -266);
+$s_icon1->drawLine(302, -405);
+$s_icon1->drawCurve(37,  -55,  111, -125);
+$s_icon1->drawCurve(102, -115, 40,  -68);
+$s_icon1->drawCurve(14,  -23,  11,  -42);
+$s_icon1->drawLine(18, -69);
+$s_icon1->drawCurve(27, -78, 76,  -8);
+$s_icon1->drawCurve(64, -7,  23,  86);
+$s_icon1->drawCurve(18, 68,  -15, 63);
+$s_icon1->drawLine(-57, 248);
+$s_icon1->drawCurve(-23, 149,  44,  99);
+$s_icon1->drawCurve(45,  104,  161, 111);
+$s_icon1->drawCurve(77,  54,   187, 101);
+$s_icon1->drawCurve(362, 200,  568, 165);
+$s_icon1->drawCurve(323, 95,   647, 170);
+$s_icon1->drawCurve(227, 67,   465, 162);
+$s_icon1->drawCurve(420, 137,  288, 34);
+$s_icon1->drawCurve(199, 24,   202, -62);
+$s_icon1->drawCurve(198, -60,  156, -128);
+$s_icon1->drawCurve(161, -133, 79,  -177);
+$s_icon1->drawCurve(84,  -190, -26, -210);
+$s_icon1->drawCurve(-8,  -72,  -55, -83);
+$s_icon1->drawLine(-90, -145);
+$s_icon1->drawLine(50,  14);
+$s_icon1->setLeftFill();
+$s_icon1->drawCurve(221, 72, 55, 223);
+$s_icon1->movePenTo(8526, 5034);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->drawCurve(-3, 3,   7,  14);
+$s_icon1->drawCurve(3,  -24, -7, 7);
+$s_icon1->movePenTo(7747, 4921);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->drawCurve(101, 43,  112,  17);
+$s_icon1->drawCurve(30,  -58, 61,   -105);
+$s_icon1->drawCurve(51,  -93, 18,   -84);
+$s_icon1->drawCurve(-86, -31, -274, -69);
+$s_icon1->drawLine(-95, 113);
+$s_icon1->drawCurve(-55, 71, -4,  56);
+$s_icon1->drawCurve(-2,  78, 143, 62);
+$s_icon1->movePenTo(7403, 4394);
+$s_icon1->drawCurve(-98, -20, -82, 50);
+$s_icon1->drawCurve(-98, 58,  -2,  82);
+$s_icon1->drawCurve(-2,  71,  68,  67);
+$s_icon1->drawCurve(64,  63,  85,  24);
+$s_icon1->drawCurve(92,  26,  60,  -38);
+$s_icon1->drawCurve(104, -64, 12,  -88);
+$s_icon1->drawCurve(10,  -77, -62, -69);
+$s_icon1->drawCurve(-60, -66, -91, -19);
+$s_icon1->movePenTo(7011, 4245);
+$s_icon1->drawCurve(-112, -53, -59,  12);
+$s_icon1->drawCurve(-118, 23,  -15,  111);
+$s_icon1->drawCurve(-14,  99,  66,   102);
+$s_icon1->drawCurve(68,   104, 90,   8);
+$s_icon1->drawCurve(106,  10,  80,   -140);
+$s_icon1->drawCurve(22,   -41, 55,   -159);
+$s_icon1->drawCurve(-17,  -5,  -152, -71);
+$s_icon1->movePenTo(6604, 4692);
+$s_icon1->setLeftFill(0xff, 0x01, 0x01);
+$s_icon1->setRightFill(0x01, 0x01, 0x01);
+$s_icon1->drawCurve(-115, 19,   -29, 150);
+$s_icon1->drawCurve(117,  56,   163, 44);
+$s_icon1->drawCurve(75,   -146, 25,  -74);
+$s_icon1->drawCurve(-150, -63,  -86, 14);
+$s_icon1->movePenTo(6543, 4644);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawCurve(-89,  47,   -29,  96);
+$s_icon1->drawCurve(-32,  103,  87,   54);
+$s_icon1->drawCurve(56,   31,   64,   19);
+$s_icon1->drawCurve(76,   27,   104,  0);
+$s_icon1->drawCurve(83,   -157, 3,    -80);
+$s_icon1->drawCurve(4,    -65,  -114, -42);
+$s_icon1->drawCurve(-142, -71,  -71,  38);
+$s_icon1->movePenTo(6969, 4928);
+$s_icon1->drawCurve(-70, 113, 21,  40);
+$s_icon1->drawCurve(27,  56,  110, 23);
+$s_icon1->drawCurve(93,  18,  -10, 43);
+$s_icon1->drawLine(90, -13);
+$s_icon1->drawCurve(31, -11, 39, -56);
+$s_icon1->drawLine(68, -93);
+$s_icon1->drawCurve(42,   -62, -10,  -45);
+$s_icon1->drawCurve(-13,  -48, -129, -57);
+$s_icon1->drawCurve(-129, -57, -49,  22);
+$s_icon1->drawCurve(-45,  19,  -66,  108);
+$s_icon1->movePenTo(7029, 5315);
+$s_icon1->drawCurve(-83,  -34, -46,  -7);
+$s_icon1->drawCurve(-70,  -13, -104, 114);
+$s_icon1->drawCurve(-103, 114, 20,   68);
+$s_icon1->drawCurve(24,   74,  140,  45);
+$s_icon1->drawCurve(139,  46,  64,   -41);
+$s_icon1->drawCurve(66,   -39, 42,   -103);
+$s_icon1->drawCurve(36,   -86, 6,    -92);
+$s_icon1->drawCurve(-41,  -9,  -90,  -37);
+$s_icon1->movePenTo(7193, 5081);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->setRightFill(0x01, 0x01, 0x01);
+$s_icon1->drawCurve(65, -18, 82, -142);
+$s_icon1->drawLine(-260, -80);
+$s_icon1->drawLine(-100, 200);
+$s_icon1->drawCurve(160, 55, 53, -15);
+$s_icon1->movePenTo(6552, 5178);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawCurve(-74,  -72,  -198, -45);
+$s_icon1->drawCurve(-144, 202,  61,   112);
+$s_icon1->drawCurve(55,   100,  248,  66);
+$s_icon1->drawCurve(140,  -215, -58,  -109);
+$s_icon1->drawLine(-23, -32);
+$s_icon1->setRightFill(0xff, 0xff, 0xff);
+$s_icon1->drawCurve(-12,  47,   -67,  149);
+$s_icon1->drawCurve(-160, -16,  -120, -64);
+$s_icon1->drawCurve(41,   -157, 90,   -17);
+$s_icon1->drawCurve(63,   -12,  158,  63);
+$s_icon1->setLeftFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawLine(8,  3);
+$s_icon1->drawLine(-1, 4);
+$s_icon1->movePenTo(7232, 5819);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawCurve(77,  40,  124, -28);
+$s_icon1->drawCurve(125, -28, 52,  -72);
+$s_icon1->drawCurve(61,  -82, -88, -95);
+$s_icon1->drawCurve(-26, -28, -81, -32);
+$s_icon1->drawCurve(-93, -38, -23, -15);
+$s_icon1->drawCurve(-93, 85,  -27, 38);
+$s_icon1->drawCurve(-37, 55,  -17, 42);
+$s_icon1->drawCurve(-43, 112, 89,  46);
+$s_icon1->movePenTo(7007, 5486);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->setRightFill(0x01, 0x01, 0x01);
+$s_icon1->drawCurve(38, -69, 15, -56);
+$s_icon1->drawLine(-200, -60);
+$s_icon1->drawCurve(-125, 199, -15, 41);
+$s_icon1->drawLine(220, 60);
+$s_icon1->drawLine(67,  -115);
+$s_icon1->movePenTo(7826, 5260);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawCurve(50,   -84, 4,    -115);
+$s_icon1->drawCurve(-223, -60, -72,  26);
+$s_icon1->drawCurve(-73,  26,  -132, 188);
+$s_icon1->drawCurve(72,   96,  89,   33);
+$s_icon1->drawCurve(83,   30,  77,   -31);
+$s_icon1->drawCurve(77,   -30, 48,   -79);
+$s_icon1->movePenTo(7796, 5107);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->setRightFill(0x01, 0x01, 0x01);
+$s_icon1->drawCurve(-63,  -129, -129, 70);
+$s_icon1->drawCurve(-117, 63,   -27,  110);
+$s_icon1->drawLine(140, 53);
+$s_icon1->drawCurve(74, 20,  77,  -52);
+$s_icon1->drawCurve(82, -56, -37, -79);
+$s_icon1->movePenTo(7350, 6527);
+$s_icon1->drawLine(2, -9);
+$s_icon1->drawCurve(-1, -8, -5, 7);
+$s_icon1->drawCurve(-3, 20, 7,  -10);
+$s_icon1->movePenTo(3956, 3921);
+$s_icon1->drawCurve(-277, 390, -59, 210);
+$s_icon1->drawCurve(175,  97,  290, 110);
+$s_icon1->drawLine(475, 186);
+$s_icon1->drawCurve(345, 163, 131, -46);
+$s_icon1->drawCurve(56,  -21, 58,  -77);
+$s_icon1->drawLine(90, -126);
+$s_icon1->drawCurve(324, -399, -61,  -141);
+$s_icon1->drawCurve(-33, -74,  -242, -61);
+$s_icon1->drawLine(-328, -75);
+$s_icon1->drawCurve(-306, -105, -234, -108);
+$s_icon1->drawLine(-117, -59);
+$s_icon1->drawCurve(-75, -35, -45, 4);
+$s_icon1->drawCurve(-49, 4,   -49, 62);
+$s_icon1->drawCurve(-28, 34,  -41, 67);
+$s_icon1->movePenTo(3904, 3788);
+$s_icon1->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1->drawLine(-114, 173);
+$s_icon1->drawLine(-195, 276);
+$s_icon1->drawCurve(-125, 202, 23,  102);
+$s_icon1->drawCurve(17,   70,  131, 75);
+$s_icon1->drawLine(199, 95);
+$s_icon1->drawCurve(519, 256, 421, 97);
+$s_icon1->drawCurve(254, 61,  99,  -54);
+$s_icon1->drawCurve(66,  -38, 79,  -117);
+$s_icon1->drawLine(112, -185);
+$s_icon1->drawCurve(111,  -145, 56,   -85);
+$s_icon1->drawCurve(101,  -154, -8,   -106);
+$s_icon1->drawCurve(-6,   -78,  -78,  -50);
+$s_icon1->drawCurve(-31,  -20,  -115, -46);
+$s_icon1->drawCurve(-240, -90,  -480, -166);
+$s_icon1->drawCurve(-208, -66,  -252, -101);
+$s_icon1->drawCurve(-63,  -31,  -34,  -13);
+$s_icon1->drawCurve(-61,  -23,  -39,  17);
+$s_icon1->drawCurve(-61,  29,   -78,  115);
+$s_icon1->movePenTo(5780, 4921);
+$s_icon1->drawCurve(65, -21, 75, 18);
+$s_icon1->drawCurve(44, 11,  96, 32);
+$s_icon1->drawLine(-100, -100);
+$s_icon1->drawLine(-104, 3);
+$s_icon1->drawCurve(-48, 9, -28, 48);
+$s_icon1->movePenTo(5952, 4584);
+$s_icon1->drawCurve(-9,  69,  44,  70);
+$s_icon1->drawCurve(44,  68,  69,  31);
+$s_icon1->drawCurve(74,  33,  66,  -31);
+$s_icon1->drawCurve(118, -56, 23,  -85);
+$s_icon1->drawCurve(21,  -73, -53, -71);
+$s_icon1->drawCurve(-51, -68, -85, -24);
+$s_icon1->drawCurve(-92, -26, -78, 43);
+$s_icon1->drawCurve(-80, 43,  -11, 77);
+$s_icon1->movePenTo(5936, 5301);
+$s_icon1->drawCurve(86,  -14,  50,  -116);
+$s_icon1->drawCurve(45,  -105, -17, -85);
+$s_icon1->drawCurve(-98, 97,   -62, 123);
+$s_icon1->drawLine(-240, -100);
+$s_icon1->drawLine(39,   -87);
+$s_icon1->drawCurve(21, -52, 0, -41);
+$s_icon1->drawLine(-67, 83);
+$s_icon1->drawCurve(-38, 53, -2,  40);
+$s_icon1->drawCurve(-5,  70, 113, 73);
+$s_icon1->drawCurve(106, 69, 69,  -8);
+$s_icon1->movePenTo(6104, 6526);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->setRightFill();
+$s_icon1->drawLine(9, 1);
+$s_icon1->drawCurve(0, -20, -10, 10);
+$s_icon1->drawLine(1, 9);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(3686, 2737);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawCurve(-3, 20, 7, -10);
+$s_icon1->drawLine(2, -9);
+$s_icon1->drawCurve(-1, -8, -5, 7);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(5820, 3007);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->drawCurve(354, 77,  366, 147);
+$s_icon1->drawCurve(97,  41,  103, 107);
+$s_icon1->drawCurve(125, 131, 55,  37);
+$s_icon1->drawCurve(70,  49,  132, 42);
+$s_icon1->drawLine(218, 63);
+$s_icon1->drawLine(-20, -140);
+$s_icon1->drawCurve(-180, -6, -119, -122);
+$s_icon1->drawLine(-100, -113);
+$s_icon1->drawCurve(-64,  -70,  -64,  -43);
+$s_icon1->drawCurve(-237, -156, -383, -72);
+$s_icon1->drawCurve(-397, -74,  -256, 76);
+$s_icon1->drawCurve(48,   20,   97,   -1);
+$s_icon1->drawLine(155, 7);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(8720, 3541);
+$s_icon1->setLeftFill(0xee, 0xeb, 0xff);
+$s_icon1->drawLine(0, 80);
+$s_icon1->drawCurve(15, -39, -15, -41);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(8700, 3621);
+$s_icon1->setLeftFill(0xee, 0xeb, 0xff);
+$s_icon1->drawLine(0, 60);
+$s_icon1->drawCurve(12, -29, -12, -31);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(8686, 3697);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->drawCurve(-3, 20, 7, -10);
+$s_icon1->drawLine(2, -9);
+$s_icon1->drawCurve(-1, -8, -5, 7);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(9280, 3701);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->drawCurve(-21,  153, -121, 227);
+$s_icon1->drawCurve(-145, 250, -57,  110);
+$s_icon1->drawCurve(-382, 775, -301, 465);
+$s_icon1->drawCurve(-200, 310, -149, 131);
+$s_icon1->drawCurve(-214, 188, -290, 27);
+$s_icon1->drawCurve(-207, 22,  -262, -62);
+$s_icon1->drawCurve(-61,  -15, -390, -118);
+$s_icon1->drawLine(-1420, -477);
+$s_icon1->drawLine(-823,  -263);
+$s_icon1->drawCurve(-464, -160, -333, -167);
+$s_icon1->drawCurve(-552, -271, -68,  -425);
+$s_icon1->drawCurve(-58,  139,  79,   165);
+$s_icon1->drawCurve(68,   143,  131,  96);
+$s_icon1->drawCurve(229,  171,  372,  166);
+$s_icon1->drawCurve(213,  96,   426,  174);
+$s_icon1->drawCurve(1304, 565,  856,  225);
+$s_icon1->drawCurve(402,  106,  154,  20);
+$s_icon1->drawCurve(318,  41,   246,  -94);
+$s_icon1->drawCurve(344,  -134, 314,  -351);
+$s_icon1->drawCurve(175,  -197, 317,  -471);
+$s_icon1->drawLine(186, -263);
+$s_icon1->drawCurve(112, -158, 66,  -108);
+$s_icon1->drawCurve(189, -311, 40,  -280);
+$s_icon1->drawCurve(47,  -317, -70, -123);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(7013, 4251);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(6693, 4691);
+$s_icon1->setLeftFill(0xb8, 0x01, 0x01);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(7093, 4791);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(3890, 4811);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawLine(16, 3);
+$s_icon1->drawCurve(7, -7, -23, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(6033, 4931);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->movePenTo(6453, 4931);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(5773, 5131);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(4780, 5141);
+$s_icon1->setLeftFill(0xdd, 0xdd, 0xdd);
+$s_icon1->drawCurve(41,  20,  59,  0);
+$s_icon1->drawCurve(-40, -15, -60, -5);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(5913, 5311);
+$s_icon1->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1->drawLine(10, 3);
+$s_icon1->drawCurve(10, -7, -20, 4);
+$s_icon1->setLeftFill();
+$s_icon1->setRightFill();
+
+$s_icon1->movePenTo(7260, 5721);
+$s_icon1->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1->drawCurve(85,  31,  31,  2);
+$s_icon1->drawCurve(78,  7,   26,  -59);
+$s_icon1->drawCurve(23,  -51, -26, -61);
+$s_icon1->drawCurve(-27, -62, -49, -2);
+$s_icon1->drawCurve(-57, -1,  -54, 96);
+$s_icon1->drawCurve(-17, 29,  -13, 71);
+
+my $s_icon1_f2 = new SWF::Shape();
+$s_icon1_f2->movePenTo(8877, 3643);
+$s_icon1_f2->setLeftFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->setRightFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(82,    -165, -25,  -185);
+$s_icon1_f2->drawCurve(-8,    -64,  -54,  -71);
+$s_icon1_f2->drawCurve(-47,   -63,  -518, -190);
+$s_icon1_f2->drawCurve(-613,  -225, -866, -239);
+$s_icon1_f2->drawCurve(-1929, -534, -108, 38);
+$s_icon1_f2->drawLine(-178, 16);
+$s_icon1_f2->drawCurve(-71, 5,   -160, 230);
+$s_icon1_f2->drawCurve(-73, 104, -51,  158);
+$s_icon1_f2->drawCurve(-51, 161, 17,   85);
+$s_icon1_f2->drawLine(11, 98);
+$s_icon1_f2->drawCurve(8,  53, 135, 163);
+$s_icon1_f2->drawCurve(16, 27, 87,  41);
+$s_icon1_f2->drawLine(327, 147);
+$s_icon1_f2->drawCurve(493, 229, 265, 68);
+$s_icon1_f2->drawLine(955, 232);
+$s_icon1_f2->drawCurve(235, 63,   445, 138);
+$s_icon1_f2->drawCurve(413, 120,  284, 30);
+$s_icon1_f2->drawCurve(194, 20,   200, -54);
+$s_icon1_f2->drawCurve(194, -52,  155, -112);
+$s_icon1_f2->drawCurve(158, -118, 78,  -154);
+$s_icon1_f2->movePenTo(9166, 3350);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(9,     35,   5,    50);
+$s_icon1_f2->drawCurve(23,    234,  -120, 312);
+$s_icon1_f2->drawCurve(-251,  663,  -642, 923);
+$s_icon1_f2->drawCurve(-183,  258,  -82,  85);
+$s_icon1_f2->drawCurve(-159,  165,  -206, 66);
+$s_icon1_f2->drawCurve(-308,  97,   -362, -54);
+$s_icon1_f2->drawCurve(-214,  -33,  -436, -134);
+$s_icon1_f2->drawCurve(-1342, -405, -838, -341);
+$s_icon1_f2->drawCurve(-399,  -160, -156, -90);
+$s_icon1_f2->drawCurve(-297,  -170, -148, -234);
+$s_icon1_f2->drawCurve(-275,  -429, 295,  -569);
+$s_icon1_f2->drawCurve(103,   -199, 195,  -261);
+$s_icon1_f2->drawCurve(221,   -289, 81,   -116);
+$s_icon1_f2->drawCurve(39,    -58,  109,  -122);
+$s_icon1_f2->drawCurve(100,   -114, 42,   -69);
+$s_icon1_f2->drawCurve(15,    -25,  10,   -40);
+$s_icon1_f2->drawLine(18, -69);
+$s_icon1_f2->drawCurve(27, -79, 76,  -7);
+$s_icon1_f2->drawCurve(64, -7,  23,  86);
+$s_icon1_f2->drawCurve(18, 68,  -15, 63);
+$s_icon1_f2->drawLine(-57, 248);
+$s_icon1_f2->drawCurve(-23, 149,  44,  99);
+$s_icon1_f2->drawCurve(45,  104,  161, 111);
+$s_icon1_f2->drawCurve(79,  56,   185, 99);
+$s_icon1_f2->drawCurve(363, 201,  567, 164);
+$s_icon1_f2->drawCurve(346, 102,  624, 163);
+$s_icon1_f2->drawCurve(240, 72,   452, 157);
+$s_icon1_f2->drawCurve(420, 137,  288, 34);
+$s_icon1_f2->drawCurve(198, 24,   203, -62);
+$s_icon1_f2->drawCurve(197, -60,  157, -128);
+$s_icon1_f2->drawCurve(161, -134, 79,  -176);
+$s_icon1_f2->drawCurve(84,  -189, -26, -211);
+$s_icon1_f2->drawCurve(-8,  -73,  -55, -82);
+$s_icon1_f2->drawLine(-90, -145);
+$s_icon1_f2->drawLine(50,  14);
+$s_icon1_f2->setRightFill();
+$s_icon1_f2->drawCurve(-98,  -84,  -1940, -604);
+$s_icon1_f2->drawCurve(-453, -141, -353,  -106);
+$s_icon1_f2->drawLine(-226, -67);
+$s_icon1_f2->drawCurve(-962, -282, -76, 30);
+$s_icon1_f2->drawLine(-181, 18);
+$s_icon1_f2->drawCurve(-166, 15,   -46,  28);
+$s_icon1_f2->drawCurve(-107, 65,   -62,  24);
+$s_icon1_f2->drawCurve(-41,  15,   -81,  3);
+$s_icon1_f2->drawCurve(-81,  3,    -41,  15);
+$s_icon1_f2->drawCurve(-53,  20,   -119, 105);
+$s_icon1_f2->drawCurve(-106, 94,   -72,  11);
+$s_icon1_f2->drawCurve(-55,  9,    -119, -51);
+$s_icon1_f2->drawCurve(-131, -62,  -41,  -16);
+$s_icon1_f2->drawCurve(-401, -145, -254, 61);
+$s_icon1_f2->drawLine(-295, 512);
+$s_icon1_f2->drawCurve(17,  87,   39,   80);
+$s_icon1_f2->drawCurve(55,  111,  79,   58);
+$s_icon1_f2->drawCurve(257, 187,  356,  -123);
+$s_icon1_f2->drawCurve(333, -115, 174,  -289);
+$s_icon1_f2->drawCurve(-22, 127,  -127, 170);
+$s_icon1_f2->drawLine(-211, 263);
+$s_icon1_f2->drawCurve(-406, 540, -134, 302);
+$s_icon1_f2->drawCurve(-244, 549, 214,  409);
+$s_icon1_f2->drawCurve(104,  203, 217,  138);
+$s_icon1_f2->drawCurve(109,  70,  320,  139);
+$s_icon1_f2->drawLine(980, 430);
+$s_icon1_f2->drawCurve(1128, 482,  652, 194);
+$s_icon1_f2->drawCurve(888,  261,  572, -261);
+$s_icon1_f2->drawCurve(215,  -102, 245, -247);
+$s_icon1_f2->drawCurve(139,  -140, 261, -287);
+$s_icon1_f2->drawLine(377, -387);
+$s_icon1_f2->drawCurve(215, -245, 68, -208);
+$s_icon1_f2->drawCurve(45,  -136, 11, -210);
+$s_icon1_f2->drawLine(7, -354);
+$s_icon1_f2->drawCurve(16, -271, -3,  -144);
+$s_icon1_f2->drawCurve(-6, -237, -77, -168);
+$s_icon1_f2->drawLine(-27, -51);
+$s_icon1_f2->setLeftFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(-55, -223, -221, -72);
+$s_icon1_f2->movePenTo(8530, 5051);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(3,  -24, -7, 7);
+$s_icon1_f2->drawCurve(-3, 3,   7,  14);
+$s_icon1_f2->movePenTo(7606, 4781);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(-2,  78,  143,  62);
+$s_icon1_f2->drawCurve(101, 43,  112,  17);
+$s_icon1_f2->drawCurve(30,  -58, 61,   -105);
+$s_icon1_f2->drawCurve(51,  -93, 18,   -84);
+$s_icon1_f2->drawCurve(-86, -31, -274, -69);
+$s_icon1_f2->drawLine(-95, 113);
+$s_icon1_f2->drawCurve(-55, 71, -4, 56);
+$s_icon1_f2->movePenTo(7490, 4777);
+$s_icon1_f2->drawCurve(104, -64, 12,  -88);
+$s_icon1_f2->drawCurve(10,  -77, -62, -69);
+$s_icon1_f2->drawCurve(-60, -66, -91, -19);
+$s_icon1_f2->drawCurve(-98, -20, -82, 50);
+$s_icon1_f2->drawCurve(-98, 58,  -2,  82);
+$s_icon1_f2->drawCurve(-2,  71,  68,  67);
+$s_icon1_f2->drawCurve(64,  63,  85,  24);
+$s_icon1_f2->drawCurve(92,  26,  60,  -38);
+$s_icon1_f2->movePenTo(7011, 4245);
+$s_icon1_f2->drawCurve(-112, -53, -59,  12);
+$s_icon1_f2->drawCurve(-118, 23,  -15,  111);
+$s_icon1_f2->drawCurve(-14,  99,  66,   102);
+$s_icon1_f2->drawCurve(68,   104, 90,   8);
+$s_icon1_f2->drawCurve(106,  10,  80,   -140);
+$s_icon1_f2->drawCurve(22,   -41, 55,   -159);
+$s_icon1_f2->drawCurve(-17,  -5,  -152, -71);
+$s_icon1_f2->movePenTo(7080, 4801);
+$s_icon1_f2->drawCurve(-45, 19,  -66, 108);
+$s_icon1_f2->drawCurve(-70, 113, 21,  40);
+$s_icon1_f2->drawCurve(27,  56,  110, 23);
+$s_icon1_f2->drawCurve(93,  18,  -10, 43);
+$s_icon1_f2->drawLine(90, -13);
+$s_icon1_f2->drawCurve(31, -11, 39, -56);
+$s_icon1_f2->drawLine(68, -93);
+$s_icon1_f2->drawCurve(42,   -62, -10,  -45);
+$s_icon1_f2->drawCurve(-13,  -48, -129, -57);
+$s_icon1_f2->drawCurve(-129, -57, -49,  22);
+$s_icon1_f2->movePenTo(6900, 5274);
+$s_icon1_f2->drawCurve(-70,  -13, -104, 114);
+$s_icon1_f2->drawCurve(-103, 114, 20,   68);
+$s_icon1_f2->drawCurve(24,   74,  140,  45);
+$s_icon1_f2->drawCurve(139,  46,  64,   -41);
+$s_icon1_f2->drawCurve(66,   -39, 42,   -103);
+$s_icon1_f2->drawCurve(36,   -86, 6,    -92);
+$s_icon1_f2->drawCurve(-41,  -9,  -90,  -37);
+$s_icon1_f2->drawCurve(-83,  -34, -46,  -7);
+$s_icon1_f2->movePenTo(7193, 5081);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->setRightFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(65, -18, 82, -142);
+$s_icon1_f2->drawLine(-260, -80);
+$s_icon1_f2->drawLine(-100, 200);
+$s_icon1_f2->drawCurve(160, 55, 53, -15);
+$s_icon1_f2->movePenTo(6552, 5178);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(-74,  -72,  -198, -45);
+$s_icon1_f2->drawCurve(-144, 202,  61,   112);
+$s_icon1_f2->drawCurve(55,   100,  248,  66);
+$s_icon1_f2->drawCurve(140,  -215, -58,  -109);
+$s_icon1_f2->drawLine(-23, -32);
+$s_icon1_f2->setRightFill(0xff, 0xff, 0xff);
+$s_icon1_f2->drawCurve(-12,  47,   -67,  149);
+$s_icon1_f2->drawCurve(-160, -16,  -120, -64);
+$s_icon1_f2->drawCurve(41,   -157, 90,   -17);
+$s_icon1_f2->drawCurve(63,   -12,  158,  63);
+$s_icon1_f2->setLeftFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawLine(8,  3);
+$s_icon1_f2->drawLine(-1, 4);
+$s_icon1_f2->movePenTo(7186, 5661);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(-43, 112, 89,  46);
+$s_icon1_f2->drawCurve(77,  40,  124, -28);
+$s_icon1_f2->drawCurve(125, -28, 52,  -72);
+$s_icon1_f2->drawCurve(61,  -82, -88, -95);
+$s_icon1_f2->drawCurve(-26, -28, -81, -32);
+$s_icon1_f2->drawCurve(-93, -38, -23, -15);
+$s_icon1_f2->drawCurve(-93, 85,  -27, 38);
+$s_icon1_f2->drawCurve(-37, 55,  -17, 42);
+$s_icon1_f2->movePenTo(7007, 5486);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->setRightFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(38, -69, 15, -56);
+$s_icon1_f2->drawLine(-200, -60);
+$s_icon1_f2->drawCurve(-125, 199, -15, 41);
+$s_icon1_f2->drawLine(220, 60);
+$s_icon1_f2->drawLine(67,  -115);
+$s_icon1_f2->movePenTo(7826, 5260);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(50,   -84, 4,    -115);
+$s_icon1_f2->drawCurve(-223, -60, -72,  26);
+$s_icon1_f2->drawCurve(-73,  26,  -132, 188);
+$s_icon1_f2->drawCurve(72,   96,  89,   33);
+$s_icon1_f2->drawCurve(83,   30,  77,   -31);
+$s_icon1_f2->drawCurve(77,   -30, 48,   -79);
+$s_icon1_f2->movePenTo(7796, 5107);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->setRightFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(-63,  -129, -129, 70);
+$s_icon1_f2->drawCurve(-117, 63,   -27,  110);
+$s_icon1_f2->drawLine(140, 53);
+$s_icon1_f2->drawCurve(74, 20,  77,  -52);
+$s_icon1_f2->drawCurve(82, -56, -37, -79);
+$s_icon1_f2->movePenTo(7346, 6517);
+$s_icon1_f2->drawCurve(-3, 20, 7, -10);
+$s_icon1_f2->drawLine(2, -9);
+$s_icon1_f2->drawCurve(-1, -8, -5, 7);
+$s_icon1_f2->movePenTo(3904, 3788);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawLine(-114, 173);
+$s_icon1_f2->drawLine(-195, 276);
+$s_icon1_f2->drawCurve(-125, 202, 23,  102);
+$s_icon1_f2->drawCurve(17,   70,  131, 75);
+$s_icon1_f2->drawLine(199, 95);
+$s_icon1_f2->drawCurve(519, 256, 421, 97);
+$s_icon1_f2->drawCurve(254, 61,  99,  -54);
+$s_icon1_f2->drawCurve(66,  -38, 79,  -117);
+$s_icon1_f2->drawLine(112, -185);
+$s_icon1_f2->drawCurve(111,  -145, 56,   -85);
+$s_icon1_f2->drawCurve(101,  -154, -8,   -106);
+$s_icon1_f2->drawCurve(-6,   -78,  -78,  -50);
+$s_icon1_f2->drawCurve(-31,  -20,  -115, -46);
+$s_icon1_f2->drawCurve(-240, -90,  -480, -166);
+$s_icon1_f2->drawCurve(-208, -66,  -252, -101);
+$s_icon1_f2->drawCurve(-63,  -31,  -34,  -13);
+$s_icon1_f2->drawCurve(-61,  -23,  -39,  17);
+$s_icon1_f2->drawCurve(-61,  29,   -78,  115);
+$s_icon1_f2->movePenTo(3956, 3921);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->setRightFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(-277, 390, -59, 210);
+$s_icon1_f2->drawCurve(175,  97,  290, 110);
+$s_icon1_f2->drawLine(475, 186);
+$s_icon1_f2->drawCurve(345, 163, 131, -46);
+$s_icon1_f2->drawCurve(56,  -21, 58,  -77);
+$s_icon1_f2->drawLine(90, -126);
+$s_icon1_f2->drawCurve(324, -399, -61,  -141);
+$s_icon1_f2->drawCurve(-33, -74,  -242, -61);
+$s_icon1_f2->drawLine(-328, -75);
+$s_icon1_f2->drawCurve(-306, -105, -234, -108);
+$s_icon1_f2->drawLine(-117, -59);
+$s_icon1_f2->drawCurve(-75, -35, -45, 4);
+$s_icon1_f2->drawCurve(-49, 4,   -49, 62);
+$s_icon1_f2->drawCurve(-28, 34,  -41, 67);
+$s_icon1_f2->movePenTo(5952, 4584);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->setRightFill(0xc9, 0xc9, 0xc9);
+$s_icon1_f2->drawCurve(-9,  69,  44,  70);
+$s_icon1_f2->drawCurve(44,  68,  69,  31);
+$s_icon1_f2->drawCurve(74,  33,  66,  -31);
+$s_icon1_f2->drawCurve(118, -56, 23,  -85);
+$s_icon1_f2->drawCurve(21,  -73, -53, -71);
+$s_icon1_f2->drawCurve(-51, -68, -85, -24);
+$s_icon1_f2->drawCurve(-92, -26, -78, 43);
+$s_icon1_f2->drawCurve(-80, 43,  -11, 77);
+$s_icon1_f2->movePenTo(6072, 5171);
+$s_icon1_f2->drawCurve(45,  -105, -17, -85);
+$s_icon1_f2->drawCurve(-98, 97,   -62, 123);
+$s_icon1_f2->drawLine(-240, -100);
+$s_icon1_f2->drawLine(39,   -87);
+$s_icon1_f2->drawCurve(21, -52, 0, -41);
+$s_icon1_f2->drawLine(-67, 83);
+$s_icon1_f2->drawCurve(-38, 53,  -2,  40);
+$s_icon1_f2->drawCurve(-5,  70,  113, 73);
+$s_icon1_f2->drawCurve(106, 69,  69,  -8);
+$s_icon1_f2->drawCurve(86,  -14, 50,  -116);
+$s_icon1_f2->movePenTo(6104, 6526);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->setRightFill();
+$s_icon1_f2->drawLine(9, 1);
+$s_icon1_f2->drawCurve(0, -20, -10, 10);
+$s_icon1_f2->drawLine(1, 9);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(3686, 2737);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawCurve(-3, 20, 7, -10);
+$s_icon1_f2->drawLine(2, -9);
+$s_icon1_f2->drawCurve(-1, -8, -5, 7);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(9280, 3701);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->drawCurve(-21,  153, -121, 227);
+$s_icon1_f2->drawCurve(-145, 250, -57,  110);
+$s_icon1_f2->drawCurve(-382, 775, -301, 465);
+$s_icon1_f2->drawCurve(-200, 310, -149, 131);
+$s_icon1_f2->drawCurve(-214, 188, -290, 27);
+$s_icon1_f2->drawCurve(-207, 22,  -262, -62);
+$s_icon1_f2->drawCurve(-61,  -15, -390, -118);
+$s_icon1_f2->drawLine(-1420, -477);
+$s_icon1_f2->drawLine(-823,  -263);
+$s_icon1_f2->drawCurve(-464, -160, -333, -167);
+$s_icon1_f2->drawCurve(-552, -271, -68,  -425);
+$s_icon1_f2->drawCurve(-58,  139,  79,   165);
+$s_icon1_f2->drawCurve(68,   143,  131,  96);
+$s_icon1_f2->drawCurve(229,  171,  372,  166);
+$s_icon1_f2->drawCurve(213,  96,   426,  174);
+$s_icon1_f2->drawCurve(1304, 565,  856,  225);
+$s_icon1_f2->drawCurve(402,  106,  154,  20);
+$s_icon1_f2->drawCurve(318,  41,   246,  -94);
+$s_icon1_f2->drawCurve(344,  -134, 314,  -351);
+$s_icon1_f2->drawCurve(175,  -197, 317,  -471);
+$s_icon1_f2->drawLine(186, -263);
+$s_icon1_f2->drawCurve(112, -158, 66,  -108);
+$s_icon1_f2->drawCurve(189, -311, 40,  -280);
+$s_icon1_f2->drawCurve(47,  -317, -70, -123);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(7013, 4251);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(6780, 5021);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(83,   -157, 3,    -80);
+$s_icon1_f2->drawCurve(4,    -65,  -114, -42);
+$s_icon1_f2->drawCurve(-142, -71,  -71,  38);
+$s_icon1_f2->drawCurve(-89,  47,   -29,  96);
+$s_icon1_f2->drawCurve(-32,  103,  87,   54);
+$s_icon1_f2->drawCurve(56,   31,   64,   19);
+$s_icon1_f2->drawCurve(76,   27,   104,  0);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(6460, 4861);
+$s_icon1_f2->setLeftFill(0xff, 0x01, 0x01);
+$s_icon1_f2->drawCurve(117,  56,   163, 44);
+$s_icon1_f2->drawCurve(75,   -146, 25,  -74);
+$s_icon1_f2->drawCurve(-150, -63,  -86, 14);
+$s_icon1_f2->drawCurve(-115, 19,   -29, 150);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(6693, 4691);
+$s_icon1_f2->setLeftFill(0xb8, 0x01, 0x01);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(7093, 4791);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(3890, 4811);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(16, 3);
+$s_icon1_f2->drawCurve(7, -7, -23, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(5780, 4921);
+$s_icon1_f2->setLeftFill(0x01, 0x01, 0x01);
+$s_icon1_f2->drawCurve(65, -21, 75, 18);
+$s_icon1_f2->drawCurve(44, 11,  96, 32);
+$s_icon1_f2->drawLine(-100, -100);
+$s_icon1_f2->drawLine(-104, 3);
+$s_icon1_f2->drawCurve(-48, 9, -28, 48);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(6033, 4931);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->movePenTo(6453, 4931);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(5773, 5131);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(4780, 5141);
+$s_icon1_f2->setLeftFill(0xdd, 0xdd, 0xdd);
+$s_icon1_f2->drawCurve(41,  20,  59,  0);
+$s_icon1_f2->drawCurve(-40, -15, -60, -5);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(7120, 5181);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(0,   40);
+$s_icon1_f2->drawLine(26,  -11);
+$s_icon1_f2->drawLine(14,  -29);
+$s_icon1_f2->drawLine(-40, 0);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(5913, 5311);
+$s_icon1_f2->setLeftFill(0xec, 0xec, 0xec);
+$s_icon1_f2->drawLine(10, 3);
+$s_icon1_f2->drawCurve(10, -7, -20, 4);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(7260, 5721);
+$s_icon1_f2->setLeftFill(0xff, 0xff, 0xff);
+$s_icon1_f2->drawCurve(85,  31,  31,  2);
+$s_icon1_f2->drawCurve(78,  7,   26,  -59);
+$s_icon1_f2->drawCurve(23,  -51, -26, -61);
+$s_icon1_f2->drawCurve(-27, -62, -49, -2);
+$s_icon1_f2->drawCurve(-57, -1,  -54, 96);
+$s_icon1_f2->drawCurve(-17, 29,  -13, 71);
+$s_icon1_f2->setLeftFill();
+$s_icon1_f2->setRightFill();
+
+$s_icon1_f2->movePenTo(1674, 4251);
+$s_icon1_f2->setLeftFill(0xab, 0x97, 0xfd);
+$s_icon1_f2->setRightFill(0x00, 0x00, 0x00);
+$s_icon1_f2->drawCurve(-18,  232,  61,   198);
+$s_icon1_f2->drawCurve(36,   126,  92,   66);
+$s_icon1_f2->drawCurve(101,  76,   118,  -47);
+$s_icon1_f2->drawCurve(222,  -87,  31,   -290);
+$s_icon1_f2->drawCurve(10,   -81,  -2,   -170);
+$s_icon1_f2->drawCurve(-2,   -164, 8,    -72);
+$s_icon1_f2->drawCurve(30,   -256, 154,  -321);
+$s_icon1_f2->drawCurve(32,   -65,  259,  -473);
+$s_icon1_f2->drawCurve(89,   -161, 41,   -59);
+$s_icon1_f2->drawCurve(89,   -127, 94,   -46);
+$s_icon1_f2->drawCurve(-55,  203,  -200, 330);
+$s_icon1_f2->drawCurve(-216, 353,  -58,  174);
+$s_icon1_f2->drawCurve(-63,  180,  -15,  385);
+$s_icon1_f2->drawCurve(-15,  376,  -65,  176);
+$s_icon1_f2->drawCurve(-29,  75,   -89,  94);
+$s_icon1_f2->drawCurve(-109, 118,  -27,  39);
+$s_icon1_f2->drawCurve(166,  61,   76,   14);
+$s_icon1_f2->drawCurve(133,  22,   111,  -53);
+$s_icon1_f2->drawCurve(95,   -47,  84,   -104);
+$s_icon1_f2->drawCurve(82,   -103, 41,   -123);
+$s_icon1_f2->drawCurve(99,   -294, -179, -157);
+$s_icon1_f2->drawCurve(-79,  292,  -252, 95);
+$s_icon1_f2->drawCurve(4,    -65,  55,   -114);
+$s_icon1_f2->drawCurve(56,   -117, 8,    -64);
+$s_icon1_f2->drawCurve(5,    -45,  -11,  -109);
+$s_icon1_f2->drawCurve(-9,   -99,  13,   -59);
+$s_icon1_f2->drawCurve(42,   -224, 150,  -278);
+$s_icon1_f2->drawCurve(86,   -160, 189,  -310);
+$s_icon1_f2->drawLine(182, -306);
+$s_icon1_f2->drawCurve(115, -169, 126, -87);
+$s_icon1_f2->drawCurve(95,  -69,  136, -19);
+$s_icon1_f2->drawLine(240, -14);
+$s_icon1_f2->drawCurve(146,  -2,   82,   -26);
+$s_icon1_f2->drawCurve(116,  -37,  78,   -98);
+$s_icon1_f2->drawCurve(241,  -304, 17,   -285);
+$s_icon1_f2->drawCurve(20,   -341, -333, -182);
+$s_icon1_f2->drawCurve(-107, -60,  -144, -8);
+$s_icon1_f2->drawCurve(43,   246,  -66,  207);
+$s_icon1_f2->drawCurve(-59,  180,  -164, 212);
+$s_icon1_f2->drawLine(-39, -10);
+$s_icon1_f2->drawCurve(5, -69, 42, -95);
+$s_icon1_f2->drawLine(77, -164);
+$s_icon1_f2->drawCurve(95,   -205, -56,  -141);
+$s_icon1_f2->drawCurve(-119, -303, -342, 195);
+$s_icon1_f2->drawCurve(-200, 112,  -247, 263);
+$s_icon1_f2->drawCurve(-252, 275,  -240, 406);
+$s_icon1_f2->drawCurve(-66,  115,  -332, 623);
+$s_icon1_f2->drawCurve(-180, 321,  -85,  163);
+$s_icon1_f2->drawCurve(-148, 282,  -62,  224);
+$s_icon1_f2->drawCurve(-70,  259,  -14,  170);
+$s_icon1_f2->movePenTo(1610, 4252);
+$s_icon1_f2->setLeftFill(0x00, 0x00, 0x00);
+$s_icon1_f2->setRightFill();
+$s_icon1_f2->drawCurve(-16, 242,  71,   209);
+$s_icon1_f2->drawCurve(41,  133,  104,  72);
+$s_icon1_f2->drawCurve(45,  31,   171,  72);
+$s_icon1_f2->drawCurve(159, 66,   -2,   3);
+$s_icon1_f2->drawCurve(191, 70,   76,   13);
+$s_icon1_f2->drawCurve(148, 24,   122,  -53);
+$s_icon1_f2->drawCurve(105, -48,  91,   -107);
+$s_icon1_f2->drawCurve(87,  -103, 46,   -132);
+$s_icon1_f2->drawCurve(116, -339, -213, -135);
+$s_icon1_f2->drawCurve(-93, -59,  -91,  -26);
+$s_icon1_f2->drawCurve(-51, -12,  -7,   -64);
+$s_icon1_f2->drawCurve(-9,  -79,  11,   -59);
+$s_icon1_f2->drawCurve(18,  -98,  86,   -148);
+$s_icon1_f2->drawLine(161, -268);
+$s_icon1_f2->drawCurve(100, -178, 193, -304);
+$s_icon1_f2->drawCurve(83,  -140, 130, -173);
+$s_icon1_f2->drawCurve(145, -193, 65,  -40);
+$s_icon1_f2->drawCurve(42,  -30,  209, -3);
+$s_icon1_f2->drawLine(351, 2);
+$s_icon1_f2->drawCurve(56,   0,    138,  -119);
+$s_icon1_f2->drawCurve(107,  -94,  64,   -77);
+$s_icon1_f2->drawCurve(262,  -315, 13,   -299);
+$s_icon1_f2->drawCurve(7,    -151, -260, -172);
+$s_icon1_f2->drawCurve(-123, -80,  -176, -79);
+$s_icon1_f2->drawCurve(-500, -222, -227, 120);
+$s_icon1_f2->drawCurve(-219, 115,  -269, 273);
+$s_icon1_f2->drawCurve(-277, 286,  -257, 419);
+$s_icon1_f2->drawCurve(-88,  149,  -340, 619);
+$s_icon1_f2->drawCurve(-182, 312,  -105, 191);
+$s_icon1_f2->drawCurve(-159, 295,  -65,  233);
+$s_icon1_f2->drawCurve(-73,  273,  -12,  177);
+
+# Icon1 Movieclip
+my $i_icon1 = new SWF::Sprite();
+$item = $i_icon1->add($s_icon1);
+$item->scaleTo(0.5);
+$item->moveTo(-3000, -2100);
+$i_icon1->nextFrame();
+$i_icon1->remove($item);
+$item = $i_icon1->add($s_icon1_f2);
+$item->scaleTo(0.5);
+$item->moveTo(-3000, -2100);
+$i_icon1->nextFrame();
+
+
+$envelope = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(8722, 1745);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawCurve(-7, -42, 6, -35);
+$s1->drawCurve(3, -14, -68, -18);
+$s1->drawLine(-40, -15);
+$s1->drawLine(0, -2);
+$s1->drawLine(-5, -2);
+$s1->drawCurve(-11, -9, 7, -9);
+$s1->drawLine(10, -12);
+$s1->drawLine(-7, 7);
+$s1->drawLine(-15, 17);
+$s1->drawCurve(-372, -133, -468, -40);
+$s1->drawCurve(-301, -26, -578, 7);
+$s1->drawCurve(-1570, 19, -1710, 381);
+$s1->drawCurve(-751, 162, -409, 194);
+$s1->drawCurve(-136, 59, -73, 40);
+$s1->drawCurve(-132, 72, -29, 76);
+$s1->drawCurve(-41, 106, 107, 251);
+$s1->drawLine(165, 376);
+$s1->drawCurve(96, 223, 43, 161);
+$s1->drawCurve(153, 581, 43, 714);
+$s1->drawCurve(21, 339, 3, 741);
+$s1->drawLine(-1, 0);
+$s1->drawCurve(-14, 37, 15, 145);
+$s1->drawLine(0, 43);
+$s1->drawLine(4, -4);
+$s1->drawCurve(24, 194, 71, 65);
+$s1->drawCurve(34, 31, 27, 39);
+$s1->setRightFill(0xff, 0xff, 0xff);
+$s1->drawCurve(8, -74, 37, -92);
+$s1->drawCurve(30, -75, 49, -88);
+$s1->drawLine(78, -126);
+$s1->drawLine(110, -195);
+$s1->drawCurve(252, -493, 132, -246);
+$s1->drawCurve(226, -424, 193, -297);
+$s1->drawCurve(114, -212, 78, -119);
+$s1->drawCurve(143, -219, 129, -17);
+$s1->drawCurve(81, -12, 149, 47);
+$s1->drawLine(230, 75);
+$s1->drawLine(641, 180);
+$s1->drawCurve(397, 96, 262, -36);
+$s1->drawCurve(153, -20, 215, -136);
+$s1->drawCurve(121, -76, 211, -165);
+$s1->drawLine(128, -121);
+$s1->drawCurve(88, -78, 64, 6);
+$s1->drawCurve(89, 6, 125, 95);
+$s1->drawLine(186, 156);
+$s1->drawCurve(272, 221, 181, 245);
+$s1->drawCurve(167, 227, 153, 337);
+$s1->drawCurve(25, 55, 109, 192);
+$s1->drawLine(14, 29);
+$s1->drawCurve(37, 75, 14, 55);
+$s1->setRightFill(0x33, 0x33, 0x33);
+$s1->drawLine(62, -139);
+$s1->setRightFill();
+$s1->drawLine(8, -17);
+$s1->drawLine(2, 16);
+$s1->setRightFill(0x33, 0x33, 0x33);
+$s1->drawLine(12, 0);
+$s1->setRightFill(0xff, 0xff, 0xff);
+$s1->drawLine(-8, -29);
+$s1->drawLine(-14, -43);
+$s1->drawCurve(-175, -524, -586, -670);
+$s1->drawLine(-250, -216);
+$s1->drawCurve(-173, -149, -24, -95);
+$s1->drawCurve(-16, -68, 116, -105);
+$s1->drawCurve(62, -56, 112, -81);
+$s1->drawCurve(343, -294, 317, -316);
+$s1->drawLine(115, -125);
+$s1->drawLine(42, -49);
+$s1->drawCurve(75, -80, 67, -43);
+$s1->drawCurve(21, -13, 20, -10);
+$s1->drawCurve(168, 451, 15, 659);
+$s1->drawCurve(8, 339, -51, 791);
+$s1->drawCurve(-26, 317, -13, 83);
+$s1->drawCurve(-41, 252, -81, 74);
+$s1->setRightFill(0x33, 0x33, 0x33);
+$s1->drawCurve(38, 1, 5, 9);
+$s1->drawCurve(12, 23, -21, 49);
+$s1->setRightFill();
+$s1->drawLine(63, -55);
+$s1->drawLine(27, -80);
+$s1->drawCurve(82, -72, 40, -254);
+$s1->drawCurve(13, -82, 26, -318);
+$s1->drawCurve(51, -773, -8, -357);
+$s1->drawCurve(-8, -325, -63, -346);
+$s1->drawLine(-53, -306);
+$s1->drawCurve(-30, -156, -36, -97);
+$s1->drawLine(4, -26);
+$s1->drawCurve(7, -40, -11, -42);
+$s1->drawLine(-20, -64);
+$s1->setRightFill(0xff, 0xff, 0xff);
+$s1->drawCurve(-25, 107, -69, 111);
+$s1->drawCurve(-78, 127, -128, 131);
+$s1->drawLine(-104, 100);
+$s1->drawCurve(-112, 101, -201, 160);
+$s1->drawLine(-276, 228);
+$s1->drawCurve(-104, 93, -224, 227);
+$s1->drawCurve(-209, 214, -128, 117);
+$s1->drawCurve(-409, 376, -366, 113);
+$s1->drawCurve(-200, 62, -323, -54);
+$s1->drawLine(-517, -118);
+$s1->drawCurve(-873, -199, -527, -258);
+$s1->drawCurve(-115, -55, -627, -345);
+$s1->drawCurve(-340, -188, -265, -110);
+$s1->drawLine(-153, -58);
+$s1->drawCurve(28, 111, 153, 92);
+$s1->drawLine(136, 74);
+$s1->drawLine(123, 59);
+$s1->drawLine(696, 405);
+$s1->drawCurve(418, 225, 326, 74);
+$s1->drawCurve(-35, 163, -200, 233);
+$s1->drawLine(-165, 187);
+$s1->drawCurve(-91, 102, -49, 75);
+$s1->drawCurve(-253, 386, -404, 834);
+$s1->drawCurve(-13, 26, -101, 276);
+$s1->drawLine(-1, 5);
+$s1->drawCurve(-37, 98, -38, 70);
+$s1->drawCurve(-37, 66, -36, 39);
+$s1->drawLine(-1, -316);
+$s1->drawCurve(14, -791, -13, -211);
+$s1->drawCurve(-45, -735, -141, -536);
+$s1->drawCurve(-72, -266, -52, -121);
+$s1->drawCurve(-167, -318, -35, -85);
+$s1->drawCurve(-109, -256, 31, -82);
+$s1->drawCurve(28, -76, 133, -72);
+$s1->drawCurve(77, -42, 132, -57);
+$s1->drawCurve(412, -195, 748, -161);
+$s1->drawCurve(1708, -380, 1572, -20);
+$s1->drawCurve(567, -7, 312, 26);
+$s1->drawCurve(386, 33, 319, 96);
+$s1->drawLine(139, 46);
+$s1->setLeftFill();
+$s1->drawLine(17, 6);
+$s1->drawLine(-7, 38);
+$s1->movePenTo(8579, 5100);
+$s1->setLeftFill(0x33, 0x33, 0x33);
+$s1->setRightFill();
+$s1->drawLine(-10, 1);
+$s1->movePenTo(8614, 5100);
+$s1->setRightFill(0xff, 0xff, 0xff);
+$s1->drawLine(-19, 14);
+$s1->drawLine(-4, -14);
+$s1->movePenTo(8648, 5182);
+$s1->setLeftFill();
+$s1->setRightFill(0x33, 0x33, 0x33);
+$s1->drawLine(-30, 53);
+$s1->drawCurve(-59, 95, 5, 18);
+$s1->drawCurve(15, 55, -11, 35);
+$s1->drawCurve(-17, 57, -122, 37);
+$s1->drawCurve(-141, 33, -36, 13);
+$s1->drawCurve(-315, 111, -665, 189);
+$s1->drawCurve(-916, 264, -1272, 173);
+$s1->drawLine(-1105, 136);
+$s1->drawLine(-1075, 127);
+$s1->drawLine(-32, 4);
+$s1->drawLine(0, -4);
+$s1->drawCurve(-2, -19, -25, -47);
+$s1->drawLine(-23, -39);
+$s1->setRightFill(0xf0, 0xf0, 0xf0);
+$s1->drawLine(-4, 1);
+$s1->drawLine(-3, 0);
+$s1->drawLine(0, -1);
+$s1->drawLine(1, -9);
+$s1->setLeftFill(0xff, 0xff, 0xff);
+$s1->drawLine(6, 9);
+$s1->setRightFill(0x33, 0x33, 0x33);
+$s1->drawLine(1100, -130);
+$s1->drawLine(1105, -136);
+$s1->drawCurve(1272, -174, 916, -263);
+$s1->drawCurve(673, -192, 307, -108);
+$s1->drawLine(177, -46);
+$s1->drawCurve(123, -38, 16, -56);
+$s1->drawCurve(11, -33, -15, -57);
+$i1 = $envelope->add($s1);
+$i1->scaleTo(0.5);
+$i1->moveTo(-2620, -1800);
+$envelope->nextFrame();  # end of frame 1
+
+
+
+$telefono3 = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(7575, 1918);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawCurve(534, 752, 0, 980);
+$s1->drawCurve(0, 1239, -855, 875);
+$s1->drawCurve(-855, 876, -1210, 0);
+$s1->drawCurve(-966, 0, -739, -558);
+$s1->drawCurve(-187, -141, -173, -177);
+$s1->drawCurve(-855, -875, 0, -1239);
+$s1->drawCurve(0, -1239, 855, -876);
+$s1->drawCurve(855, -875, 1210, 0);
+$s1->drawCurve(1210, 0, 855, 875);
+$s1->drawCurve(179, 183, 142, 200);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(8001, 3420);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawCurve(98, 665, -296, 644);
+$s1->drawCurve(-342, 737, -687, 446);
+$s1->drawCurve(-697, 454, -805, 0);
+$s1->drawCurve(-673, 0, -404, -219);
+$s1->drawCurve(-527, -286, 140, -586);
+$s1->drawCurve(530, 95, 272, -641);
+$s1->drawCurve(76, -198, -14, -463);
+$s1->drawCurve(-14, -433, 136, -269);
+$s1->drawCurve(129, -249, 220, -249);
+$s1->drawCurve(125, -143, 255, -259);
+$s1->drawCurve(443, -478, 73, -532);
+$s1->drawCurve(-966, 127, -641, 1138);
+$s1->drawCurve(-478, 839, -205, 1169);
+$s1->drawCurve(-32, 164, -83, 320);
+$s1->drawCurve(-67, 280, 0, 170);
+$s1->drawCurve(4, 478, 516, 235);
+$s1->drawCurve(1119, 518, 1052, -426);
+$s1->drawCurve(949, -385, 557, -982);
+$s1->drawCurve(551, -975, -132, -1040);
+$s1->drawCurve(-150, -1142, -948, -716);
+$s1->drawCurve(-558, -419, -628, -103);
+$s1->drawCurve(-1174, -184, -1011, 549);
+$s1->drawCurve(-1056, 576, -314, 1105);
+$s1->drawCurve(-188, 709, 73, 777);
+$s1->drawCurve(97, 1050, 645, -13);
+$s1->drawCurve(-505, -907, -42, -730);
+$s1->drawCurve(-38, -726, 359, -627);
+$s1->drawCurve(338, -587, 606, -375);
+$s1->drawCurve(603, -371, 701, -65);
+$s1->drawCurve(736, -68, 658, 297);
+$s1->drawCurve(677, 300, 428, 644);
+$s1->drawCurve(391, 590, 118, 770);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(6224, 1529);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawLine(-419, 1023);
+$s1->drawCurve(356, -52, 139, -341);
+$s1->drawCurve(140, -340, -216, -290);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(4920, 4347);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawLine(-558, 954);
+$s1->drawCurve(397, -27, 213, -300);
+$s1->drawCurve(226, -324, -278, -303);
+$i4 = $telefono3->add($s1);
+$i4->scaleTo(0.5);
+$i4->moveTo(-2620, -1800);
+$telefono3->nextFrame();  # end of frame 1
+
+
+### Shape 1 ###
+
+$telefono4 = new SWF::Sprite();
+$s1 = new SWF::Shape();
+$s1->movePenTo(8338, 3364);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawCurve(301, -19, 150, -103);
+$s1->drawCurve(138, -96, 48, -167);
+$s1->drawCurve(44, -155, -37, -181);
+$s1->drawCurve(-36, -176, -99, -146);
+$s1->drawCurve(-51, -75, -139, -135);
+$s1->drawCurve(-141, -134, -79, -50);
+$s1->drawCurve(-106, -67, -122, -53);
+$s1->drawCurve(-49, -21, -58, -15);
+$s1->drawLine(-5230, 0);
+$s1->drawCurve(-275, 97, -202, 205);
+$s1->drawCurve(-172, 171, -152, 382);
+$s1->drawLine(-45, 91);
+$s1->drawCurve(-27, 54, 0, 43);
+$s1->drawCurve(-3, 172, 66, 126);
+$s1->drawCurve(78, 149, 155, 31);
+$s1->drawCurve(190, 38, 174, 9);
+$s1->setRightFill(0x00, 0x33, 0x99, 0x00);
+$s1->drawLine(298, -10);
+$s1->drawCurve(414, -51, 126, -252);
+$s1->drawCurve(33, -66, 11, -101);
+$s1->drawLine(11, -180);
+$s1->drawCurve(15, -225, 114, -90);
+$s1->drawCurve(86, -70, 209, -15);
+$s1->drawLine(170, -9);
+$s1->drawLine(149, -15);
+$s1->drawLine(0, 587);
+$s1->drawLine(2285, 0);
+$s1->drawLine(0, -616);
+$s1->drawLine(352, 24);
+$s1->drawCurve(221, 21, 84, 114);
+$s1->drawCurve(66, 90, 43, 170);
+$s1->drawLine(67, 299);
+$s1->drawCurve(44, 168, 71, 89);
+$s1->drawCurve(91, 113, 161, 23);
+$s1->drawCurve(281, 39, 239, -10);
+$s1->drawLine(38, -2);
+$s1->setLeftFill();
+$s1->setLine(20, 0xcc, 0xcc, 0xcc, 0x00);
+$s1->drawLine(0, 1760);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawCurve(75, 104, 58, 98);
+$s1->drawCurve(96, 167, 40, 101);
+$s1->drawCurve(63, 159, -11, 130);
+$s1->drawCurve(-15, 199, -132, 16);
+$s1->drawLine(14, 28);
+$s1->drawLine(-314, 95);
+$s1->drawLine(-486, 19);
+$s1->drawLine(-4671, 0);
+$s1->drawLine(-514, -85);
+$s1->drawLine(-114, -74);
+$s1->drawCurve(-68, -45, -28, -53);
+$s1->drawCurve(-97, -173, 100, -266);
+$s1->drawCurve(59, -160, 159, -243);
+$s1->drawCurve(45, -68, 62, -74);
+$s1->setRightFill(0x00, 0x33, 0x99, 0x00);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc, 0x00);
+$s1->drawLine(0, -1660);
+$s1->movePenTo(8338, 5124);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawCurve(-149, -207, -220, -232);
+$s1->drawCurve(-388, -388, -184, -199);
+$s1->drawLine(-246, -288);
+$s1->drawCurve(-161, -182, -121, -58);
+$s1->drawLine(128, 179);
+$s1->drawCurve(73, 106, 35, 86);
+$s1->drawCurve(117, 301, -82, 325);
+$s1->drawCurve(-78, 311, -232, 236);
+$s1->drawLine(-165, 168);
+$s1->drawCurve(-113, 100, -83, 16);
+$s1->drawLine(-14, 43);
+$s1->drawCurve(-57, -5, -95, 42);
+$s1->drawLine(-148, 65);
+$s1->drawCurve(-239, 83, -276, 26);
+$s1->drawCurve(-304, 29, -309, -82);
+$s1->drawCurve(-308, -81, -253, -176);
+$s1->drawCurve(-263, -183, -157, -251);
+$s1->drawCurve(-168, -269, -21, -312);
+$s1->drawCurve(-16, -209, 190, -362);
+$s1->drawLine(77, -125);
+$s1->drawCurve(48, -84, -1, -48);
+$s1->drawLine(-1029, 1028);
+$s1->drawLine(-302, 293);
+$s1->drawCurve(-94, 94, -71, 85);
+$s1->movePenTo(6484, 5069);
+$s1->setLeftFill(0x00, 0x33, 0x99, 0x00);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(-15, 13);
+$s1->drawCurve(-400, 316, -564, 0);
+$s1->drawCurve(-438, 0, -339, -190);
+$s1->drawCurve(-98, -55, -90, -71);
+$s1->drawLine(-15, -13);
+$s1->drawCurve(-385, -312, 1, -437);
+$s1->drawCurve(-1, -447, 400, -316);
+$s1->drawCurve(400, -316, 565, 0);
+$s1->drawCurve(550, 0, 393, 301);
+$s1->drawLine(21, 15);
+$s1->drawCurve(400, 316, 0, 447);
+$s1->drawCurve(-1, 437, -384, 312);
+$s1->movePenTo(5501, 1760);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->setRightFill();
+$s1->drawLine(-4, 0);
+$s1->drawLine(0, 6);
+$s1->drawLine(4, -6);
+$i1 = $telefono4->add($s1);
+$i1->scaleTo(0.5);
+$i1->moveTo(-2720, -1890);
+$telefono4->nextFrame();  # end of frame 1
+$telefono4->remove($i1);
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(8338, 5128);
+$s2->setLeftFill(0x00, 0x00, 0x00);
+$s2->setRightFill(0x00, 0x33, 0x99, 0x00);
+$s2->drawCurve(-151, -210, -223, -236);
+$s2->drawCurve(-388, -388, -184, -199);
+$s2->drawLine(-246, -288);
+$s2->drawCurve(-161, -182, -121, -58);
+$s2->drawLine(128, 179);
+$s2->drawCurve(73, 106, 35, 86);
+$s2->drawCurve(117, 301, -82, 325);
+$s2->drawCurve(-78, 311, -232, 236);
+$s2->drawLine(-165, 168);
+$s2->drawCurve(-113, 100, -83, 16);
+$s2->drawLine(-14, 43);
+$s2->drawCurve(-57, -5, -95, 42);
+$s2->drawLine(-148, 65);
+$s2->drawCurve(-239, 83, -276, 26);
+$s2->drawCurve(-304, 29, -309, -82);
+$s2->drawCurve(-308, -81, -253, -176);
+$s2->drawCurve(-263, -183, -157, -251);
+$s2->drawCurve(-168, -269, -21, -312);
+$s2->drawCurve(-16, -209, 190, -362);
+$s2->drawLine(77, -125);
+$s2->drawCurve(48, -84, -1, -48);
+$s2->drawLine(-1029, 1028);
+$s2->drawLine(-302, 293);
+$s2->drawCurve(-91, 90, -69, 83);
+$s2->setRightFill();
+$s2->drawCurve(-65, 77, -47, 71);
+$s2->drawCurve(-159, 243, -59, 160);
+$s2->drawCurve(-100, 266, 97, 173);
+$s2->drawCurve(28, 53, 68, 45);
+$s2->drawLine(114, 74);
+$s2->drawLine(514, 85);
+$s2->drawLine(4671, 0);
+$s2->drawLine(486, -19);
+$s2->drawLine(314, -95);
+$s2->drawLine(-14, -28);
+$s2->drawCurve(132, -16, 15, -199);
+$s2->drawCurve(11, -130, -63, -159);
+$s2->drawCurve(-40, -101, -96, -167);
+$s2->drawCurve(-56, -94, -72, -101);
+$s2->setLeftFill(0x00, 0x33, 0x99, 0x00);
+$s2->drawLine(0, -3048);
+$s2->drawLine(-2669, 0);
+$s2->setRightFill(0x00, 0x00, 0x00);
+$s2->drawLine(-162, 131);
+$s2->drawCurve(-130, 97, -144, -15);
+$s2->drawCurve(-113, -12, -149, -87);
+$s2->drawLine(-178, -114);
+$s2->setRightFill();
+$s2->drawLine(-688, 0);
+$s2->setRightFill(0x00, 0x00, 0x00);
+$s2->drawCurve(-154, 146, -75, 52);
+$s2->drawLine(436, 433);
+$s2->drawLine(-1609, 1617);
+$s2->drawLine(-44, -44);
+$s2->setRightFill();
+$s2->drawLine(0, 706);
+$s2->movePenTo(5669, 2080);
+$s2->setLeftFill(0x00, 0x00, 0x00);
+$s2->drawCurve(124, -108, 101, -109);
+$s2->drawLine(25, -28);
+$s2->drawCurve(199, -226, 32, -179);
+$s2->drawCurve(29, -165, -84, -152);
+$s2->drawCurve(-79, -140, -154, -101);
+$s2->drawCurve(-149, -99, -174, -32);
+$s2->drawLine(-282, -13);
+$s2->drawCurve(-194, 4, -91, 21);
+$s2->drawCurve(-122, 28, -124, 49);
+$s2->drawCurve(-49, 20, -52, 31);
+$s2->drawLine(-1193, 1199);
+$s2->setRightFill(0x00, 0x33, 0x99, 0x00);
+$s2->drawLine(-773, 776);
+$s2->setRightFill();
+$s2->drawLine(-1715, 1724);
+$s2->drawCurve(-125, 263, 3, 288);
+$s2->drawCurve(0, 241, 162, 377);
+$s2->drawLine(33, 96);
+$s2->drawCurve(20, 56, 30, 31);
+$s2->drawCurve(120, 123, 135, 43);
+$s2->drawCurve(161, 49, 131, -88);
+$s2->drawCurve(161, -108, 128, -116);
+$s2->drawCurve(115, -106, 88, -112);
+$s2->drawCurve(255, -328, -89, -268);
+$s2->drawCurve(-24, -69, -64, -79);
+$s2->drawLine(-119, -135);
+$s2->drawCurve(-149, -169, 16, -143);
+$s2->drawCurve(12, -110, 136, -159);
+$s2->drawLine(113, -126);
+$s2->drawLine(95, -116);
+$s2->drawLine(371, 369);
+$s2->movePenTo(4105, 2080);
+$s2->drawLine(36, -34);
+$s2->drawCurve(170, -142, 140, 21);
+$s2->drawCurve(110, 16, 151, 90);
+$s2->drawLine(81, 49);
+$s2->movePenTo(6464, 3554);
+$s2->setLeftFill(0x00, 0x33, 0x99, 0x00);
+$s2->setRightFill(0x00, 0x00, 0x00);
+$s2->drawCurve(400, 316, 0, 447);
+$s2->drawCurve(-1, 437, -384, 312);
+$s2->drawLine(-15, 13);
+$s2->drawCurve(-400, 316, -564, 0);
+$s2->drawCurve(-438, 0, -339, -190);
+$s2->drawCurve(-98, -55, -90, -71);
+$s2->drawLine(-15, -13);
+$s2->drawCurve(-385, -312, 1, -437);
+$s2->drawCurve(-1, -447, 400, -316);
+$s2->drawCurve(400, -316, 565, 0);
+$s2->drawCurve(550, 0, 393, 301);
+$s2->drawLine(21, 15);
+$s2->movePenTo(2659, 2856);
+$s2->setLeftFill();
+$s2->setRightFill(0x00, 0x33, 0x99, 0x00);
+$s2->drawLine(0, -776);
+$s2->drawLine(773, 0);
+$i1 = $telefono4->add($s2);
+$i1->scaleTo(0.5);
+$i1->moveTo(-2720, -1890);
+$telefono4->nextFrame();  # end of frame 2
+$telefono4->remove($i1);
+
+
+
+$conference1 = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(7708, 2179);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->drawCurve(-94, -8, -225, 66);
+$s1->drawCurve(-209, 62, -92, -23);
+$s1->drawCurve(-122, -31, -248, -183);
+$s1->drawCurve(-230, -168, -160, -18);
+$s1->drawCurve(0, -285, -17, -118);
+$s1->drawCurve(-34, -233, -116, -138);
+$s1->drawCurve(-43, -50, -111, -68);
+$s1->drawCurve(-110, -66, -39, -49);
+$s1->drawCurve(-30, -36, -17, -78);
+$s1->drawCurve(-18, -84, -22, -32);
+$s1->drawCurve(-65, -97, -133, -15);
+$s1->drawCurve(-127, -15, -95, 67);
+$s1->drawCurve(-65, 46, -27, 104);
+$s1->drawCurve(-32, 117, -33, 36);
+$s1->drawCurve(-47, 51, -73, 40);
+$s1->drawLine(-124, 62);
+$s1->drawCurve(-146, 77, -43, 144);
+$s1->drawCurve(-20, 66, 3, 224);
+$s1->drawCurve(2, 199, -42, 67);
+$s1->drawCurve(-25, 42, -64, 28);
+$s1->drawLine(-107, 40);
+$s1->drawCurve(-123, 57, -237, 157);
+$s1->drawCurve(-84, -177, -230, -160);
+$s1->drawCurve(-244, -171, -183, 21);
+$s1->drawCurve(-68, 7, -117, 64);
+$s1->drawCurve(-116, 64, -59, 5);
+$s1->drawCurve(-59, 4, -105, -25);
+$s1->drawCurve(-120, -29, -39, -3);
+$s1->drawCurve(-172, -12, -35, 232);
+$s1->drawCurve(-14, 83, 57, 86);
+$s1->drawCurve(80, 121, 10, 30);
+$s1->drawCurve(15, 49, -10, 100);
+$s1->drawCurve(-10, 110, 5, 41);
+$s1->drawCurve(23, 212, 177, 208);
+$s1->drawCurve(32, 37, 181, 138);
+$s1->drawCurve(148, 113, 29, 75);
+$s1->drawCurve(22, 54, -39, 125);
+$s1->drawLine(-56, 178);
+$s1->drawCurve(-35, 154, -5, 205);
+$s1->drawCurve(-3, 119, 3, 242);
+$s1->drawCurve(-314, 56, -182, 207);
+$s1->drawCurve(-200, 225, 76, 292);
+$s1->drawCurve(-84, 43, -60, 82);
+$s1->drawCurve(-59, 81, -12, 89);
+$s1->drawCurve(-30, 211, 225, 64);
+$s1->drawLine(139, -6);
+$s1->drawCurve(92, -17, 42, 19);
+$s1->drawCurve(61, 27, 65, 48);
+$s1->drawLine(105, 80);
+$s1->drawCurve(124, 86, 152, -8);
+$s1->drawCurve(78, -3, 205, -89);
+$s1->drawCurve(188, -83, 79, 12);
+$s1->drawCurve(59, 8, 93, 81);
+$s1->drawLine(139, 120);
+$s1->drawCurve(82, 60, 219, 94);
+$s1->drawCurve(206, 90, 86, 70);
+$s1->drawCurve(54, 47, 9, 169);
+$s1->drawCurve(11, 214, 9, 30);
+$s1->drawCurve(47, 153, 129, 76);
+$s1->drawLine(117, 63);
+$s1->drawCurve(73, 40, 51, 44);
+$s1->drawCurve(34, 30, 27, 51);
+$s1->drawLine(41, 84);
+$s1->drawCurve(50, 93, 115, 6);
+$s1->drawCurve(147, 10, 58, -77);
+$s1->drawCurve(56, -112, 69, -65);
+$s1->drawCurve(28, -29, 72, -20);
+$s1->drawLine(110, -37);
+$s1->drawCurve(164, -85, 96, -225);
+$s1->drawCurve(17, -41, 15, -81);
+$s1->drawLine(28, -142);
+$s1->drawCurve(37, -176, 83, -44);
+$s1->drawCurve(34, -19, 208, -99);
+$s1->drawCurve(148, -71, 90, -61);
+$s1->drawLine(112, -88);
+$s1->drawCurve(76, -58, 52, -3);
+$s1->drawCurve(41, -5, 54, 41);
+$s1->drawLine(85, 70);
+$s1->drawCurve(145, 112, 195, 58);
+$s1->drawCurve(237, 76, 199, -119);
+$s1->drawLine(90, -74);
+$s1->drawCurve(56, -50, 41, -10);
+$s1->drawLine(125, 10);
+$s1->drawCurve(78, 16, 50, -26);
+$s1->drawCurve(176, -86, -36, -142);
+$s1->drawCurve(-9, -35, -41, -94);
+$s1->drawCurve(-38, -86, -8, -52);
+$s1->drawCurve(-7, -47, 12, -110);
+$s1->drawCurve(11, -102, -16, -61);
+$s1->drawCurve(-108, -386, -592, -254);
+$s1->drawCurve(44, -191, -8, -349);
+$s1->drawLine(-12, -119);
+$s1->drawCurve(-6, -76, 22, -39);
+$s1->drawCurve(42, -77, 165, -101);
+$s1->drawCurve(167, -102, 49, -86);
+$s1->drawCurve(55, -93, -7, -182);
+$s1->drawCurve(-6, -190, 35, -72);
+$s1->drawCurve(21, -45, 45, -53);
+$s1->drawLine(71, -86);
+$s1->drawCurve(77, -102, -34, -114);
+$s1->drawCurve(-55, -175, -157, 10);
+$s1->drawLine(-141, 23);
+$s1->drawLine(-144, 12);
+$s1->drawCurve(-66, -6, -134, -99);
+$s1->drawCurve(-134, -98, -89, -7);
+$s1->movePenTo(7475, 2574);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->setRightFill(0x06, 0x04, 0x07);
+$s1->drawLine(76, -16);
+$s1->drawCurve(82, -14, 35, 92);
+$s1->drawLine(-180, 40);
+$s1->drawLine(320, 580);
+$s1->drawLine(200, -40);
+$s1->drawLine(-160, 140);
+$s1->drawLine(60, 300);
+$s1->drawLine(20, 20);
+$s1->drawCurve(80, -27, 98, -68);
+$s1->drawCurve(107, -77, 73, -89);
+$s1->drawCurve(190, -234, -152, -172);
+$s1->drawCurve(-24, -28, -86, 11);
+$s1->drawLine(-126, 4);
+$s1->drawCurve(-200, -78, 8, -176);
+$s1->drawCurve(7, -139, 125, -167);
+$s1->drawCurve(-164, -145, -234, -11);
+$s1->drawCurve(-219, -11, -203, 107);
+$s1->drawCurve(127, 165, 56, 25);
+$s1->drawCurve(37, 15, 47, -7);
+$s1->movePenTo(8069, 2800);
+$s1->drawCurve(62, 82, 101, -5);
+$s1->drawCurve(117, -7, 99, -134);
+$s1->drawCurve(-55, 15, -23, -20);
+$s1->drawCurve(-20, -20, -2, -55);
+$s1->drawLine(-160, 160);
+$s1->drawLine(-80, -120);
+$s1->drawLine(300, -120);
+$s1->drawLine(-40, 60);
+$s1->drawLine(100, 80);
+$s1->drawCurve(91, -115, -70, -84);
+$s1->drawCurve(-63, -76, -138, -5);
+$s1->drawLine(23, 60);
+$s1->drawLine(-15, 15);
+$s1->drawCurve(-15, 15, -24, -12);
+$s1->drawLine(-29, -38);
+$s1->drawCurve(-150, 45, -37, 105);
+$s1->drawCurve(-34, 91, 62, 83);
+$s1->movePenTo(6728, 2876);
+$s1->drawLine(-60, 200);
+$s1->drawLine(100, -200);
+$s1->drawLine(-40, 0);
+$s1->movePenTo(6768, 2597);
+$s1->drawCurve(-162, 217, -18, 202);
+$s1->drawLine(233, -397);
+$s1->drawLine(307, -283);
+$s1->drawCurve(-187, 26, -173, 235);
+$s1->movePenTo(7268, 3396);
+$s1->drawCurve(-87, -292, -133, -88);
+$s1->drawCurve(22, 110, 55, 103);
+$s1->drawCurve(65, 122, 78, 45);
+$s1->movePenTo(7268, 3716);
+$s1->drawLine(-260, -20);
+$s1->drawCurve(14, 75, 106, 7);
+$s1->drawCurve(104, 6, 36, -68);
+$s1->movePenTo(7248, 3596);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->setRightFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(0, 40);
+$s1->drawLine(-240, 0);
+$s1->drawLine(0, -40);
+$s1->drawLine(240, 0);
+$s1->movePenTo(7908, 3736);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->setRightFill(0x06, 0x04, 0x07);
+$s1->drawCurve(-377, 104, -523, -4);
+$s1->drawCurve(165, 80, 310, -16);
+$s1->drawCurve(340, -20, 85, -144);
+$s1->movePenTo(7808, 3316);
+$s1->drawLine(-820, 180);
+$s1->drawCurve(142, 59, 293, -57);
+$s1->drawCurve(303, -61, 82, -121);
+$s1->movePenTo(8267, 5159);
+$s1->drawCurve(-150, -97, -69, -32);
+$s1->drawCurve(-255, -119, -45, 265);
+$s1->drawLine(360, 200);
+$s1->drawLine(-20, -140);
+$s1->drawLine(440, 260);
+$s1->drawLine(-20, -280);
+$s1->drawLine(-40, 60);
+$s1->drawCurve(-59, -26, -142, -91);
+$s1->movePenTo(8488, 5176);
+$s1->drawCurve(-77, -155, -168, -129);
+$s1->drawCurve(-158, -121, -177, -55);
+$s1->drawCurve(-22, 132, 234, 153);
+$s1->drawCurve(178, 115, 190, 60);
+$s1->movePenTo(8228, 5636);
+$s1->drawLine(240, 120);
+$s1->drawLine(-20, -80);
+$s1->drawLine(60, -20);
+$s1->drawCurve(-39, -43, -73, -27);
+$s1->drawCurve(-72, -28, -68, 3);
+$s1->drawCurve(-170, 6, 38, 169);
+$s1->drawCurve(33, 130, 231, 90);
+$s1->drawCurve(-12, -38, 2, -20);
+$s1->drawLine(-30, -22);
+$s1->drawLine(100, -20);
+$s1->drawLine(-18, 71);
+$s1->drawLine(-2, 29);
+$s1->drawCurve(132, 10, 35, -91);
+$s1->drawCurve(32, -86, -59, -113);
+$s1->drawLine(-20, 20);
+$s1->drawLine(0, 40);
+$s1->drawLine(-20, 20);
+$s1->drawLine(-40, 0);
+$s1->drawLine(0, 100);
+$s1->drawLine(-240, -120);
+$s1->drawLine(-25, 17);
+$s1->drawLine(-35, 3);
+$s1->drawLine(36, -89);
+$s1->drawLine(4, -31);
+$s1->movePenTo(7648, 4836);
+$s1->drawCurve(-122, 198, -43, 128);
+$s1->drawCurve(-65, 189, 50, 165);
+$s1->drawLine(60, -320);
+$s1->drawLine(160, -360);
+$s1->drawLine(-40, 0);
+$s1->movePenTo(7528, 4796);
+$s1->drawLine(-80, 200);
+$s1->drawLine(120, -200);
+$s1->drawLine(-40, 0);
+$s1->movePenTo(7408, 4736);
+$s1->drawLine(-80, 220);
+$s1->drawLine(140, -220);
+$s1->drawLine(-60, 0);
+$s1->movePenTo(7055, 5518);
+$s1->drawCurve(-12, 225, 145, 113);
+$s1->drawLine(-97, -380);
+$s1->drawLine(37, -340);
+$s1->drawLine(-43, 186);
+$s1->drawCurve(-27, 115, -3, 81);
+$s1->movePenTo(7609, 5363);
+$s1->drawCurve(-49, 80, -2, 53);
+$s1->drawCurve(-9, 112, 142, 124);
+$s1->drawCurve(68, 59, 169, 105);
+$s1->drawLine(-40, 79);
+$s1->drawCurve(-241, -105, -179, -274);
+$s1->drawLine(-220, 240);
+$s1->drawCurve(187, 258, 260, 46);
+$s1->drawCurve(255, 45, 258, -170);
+$s1->drawCurve(-153, -185, -22, -52);
+$s1->drawCurve(-58, -138, 133, -124);
+$s1->drawLine(-420, -280);
+$s1->drawLine(-79, 127);
+$s1->movePenTo(6655, 3654);
+$s1->drawCurve(-130, -240, -117, -118);
+$s1->drawLine(400, 800);
+$s1->drawLine(320, -140);
+$s1->drawLine(-300, 100);
+$s1->drawCurve(-54, -181, -119, -221);
+$s1->movePenTo(5368, 776);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->setRightFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(20, 100);
+$s1->drawLine(40, 0);
+$s1->drawLine(20, -100);
+$s1->drawLine(-80, 0);
+$s1->movePenTo(5648, 876);
+$s1->drawLine(20, -100);
+$s1->drawLine(-100, 80);
+$s1->drawLine(80, 20);
+$s1->movePenTo(5488, 776);
+$s1->drawLine(0, 300);
+$s1->drawLine(100, -60);
+$s1->drawCurve(-55, -32, -6, -73);
+$s1->drawLine(1, -135);
+$s1->drawLine(-40, 0);
+$s1->movePenTo(5448, 652);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->setRightFill(0x06, 0x04, 0x07);
+$s1->drawCurve(-85, 35, -29, 106);
+$s1->drawCurve(-28, 97, 29, 108);
+$s1->drawCurve(29, 112, 72, 53);
+$s1->drawCurve(79, 61, 103, -42);
+$s1->drawCurve(79, -33, 29, -106);
+$s1->drawCurve(28, -98, -26, -108);
+$s1->drawCurve(-27, -112, -69, -54);
+$s1->drawCurve(-79, -61, -105, 42);
+$s1->movePenTo(5361, 1221);
+$s1->drawCurve(-97, -82, -56, -123);
+$s1->drawCurve(-261, 108, -73, 204);
+$s1->drawCurve(-47, 127, 1, 341);
+$s1->drawLine(280, -60);
+$s1->drawCurve(-16, -158, 6, -81);
+$s1->drawCurve(8, -143, 102, -38);
+$s1->drawLine(40, 400);
+$s1->drawLine(580, 0);
+$s1->drawLine(0, -400);
+$s1->drawLine(120, 20);
+$s1->drawLine(0, 420);
+$s1->drawLine(280, 60);
+$s1->drawCurve(0, -316, -55, -160);
+$s1->drawCurve(-85, -246, -240, -78);
+$s1->drawCurve(-30, 167, -84, 78);
+$s1->drawCurve(-75, 69, -105, -14);
+$s1->drawCurve(-100, -13, -93, -82);
+$s1->movePenTo(4178, 2602);
+$s1->drawCurve(109, -305, -159, -121);
+$s1->drawLine(-4, 340);
+$s1->drawLine(-196, 480);
+$s1->drawCurve(63, -55, 70, -106);
+$s1->drawCurve(74, -114, 43, -119);
+$s1->movePenTo(3847, 2376);
+$s1->drawLine(221, -160);
+$s1->drawCurve(-123, -258, -273, -120);
+$s1->drawCurve(-290, -126, -235, 144);
+$s1->drawLine(65, 107);
+$s1->drawCurve(42, 64, 6, 49);
+$s1->drawCurve(16, 190, -144, 58);
+$s1->drawCurve(-122, 50, -163, -58);
+$s1->drawLine(-20, 60);
+$s1->drawLine(-80, -20);
+$s1->drawCurve(-34, 265, 174, 256);
+$s1->drawCurve(161, 236, 259, 123);
+$s1->drawCurve(3, -18, 50, -119);
+$s1->drawCurve(38, -92, -18, -45);
+$s1->drawCurve(-19, -48, -49, -42);
+$s1->drawLine(-91, -67);
+$s1->drawCurve(-114, -82, 0, -107);
+$s1->drawLine(380, 220);
+$s1->drawLine(167, -214);
+$s1->drawCurve(100, -140, -14, -106);
+$s1->drawCurve(-5, -44, -114, -125);
+$s1->drawCurve(-105, -116, 14, -29);
+$s1->drawCurve(29, -49, 104, 69);
+$s1->drawCurve(170, 114, 14, 180);
+$s1->movePenTo(3928, 2736);
+$s1->drawLine(-101, 200);
+$s1->drawLine(141, -200);
+$s1->drawLine(-40, 0);
+$s1->movePenTo(3767, 2516);
+$s1->drawLine(-140, 320);
+$s1->drawCurve(68, -44, 47, -98);
+$s1->drawCurve(49, -104, -24, -74);
+$s1->movePenTo(3827, 2676);
+$s1->drawLine(-80, 220);
+$s1->drawLine(120, -200);
+$s1->drawLine(-40, -20);
+$s1->movePenTo(3307, 3296);
+$s1->drawCurve(47, 136, 292, 56);
+$s1->drawCurve(253, 47, 169, -39);
+$s1->drawLine(-321, -37);
+$s1->drawLine(-440, -163);
+$s1->movePenTo(3964, 3390);
+$s1->drawCurve(75, 6, 89, -20);
+$s1->drawLine(-281, -60);
+$s1->drawCurve(13, 63, 104, 11);
+$s1->movePenTo(3867, 3196);
+$s1->drawCurve(109, 116, 192, -56);
+$s1->drawLine(-301, -60);
+$s1->movePenTo(3467, 2916);
+$s1->drawCurve(77, 120, 252, 59);
+$s1->drawCurve(180, 40, 212, 1);
+$s1->drawLine(-361, -87);
+$s1->drawLine(-360, -133);
+$s1->movePenTo(5868, 2416);
+$s1->drawLine(-680, -20);
+$s1->drawLine(20, 360);
+$s1->drawLine(460, 0);
+$s1->drawLine(176, -30);
+$s1->drawLine(24, -310);
+$s1->movePenTo(6348, 3296);
+$s1->drawLine(-60, 240);
+$s1->drawCurve(100, -126, -40, -114);
+$s1->movePenTo(6328, 3022);
+$s1->drawLine(240, -146);
+$s1->drawLine(-320, 120);
+$s1->drawLine(80, 200);
+$s1->drawLine(0, -174);
+$s1->movePenTo(2802, 1907);
+$s1->setLeftFill(0xff, 0xff, 0xff);
+$s1->setRightFill();
+$s1->drawLine(-2, -1);
+$s1->drawLine(2, 0);
+$s1->drawLine(0, 1);
+$s1->movePenTo(2894, 1941);
+$s1->setRightFill(0x06, 0x04, 0x07);
+$s1->drawLine(-118, -51);
+$s1->drawLine(33, -6);
+$s1->drawLine(13, -1);
+$s1->drawLine(21, 4);
+$s1->drawLine(3, 1);
+$s1->drawLine(4, 1);
+$s1->drawLine(0, 1);
+$s1->drawLine(6, 3);
+$s1->drawLine(12, 11);
+$s1->drawLine(26, 37);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(-2, 1);
+$s1->drawLine(-1, 1);
+$s1->drawLine(-2, 2);
+$s1->drawLine(-6, 2);
+$s1->drawCurve(-22, 11, -24, -3);
+$s1->drawLine(-18, -4);
+$s1->drawLine(-15, -6);
+$s1->setRightFill();
+$s1->drawLine(-5, -3);
+$s1->drawLine(-2, -1);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(-5, -4);
+$s1->drawLine(-6, -4);
+$s1->drawLine(-24, -19);
+$s1->drawLine(82, 17);
+$s1->setRightFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(4, -4);
+$s1->drawLine(12, 5);
+$s1->drawLine(-1, 2);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(35, 7);
+$s1->movePenTo(2804, 1945);
+$s1->setLeftFill();
+$s1->drawLine(-5, -3);
+$s1->drawLine(-2, -1);
+$s1->movePenTo(2605, 1962);
+$s1->setLeftFill(0xff, 0xff, 0xff);
+$s1->setRightFill(0x06, 0x04, 0x07);
+$s1->drawCurve(9, 89, 104, 99);
+$s1->drawCurve(106, 98, 111, 22);
+$s1->drawCurve(127, 26, 58, -100);
+$s1->drawCurve(35, -60, -38, -86);
+$s1->drawCurve(-34, -76, -78, -69);
+$s1->drawCurve(-78, -68, -76, -22);
+$s1->drawCurve(-83, -24, -41, 45);
+$s1->drawCurve(-133, 24, 11, 102);
+$s1->movePenTo(2844, 1931);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(15, 3);
+$s1->movePenTo(2909, 1955);
+$s1->setRightFill(0xff, 0xff, 0xff);
+$s1->drawLine(9, 2);
+$s1->drawLine(-8, -3);
+$s1->drawLine(-1, 1);
+$s1->movePenTo(2703, 2064);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->drawCurve(15, 19, 49, 13);
+$s1->drawLine(-80, -100);
+$s1->drawCurve(0, 49, 16, 19);
+$s1->movePenTo(2707, 1976);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawLine(60, 120);
+$s1->drawCurve(23, -68, -83, -52);
+$s1->movePenTo(5046, 5838);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->setRightFill(0x06, 0x04, 0x07);
+$s1->drawCurve(-272, 156, -6, 381);
+$s1->drawLine(40, 0);
+$s1->drawCurve(25, -257, 81, -120);
+$s1->drawCurve(147, -234, 413, -25);
+$s1->drawCurve(132, -9, 213, 12);
+$s1->drawLine(309, 14);
+$s1->drawCurve(-87, -36, -141, -5);
+$s1->drawLine(-232, 1);
+$s1->drawCurve(-413, 0, -209, 122);
+$s1->movePenTo(5588, 5636);
+$s1->drawLine(500, 20);
+$s1->drawLine(20, -520);
+$s1->drawLine(-520, -20);
+$s1->drawLine(0, 520);
+$s1->movePenTo(5028, 5116);
+$s1->drawLine(-20, 640);
+$s1->drawLine(460, -120);
+$s1->drawLine(-20, -520);
+$s1->drawLine(-420, 0);
+$s1->movePenTo(5908, 5836);
+$s1->drawLine(220, 40);
+$s1->drawLine(0, -40);
+$s1->drawLine(-220, 0);
+$s1->movePenTo(3247, 4776);
+$s1->drawLine(0, 40);
+$s1->drawCurve(292, 7, 74, 215);
+$s1->drawCurve(67, 195, -133, 243);
+$s1->drawCurve(138, -82, 26, -122);
+$s1->drawCurve(24, -109, -67, -117);
+$s1->drawCurve(-63, -110, -116, -76);
+$s1->drawCurve(-119, -78, -123, -6);
+$s1->movePenTo(3807, 4796);
+$s1->drawLine(101, 300);
+$s1->drawCurve(22, -64, -33, -99);
+$s1->drawCurve(-34, -97, -56, -40);
+$s1->movePenTo(3852, 4712);
+$s1->drawCurve(134, 147, 57, 188);
+$s1->drawCurve(59, 198, -44, 191);
+$s1->drawCurve(-21, 92, -84, 94);
+$s1->drawLine(-146, 154);
+$s1->drawCurve(208, -57, 70, -181);
+$s1->drawCurve(61, -158, -51, -225);
+$s1->drawCurve(-46, -203, -118, -192);
+$s1->drawCurve(-116, -187, -128, -84);
+$s1->drawCurve(-122, -75, -158, -24);
+$s1->drawCurve(-200, -31, -40, 117);
+$s1->drawCurve(188, -46, 187, 69);
+$s1->drawCurve(175, 64, 135, 149);
+$s1->movePenTo(4548, 4996);
+$s1->drawLine(-300, -600);
+$s1->drawLine(-361, 160);
+$s1->drawLine(227, 440);
+$s1->drawLine(77, 166);
+$s1->drawLine(357, -166);
+$s1->movePenTo(3707, 4836);
+$s1->drawCurve(-19, 202, 139, 78);
+$s1->drawLine(-120, -280);
+$s1->movePenTo(6108, 6055);
+$s1->drawCurve(-414, -49, -216, 50);
+$s1->drawCurve(-356, 81, -14, 338);
+$s1->drawLine(57, -143);
+$s1->drawCurve(32, -85, 51, -49);
+$s1->drawCurve(126, -125, 284, -1);
+$s1->drawLine(450, 23);
+$s1->drawLine(0, -40);
+$s1->movePenTo(6328, 6136);
+$s1->drawCurve(-28, -147, -72, -73);
+$s1->drawLine(80, 459);
+$s1->drawCurve(48, -88, -28, -151);
+$s1->movePenTo(5828, 6675);
+$s1->drawLine(20, -140);
+$s1->drawLine(-680, -20);
+$s1->drawCurve(-1, 86, -22, 47);
+$s1->drawCurve(-20, 41, -25, -5);
+$s1->drawCurve(-25, -6, -10, -48);
+$s1->drawCurve(-12, -54, 15, -81);
+$s1->drawLine(-240, -60);
+$s1->drawCurve(-1, 271, 58, 140);
+$s1->drawCurve(81, 199, 222, 50);
+$s1->drawCurve(20, -114, 15, -53);
+$s1->drawCurve(25, -88, 63, -55);
+$s1->drawCurve(166, -153, 161, 134);
+$s1->drawCurve(66, 56, 42, 91);
+$s1->drawCurve(41, 90, 1, 92);
+$s1->drawCurve(244, -24, 110, -209);
+$s1->drawCurve(41, -79, 33, -125);
+$s1->drawLine(52, -223);
+$s1->drawCurve(-171, 27, -56, 27);
+$s1->drawCurve(-94, 43, 1, 143);
+$s1->drawLine(-120, 0);
+$s1->movePenTo(6128, 5975);
+$s1->drawLine(-220, -39);
+$s1->drawLine(0, 39);
+$s1->drawLine(220, 0);
+$s1->movePenTo(5330, 6929);
+$s1->drawCurve(-43, 89, 11, 116);
+$s1->drawCurve(9, 117, 59, 73);
+$s1->drawCurve(64, 81, 98, -14);
+$s1->drawCurve(97, -14, 48, -100);
+$s1->drawCurve(43, -91, -12, -118);
+$s1->drawCurve(-12, -119, -60, -72);
+$s1->drawCurve(-66, -81, -98, 19);
+$s1->drawCurve(-92, 15, -46, 99);
+$s1->movePenTo(5448, 7255);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->setRightFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(0, -80);
+$s1->drawLine(-80, 80);
+$s1->drawLine(80, 0);
+$s1->movePenTo(5548, 7255);
+$s1->drawLine(0, -320);
+$s1->drawLine(-120, 0);
+$s1->drawLine(60, 320);
+$s1->drawLine(60, 0);
+$s1->movePenTo(5588, 7255);
+$s1->drawLine(80, -100);
+$s1->drawCurve(-53, 10, -15, 20);
+$s1->drawCurve(-15, 19, 3, 51);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(6048, 1896);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(-601, -7);
+$s1->drawLine(-260, -133);
+$s1->drawCurve(129, 185, 264, 16);
+$s1->drawLine(468, -21);
+$s1->drawLine(0, -40);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(5531, 2332);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawCurve(-300, -2, -184, -144);
+$s1->drawCurve(-66, -49, -80, -129);
+$s1->drawCurve(-82, -131, -52, -41);
+$s1->drawCurve(26, 412, 472, 81);
+$s1->drawCurve(162, 28, 249, -6);
+$s1->drawLine(372, -15);
+$s1->drawLine(0, -40);
+$s1->drawLine(-517, 36);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(6268, 1856);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(-100, 320);
+$s1->drawCurve(153, -175, -53, -145);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(5828, 2176);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(0, 40);
+$s1->drawLine(220, -20);
+$s1->drawLine(-220, -20);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(7107, 2908);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawCurve(162, -165, 179, -47);
+$s1->drawCurve(-53, -49, -68, 20);
+$s1->drawCurve(-44, 13, -75, 56);
+$s1->drawCurve(-376, 251, 16, 229);
+$s1->drawLine(259, -308);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(7241, 3614);
+$s1->setRightFill(0x63, 0x62, 0x63);
+$s1->drawLine(7, 22);
+$s1->drawLine(-16, 0);
+$s1->drawCurve(-15, 14, -35, 4);
+$s1->drawCurve(-75, 9, -59, -27);
+$s1->drawLine(184, 0);
+$s1->drawCurve(8, -9, 1, -13);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(3147, 4535);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawCurve(-81, 15, -120, 58);
+$s1->drawCurve(-132, 64, -98, 82);
+$s1->drawCurve(-262, 217, 143, 180);
+$s1->drawCurve(34, 44, 64, 9);
+$s1->drawLine(120, 2);
+$s1->drawCurve(157, -1, 51, 133);
+$s1->drawCurve(41, 97, -91, 116);
+$s1->drawLine(-66, 89);
+$s1->drawCurve(-30, 51, 6, 47);
+$s1->drawCurve(12, 96, 172, 61);
+$s1->drawCurve(151, 54, 187, -49);
+$s1->drawCurve(81, -22, 241, -103);
+$s1->drawLine(-160, -240);
+$s1->drawLine(-200, 117);
+$s1->drawCurve(-126, 47, -34, -124);
+$s1->drawCurve(298, -29, -77, -246);
+$s1->drawCurve(-22, -71, -79, -153);
+$s1->drawCurve(-79, -154, -21, -67);
+$s1->drawLine(-360, 140);
+$s1->drawCurve(-5, -101, 114, -64);
+$s1->drawCurve(67, -38, 144, -37);
+$s1->drawLine(-40, -220);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(2787, 5288);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(-188, 11);
+$s1->drawCurve(-116, 13, -50, 53);
+$s1->drawCurve(-98, 100, 56, 120);
+$s1->drawCurve(56, 120, 140, -10);
+$s1->drawCurve(90, -8, 89, -49);
+$s1->drawCurve(100, -53, 37, -74);
+$s1->drawCurve(43, -81, -33, -73);
+$s1->drawCurve(-35, -76, -91, 7);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(2447, 5395);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->drawLine(40, 80);
+$s1->drawLine(60, -100);
+$s1->drawLine(-100, 20);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(5768, 6155);
+$s1->setLeftFill(0xfa, 0xfc, 0xfa);
+$s1->drawLine(100, 320);
+$s1->drawCurve(87, -58, -43, -124);
+$s1->drawCurve(-43, -122, -101, -16);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(2522, 5549);
+$s1->setLeftFill(0x06, 0x04, 0x07);
+$s1->drawLine(40, 80);
+$s1->drawLine(60, -100);
+$s1->drawLine(-100, 20);
+$i1 = $conference1->add($s1);
+$i1->scaleTo(0.5);
+$i1->moveTo(-2720, -1890);
+$conference1->nextFrame();  # end of frame 1
+
+
+$conference2 = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(6139, 1671);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawCurve(28, -75, 62, -60);
+$s1->drawCurve(112, -109, 158, 0);
+$s1->drawCurve(158, 0, 112, 109);
+$s1->drawCurve(62, 60, 28, 75);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(504, 0);
+$s1->drawCurve(33, 0, 23, 23);
+$s1->drawCurve(24, 24, 0, 33);
+$s1->drawLine(0, 3987);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 823);
+$s1->drawLine(0, 12);
+$s1->drawLine(-305, 0);
+$s1->drawLine(0, -123);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(-122, 0);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 123);
+$s1->drawLine(-928, 0);
+$s1->drawLine(0, -123);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(-122, 0);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 123);
+$s1->drawLine(-354, 0);
+$s1->drawLine(0, -12);
+$s1->drawLine(0, -111);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(-217, 0);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 111);
+$s1->drawLine(0, 12);
+$s1->drawLine(-305, 0);
+$s1->drawLine(0, -123);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(-122, 0);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 123);
+$s1->drawLine(-928, 0);
+$s1->drawLine(0, -123);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(-122, 0);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 123);
+$s1->drawLine(-354, 0);
+$s1->drawLine(0, -12);
+$s1->drawLine(0, -813);
+$s1->drawCurve(0, -166, 117, -117);
+$s1->drawLine(2, -2);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(0, -864);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawCurve(-62, 43, -57, 44);
+$s1->drawCurve(-9, -41, 0, -45);
+$s1->drawLine(0, -1238);
+$s1->drawCurve(0, -166, 117, -117);
+$s1->drawLine(11, -10);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawLine(0, -1318);
+$s1->drawCurve(0, -33, 23, -24);
+$s1->drawCurve(24, -23, 33, 0);
+$s1->drawLine(2376, 0);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->drawCurve(-22, 60, 0, 69);
+$s1->drawCurve(0, 155, 112, 109);
+$s1->drawCurve(112, 109, 158, 0);
+$s1->drawCurve(158, 0, 112, -109);
+$s1->drawCurve(112, -109, 0, -155);
+$s1->drawCurve(0, -69, -22, -60);
+$s1->movePenTo(7441, 2773);
+$s1->setLeftFill(0x99, 0x99, 0x99, 0x00);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawLine(0, 730);
+$s1->drawLine(-398, 25);
+$s1->drawLine(0, -506);
+$s1->drawCurve(0, -25, -18, -18);
+$s1->drawCurve(-17, -17, -25, 0);
+$s1->drawLine(-1, 0);
+$s1->drawCurve(-25, 0, -18, 17);
+$s1->drawCurve(-17, 18, 0, 25);
+$s1->drawLine(0, 517);
+$s1->drawLine(-429, 53);
+$s1->drawLine(-385, 64);
+$s1->drawLine(0, -634);
+$s1->drawCurve(0, -25, -18, -18);
+$s1->drawCurve(-17, -17, -25, 0);
+$s1->drawLine(-1, 0);
+$s1->drawCurve(-25, 0, -18, 17);
+$s1->drawCurve(-17, 18, 0, 25);
+$s1->drawLine(0, 658);
+$s1->drawCurve(-193, 38, -184, 47);
+$s1->drawLine(0, -992);
+$s1->drawCurve(0, -166, 117, -117);
+$s1->drawCurve(117, -117, 166, 0);
+$s1->drawLine(1031, 0);
+$s1->drawCurve(166, 0, 117, 117);
+$s1->drawCurve(117, 117, 0, 166);
+$s1->movePenTo(6796, 4533);
+$s1->drawCurve(112, 109, 0, 155);
+$s1->drawCurve(0, 155, -112, 109);
+$s1->drawCurve(-112, 109, -158, 0);
+$s1->drawCurve(-158, 0, -112, -109);
+$s1->drawCurve(-112, -109, 0, -155);
+$s1->drawCurve(0, -155, 112, -109);
+$s1->drawCurve(112, -109, 158, 0);
+$s1->drawCurve(158, 0, 112, 109);
+$s1->movePenTo(7138, 6450);
+$s1->drawLine(0, -532);
+$s1->drawCurve(0, -25, -18, -18);
+$s1->drawCurve(-18, -18, -25, 0);
+$s1->drawCurve(-25, 0, -18, 18);
+$s1->drawCurve(-18, 18, 0, 25);
+$s1->drawLine(0, 532);
+$s1->movePenTo(5612, 6450);
+$s1->drawLine(0, -702);
+$s1->drawCurve(0, -166, 117, -117);
+$s1->drawCurve(117, -117, 166, 0);
+$s1->drawLine(1031, 0);
+$s1->drawCurve(166, 0, 117, 117);
+$s1->drawCurve(113, 113, 4, 160);
+$s1->movePenTo(4511, 2774);
+$s1->drawCurve(-158, 0, -112, -109);
+$s1->drawCurve(-112, -109, 0, -155);
+$s1->drawCurve(0, -155, 112, -109);
+$s1->drawCurve(112, -109, 158, 0);
+$s1->drawCurve(158, 0, 112, 109);
+$s1->drawCurve(112, 109, 0, 155);
+$s1->drawCurve(0, 155, -112, 109);
+$s1->drawCurve(-112, 109, -158, 0);
+$s1->movePenTo(3683, 4599);
+$s1->setLeftFill(0x00, 0x00, 0x00);
+$s1->setRightFill(0x99, 0x99, 0x99, 0x00);
+$s1->drawCurve(62, -43, 66, -42);
+$s1->drawLine(142, -88);
+$s1->drawLine(0, -839);
+$s1->drawCurve(0, -25, 17, -18);
+$s1->drawCurve(18, -17, 25, 0);
+$s1->drawLine(1, 0);
+$s1->drawCurve(25, 0, 17, 17);
+$s1->drawCurve(18, 18, 0, 25);
+$s1->drawLine(0, 769);
+$s1->drawCurve(365, -204, 421, -156);
+$s1->drawLine(0, -409);
+$s1->drawCurve(0, -25, 17, -18);
+$s1->drawCurve(18, -17, 25, 0);
+$s1->drawLine(1, 0);
+$s1->drawCurve(25, 0, 17, 17);
+$s1->drawCurve(18, 18, 0, 25);
+$s1->drawLine(0, 365);
+$s1->drawCurve(197, -69, 208, -59);
+$s1->drawLine(0, -462);
+$s1->drawCurve(0, -166, -117, -117);
+$s1->drawCurve(-117, -117, -166, 0);
+$s1->drawLine(-1031, 0);
+$s1->drawCurve(-158, 0, -114, 107);
+$s1->movePenTo(3683, 5463);
+$s1->setLeftFill(0x99, 0x99, 0x99, 0x00);
+$s1->setRightFill(0x00, 0x00, 0x00);
+$s1->drawCurve(116, -115, 165, 0);
+$s1->drawLine(1031, 0);
+$s1->drawCurve(166, 0, 117, 117);
+$s1->drawCurve(117, 117, 0, 166);
+$s1->drawLine(0, 702);
+$s1->movePenTo(5090, 6450);
+$s1->drawLine(0, -532);
+$s1->drawCurve(0, -25, -18, -18);
+$s1->drawCurve(-18, -18, -25, 0);
+$s1->drawCurve(-25, 0, -18, 18);
+$s1->drawCurve(-18, 18, 0, 25);
+$s1->drawLine(0, 532);
+$s1->movePenTo(6088, 6450);
+$s1->drawLine(0, -532);
+$s1->drawCurve(0, -25, -18, -18);
+$s1->drawCurve(-18, -18, -25, 0);
+$s1->drawCurve(-25, 0, -18, 18);
+$s1->drawCurve(-18, 18, 0, 25);
+$s1->drawLine(0, 532);
+$s1->movePenTo(4784, 4530);
+$s1->drawCurve(112, 109, 0, 155);
+$s1->drawCurve(0, 155, -112, 109);
+$s1->drawCurve(-112, 109, -158, 0);
+$s1->drawCurve(-158, 0, -112, -109);
+$s1->drawCurve(-134, -130, 0, -133);
+$s1->drawCurve(0, -135, 134, -130);
+$s1->drawCurve(112, -109, 158, 0);
+$s1->drawCurve(158, 0, 112, 109);
+$s1->movePenTo(4040, 6450);
+$s1->drawLine(0, -532);
+$s1->drawCurve(0, -25, -18, -18);
+$s1->drawCurve(-18, -18, -25, 0);
+$s1->drawCurve(-25, 0, -18, 18);
+$s1->drawCurve(-18, 18, 0, 25);
+$s1->drawLine(0, 532);
+$i1 = $conference2->add($s1);
+$i1->scaleTo(0.5);
+$i1->moveTo(-2720, -1890);
+$conference2->nextFrame();  # end of frame 1
+
+
+
+# status log toolbar
+#  $statusbar = new SWF::Sprite();
+### Shape 1 ###
+#  $s1 = new SWF::Shape();
+#  $s1->movePenTo(19920, 0);
+#  $s1->setRightFill(0xcc, 0xcc, 0xcc);
+#  $s1->drawLine(0, 600);
+#  $s1->setLine(20, 0x00, 0x00, 0x00);
+#  $s1->drawLine(-19920, 0);
+#  $s1->setLine(20, 0xcc, 0xcc, 0xcc);
+#  $s1->drawLine(0, -600);
+#  $s1->setLine(20, 0x99, 0x99, 0x99);
+#  $s1->drawLine(19920, 0);
+#  $i1 = $statusbar->add($s1);
+#  $i1->scaleTo(0.5);
+#  $statusbar->nextFrame();  # end of frame 1
+
+
+
+$extrainfo = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(5400, 0);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, 600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(-5400, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, -600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(5400, 0);
+$s1->setLeftFill();
+$s1->setRightFill();
+$s1->movePenTo(5367, 91);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->setLine(20, 0xff, 0xff, 0xff);
+$s1->drawLine(0, 400);
+$s1->drawLine(-3900, 0);
+$s1->setLine(20, 0x66, 0x66, 0x66);
+$s1->drawLine(0, -400);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(3900, 0);
+$i2 = $extrainfo->add($s1);
+$i2->scaleTo(0.5);
+
+#$s3 = new SWF::TextField(SWFTEXTFIELD_USEFONT );
+#$s3->setBounds(3740, 398);
+#$s3->setFont($font_general);
+#$s3->setHeight(320);
+###$s3->setColor(0x00, 0x00, 0x00, 0xff);
+#$s3->align(SWFTEXTFIELD_ALIGN_LEFT);
+#$s3->setName('clidvalue');
+#$i3 = $extrainfo->add($s3);
+#$i3->scaleTo(0.5, 0.5);
+#$i3->moveTo(770, 65);
+#$i3->setName('clid_text');
+
+$extrainfo->nextFrame();  
+
+
+
+$boton_ayuda = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(439, 222);
+$s1->setLeftFill(0xff, 0xa8, 0x37);
+$s1->setRightFill(0x79, 0x79, 0x79);
+$s1->drawCurve(-1, 24, -16, 23);
+$s1->drawLine(-34, 35);
+$s1->drawCurve(-32, 29, 2, 32);
+$s1->drawLine(0, 9);
+$s1->drawLine(-78, 0);
+$s1->drawLine(-2, -13);
+$s1->drawCurve(-2, -41, 37, -35);
+$s1->drawLine(24, -27);
+$s1->drawLine(10, -25);
+$s1->drawCurve(0, -28, -42, -1);
+$s1->drawCurve(-34, 0, -25, 15);
+$s1->drawLine(-20, -53);
+$s1->drawCurve(42, -21, 57, 1);
+$s1->drawCurve(55, 0, 31, 23);
+$s1->drawCurve(27, 20, 1, 33);
+$s1->movePenTo(418, 82);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->drawCurve(-46, -21, -49, -1);
+$s1->drawCurve(-51, -1, -46, 19);
+$s1->drawCurve(-44, 18, -35, 34);
+$s1->drawCurve(-35, 33, -20, 44);
+$s1->drawCurve(-21, 46, -2, 49);
+$s1->drawCurve(-3, 50, 19, 46);
+$s1->drawCurve(17, 45, 33, 36);
+$s1->drawCurve(33, 35, 44, 21);
+$s1->drawCurve(45, 22, 49, 3);
+$s1->drawCurve(50, 2, 47, -17);
+$s1->drawCurve(45, -16, 36, -33);
+$s1->drawCurve(36, -33, 22, -43);
+$s1->drawCurve(22, -45, 4, -49);
+$s1->drawLine(0, -15);
+$s1->drawLine(0, -2);
+$s1->drawCurve(0, -50, -19, -45);
+$s1->drawCurve(-19, -44, -34, -34);
+$s1->drawCurve(-34, -35, -44, -19);
+$s1->movePenTo(518, 404);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(-21, 44, -38, 32);
+$s1->drawCurve(-37, 32, -50, 12);
+$s1->drawLine(-98, 3);
+$s1->drawCurve(-47, -10, -39, -29);
+$s1->drawCurve(-39, -29, -24, -43);
+$s1->drawCurve(-25, -43, -2, -51);
+$s1->drawCurve(-2, -50, 19, -47);
+$s1->drawCurve(28, -72, 72, -37);
+$s1->drawCurve(71, -38, 77, 16);
+$s1->drawCurve(76, 15, 50, 62);
+$s1->drawCurve(49, 61, 1, 78);
+$s1->drawLine(0, 1);
+$s1->drawCurve(-1, 49, -20, 44);
+$s1->movePenTo(278, 410);
+$s1->setLeftFill(0xff, 0xa8, 0x37);
+$s1->setRightFill(0x79, 0x79, 0x79);
+$s1->drawCurve(15, -12, 23, 0);
+$s1->drawCurve(24, 0, 15, 12);
+$s1->drawCurve(14, 12, 0, 20);
+$s1->drawCurve(0, 20, -14, 12);
+$s1->drawCurve(-15, 13, -23, 0);
+$s1->drawLine(-1, 0);
+$s1->drawCurve(-23, 0, -15, -13);
+$s1->drawCurve(-15, -13, 0, -19);
+$s1->drawCurve(0, -20, 15, -12);
+$s1->movePenTo(640, 600);
+$s1->setLeftFill();
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s1->drawLine(-640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, -600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, 600);
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(439, 221);
+$s2->setLeftFill(0x79, 0x79, 0x79);
+$s2->setRightFill(0xff, 0xa8, 0x37);
+$s2->drawCurve(-1, 25, -16, 23);
+$s2->drawLine(-34, 35);
+$s2->drawCurve(-32, 28, 1, 32);
+$s2->drawLine(0, 9);
+$s2->drawLine(-78, 0);
+$s2->drawLine(-1, -13);
+$s2->drawCurve(-2, -40, 37, -36);
+$s2->drawLine(24, -26);
+$s2->drawLine(10, -25);
+$s2->drawCurve(0, -29, -42, 0);
+$s2->drawCurve(-34, 0, -25, 14);
+$s2->drawLine(-20, -53);
+$s2->drawCurve(42, -20, 57, 0);
+$s2->drawCurve(55, 0, 31, 23);
+$s2->drawCurve(27, 21, 1, 32);
+$s2->movePenTo(515, 157);
+$s2->setLeftFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(25, 40);
+$s2->drawLine(9, 17);
+$s2->drawLine(8, 23);
+$s2->drawLine(11, 72);
+$s2->drawLine(0, 2);
+$s2->drawLine(0, 15);
+$s2->drawLine(-16, 71);
+$s2->drawLine(-10, 23);
+$s2->drawCurve(-22, 43, -36, 33);
+$s2->drawCurve(-36, 33, -45, 16);
+$s2->drawCurve(-47, 17, -50, -2);
+$s2->drawCurve(-49, -3, -45, -22);
+$s2->drawCurve(-44, -21, -33, -35);
+$s2->drawLine(-29, -39);
+$s2->drawLine(-21, -42);
+$s2->drawLine(-1, -1);
+$s2->drawLine(-13, -46);
+$s2->setRightFill();
+$s2->drawLine(-3, -50);
+$s2->drawCurve(2, -49, 22, -45);
+$s2->drawCurve(20, -44, 35, -34);
+$s2->drawLine(18, -15);
+$s2->setRightFill(0xff, 0xa8, 0x37);
+$s2->drawLine(61, -36);
+$s2->drawCurve(46, -19, 50, 1);
+$s2->drawLine(1, 0);
+$s2->drawLine(4, 0);
+$s2->drawLine(69, 13);
+$s2->setRightFill();
+$s2->drawLine(22, 8);
+$s2->drawCurve(44, 20, 34, 34);
+$s2->drawLine(19, 22);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->drawLine(-19, -21);
+$s2->drawCurve(-34, -35, -44, -19);
+$s2->drawLine(-22, -9);
+$s2->movePenTo(539, 311);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(-1, 49, -20, 44);
+$s2->drawCurve(-21, 44, -38, 32);
+$s2->drawCurve(-37, 32, -50, 12);
+$s2->drawLine(-98, 3);
+$s2->drawCurve(-47, -10, -39, -29);
+$s2->drawCurve(-39, -29, -24, -43);
+$s2->drawCurve(-25, -43, -2, -51);
+$s2->drawCurve(-2, -50, 19, -47);
+$s2->drawCurve(28, -72, 72, -37);
+$s2->drawCurve(71, -38, 77, 16);
+$s2->drawCurve(76, 15, 50, 62);
+$s2->drawCurve(49, 61, 1, 78);
+$s2->drawLine(0, 1);
+$s2->movePenTo(165, 114);
+$s2->setRightFill();
+$s2->drawCurve(-10, 7, -8, 9);
+$s2->drawCurve(-35, 33, -20, 44);
+$s2->drawCurve(-21, 46, -2, 49);
+$s2->drawLine(2, 49);
+$s2->movePenTo(278, 409);
+$s2->setLeftFill(0x79, 0x79, 0x79);
+$s2->setRightFill(0xff, 0xa8, 0x37);
+$s2->drawCurve(15, -12, 23, 0);
+$s2->drawCurve(24, 0, 14, 12);
+$s2->drawCurve(15, 12, 0, 20);
+$s2->drawCurve(0, 19, -14, 13);
+$s2->drawCurve(-15, 12, -23, 1);
+$s2->drawLine(-1, 0);
+$s2->drawCurve(-24, -1, -14, -12);
+$s2->drawCurve(-15, -13, 0, -19);
+$s2->drawCurve(0, -20, 15, -12);
+$s2->movePenTo(640, 600);
+$s2->setLeftFill();
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s2->drawLine(-640, 0);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, -600);
+$s2->setLine(20, 0x99, 0x99, 0x99);
+$s2->drawLine(640, 0);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, 600);
+
+$i1 = $boton_ayuda->add($s1);
+$i1->scaleTo(0.5);
+$boton_ayuda->nextFrame();  # end of frame 1
+$boton_ayuda->remove($i1);
+$i1 = $boton_ayuda->add($s2);
+$i1->scaleTo(0.5);
+$boton_ayuda->nextFrame();  # end of frame 1
+
+
+$boton_debug = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(415, 159);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(-10, 0, 0, 10);
+$s1->drawCurve(3, 58, -32, 23);
+$s1->drawLine(-23, 11);
+$s1->drawLine(-9, 1);
+$s1->drawLine(-4, 1);
+$s1->drawLine(-17, -2);
+$s1->drawLine(-21, 4);
+$s1->drawCurve(-3, -3, -4, 0);
+$s1->drawCurve(-14, -1, -16, -10);
+$s1->drawCurve(-34, -22, 3, -60);
+$s1->drawCurve(0, -10, -10, 0);
+$s1->drawCurve(-10, 0, 0, 10);
+$s1->drawCurve(-3, 66, 39, 30);
+$s1->drawLine(27, 15);
+$s1->drawLine(-50, 3);
+$s1->drawCurve(-26, -8, -21, -22);
+$s1->drawLine(-15, 1);
+$s1->drawCurve(-7, 7, 7, 7);
+$s1->drawCurve(26, 26, 33, 10);
+$s1->drawLine(33, 3);
+$s1->drawLine(-6, 18);
+$s1->drawLine(-2, 1);
+$s1->drawCurve(-34, 25, -29, -17);
+$s1->drawCurve(-8, -5, -5, 9);
+$s1->drawCurve(-6, 9, 9, 5);
+$s1->drawCurve(34, 20, 38, -21);
+$s1->drawCurve(1, 33, 21, 24);
+$s1->drawCurve(22, 25, 31, 0);
+$s1->drawCurve(30, 0, 22, -25);
+$s1->drawCurve(20, -23, 2, -31);
+$s1->drawLine(66, -2);
+$s1->drawCurve(9, -5, -5, -9);
+$s1->drawCurve(-6, -9, -8, 5);
+$s1->drawCurve(-26, 16, -31, -20);
+$s1->drawLine(-7, -23);
+$s1->drawLine(26, -3);
+$s1->drawCurve(33, -10, 26, -26);
+$s1->drawCurve(7, -7, -7, -7);
+$s1->drawLine(-14, -1);
+$s1->drawCurve(-22, 22, -25, 8);
+$s1->drawLine(-40, 1);
+$s1->drawLine(-7, -6);
+$s1->drawLine(22, -12);
+$s1->drawCurve(40, -29, -2, -68);
+$s1->drawCurve(-1, -10, -10, 0);
+$s1->movePenTo(416, 81);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->drawCurve(-46, -20, -49, -1);
+$s1->drawCurve(-50, -1, -46, 19);
+$s1->drawCurve(-45, 17, -34, 34);
+$s1->drawCurve(-36, 34, -20, 44);
+$s1->drawCurve(-21, 45, -2, 49);
+$s1->drawCurve(-2, 50, 18, 46);
+$s1->drawCurve(17, 45, 34, 36);
+$s1->drawCurve(33, 35, 44, 21);
+$s1->drawCurve(44, 21, 50, 3);
+$s1->drawCurve(49, 3, 47, -17);
+$s1->drawCurve(45, -16, 36, -33);
+$s1->drawCurve(36, -33, 22, -43);
+$s1->drawCurve(22, -44, 4, -49);
+$s1->drawLine(0, -16);
+$s1->drawLine(0, -1);
+$s1->drawCurve(-1, -50, -19, -45);
+$s1->drawCurve(-19, -45, -33, -34);
+$s1->drawCurve(-34, -34, -44, -20);
+$s1->movePenTo(537, 310);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(-1, 49, -20, 44);
+$s1->drawCurve(-21, 44, -38, 32);
+$s1->drawCurve(-37, 32, -50, 12);
+$s1->drawCurve(-49, 12, -48, -10);
+$s1->drawCurve(-48, -9, -39, -29);
+$s1->drawCurve(-39, -29, -24, -43);
+$s1->drawCurve(-24, -43, -2, -51);
+$s1->drawCurve(-3, -50, 19, -46);
+$s1->drawCurve(29, -73, 72, -37);
+$s1->drawCurve(70, -37, 77, 15);
+$s1->drawCurve(76, 15, 50, 62);
+$s1->drawCurve(49, 61, 1, 78);
+$s1->drawLine(0, 1);
+$s1->movePenTo(277, 206);
+$s1->setLeftFill(0xff, 0xa8, 0x37);
+$s1->setRightFill(0x79, 0x79, 0x79);
+$s1->drawCurve(0, -19, 13, -12);
+$s1->drawCurve(13, -13, 18, 0);
+$s1->drawCurve(18, 0, 13, 13);
+$s1->drawCurve(13, 12, 0, 19);
+$s1->drawCurve(0, 18, -13, 13);
+$s1->drawCurve(-13, 12, -18, 1);
+$s1->drawCurve(-18, -1, -13, -12);
+$s1->drawCurve(-13, -13, 0, -18);
+$s1->movePenTo(640, 600);
+$s1->setLeftFill();
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s1->drawLine(-640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, -600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, 600);
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(366, 554);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->drawLine(35, -10);
+$s2->drawCurve(45, -16, 36, -33);
+$s2->drawCurve(36, -33, 22, -43);
+$s2->drawCurve(22, -44, 4, -49);
+$s2->drawLine(0, -16);
+$s2->drawLine(0, -1);
+$s2->drawCurve(-1, -50, -19, -45);
+$s2->drawCurve(-19, -45, -33, -34);
+$s2->drawCurve(-34, -34, -44, -20);
+$s2->drawCurve(-46, -20, -49, -1);
+$s2->drawLine(-39, 2);
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(-38, 9);
+$s2->drawLine(-18, 6);
+$s2->drawLine(-1, 1);
+$s2->drawLine(-42, 21);
+$s2->drawLine(-37, 30);
+$s2->drawCurve(-36, 34, -20, 44);
+$s2->drawCurve(-21, 45, -2, 49);
+$s2->drawCurve(-2, 50, 18, 46);
+$s2->drawCurve(17, 45, 34, 36);
+$s2->drawCurve(33, 35, 44, 21);
+$s2->drawLine(46, 17);
+$s2->drawLine(48, 7);
+$s2->drawLine(1, 0);
+$s2->drawLine(60, -4);
+$s2->setLeftFill();
+$s2->drawLine(37, -10);
+$s2->drawCurve(44, -17, 37, -32);
+$s2->drawCurve(36, -33, 22, -43);
+$s2->drawCurve(22, -44, 4, -49);
+$s2->drawLine(0, -16);
+$s2->drawLine(0, -1);
+$s2->drawCurve(0, -50, -19, -45);
+$s2->drawCurve(-19, -45, -34, -34);
+$s2->drawCurve(-34, -34, -44, -20);
+$s2->drawCurve(-46, -20, -49, -1);
+$s2->drawLine(-41, 2);
+$s2->movePenTo(407, 169);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(3, 58, -32, 23);
+$s2->drawLine(-23, 11);
+$s2->drawLine(-9, 1);
+$s2->drawLine(-4, 1);
+$s2->drawLine(-18, -2);
+$s2->drawLine(-21, 3);
+$s2->drawLine(-6, -2);
+$s2->drawLine(-30, -11);
+$s2->drawCurve(-34, -22, 3, -60);
+$s2->drawCurve(0, -10, -10, 0);
+$s2->drawCurve(-11, 0, 0, 10);
+$s2->drawCurve(-3, 66, 39, 30);
+$s2->drawLine(27, 15);
+$s2->drawLine(-50, 3);
+$s2->drawCurve(-26, -8, -21, -22);
+$s2->drawCurve(-7, -7, -7, 7);
+$s2->drawCurve(-8, 7, 8, 8);
+$s2->drawCurve(26, 26, 33, 10);
+$s2->drawLine(32, 3);
+$s2->drawLine(-6, 18);
+$s2->drawLine(-1, 1);
+$s2->drawCurve(-35, 25, -28, -17);
+$s2->drawCurve(-9, -5, -5, 9);
+$s2->drawCurve(-6, 8, 9, 6);
+$s2->drawCurve(34, 20, 39, -21);
+$s2->drawCurve(1, 33, 21, 24);
+$s2->drawCurve(21, 25, 31, 0);
+$s2->drawCurve(31, 0, 22, -25);
+$s2->drawCurve(19, -23, 3, -31);
+$s2->drawLine(66, -2);
+$s2->drawCurve(9, -6, -5, -8);
+$s2->drawCurve(-6, -9, -8, 5);
+$s2->drawCurve(-27, 16, -31, -20);
+$s2->drawLine(-7, -23);
+$s2->drawLine(27, -3);
+$s2->drawCurve(33, -10, 26, -26);
+$s2->drawCurve(7, -8, -7, -7);
+$s2->drawCurve(-8, -7, -6, 7);
+$s2->drawCurve(-22, 22, -26, 8);
+$s2->drawLine(-39, 1);
+$s2->drawLine(-6, -6);
+$s2->drawLine(21, -12);
+$s2->drawCurve(40, -29, -2, -68);
+$s2->drawCurve(-1, -10, -10, 0);
+$s2->drawCurve(-11, 0, 1, 10);
+$s2->movePenTo(537, 310);
+$s2->drawCurve(-1, 49, -20, 44);
+$s2->drawCurve(-21, 44, -38, 32);
+$s2->drawCurve(-37, 32, -50, 12);
+$s2->drawCurve(-49, 12, -48, -10);
+$s2->drawCurve(-48, -9, -39, -29);
+$s2->drawCurve(-39, -29, -24, -43);
+$s2->drawCurve(-24, -43, -2, -51);
+$s2->drawCurve(-3, -50, 19, -46);
+$s2->drawCurve(29, -73, 72, -37);
+$s2->drawCurve(70, -37, 77, 15);
+$s2->drawCurve(76, 15, 50, 62);
+$s2->drawCurve(49, 61, 1, 78);
+$s2->drawLine(0, 1);
+$s2->movePenTo(279, 206);
+$s2->setLeftFill(0x79, 0x79, 0x79);
+$s2->setRightFill(0xff, 0xa8, 0x37);
+$s2->drawCurve(0, -19, 13, -12);
+$s2->drawCurve(12, -13, 19, 0);
+$s2->drawCurve(18, 0, 13, 13);
+$s2->drawCurve(12, 12, 1, 19);
+$s2->drawCurve(-1, 18, -12, 13);
+$s2->drawCurve(-13, 12, -18, 1);
+$s2->drawCurve(-19, -1, -12, -12);
+$s2->drawCurve(-13, -13, 0, -18);
+$s2->movePenTo(640, 0);
+$s2->setLeftFill();
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc); 
+$s2->drawLine(0, 600);
+$s2->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s2->drawLine(-640, 0);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc); # raya izq
+$s2->drawLine(0, -600);
+$s2->setLine(20, 0x99, 0x99, 0x99); # raya sup
+$s2->drawLine(640, 0);
+
+$i1 = $boton_debug->add($s1);
+$i1->scaleTo(0.5);
+$boton_debug->nextFrame();
+$boton_debug->remove($i1);
+$i1 = $boton_debug->add($s2);
+$i1->scaleTo(0.5);
+$boton_debug->nextFrame();  
+$boton_debug->remove($i1);
+$boton_debug->nextFrame();  
+
+
+
+$boton_reload = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(424, 154);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawLine(-71, -37);
+$s1->drawCurve(-8, -4, -6, 4);
+$s1->drawCurve(-7, 4, -1, 9);
+$s1->drawLine(-1, 11);
+$s1->drawLine(-52, 5);
+$s1->drawCurve(-53, 12, -36, 39);
+$s1->drawCurve(-37, 39, -6, 56);
+$s1->drawCurve(-7, 53, 25, 49);
+$s1->drawCurve(23, 47, 49, 26);
+$s1->drawCurve(49, 25, 52, -6);
+$s1->drawCurve(56, -7, 41, -37);
+$s1->drawCurve(42, -37, 12, -55);
+$s1->drawCurve(5, -25, -2, -28);
+$s1->drawCurve(-2, -12, -6, -7);
+$s1->drawCurve(-8, -8, -10, 1);
+$s1->drawCurve(-11, -1, -8, 8);
+$s1->drawCurve(-9, 8, 1, 11);
+$s1->drawCurve(5, 45, -23, 37);
+$s1->drawCurve(-24, 37, -43, 14);
+$s1->drawLine(-76, -2);
+$s1->drawCurve(-38, -14, -22, -33);
+$s1->drawCurve(-22, -33, 2, -40);
+$s1->drawCurve(2, -41, 25, -30);
+$s1->drawCurve(26, -31, 39, -9);
+$s1->drawLine(37, -3);
+$s1->drawLine(-2, 16);
+$s1->drawCurve(0, 8, 8, 5);
+$s1->drawCurve(7, 4, 7, -4);
+$s1->drawLine(78, -43);
+$s1->drawLine(7, -9);
+$s1->drawLine(0, -3);
+$s1->drawLine(0, -5);
+$s1->drawLine(-7, -9);
+$s1->movePenTo(496, 135);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->drawCurve(-34, -34, -44, -20);
+$s1->drawCurve(-46, -20, -50, -1);
+$s1->drawCurve(-50, -1, -46, 19);
+$s1->drawCurve(-44, 17, -35, 34);
+$s1->drawCurve(-35, 34, -20, 44);
+$s1->drawCurve(-22, 45, -2, 49);
+$s1->drawCurve(-2, 50, 18, 46);
+$s1->drawCurve(18, 45, 33, 36);
+$s1->drawCurve(33, 35, 44, 21);
+$s1->drawCurve(45, 21, 49, 3);
+$s1->drawCurve(50, 3, 47, -17);
+$s1->drawCurve(44, -16, 37, -33);
+$s1->drawCurve(36, -33, 22, -43);
+$s1->drawCurve(22, -44, 4, -49);
+$s1->drawLine(0, -16);
+$s1->drawLine(0, -1);
+$s1->drawCurve(-1, -50, -19, -45);
+$s1->drawCurve(-19, -45, -33, -34);
+$s1->movePenTo(539, 310);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(-1, 49, -20, 44);
+$s1->drawCurve(-22, 44, -37, 32);
+$s1->drawCurve(-38, 32, -49, 12);
+$s1->drawCurve(-49, 12, -49, -10);
+$s1->drawCurve(-47, -9, -40, -29);
+$s1->drawCurve(-39, -29, -23, -43);
+$s1->drawCurve(-25, -43, -2, -51);
+$s1->drawCurve(-3, -50, 19, -46);
+$s1->drawCurve(29, -73, 72, -37);
+$s1->drawCurve(71, -37, 76, 15);
+$s1->drawCurve(76, 15, 51, 62);
+$s1->drawCurve(49, 61, 1, 78);
+$s1->drawLine(0, 1);
+$s1->movePenTo(640, 0);
+$s1->setLeftFill();
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, 600);
+$s1->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s1->drawLine(-640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, -600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(640, 0);
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(424, 154);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawLine(-71, -37);
+$s2->drawCurve(-8, -4, -6, 4);
+$s2->drawCurve(-7, 4, -1, 9);
+$s2->drawLine(-1, 11);
+$s2->drawLine(-53, 4);
+$s2->drawCurve(-52, 13, -36, 39);
+$s2->drawCurve(-37, 39, -6, 56);
+$s2->drawCurve(-7, 53, 24, 49);
+$s2->drawCurve(23, 47, 50, 26);
+$s2->drawCurve(49, 25, 52, -6);
+$s2->drawCurve(56, -7, 41, -37);
+$s2->drawCurve(42, -37, 12, -55);
+$s2->drawCurve(5, -25, -2, -28);
+$s2->drawCurve(-2, -12, -6, -7);
+$s2->drawCurve(-8, -8, -11, 1);
+$s2->drawCurve(-10, -1, -8, 8);
+$s2->drawCurve(-9, 8, 1, 11);
+$s2->drawCurve(5, 45, -23, 37);
+$s2->drawCurve(-24, 37, -43, 14);
+$s2->drawLine(-76, -2);
+$s2->drawCurve(-38, -14, -22, -33);
+$s2->drawCurve(-22, -33, 2, -40);
+$s2->drawCurve(1, -41, 26, -30);
+$s2->drawCurve(25, -31, 40, -9);
+$s2->drawLine(37, -3);
+$s2->drawLine(-2, 16);
+$s2->drawCurve(0, 8, 8, 5);
+$s2->drawCurve(7, 4, 7, -4);
+$s2->drawLine(78, -43);
+$s2->drawLine(7, -9);
+$s2->drawLine(0, -3);
+$s2->drawLine(0, -5);
+$s2->drawLine(-7, -9);
+$s2->movePenTo(152, 495);
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(60, 39);
+$s2->drawCurve(44, 21, 50, 3);
+$s2->drawCurve(50, 3, 47, -17);
+$s2->drawCurve(44, -16, 37, -33);
+$s2->drawLine(46, -55);
+$s2->drawLine(12, -21);
+$s2->drawLine(10, -22);
+$s2->drawLine(16, -71);
+$s2->drawLine(0, -16);
+$s2->drawLine(0, -1);
+$s2->drawCurve(-1, -50, -19, -45);
+$s2->drawCurve(-19, -45, -33, -34);
+$s2->drawCurve(-34, -34, -44, -20);
+$s2->drawCurve(-46, -20, -50, -1);
+$s2->drawCurve(-50, -1, -46, 19);
+$s2->drawCurve(-44, 17, -35, 34);
+$s2->drawLine(-44, 56);
+$s2->setRightFill();
+$s2->drawLine(-11, 22);
+$s2->drawLine(-10, 23);
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(-14, 71);
+$s2->drawCurve(-2, 50, 18, 46);
+$s2->drawLine(35, 62);
+$s2->setRightFill();
+$s2->drawLine(16, 19);
+$s2->drawLine(17, 17);
+$s2->setLeftFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(-17, -17);
+$s2->drawLine(-16, -19);
+$s2->movePenTo(539, 310);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(-1, 49, -20, 44);
+$s2->drawCurve(-22, 44, -37, 32);
+$s2->drawCurve(-38, 32, -49, 12);
+$s2->drawCurve(-49, 12, -49, -10);
+$s2->drawCurve(-47, -9, -40, -29);
+$s2->drawCurve(-39, -29, -23, -43);
+$s2->drawCurve(-25, -43, -2, -51);
+$s2->drawCurve(-3, -50, 19, -46);
+$s2->drawCurve(29, -73, 72, -37);
+$s2->drawCurve(71, -37, 76, 15);
+$s2->drawCurve(76, 15, 51, 62);
+$s2->drawCurve(49, 61, 1, 78);
+$s2->drawLine(0, 1);
+$s2->movePenTo(103, 185);
+$s2->setLeftFill();
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc);
+$s2->drawLine(-12, 22);
+$s2->drawLine(-9, 23);
+$s2->movePenTo(640, 0);
+$s2->drawLine(0, 600);
+#$s2->setLine(20, 0x00, 0x00, 0x00);
+$s2->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s2->drawLine(-640, 0);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, -600);
+$s2->setLine(20, 0x99, 0x99, 0x99);
+$s2->drawLine(640, 0);
+$i1 = $boton_reload->add($s1);
+$i1->scaleTo(0.5);
+$boton_reload->nextFrame();  # end of frame 1
+$boton_reload->remove($i1);
+$i1 = $boton_reload->add($s2);
+$i1->scaleTo(0.5);
+$boton_reload->nextFrame();  # end of frame 2
+$boton_reload->remove($i1);
+
+
+$boton_security = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(493, 135);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->drawCurve(-34, -34, -44, -19);
+$s1->drawCurve(-45, -21, -50, -1);
+$s1->drawCurve(-49, -1, -46, 19);
+$s1->drawCurve(-45, 18, -35, 34);
+$s1->drawCurve(-35, 33, -20, 44);
+$s1->drawCurve(-21, 45, -2, 49);
+$s1->drawCurve(-2, 50, 18, 46);
+$s1->drawCurve(17, 44, 34, 36);
+$s1->drawCurve(33, 35, 43, 21);
+$s1->drawCurve(45, 22, 49, 3);
+$s1->drawCurve(49, 3, 47, -17);
+$s1->drawCurve(45, -17, 36, -32);
+$s1->drawCurve(36, -33, 22, -43);
+$s1->drawCurve(22, -45, 4, -48);
+$s1->drawLine(0, -16);
+$s1->drawLine(0, -1);
+$s1->drawCurve(-1, -50, -19, -45);
+$s1->drawCurve(-19, -45, -33, -34);
+$s1->movePenTo(536, 310);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(-1, 48, -20, 45);
+$s1->drawCurve(-21, 43, -38, 33);
+$s1->drawCurve(-37, 31, -49, 13);
+$s1->drawCurve(-49, 11, -49, -9);
+$s1->drawCurve(-47, -10, -39, -29);
+$s1->drawCurve(-39, -29, -24, -42);
+$s1->drawCurve(-24, -43, -2, -51);
+$s1->drawCurve(-3, -50, 19, -46);
+$s1->drawCurve(28, -72, 72, -37);
+$s1->drawCurve(71, -37, 76, 15);
+$s1->drawCurve(76, 15, 50, 61);
+$s1->drawCurve(49, 61, 1, 78);
+$s1->drawLine(0, 1);
+$s1->movePenTo(446, 290);
+$s1->setLeftFill(0xff, 0xa8, 0x37);
+$s1->setRightFill(0x79, 0x79, 0x79);
+$s1->drawLine(0, 129);
+$s1->drawCurve(0, 17, -17, 13);
+$s1->drawCurve(-17, 13, -23, 0);
+$s1->drawLine(-143, 0);
+$s1->drawCurve(-23, 0, -17, -13);
+$s1->drawCurve(-16, -13, 0, -17);
+$s1->drawLine(0, -129);
+$s1->drawCurve(-1, -15, 12, -11);
+$s1->drawLine(1, -8);
+$s1->drawCurve(7, -50, 32, -35);
+$s1->drawCurve(35, -40, 49, 5);
+$s1->drawCurve(49, 5, 31, 42);
+$s1->drawCurve(25, 35, 4, 46);
+$s1->drawCurve(12, 11, 0, 15);
+$s1->movePenTo(382, 200);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(15, 22, 6, 26);
+$s1->drawLine(-14, -1);
+$s1->drawLine(-143, 0);
+$s1->drawLine(-14, 1);
+$s1->drawCurve(5, -26, 16, -21);
+$s1->drawCurve(25, -35, 40, -1);
+$s1->drawCurve(39, -1, 25, 36);
+$s1->movePenTo(323, 345);
+$s1->drawLine(14, 75);
+$s1->drawLine(-40, 0);
+$s1->drawLine(14, -75);
+$s1->drawCurve(-8, -2, -6, -6);
+$s1->drawCurve(-8, -8, 0, -12);
+$s1->drawCurve(0, -13, 8, -8);
+$s1->drawCurve(9, -9, 12, 1);
+$s1->drawCurve(12, -1, 8, 9);
+$s1->drawCurve(9, 8, 0, 13);
+$s1->drawCurve(0, 12, -9, 8);
+$s1->drawLine(-15, 8);
+$s1->movePenTo(640, 600);
+$s1->setLeftFill();
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+#$s1->setLine(20, 0x00, 0x00, 0x00);
+$s1->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s1->drawLine(-640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, -600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, 600);
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(495, 136);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawCurve(-34, -35, -44, -19);
+$s2->drawCurve(-46, -21, -49, -1);
+$s2->drawCurve(-50, -1, -46, 19);
+$s2->drawCurve(-45, 18, -35, 34);
+$s2->drawCurve(-35, 33, -20, 45);
+$s2->drawCurve(-21, 45, -2, 49);
+$s2->drawCurve(-2, 50, 18, 47);
+$s2->drawCurve(17, 44, 34, 36);
+$s2->drawCurve(33, 35, 44, 21);
+$s2->drawCurve(44, 22, 50, 3);
+$s2->drawCurve(49, 3, 47, -17);
+$s2->drawCurve(45, -17, 36, -33);
+$s2->drawCurve(36, -33, 22, -43);
+$s2->drawCurve(22, -44, 4, -49);
+$s2->drawLine(1, -16);
+$s2->drawLine(0, -1);
+$s2->drawCurve(-1, -50, -19, -45);
+$s2->drawCurve(-19, -45, -34, -34);
+$s2->movePenTo(539, 311);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(-1, 49, -21, 44);
+$s2->drawCurve(-21, 44, -38, 32);
+$s2->drawCurve(-37, 32, -50, 12);
+$s2->drawLine(-97, 3);
+$s2->drawCurve(-48, -10, -39, -29);
+$s2->drawCurve(-39, -29, -24, -43);
+$s2->drawCurve(-24, -43, -2, -51);
+$s2->drawCurve(-3, -50, 19, -47);
+$s2->drawCurve(29, -72, 72, -37);
+$s2->drawCurve(70, -38, 77, 16);
+$s2->drawCurve(76, 15, 50, 62);
+$s2->drawCurve(50, 61, 1, 78);
+$s2->drawLine(0, 1);
+$s2->movePenTo(448, 291);
+$s2->setLeftFill(0x79, 0x79, 0x79);
+$s2->setRightFill(0xff, 0xa8, 0x37);
+$s2->drawLine(0, 129);
+$s2->drawCurve(0, 18, -17, 13);
+$s2->drawCurve(-17, 12, -23, 1);
+$s2->drawLine(-144, 0);
+$s2->drawCurve(-23, -1, -17, -12);
+$s2->drawCurve(-17, -13, 1, -18);
+$s2->drawLine(0, -129);
+$s2->drawCurve(-1, -15, 12, -12);
+$s2->drawLine(1, -8);
+$s2->drawCurve(7, -50, 32, -35);
+$s2->drawCurve(36, -40, 49, 6);
+$s2->drawCurve(49, 4, 31, 42);
+$s2->drawCurve(25, 35, 4, 46);
+$s2->drawCurve(12, 12, 0, 15);
+$s2->movePenTo(319, 165);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(39, -1, 26, 37);
+$s2->drawCurve(15, 21, 5, 26);
+$s2->drawLine(-13, -1);
+$s2->drawLine(-144, 0);
+$s2->drawLine(-13, 1);
+$s2->drawCurve(4, -26, 16, -21);
+$s2->drawCurve(26, -35, 39, -1);
+$s2->movePenTo(324, 346);
+$s2->drawLine(15, 76);
+$s2->drawLine(-41, 0);
+$s2->drawLine(14, -76);
+$s2->drawCurve(-8, -2, -5, -6);
+$s2->drawCurve(-9, -9, 0, -12);
+$s2->drawCurve(0, -12, 9, -8);
+$s2->drawCurve(8, -9, 12, 0);
+$s2->drawCurve(12, 0, 9, 9);
+$s2->drawLine(9, 20);
+$s2->drawCurve(-1, 12, -8, 9);
+$s2->drawLine(-16, 8);
+$s2->movePenTo(640, 0);
+$s2->setLeftFill();
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, 600);
+#$s2->setLine(20, 0x00, 0x00, 0x00);
+$s2->setLine(20, 0x99, 0x99, 0x99); # raya inferior
+$s2->drawLine(-640, 0);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, -600);
+$s2->setLine(20, 0x99, 0x99, 0x99);
+$s2->drawLine(640, 0);
+
+$i1 = $boton_security->add($s1);
+$i1->scaleTo(0.5);
+$boton_security->add(new SWF::Action("stop();"));
+$boton_security->nextFrame();  # end of frame 1
+$boton_security->remove($i1);
+$i1 = $boton_security->add($s2);
+$i1->scaleTo(0.5);
+$boton_security->add(new SWF::Action("stop();"));
+$boton_security->nextFrame();  # end of frame 1
+$boton_security->remove($i1);
+
+$boton_security_unlock = new SWF::Sprite();
+### Shape 1 ###
+$s1 = new SWF::Shape();
+$s1->movePenTo(493, 135);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->drawCurve(-34, -34, -44, -19);
+$s1->drawCurve(-45, -21, -50, -1);
+$s1->drawCurve(-49, -1, -46, 19);
+$s1->drawCurve(-45, 18, -35, 34);
+$s1->drawCurve(-35, 33, -20, 44);
+$s1->drawCurve(-21, 45, -2, 49);
+$s1->drawCurve(-2, 50, 18, 46);
+$s1->drawCurve(17, 44, 34, 36);
+$s1->drawCurve(33, 35, 43, 21);
+$s1->drawCurve(45, 22, 49, 3);
+$s1->drawCurve(49, 3, 47, -17);
+$s1->drawCurve(45, -17, 36, -32);
+$s1->drawCurve(36, -33, 22, -43);
+$s1->drawCurve(22, -45, 4, -48);
+$s1->drawLine(0, -16);
+$s1->drawLine(0, -1);
+$s1->drawCurve(-1, -50, -19, -45);
+$s1->drawCurve(-19, -45, -33, -34);
+$s1->movePenTo(536, 310);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(-1, 48, -20, 45);
+$s1->drawCurve(-21, 43, -38, 33);
+$s1->drawCurve(-37, 31, -49, 13);
+$s1->drawCurve(-49, 11, -49, -9);
+$s1->drawCurve(-47, -10, -39, -29);
+$s1->drawCurve(-39, -29, -24, -42);
+$s1->drawCurve(-24, -43, -2, -51);
+$s1->drawCurve(-3, -50, 19, -46);
+$s1->drawCurve(28, -72, 72, -37);
+$s1->drawCurve(71, -37, 76, 15);
+$s1->drawCurve(76, 15, 50, 61);
+$s1->drawCurve(49, 61, 1, 78);
+$s1->drawLine(0, 1);
+$s1->movePenTo(446, 290);
+$s1->setLeftFill(0xff, 0xa8, 0x37);
+$s1->setRightFill(0x79, 0x79, 0x79);
+$s1->drawLine(0, 129);
+$s1->drawCurve(0, 17, -17, 13);
+$s1->drawCurve(-17, 13, -23, 0);
+$s1->drawLine(-143, 0);
+$s1->drawCurve(-23, 0, -17, -13);
+$s1->drawCurve(-16, -13, 0, -17);
+$s1->drawLine(0, -129);
+$s1->drawCurve(-1, -15, 12, -11);
+$s1->drawLine(1, -8);
+$s1->drawCurve(7, -50, 32, -35);
+$s1->drawCurve(35, -40, 49, 5);
+$s1->drawCurve(49, 5, 31, 42);
+$s1->drawCurve(25, 35, 4, 46);
+$s1->drawCurve(12, 11, 0, 15);
+$s1->movePenTo(382, 200);
+$s1->setLeftFill(0x79, 0x79, 0x79);
+$s1->setRightFill(0xff, 0xa8, 0x37);
+$s1->drawCurve(15, 22, 6, 26);
+$s1->drawLine(-14, -1);
+$s1->drawLine(-143, 0);
+$s1->drawLine(-14, 1);
+$s1->drawCurve(5, -26, 16, -21);
+$s1->drawCurve(25, -35, 40, -1);
+$s1->drawCurve(39, -1, 25, 36);
+$s1->movePenTo(323, 345);
+$s1->drawLine(14, 75);
+$s1->drawLine(-40, 0);
+$s1->drawLine(14, -75);
+$s1->drawCurve(-8, -2, -6, -6);
+$s1->drawCurve(-8, -8, 0, -12);
+$s1->drawCurve(0, -13, 8, -8);
+$s1->drawCurve(9, -9, 12, 1);
+$s1->drawCurve(12, -1, 8, 9);
+$s1->drawCurve(9, 8, 0, 13);
+$s1->drawCurve(0, 12, -9, 8);
+$s1->drawLine(-15, 8);
+$s1->movePenTo(640, 600);
+$s1->setLeftFill();
+$s1->setRightFill(0xcc, 0xcc, 0xcc);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(-640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, -600);
+$s1->setLine(20, 0x99, 0x99, 0x99);
+$s1->drawLine(640, 0);
+$s1->setLine(20, 0xcc, 0xcc, 0xcc);
+$s1->drawLine(0, 600);
+# Agregado
+$s1b = new SWF::Shape();
+$s1b->movePenTo(430,135);
+$s1b->setLine(0,0xFF,0xa8,0x37);
+$s1b->setRightFill(0xFF,0xa8,0x37,0xFF);
+$s1b->drawLine(0,110);
+$s1b->drawLine(-110,0);
+$s1b->drawLine(0,-110);
+$s1b->drawLine(110,0);
+
+
+### Shape 2 ###
+$s2 = new SWF::Shape();
+$s2->movePenTo(495, 136);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawCurve(-34, -35, -44, -19);
+$s2->drawCurve(-46, -21, -49, -1);
+$s2->drawCurve(-50, -1, -46, 19);
+$s2->drawCurve(-45, 18, -35, 34);
+$s2->drawCurve(-35, 33, -20, 45);
+$s2->drawCurve(-21, 45, -2, 49);
+$s2->drawCurve(-2, 50, 18, 47);
+$s2->drawCurve(17, 44, 34, 36);
+$s2->drawCurve(33, 35, 44, 21);
+$s2->drawCurve(44, 22, 50, 3);
+$s2->drawCurve(49, 3, 47, -17);
+$s2->drawCurve(45, -17, 36, -33);
+$s2->drawCurve(36, -33, 22, -43);
+$s2->drawCurve(22, -44, 4, -49);
+$s2->drawLine(1, -16);
+$s2->drawLine(0, -1);
+$s2->drawCurve(-1, -50, -19, -45);
+$s2->drawCurve(-19, -45, -34, -34);
+$s2->movePenTo(539, 311);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(-1, 49, -21, 44);
+$s2->drawCurve(-21, 44, -38, 32);
+$s2->drawCurve(-37, 32, -50, 12);
+$s2->drawLine(-97, 3);
+$s2->drawCurve(-48, -10, -39, -29);
+$s2->drawCurve(-39, -29, -24, -43);
+$s2->drawCurve(-24, -43, -2, -51);
+$s2->drawCurve(-3, -50, 19, -47);
+$s2->drawCurve(29, -72, 72, -37);
+$s2->drawCurve(70, -38, 77, 16);
+$s2->drawCurve(76, 15, 50, 62);
+$s2->drawCurve(50, 61, 1, 78);
+$s2->drawLine(0, 1);
+$s2->movePenTo(448, 291);
+$s2->setLeftFill(0x79, 0x79, 0x79);
+$s2->setRightFill(0xff, 0xa8, 0x37);
+$s2->drawLine(0, 129);
+$s2->drawCurve(0, 18, -17, 13);
+$s2->drawCurve(-17, 12, -23, 1);
+$s2->drawLine(-144, 0);
+$s2->drawCurve(-23, -1, -17, -12);
+$s2->drawCurve(-17, -13, 1, -18);
+$s2->drawLine(0, -129);
+$s2->drawCurve(-1, -15, 12, -12);
+$s2->drawLine(1, -8);
+$s2->drawCurve(7, -50, 32, -35);
+$s2->drawCurve(36, -40, 49, 6);
+$s2->drawCurve(49, 4, 31, 42);
+$s2->drawCurve(25, 35, 4, 46);
+$s2->drawCurve(12, 12, 0, 15);
+$s2->movePenTo(319, 165);
+$s2->setLeftFill(0xff, 0xa8, 0x37);
+$s2->setRightFill(0x79, 0x79, 0x79);
+$s2->drawCurve(39, -1, 26, 37);
+$s2->drawCurve(15, 21, 5, 26);
+$s2->drawLine(-13, -1);
+$s2->drawLine(-144, 0);
+$s2->drawLine(-13, 1);
+$s2->drawCurve(4, -26, 16, -21);
+$s2->drawCurve(26, -35, 39, -1);
+$s2->movePenTo(324, 346);
+$s2->drawLine(15, 76);
+$s2->drawLine(-41, 0);
+$s2->drawLine(14, -76);
+$s2->drawCurve(-8, -2, -5, -6);
+$s2->drawCurve(-9, -9, 0, -12);
+$s2->drawCurve(0, -12, 9, -8);
+$s2->drawCurve(8, -9, 12, 0);
+$s2->drawCurve(12, 0, 9, 9);
+$s2->drawLine(9, 20);
+$s2->drawCurve(-1, 12, -8, 9);
+$s2->drawLine(-16, 8);
+$s2->movePenTo(640, 0);
+$s2->setLeftFill();
+$s2->setRightFill(0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, 600);
+$s2->setLine(20, 0x99, 0x99, 0x99);
+$s2->drawLine(-640, 0);
+$s2->setLine(20, 0xcc, 0xcc, 0xcc);
+$s2->drawLine(0, -600);
+$s2->setLine(20, 0x99, 0x99, 0x99);
+$s2->drawLine(640, 0);
+# Agregado
+$s2b = new SWF::Shape();
+$s2b->movePenTo(430,135);
+$s2b->setLine(0,0x79,0x79,0x79);
+$s2b->setRightFill(0x79,0x79,0x79,0xFF);
+$s2b->drawLine(0,110);
+$s2b->drawLine(-110,0);
+$s2b->drawLine(0,-110);
+$s2b->drawLine(110,0);
+
+$i1 = $boton_security_unlock->add($s1);
+$i1->scaleTo(0.5);
+$i1 = $boton_security_unlock->add($s1b);
+$i1->scaleTo(0.5);
+$boton_security_unlock->add(new SWF::Action("stop();"));
+$boton_security_unlock->nextFrame();  # end of frame 1
+$boton_security_unlock->remove($i1);
+$i1 = $boton_security_unlock->add($s2);
+$i1->scaleTo(0.5);
+$i1 = $boton_security_unlock->add($s2b);
+$i1->scaleTo(0.5);
+$boton_security_unlock->add(new SWF::Action("stop();"));
+$boton_security_unlock->nextFrame();  # end of frame 1
+$boton_security_unlock->remove($i1);
+
+# Exports all Movieclips for Actionscript
+$movie->addExport($ledcolor,"ledcolor");
+$movie->addExport($ledsombra,"ledsombra");
+$movie->addExport($ledbrillo,"ledbrillo");
+$movie->addExport($fle,         "arrow");
+$movie->addExport($i_icon1,     "telefono1");
+$movie->addExport($i_icon2,     "telefono2");
+$movie->addExport($telefono3,   "telefono3");
+$movie->addExport($telefono4,   "telefono4");
+$movie->addExport($conference2, "telefono5");
+$movie->addExport($conference1, "telefono6");
+$movie->addExport($envelope,    "sobre");
+# $movie->addExport($statusbar,   "logtext");
+$movie->addExport($extrainfo,   "infotext");
+$movie->addExport($boton_ayuda, "boton_ayuda");
+$movie->addExport($boton_debug, "boton_debug");
+$movie->addExport($boton_reload,"boton_reload");
+$movie->addExport($boton_security,"boton_security");
+$movie->addExport($boton_security_unlock,"boton_security_unlock");
+$movie->addExport($option,"option");
+$movie->writeExports();
+
+
+# Adds ActionScript
+$movie->add(new SWF::Action(<<"EndOfActionScript"));
+
+
+function conecta() {
+	_global.sock = new XMLSocket;
+	_global.sock.onConnect = handleConnect;
+	_global.sock.onClose = handleDisconnect;
+	_global.sock.onXML = handleXML;
+    if(_global.port   == undefined) {
+        _global.port = 4445;
+    }
+    if(_global.server == undefined) {
+	    _global.sock.connect(null, _global.port);
+        _global.server_print = "default";
+    } else {
+	    _global.sock.connect(_global.server, _global.port);
+        _global.server_print = _global.server;
+    }
+}
+
+function logea(texto) {
+	if(buttondebug._visible != true) {
+		return;
+	}
+    var fecha = new Date();
+    var hora = fecha.getHours();
+    var minutos = fecha.getMinutes();
+    var segundos = fecha.getSeconds();
+    if (hora<10) {
+        hora = "0"+hora;
+    }
+    if (minutos<10) {
+        minutos = "0"+minutos;
+    }
+    if (segundos<10) {
+        segundos = "0"+segundos;
+    }
+    var textologea = hora+":"+minutos+":"+segundos+" "+texto;
+    _global.loglines.push(textologea);
+    if (_global.loglines.length>35) {
+        _global.loglines.shift();
+    }
+    _level0.log.Field1.text = "";
+	var acount=-1;
+	while (++acount <= _global.loglines.length) {
+//    for (var acount=0; acount<_global.loglines.length; acount++) {
+        _level0.log.Field1.text = _level0.log.Field1.text+_global.loglines[acount]+"\n";
+    }
+    log.logcontent.scroll = log.logcontent.maxscroll;
+};
+
+
+function handleConnect(connectionStatus){
+
+    if (connectionStatus) {
+        for (var a in _root) {
+            if (typeof (_root[a]) == "movieclip") {
+                if (a.substring(0, 10) == "rectangulo") {
+                    for (var b in _root[a]) {
+                        if (_root[a][b]._name.substring(0, 7) == "casicol") {
+							var numero=ExtraeNumeroClip(_root[a][b]);
+                            _root[a][b].changeledcolor(0,_global.colorlibre[numero],_global.color[1]); 
+                        }
+                    } 
+                }
+            }
+        }
+        logea("Connected to server "+server_print+" on port "+port);
+
+        _global.reconecta = 0;
+		if(_global.enable_crypto==1) {
+        	envia_comando("contexto", 0, 0);
+		} else {
+        	envia_comando("contexto", 1, 0);
+		}
+		if(restrict != undefined) {
+			envia_comando("restrict",restrict,0);
+		}
+    } else {
+        logea("Error while connecting to "+server+" on port "+port);
+        for (var a in _root) {
+            if (typeof (_root[a]) == "movieclip") {
+                if (a.substring(0, 10) == "rectangulo") {
+                    for (var b in _root[a]) {
+                        if (_root[a][b]._name.substring(0, 7) == "casicol") {
+							var numero=ExtraeNumeroClip(_root[a][b]);
+                            _root[a][b].changeledcolor(3,_global.colorlibre[numero],_global.color[1]);
+                        }
+                    }
+                }
+            }
+        }
+        _global.reconecta = 1;
+    }
+}
+
+function handleXML(doc){
+ 	var e = doc.firstChild;
+	if (e != null) {
+		if (e.nodeName == "response") {
+		    var numeroboton = e.attributes.btn; // btn is the button number
+			var comando     = e.attributes.cmd;
+			var textofinal  = e.attributes.data;
+
+			if (_global.key != undefined) {
+				if(_global.enable_crypto == 1) {
+					comando    = decrypt(comando,    _global.key);
+					if (textofinal.length > 0) {
+						textofinal = decrypt(textofinal, _global.key);
+					} 
+				} 
+			} 
+
+			logea(numeroboton+"|"+comando+"|"+textofinal.substring(0,20));
+
+			var botonparte = numeroboton.split("@");
+			var boton_numero = botonparte[0];
+			var boton_contexto = botonparte[1];
+			var timernumber = 0;
+			if (boton_contexto == undefined) {
+				boton_contexto = "";
+			}
+			if (_root.context == undefined) {
+				_root.context = "";
+			}
+			if (comando == "key") {
+				_global.key = textofinal;
+				return;
+			}
+			if (comando == "incorrect") {
+				_global.authorized = false;
+				_root.codebox._visible = true;
+				Selection.setFocus(_root.codebox.claveform);
+				_root.codebox.swapDepths(_root.log);
+				SecurityCode_Unlocked();
+				return;
+			}
+			if (comando == "correct") {
+				_global.authorized = true;
+				SecurityCode_Locked();
+				return;
+			}
+
+			if (comando == "showdetails") {
+				var myclip = eval('_level0.rectangulo'+boton_numero+'.flecha'+boton_numero);
+				_root.displaydetails(myclip);
+			}
+
+			if (comando == "restrict") {
+				_global.restrict = numeroboton;
+                _global.mybutton = numeroboton;
+				logea("Set restriction for button "+_global.restrict);
+				var myresa = eval('_root.resaltado'+_global.restrict);
+				myresa._visible = true;
+				return;
+			}
+			if (comando == "version") {
+				logea("Version "+textofinal);
+				logea("Top "+_root._y);
+				logea("Left "+_root._x);
+				if(textofinal != _global.swfversion) 
+				{
+					_global.statusline=vr.version_mismatch;
+				} else {
+					_global.statusline="";
+				}
+			}
+
+			if (_root.context == boton_contexto) {
+				var botonazo = eval("rectangulo"+boton_numero+".casicol"+boton_numero);
+				var statusclid = eval("rectangulo"+boton_numero+".statusprint"+boton_numero);
+				var timerprint = eval("rectangulo"+boton_numero+".timer"+boton_numero);
+				var flechita = eval("rectangulo"+boton_numero+".flecha"+boton_numero);
+				var telefonito = eval("rectangulo"+boton_numero+".tele"+boton_numero);
+				var sobrecito = eval("rectangulo"+boton_numero+".sobrecito"+boton_numero);
+				if (_global.rectanguloprendido!=0) {
+					makeStatus(_global.rectanguloprendido);
+				}
+
+				if (comando == "setalpha") {
+					var myboton = eval('_root.rectangulo'+boton_numero);
+				    myboton._alpha = textofinal;
+				}
+
+				if (comando == "flip") {
+					var myboton = eval('_root.rectangulo'+boton_numero);
+				    myboton.flip(textofinal);
+				}
+
+				if (comando == "monitor") {
+					createCircle(_root["rectangulo"+boton_numero]["circle"+boton_numero],11,0,0,'0xff0000');
+				}
+				if (comando == "stopmonitor") {
+					createCircle(_root["rectangulo"+boton_numero]["circle"+boton_numero],11,0,0,'0x00ff00');
+				}
+
+				if (comando == "settext") {
+					setclid(statusclid,textofinal);
+				}
+
+				if (comando == "setstatus") {
+					_global.texto_tip[boton_numero] = textofinal;
+				}
+
+				if (comando == "setlabel") {
+					var botref   = eval("rectangulo"+boton_numero+".textoprint");
+					var botshref = eval("rectangulo"+boton_numero+".textosh");
+					botref.text   = textofinal;
+					botshref.text = textofinal;
+				}
+
+				if (comando == "fopledcolor") {
+					if(textofinal!="")
+					{
+						var partes = textofinal.split("^");
+						var fcolor = partes[0];
+						var fstate = Number(partes[1]);
+
+						if(fcolor == "ledcolor_paused") {
+							fcolor = ledcolor_paused;
+						}
+						if(fcolor == "ledcolor_agent") {
+							fcolor = ledcolor_agent;
+						}
+						_root.logea("color "+fcolor);
+						_global.color[fstate]=fcolor;
+						if(fstate!=1) {
+							_global.colorlibre[boton_numero]=fcolor;
+						} 
+						_global.color[fstate] = fcolor;
+						logea(" color "+fstate+"="+_global.color[fstate]);
+						botonazo.changeledcolor(1,_global.colorlibre[boton_numero],_global.color[1]);
+					}
+				}
+				if (comando == "foppopup") {
+					if(textofinal!="")
+					{
+						var partes = textofinal.split("^");
+						var url    = partes[0];
+						var target = partes[1];
+						var posi   = partes[2];
+
+						if(posi == "" || posi == mybutton) {
+							partes = url.split("?");
+							url        = partes[0];
+							parametros = partes[1];
+
+							logea("url "+url);
+							logea("parametros "+parametros);
+							logea("target "+target);
+							logea("posi "+posi);
+
+							var cadauno = parametros.split("&");
+
+
+							if (url != "") {
+								if (target == undefined || target == "") {
+									target = "_self";
+								}
+								var c = new LoadVars();
+	
+								for (var aget in cadauno) {
+									partes = cadauno[aget].split("=");
+									c[partes[0]]=partes[1];
+									logea("c."+partes[0]);
+									logea("es igual a "+partes[1]);
+								}
+								c.send(url, target, 'GET');
+								logea("Abro "+url+" en target "+target);
+							}
+						}
+					}
+				}
+
+				if (comando == "state") {
+
+					if(textofinal == "ringing") {
+						botonazo.changeledcolor(3,_global.colorlibre[boton_numero],_global.color[1]);
+						if (enable_animation == 1) {
+							telefonito.shake(_global.shakepixels);
+						}
+					}
+
+					if(textofinal == "free") {
+						createCircle(_root["rectangulo"+boton_numero]["circle"+boton_numero],11,0,0,'0x00ff00');
+						botonazo.changeledcolor(0,_global.colorlibre[boton_numero],_global.color[1]);
+						if (enable_animation == 1) {
+							telefonito.shake();
+							telefonito.gotoAndStop(1);
+						}
+					}
+				
+					if(textofinal == "busy") {
+						_root["rectangulo"+boton_numero]._alpha = 100;
+	                    _root["resaltado"+boton_numero]._alpha = 100;
+						botonazo.changeledcolor(1,_global.colorlibre[boton_numero],_global.color[1]);
+						if (enable_animation == 1) {
+							telefonito.shake();
+							telefonito.gotoAndStop(2);
+						}
+						flechita._visible = true;
+					}
+				}
+
+				if (comando == "meetmemute") {
+					_root["rectangulo"+boton_numero]._alpha = 40;
+					logea("muted "+boton_numero);
+					_global.meetmemute[boton_numero]=0;
+				}
+				
+				if (comando == "meetmeunmute") {
+					_root["rectangulo"+boton_numero]._alpha = 100;
+					logea("Unmuted "+boton_numero);
+					_global.meetmemute[boton_numero] = 1;
+				}
+
+				if (comando.substring(0,11) == "changelabel") {
+					var changeled = comando.substring(11,12);
+					var botref   = eval("rectangulo"+boton_numero+".textoprint");
+					var botshref = eval("rectangulo"+boton_numero+".textosh");
+					var cual = eval("rectangulo"+boton_numero);
+					var casillero = eval("rectangulo"+boton_numero+".casilla"+boton_numero);
+					if(textofinal == "original") {
+						labeltexto=_global.labels[boton_numero];
+					    _global.colorlibre[boton_numero] = _global.color[0];
+					} else if (textofinal == "labeloriginal") {
+						labeltexto=_global.labels[boton_numero];
+					} else if (textofinal == ".") {
+						labeltexto=botref.text;
+						if(changeled == 1) {
+					    	_global.colorlibre[boton_numero] = _global.color[2];
+						}
+					} else {
+						labeltexto=textofinal;
+						if(changeled == 1) {
+					    	_global.colorlibre[boton_numero] = _global.color[2];
+						}
+					}
+					if(changeled == 1) {
+						if(_global.valorchangeledcolor[boton_numero] == "0") {
+							botonazo.changeledcolor(0,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+						} else {
+							 logea("esta ocupado "+boton_numero+" no cambio led '"+_global.valorchangeledcolor[boton_numero]+"'");
+						}
+						
+					}
+					botref.text   = labeltexto;
+					botshref.text = labeltexto;
+					var width = botref.textWidth; 
+					//botref._width = width+20;
+					//botshref._width = width+20;
+					return;
+				}
+
+				if (comando == "voicemailcount") {
+					_global.texto_mail[boton_numero] = textofinal;
+					return;
+				}
+				if (comando.substr(0, 4) == "info") {
+					var texto = base64_decode(textofinal);
+					var queue = comando.substr(4);
+					if(queue != "" ) {
+						if(_global.queuemember[boton_numero]==undefined) {
+							_global.queuemember[boton_numero]="";
+						}
+						if(queue=="qstat") {
+							queuemember[boton_numero] = new Object();
+					    	queuemember[boton_numero]["qstat"]=texto;
+						} else if (queue=="qstat2") {
+							var lugar = queuemember[boton_numero]["qstat"].indexOf("Agents Logged");
+							var str1= queuemember[boton_numero]["qstat"].slice(0,lugar);
+							str1 = str1+texto;
+					    	queuemember[boton_numero]["qstat"]=str1;
+						} else {
+							var lineas = texto.split("\n");
+							for (val in lineas) {
+								campos = lineas[val].split("=");
+								if(Trim(campos[0])=="CallsTaken") {
+									var id1 = eval("queuemember."+boton_numero);
+									if(typeof(id1)!='object') {
+									   queuemember[boton_numero] = new Object();
+									}
+					    			queuemember[boton_numero][queue] =  vr.tab_queue_text + ": "+queue+"\n"+vr.calls_taken_text+": "+campos[1]+"\n\n";
+								}
+							}
+						}
+					} else {
+						_global.st_direction[boton_numero] = texto;
+					}
+					if(flechita._visible == false) {
+						flechita._visible = true;
+						flechita.gotoAndStop(3);
+					}
+					return;
+				}
+				if (comando == "meetmeuser") {
+					partes = textofinal.split(",");
+					_global.meetmemember[boton_numero] = partes[0];
+					_global.meetmeroom[boton_numero] = partes[1];
+					_global.meetmemute[boton_numero] = 1;
+					return;
+				}
+				if (comando == "desocupado" || comando == "corto") {
+					createCircle(_root["rectangulo"+boton_numero]["circle"+boton_numero],11,0,0,'0x00ff00');
+					_global.meetmemember[boton_numero] = 0;
+					_global.meetmeroom[boton_numero] = 0;
+					botonazo.changeledcolor(0,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+					if (enable_animation == 1) {
+						telefonito.shake();
+						telefonito.gotoAndStop(1);
+					}
+
+					_global.st_duration[boton_numero] = eval("rectangulo"+boton_numero+".timer"+boton_numero+".text");
+					_global.texto_tip[boton_numero] = "";
+					timerprint.text = "";
+
+					logea(boton_numero+" pongo timer_type stop y valor 0");
+					timer_type[boton_numero] = "STOP";
+					inicio_timer[boton_numero] = 0;
+
+					if (_global.ipboton[boton_numero] != undefined) {
+						setclid(statusclid,_global.ipboton[boton_numero]);
+					} else {
+						statusclid.text = "";  
+					}
+
+					flechita.gotoAndStop(3);
+					linkeado[boton_numero]="";	
+
+					return;
+				}
+				if (comando == "timeout") {
+					var timeout = Number(textofinal);
+					inicio_timer[boton_numero] = Math.floor(getTimer());
+					mytimeout = Math.floor(timeout)*1000;
+					inicio_timer[boton_numero] += mytimeout;
+					timer_type[boton_numero] = "DOWN";
+					logea("TIMEOUT "+timer_type[boton_numero]);
+				}
+				if (comando == "linked") {
+					if (textofinal.indexof("@") == -1) {
+						sdo_boton = textofinal;
+					} else {
+						var boton2parte = textofinal.split("@");
+						sdo_boton = boton2parte[0];
+					}
+					linkeado[boton_numero]=sdo_boton;	
+					return;
+				}
+				if (comando == "clidnum") {
+					var clidnum = base64_decode(textofinal);
+					_global.clidnumber[boton_numero]=clidnum;
+				}
+				if (comando == "clidname") {
+					//var clidname = base64_decode(textofinal);
+					_global.clidname[boton_numero]=textofinal;
+					var clidname = base64_decode(textofinal);
+				}
+	
+				if (comando == "ringing") {
+//					if (timer_type[boton_numero]!="UP") {
+						inicio_timer[boton_numero]=getTimer();
+						botonazo.changeledcolor(3,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+						if (enable_animation == 1) {
+							telefonito.shake(_global.shakepixels);
+						}
+						_global.texto_tip[boton_numero] = textofinal;
+
+						var clnumber = extract_text_inside_delimiters(textofinal,"[","]");
+						if(clnumber != "") {
+							setclid(statusclid,clnumber);
+							_global.st_originclid[boton_numero] = clnumber;
+							_global.st_destinationclid[boton_numero] = undefined;
+						}
+						flechita._visible = true;
+						flechita.gotoAndStop(1);
+
+						// CRM, redirige a url 
+						if (boton_numero == mybutton) {
+							if (url != "") {
+								if (target == "") {
+									target = "_self";
+								}
+								var c = new LoadVars();
+								//c.clid = clidnumber;
+								c.clid      = _global.clidnumber[boton_numero];
+								c.clidname  = _global.clidname[boton_numero];
+								c.send(url, target, 'GET');
+								logea("Open url "+url+" in target "+target+" with clid "+clidnumber);
+							}
+						} else {
+						//		logea("No popup mybutton "+mybutton+" <> boton_numero "+boton_numero);
+						}
+						return;
+//					}
+					return;
+				}
+				if (comando == "voicemail") {
+					if (textofinal == "1") {
+						sobrecito._visible = true;
+						sobrecito._alpha = 100;
+//						sobrecito.glow(1);
+					} else {
+						sobrecito._visible = true;
+						sobrecito._alpha = 50;
+//						sobrecito.glow(0);
+					}
+					return;
+				}
+
+				if (comando == "park") {
+					var mytext = extract_text_inside_delimiters(textofinal,"[","]");
+					setclid(statusclid,mytext);
+					var mytimeout = extract_text_inside_delimiters(textofinal,"(",")");
+					inicio_timer[boton_numero] = Math.floor(getTimer());
+					mytimeout = Math.floor(mytimeout)*1000;
+					inicio_timer[boton_numero] += mytimeout;
+					timer_type[boton_numero] = "DOWN";
+					_global.st_destinationclid[boton_numero] = mytext;
+					_global.st_originclid[boton_numero] = undefined;
+					botonazo.changeledcolor(3,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+					return;
+				}
+
+				if (comando == "ip") {
+					_global.ipboton[boton_numero]=textofinal;
+					if(statusclid.text == "") {
+						setclid(statusclid,textofinal);
+					}
+				};
+
+				if (comando == "state") {
+					if(textofinal == "busy") {
+						botonazo.changeledcolor(1,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+						return;
+					}
+				}
+
+				if (comando.substr(0, 7) == "ocupado") {
+					var flecha_frame = comando.substr(7, 1);
+					if (flecha_frame == 3) {				// Parked channel
+						var mytext = extract_text_inside_delimiters(textofinal,"[","]");
+						setclid(statusclid,mytext);
+						_global.st_destinationclid[boton_numero] = mytext;
+						_global.st_originclid[boton_numero] = undefined;
+						botonazo.changeledcolor(3,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+						return;
+					}
+
+					flecha_frame = Number(flecha_frame);
+					_root["rectangulo"+boton_numero]._alpha = 100;
+                    _root["resaltado"+boton_numero]._alpha = 100;
+					botonazo.changeledcolor(1,_global.colorlibre[boton_numero],_global.color[1],boton_numero);
+					if (enable_animation == 1) {
+						telefonito.shake();
+						telefonito.gotoAndStop(2);
+					}
+					flechita._visible = true;
+					if (flechita._currentframe>=1) {
+						if (textofinal != undefined) {
+							
+							var myclid  = extract_text_inside_delimiters(textofinal,"[","]");
+							if(myclid != "") {
+								setclid(statusclid,myclid);
+								_global.st_destinationclid[boton_numero] = myclid;
+								_global.st_originclid[boton_numero] = undefined;
+							}
+
+							//var timernumber = extract_text_inside_delimiters(textofinal,"(",")");
+							//if (isNaN(timernumber)) { timernumber = "0"; }
+                            //timernumber = Number(timernumber);  
+					
+						}
+					}
+					if (flecha_frame>0) {
+						flechita.gotoAndStop(flecha_frame);
+						_global.st_direction[boton_numero] = flecha_frame;
+					}
+
+					if (statusclid.text.substring(0, 6) == "Parked") {
+						setclid(statusclid,"");
+					}
+					if (textofinal != "") {
+						_global.texto_tip[boton_numero] = textofinal;
+					}
+					
+					return;
+				}
+
+				if (comando == "settimer") {
+					var timerpartes = textofinal.split("@");
+					var segundos = Number(timerpartes[0]);
+					if (isNaN(segundos)) {
+						segundos=0;
+					}
+					var type     = timerpartes[1];
+					if(type == undefined) {
+						type="UP";
+					}
+
+					if(timer_type[boton_numero] != type)
+					{
+					logea(boton_numero+" cambio de tipo vino "+type+" y era "+timer_type[boton_numero]);
+						if(type=="DOWN")
+						{
+							inicio_timer[boton_numero] = getTimer()+(segundos*1000);
+						} else if (type == "UP") {
+							inicio_timer[boton_numero] = getTimer()-(segundos*1000);
+						} else if (type == "IDLE") {
+							inicio_timer[boton_numero] = getTimer()-(segundos*1000);
+						} else if (type == "STOP") {
+							inicio_timer[boton_numero] = 0;
+							logea("tipo stop, pongo inicio_timer en cero");
+						} 
+					} else {
+						logea(boton_numero+" timer tipo no cambio era igual "+type);
+					}
+					timer_type[boton_numero]=type;
+				}
+	
+				if (comando == "noregistrado") {
+					_root["rectangulo"+boton_numero]._alpha = dimm_noregister;
+					_root["resaltado"+boton_numero]._alpha = dimm_noregister;
+					_global.texto_tip[boton_numero] = "";
+					return;
+				}
+
+				if (comando == "unreachable") {
+					_root["rectangulo"+boton_numero]._alpha = dimm_lagged;
+					_root["resaltado"+boton_numero]._alpha = dimm_lagged;
+					_global.texto_tip[boton_numero] = "";
+					return;
+				}
+
+				if (comando == "registrado") {
+					_root["rectangulo"+boton_numero]._alpha = 100;
+					_root["resaltado"+boton_numero]._alpha = 100;
+					return;
+				}
+			}
+			// endif root.context
+		}
+		// endif == response
+	}
+	// endiff e != null
+}
+
+function setclid(statusclid,textofinal) {
+	statusclid.text = textofinal;
+	if(_global.clid_centered == 1) {
+		clidExtent = fmtClid.getTextExtent ( textofinal );
+		cordx = (_global.ancho_a_centrar - clidExtent.textFieldWidth) / 2;
+		if(cordx<0) { cordx = 0; }
+		statusclid._x = cordx;
+	}
+}
+
+function extract_text_inside_delimiters(inputText,start_char,end_char) {
+	var outputText="";
+	var start_delimiter = inputText.lastIndexOf(start_char);
+	start_delimiter++;
+	if (start_delimiter>0) {
+    	var end_delimiter = inputText.indexOf(end_char, start_delimiter);
+        outputText = inputText.substring(start_delimiter, end_delimiter);
+        outputText = only_allowed_chars(outputText);
+        outputText = Trim(outputText);
+	}
+	return outputText;
+};
+
+function handleDisconnect(){
+        logea("Lost connection to "+server+" on port "+port);
+        delete _global.key;
+        for (var b in timer_type) {
+                timer_type[b] = "STOP";
+                inicio_timer[b] = 0;
+        }
+        for (var a in _root) {
+                if (typeof (_root[a]) == "movieclip") {
+                        if (a.substring(0, 10) == "rectangulo") {
+                                for (b in _root[a]) {
+                                    if (_root[a][b]._name.substring(0, 7) == "casicol") {
+										var numero = _root[a][b]._name.substring(7,1);
+                            			_root[a][b].changeledcolor(3,_global.color[0],_global.color[1],numero);
+									}
+                                }
+                        }
+                }
+                _root.log.gotoAndPlay(1);
+        }
+        _global.reconecta = 1;
+}
+
+
+function createCircle(tMC, r, x, y, color) {
+
+	// constant used in calculation
+	var A = Math.tan(22.5 * Math.PI/180);
+	// variables for each of 8 segments
+	var endx;
+	var endy;
+	var cx;
+	var cy;
+
+	color_normalizado = parseInt(color,16);
+	with (tMC) {
+        lineStyle(1,color_normalizado,100);
+		beginFill(color_normalizado, 100);
+		moveTo(x+r, y);
+		for (var angle = 45; angle<=360; angle += 45) {
+		   // endpoint
+		   endx = r*Math.cos(angle*Math.PI/180);
+		   endy = r*Math.sin(angle*Math.PI/180);
+	 	  // control:
+		   // (angle-90 is used to give the correct sign)
+		   cx =endx + r* A *Math.cos((angle-90)*Math.PI/180);
+		   cy =endy + r* A *Math.sin((angle-90)*Math.PI/180);
+		   curveTo(cx+x, cy+y, endx+x, endy+y);
+		}
+		endFill();
+	}
+}
+
+function createSquare(tMC, tW, tH, lW, lC, fC, f2C, cRad) {
+	tW -= lW;
+	tH -= lW;
+	with (tMC) {
+		var zerox = 0;
+		var zeroy = (tH/2)*-1;
+		lineStyle(lW, parseInt(lC, 16), 50);
+		moveTo(cRad+lW+zerox, zeroy);
+		colors = [parseInt(fC, 16), parseInt(f2C, 16)];
+		alphas = [100, 100];
+		ratios = [0, 0xFF];
+		matrix = {a:200, b:0, c:0, d:0, e:200, f:0, g:200, h:200, i:1};
+		matrix = {matrixType:"box", x:1, y:1, w:tW, h:tH, r:(45/180)*Math.PI};
+		if(fC != "transparent") {
+		beginGradientFill("linear", colors, alphas, ratios, matrix);
+		}
+		// 
+		lineTo(cRad+lW+zerox, zeroy);
+		curveTo(lW+zerox, zeroy, lW+zerox, cRad+zeroy);
+		lineTo(lW+zerox, tH-cRad+zeroy);
+		curveTo(lW+zerox, tH+zeroy, cRad+lW+zerox, tH+zeroy);
+		lineTo(tW-cRad+zerox, tH+zeroy);
+		// 
+		curveTo(tW+zerox, tH+zeroy, tW+zerox, tH-cRad+zeroy);
+		lineTo(tW+zerox, cRad+zeroy);
+		curveTo(tW+zerox, zeroy, tW-cRad+zerox, zeroy);
+		lineTo(cRad+lW+zerox, zeroy);
+		endFill();
+	}
+};
+
+
+dibuja = function () {
+
+    _root.preload._visible=false;
+	contador = 1;
+	depth = -10000;
+	cantidad_botones = 1;
+
+	// Draw rectangles bellow buttons
+	var a=-1;
+	while (++a <= vr.total_rectangles) {
+//	for (a=1; a<=vr.total_rectangles; a++) {
+		v = eval("vr.rect_"+a);
+		if (v != undefined) {
+			var datos = v.split(",");
+			var rect_x = Number(datos[0]);
+			var rect_y = Number(datos[1]);
+			var rect_width =  Number(datos[2]);
+			var rect_height = Number(datos[3]);
+			var line_width = Number(datos[4]);
+			var line_color = datos[5];
+			var fade_color1 = datos[6];
+			var fade_color2 = datos[7];
+			var rnd_border = Number(datos[8]);
+			var alpha = Number(datos[9]);
+			offsetboton = (rect_height/2);
+			if(datos[10]=="bottom") {
+				rect_y += offsetboton;
+				cusl = createEmptyMovieClip("dibujo"+a, depth);
+				createSquare(cusl, rect_width, rect_height, line_width, line_color, fade_color1, fade_color2, rnd_border);
+				cusl._x = rect_x;
+				cusl._y = rect_y;
+				cusl._visible = true;
+				cusl._alpha = alpha;
+				cusl.useHandCursor = false;
+				depth++;
+			}
+		}
+	}
+
+
+	var a=0;
+	while (++a <= _root.cuantas_columnas) {
+//	for (a=1; a<=_root.cuantas_columnas; a++) {
+		depth++;
+		var b=0;
+		while (++b <= _root.cuantas_filas) {
+//		for (b=1; b<=_root.cuantas_filas; b++) {
+			var coordenada_y = (b*(alto_boton+separacion))-alto_boton+30;
+			var coordenada_x = (a*(ancho_boton+separacion))-ancho_boton;
+			var coordenada_x = coordenada_x-separacion;
+			var offsetboton = (alto_boton/2);
+			var v = eval("vr.texto"+contador);
+			var lurl    = eval("vr.url"+contador);
+			var lurl    = base64_decode(lurl);
+			var ltarget = eval("vr.target"+contador);
+			if (v != undefined) {
+				// El boton esta definido en la configuracion, lo muestro
+
+				if(lurl != "0") {
+					fmtLabel.url = lurl;
+				} else {
+					fmtLabel.url = undefined;
+				}
+				if(ltarget != "0") {
+					fmtLabel.target = ltarget;
+				} else {
+					fmtLabel.target = undefined;
+				}
+
+				// Guardo el label original en un array
+			    _global.labels[contador] = v;	
+				var ima = eval("vr.bg"+contador);
+
+				 cuel = createEmptyMovieClip("resaltado"+contador, getNextHighestDepth());
+				if(_root["nodraw_"+contador] == undefined || ima != undefined) {
+					createSquare(cuel, ancho_boton+4, alto_boton+4, ancho_linea, color_linea, resaltado_color, resaltado_color, btn_round_border);
+				}
+				with(cuel) { 
+					_x = coordenada_x-2;
+					_y = coordenada_y+offsetboton;
+					_visible = false;
+					useHandCursor = false;
+				}
+
+				if(ima != undefined) {
+					cauel = createEmptyMovieClip("resaltadobg"+contador, getNextHighestDepth());
+					with(cauel) {
+						_x = coordenada_x;
+						_y = coordenada_y;
+						_visible = true;
+						useHandCursor = false;
+					}
+					loadMovie(ima,cauel);
+				}
+
+				cual = createEmptyMovieClip("rectangulo"+contador, getNextHighestDepth());
+				with(cual) {
+					useHandCursor = false;
+					//menu = myMenu;
+					_visible = true;
+					_x = coordenada_x;
+					_y = coordenada_y+offsetboton;
+				}
+
+				led_margin_left = Number(vr.led_margin_left);
+				led_margin_top = Number(vr.led_margin_top);
+				if(_root["nodraw_"+contador] == undefined) {
+				createSquare(cual, ancho_boton, alto_boton, ancho_linea, color_linea, boton1_fade, boton2_fade, btn_round_border);
+				}
+				cual.createTextField("statusprint"+contador, depth, clid_margin_left, clid_margin_top-offsetboton, 1, 1);
+				depth++;
+				with (cual["statusprint"+contador]) {
+					selectable = false;
+					setNewTextFormat(fmtClid);
+					text = "000000000000000000000000000000000000";
+					border = false;
+					_width = vr.btn_width - clid_margin_left * 2;
+					_height = textHeight;
+					text = "";
+					if(use_embed_fonts==1) {
+						embedFonts = true;
+					}
+				}
+
+				cual.createTextField("timer"+contador, depth, timer_margin_left, timer_margin_top-offsetboton, 1, 1);
+				depth++;
+				cual["timer"+contador].selectable = false;
+				cual["timer"+contador].border = false;
+				cual["timer"+contador].setNewTextFormat(fmtTimer);
+				cual["timer"+contador].text = "00:00:00";
+				cual["timer"+contador]._width = cual["timer"+contador].textWidth+15;
+				cual["timer"+contador]._height = cual["timer"+contador].textHeight+15;
+				cual["timer"+contador].text = "";
+				cual["timer"+contador].tabIndex = contador;
+				if(use_embed_fonts==1) {
+					cual["timer"+contador].embedFonts = true;
+				}
+
+       			var lTextExtent = fmtLabel.getTextExtent ( v );
+        	    var lWidth  = lTextExtent.textFieldWidth + 10;
+        	    var lHeight = lTextExtent.textFieldHeight + 2;
+
+				cual.createTextField("textobg", depth, label_margin_left, label_margin_top-offsetboton, 1, 1);
+				with (cual["textobg"]) {
+					setNewTextFormat(fmtLabel);
+					_width = vr.btn_width - label_margin_left * 2;
+					_height = lHeight;
+				}
+				depth++;
+
+				if (label_shadow == 1) {
+					cual.createTextField("textosh", depth, label_margin_left+1, label_margin_top+1-offsetboton, 1, 1);
+					with (cual["textosh"]) {
+						setNewTextFormat(fmtLabelsh);
+						_width  = lWidth; 
+						_height = lHeight; 
+						selectable = false;
+						border = false;
+						multiline = true;
+						wordWrap = true;
+						if(use_embed_fonts==1) {
+							embedFonts = true;
+					    	htmlText = v;
+						    html = true;
+						} else {
+							text = v;
+						}
+					}
+					depth++;
+				}
+
+				cual.createTextField("textoprint", depth, label_margin_left, label_margin_top-offsetboton, 1, 1);
+				with (cual["textoprint"]) {
+				    setNewTextFormat(fmtLabel);
+					_width  = lWidth; 
+					_height = lHeight; 
+					border = false;
+					selectable = false;
+					multiline = true;
+					wordWrap = true;
+					if(use_embed_fonts==1) {
+						embedFonts = true;
+					    htmlText = v;
+					    html = true;
+					} else {
+						text = v;
+					}
+				}
+				depth++;
+
+				casilli = cual.attachMovie("ledsombra","casish"+contador, depth,  {_x:led_margin_left, _y:led_margin_top-offsetboton+1});
+				casilli._xscale = led_scale;
+				casilli._yscale = led_scale;
+				depth++;
+				casilli = cual.attachMovie("ledcolor","casicol"+contador, depth, {_x:led_margin_left, _y:led_margin_top-offsetboton+1});
+				casilli._xscale = led_scale;
+				casilli._yscale = led_scale;
+				_global.colorlibre[contador]=_global.color[0];
+				casilli.changeledcolor(0,_global.color[0],_global.color[1],contador);
+				depth++;
+				casilli = cual.attachMovie("ledbrillo","casilla"+contador, depth, {_x:led_margin_left, _y:led_margin_top-offsetboton+1});
+				casilli._xscale = led_scale;
+				casilli._yscale = led_scale;
+
+				depth++;
+
+				circle = cual.createEmptyMovieClip("circle"+contador, depth);
+				createCircle(circle,11,0,0,'0x00ff00');
+				circle._xscale = arrow_scale;
+				circle._yscale = arrow_scale;
+				circle._x = arrow_margin_left;
+				circle._y = arrow_margin_top - offsetboton + 1;
+
+				depth++;
+
+				flechi = cual.attachMovie("arrow", "flecha"+contador, depth, {_x:arrow_margin_left, _y:arrow_margin_top-offsetboton+1});
+				depth++;
+//				flechi._visible = false; NICO
+				flechi.gotoAndStop(3);
+				flechi._xscale = arrow_scale;
+				flechi._yscale = arrow_scale;
+				flechi.onRelease = function() {
+					doubleClick(this);
+				};
+
+				
+//				createCircle(cual,12*(arrow_scale/100),arrow_margin_left,arrow_margin_top-offsetboton+1,'0xff0000');
+//				var tama = (arrow_scale * 6 / 100) * 2;
+//				createCircle(_root["rectangulo"+contador]["flecha"+contador],tama,0,0,'0xff0000');
+
+
+
+				w = Number(eval("vr.icono"+contador));
+				if (w<0) {
+					w = 1;
+				}
+				top = Number(eval("vr.icon"+w+"_margin_top"));
+				left = Number(eval("vr.icon"+w+"_margin_left"));
+				escala = Number(eval("vr.icon"+w+"_scale"));
+				telef = cual.attachMovie("telefono"+w, "tele"+contador, depth, {_x:ancho_boton+left, _y:top-offsetboton});
+				telef.gotoAndStop(1);
+				depth++;
+				sobrec = cual.attachMovie("sobre", "sobrecito"+contador, depth, {_x:ancho_boton+mail_margin_left, _y:mail_margin_top-offsetboton});
+				depth++;
+				sobrec._xscale = mail_scale;
+				sobrec._yscale = mail_scale;
+				sobrec._visible = false;
+				sobrec._alpha = 50;
+
+				sobrec.onRollOut = function() {
+					this._xscale = mail_scale;
+					this._yscale = mail_scale;
+				};
+
+				sobrec.onEnterFrame = function() {
+//					if(this.hitTest(_xmouse,_ymouse,true)) {
+					if(this.hitTest(clip_arrastrado)) {
+						this._xscale = mail_scale * 1.5;
+						this._yscale = mail_scale * 1.5;
+						this.hitted = 1;
+						_global.sobrehit = this;
+					} else {
+						if(this.hitted == 1) {
+							this.hitted = 0;
+							_global.sobrehit = undefined;
+						}
+					}
+					if(this.hitted == 0) {
+						this._xscale = mail_scale;
+						this._yscale = mail_scale;
+						this.hitted = -1;
+					}
+				};
+
+				sobrec.onRollOver = function() {
+				//	this._xscale = mail_scale * 1.5;
+				//	this._yscale = mail_scale * 1.5;
+					var origen = ExtraeNumeroClip(this);
+					makeStatusMail(origen);
+				};
+				sobrec.onRelease = function() {
+					doubleClick(this);
+				};
+				telef.onPress = function() {
+					dragClip(this);
+				};
+				casilli.onRelease = function() {
+					doubleClick(this);
+				};
+				telef._xscale = escala;
+				telef._yscale = escala;
+
+				inicio_timer[cantidad_botones] = 0;
+				timer_type[contador] = "STOP";
+				cantidad_botones++;
+				ultimo = contador;
+			} 
+			contador++;
+		}
+	}
+
+	// Draw rectangles over buttons
+	var a=0;
+	while (++a <= vr.total_rectangles) {
+//	for (a=1; a<=vr.total_rectangles; a++) {
+		v = eval("vr.rect_"+a);
+		if (v != undefined) {
+			var datos = v.split(",");
+			var rect_x = Number(datos[0]);
+			var rect_y = Number(datos[1]);
+			var rect_width =  Number(datos[2]);
+			var rect_height = Number(datos[3]);
+			var line_width = Number(datos[4]);
+			var line_color = datos[5];
+			var fade_color1 = datos[6];
+			var fade_color2 = datos[7];
+			var rnd_border = Number(datos[8]);
+			var alpha = Number(datos[9]);
+			offsetboton = (rect_height/2);
+			if(datos[10]=="top") {
+				rect_y += offsetboton;
+				cusl = createEmptyMovieClip("dibujo"+a, getNextHighestDepth());
+				createSquare(cusl, rect_width, rect_height, line_width, line_color, fade_color1, fade_color2, rnd_border);
+				cusl._x = rect_x;
+				cusl._y = rect_y;
+				cusl._visible = true;
+				cusl._alpha = alpha;
+				cusl.useHandCursor = false;
+			}
+		}
+	}
+	// Draw TEXT LEGENDS
+	var a=0;
+	while (++a <= vr.total_legends) {
+//	for (var a=1; a<=vr.total_legends; a++) {
+		v = eval("vr.legend_"+a);
+		if (v != undefined) {
+			var datos = v.split(",");
+			var legend_x = Number(datos[0]);
+			var legend_y = Number(datos[1]);
+			var legend_fontsize = Number(datos[3]);
+			var legend_fontfamily = datos[4];
+			var legend_fontcolor = parseInt(datos[5], 16);
+			var legend_embedfonts = Number(datos[6]);
+			var legend_no_base64 = Number(datos[7]);
+			var legend_url = datos[8];
+			var legend_target = datos[9];
+
+			if(legend_no_base64==0) {
+			    var legend_text = base64_decode(datos[2]);
+			} else {
+			    var legend_text = datos[2];
+			}
+
+    		var fmtLege = new TextFormat();
+    		fmtLege.size = legend_fontsize;
+			fmtLege.color = legend_fontcolor;
+
+			if(legend_embedfonts == 1) {
+    			fmtLege.font = "$fuente_nombre";
+			} else {
+    			fmtLege.font = legend_fontfamily;
+			}
+
+			if(legend_url != "no") {
+				fmtLege.url = legend_url;
+				fmtLege.underline = true;
+			}
+
+			if(legend_target != "NONTARFOP") {
+				fmtLege.target = legend_target;
+			}
+
+    		createTextField("lege"+a, getNextHighestDepth(), legend_x, legend_y, 10, 10);
+    		_root["lege"+a].setNewTextFormat(fmtLege);
+			if(legend_embedfonts == 1) {
+    			_root["lege"+a].embedFonts = true;
+			} else {
+    			_root["lege"+a].embedFonts = false;
+			}
+    		_root["lege"+a].htmlText = legend_text;
+			_root["lege"+a].html = true;
+			_root["lege"+a].border = false;
+			_root["lege"+a].selectable = false;
+			_root["lege"+a].multiline = true;
+			_root["lege"+a].wordWrap = true;
+
+        	var lTextExtent = fmtLege.getTextExtent ( legend_text );
+        	var lWidth  = lTextExtent.textFieldWidth + 40;
+        	var lHeight = lTextExtent.textFieldHeight + 40;
+
+			_root["lege"+a]._width  = lWidth;
+			_root["lege"+a]._height = lHeight;
+		}
+	}
+
+
+	ultimo++;
+	attachMovie("telefono1", "tele"+ultimo, getNextHighestDepth(), {_x:1, _y:1, _visible:false});
+	_global.masalto = ultimo;
+
+	_root.onMouseMove = function() {
+		if(_global.nohighlight == 1) {
+			return;
+		}
+		var columna = int((_xmouse+ancho_boton+separacion)/(ancho_boton+separacion));
+		var fila = Math.floor((_ymouse-30-separacion)/(alto_boton+separacion))+1;
+		var boton = 1;
+		if (columna<1) {
+			columna = 1;
+			boton = -1;
+		} else if (columna>cuantas_columnas) {
+			columna = cuantas_columnas;
+			boton = -1;
+		}
+		if (fila>cuantas_filas) {
+			fila = cuantas_filas;
+			boton = -1;
+		} else if (fila<1) {
+			fila = 1;
+			boton = -1;
+		}
+		if(boton!=-1) {
+		boton = ((columna*cuantas_filas)-cuantas_filas)+fila;
+			if (boton!=_global.rectanguloprendido) {
+				var a=0;
+				while (++a < _global.otrosprendidos.length) {
+//			 	for (a=0; a<_global.otrosprendidos.length; a++) {
+					var prendeme = eval("resaltado"+_global.otrosprendidos[a]);
+					prendeme._visible = false;	
+				}
+
+				//var myresa = eval("resaltado"+boton);
+				//var myapaga = eval("resaltado"+_global.rectanguloprendido);
+				if(_global.rectanguloprendido != _global.restrict) {
+					//myapaga._visible = false;
+					_root["resaltado"+_global.rectanguloprendido]._visible = false;
+				}
+				//myresa._visible = true;
+				_root["resaltado"+boton]._visible = true;
+				_global.rectanguloprendido = boton;
+				makeStatus(boton);
+
+				var botresa = linkeado[boton].split(",");
+				for (b in botresa) {
+					//var prendeme = eval("resaltado"+botresa[b]);
+					//prendeme._visible = true;	
+					_root["resaltado"+botresa[b]]._visible = true;
+					_global.otrosprendidos.push(botresa[b]);
+				}
+			}
+		} else {
+			//var myapaga = eval("resaltado"+_global.rectanguloprendido);
+			//myapaga._visible = false;
+			_root["resaltado"+_global.rectanguloprendido]._visible = false;
+			for (b in _global.otrosprendidos) {
+				//var prendeme = eval("resaltado"+_global.otrosprendidos[b]);
+				if(_global.otrosprendidos[b]!=_global.restrcit) {
+					//prendeme._visible = false;	
+					_root["resaltado"+_global.otrosprendidos[b]]._visible = false;
+				}
+			}
+		}
+	};
+ _root.detail.swapDepths(getNextHighestDepth());
+ _root.superdetails.swapDepths(getNextHighestDepth());
+ _root.log.swapDepths(getNextHighestDepth());
+ _root.codebox.swapDepths(getNextHighestDepth());
+
+ _root.selectbox1.swapDepths(getNextHighestDepth());
+ if(vr.totaltimes > 0) {
+	genera_selecttimeout();
+	_root.selectbox1._visible = true;
+ } else {
+	_root.selectbox1._visible = false;
+ }
+
+if(defined(_root.margintop))
+{
+	_root._y+=_root.margintop;
+}
+
+if(defined(_root.marginleft))
+{
+	_root._x+=_root.marginleft;
+}
+
+};
+
+
+Inicia_Variables = function () {
+    lastclick=0;
+	doubleclickduration=300;
+	_global.swfversion="026.001";
+	_global.frames = 0;
+	_global.step=2;
+	_global.statusline="";
+	_global.server = vr.server;
+	_global.port = vr.port;
+	_global.clid_centered = Number(vr.clid_centered);
+	_global.shakepixels = Number(vr.shake_pixels);
+	_root.log._visible = false;
+	_root.log._alpha = 100;
+	_root.codebox._visible = false;
+	_root.codebox._alpha = 100;
+	_root.detail._visible = false;
+	_root.superdetails._visible = false;
+	_root.superdetails.tab1.gotoAndStop(1);
+	_root.superdetails.tab2.gotoAndStop(2);
+	_root.superdetails._alpha = 90;
+	_global.logwindow = 1;
+	_global.margenbar = 2;
+	_global.loglines = new Array();
+	_global.texto_tip = new Array();
+	_global.texto_mail = new Array();
+	_global.st_originclid = new Array();
+	_global.st_destinationclid = new Array();
+    _global.ipboton = new Array();
+	_global.st_direction = new Array();
+	_global.queuemember = new Object();
+	_global.superdetailstexttab1 = "";
+	_global.superdetailstexttab2 = "";
+	_global.st_duration = new Array();
+	_global.meetmemember = new Array();
+	_global.meetmeroom = new Array();
+	_global.meetmemute = new Array();
+	_global.linkeado = new Array();
+	_global.authorized = false;
+	_global.wait5seconds = 1;
+	_global.rectanguloprendido = 1;
+	_global.otrosprendidos = new Array();
+	_global.colorlibre = new Array();
+	_global.labels = new Array();
+	_global.clidnumber = new Array();
+	_global.clidname = new Array();
+	_global.enable_crypto = Number(vr.enable_crypto);
+    _global.enable_label_background = Number(vr.enable_label_background);
+	_global.restart = Number(vr.restart);
+	_global.nosecurity = vr.nosecurity;
+    _global.valorchangeledcolor = new Array();
+	if(_global.nosecurity == 1) {
+		_global.claveingresada="";
+	}
+	_global.claveingresada = LocalLoad("auth","clave");
+	_root.codebox.claveform.text = _global.claveingresada;
+	_global.timeout_value = 0;
+	if (isNaN(_global.enable_crypto)) {
+		_global.enable_crypto=0;
+	} else {
+		if(_global.enable_crypto != 0) {
+			_global.enable_crypto = 1;
+		}
+	}
+
+	_global.led_color = Number(vr.led_color);
+	if (_global.led_color>1 || _global.led_color<0) {
+		_global.led_color = 0;
+	}
+	// ancho_pantalla = System.capabilities.screenResolutionX;
+	// alto_pantalla = System.capabilities.screenResolutionY;
+	ancho_pantalla_real = 996;
+	alto_pantalla_real = 600;
+	ancho_boton = Number(_root.vr.btn_width);
+	alto_boton = Number(_root.vr.btn_height);
+
+	if (ancho_boton<=0) {
+		ancho_boton = 200;
+	}
+	if (alto_boton<=0) {
+		alto_boton = 80;
+	}
+	separacion = Number(_root.vr.btn_padding);
+	ancho_linea = Number(_root.vr.btn_line_width);
+	color_linea = _root.vr.btn_line_color;
+	boton1_fade = _root.vr.btn_fadecolor_1;
+	boton2_fade = _root.vr.btn_fadecolor_2;
+	ledcolor_busy = _root.vr.ledcolor_busy;
+	ledcolor_ready = _root.vr.ledcolor_ready;
+	ledcolor_agent = _root.vr.ledcolor_agent;
+	ledcolor_paused = _root.vr.ledcolor_paused;
+	_global.resaltado_color = _root.vr.btn_highlight_color;
+
+	if(ledcolor_busy==undefined) {
+		ledcolor_busy="0xC00000";
+	}
+	if(ledcolor_ready==undefined) {
+		ledcolor_ready="0x00A000";
+	}
+	if(ledcolor_agent==undefined) {
+		ledcolor_agent="0xC0A000";
+	}
+	if(_global.resaltado_color==undefined) {
+		_global.resaltado_color="FF0000";
+	}
+
+
+	_global.color = new Array();
+	_global.color[0] = ledcolor_ready;
+	_global.color[1] = ledcolor_busy;
+	_global.color[2] = ledcolor_agent;
+	btn_round_border = Number(_root.vr.btn_round_border);
+	label_margin_top = Number(_root.vr.label_margin_top);
+	label_margin_left = Number(_root.vr.label_margin_left);
+	clid_margin_top = Number(_root.vr.clid_margin_top);
+	clid_margin_left = Number(_root.vr.clid_margin_left);
+	timer_margin_top = Number(_root.vr.timer_margin_top);
+	timer_margin_left = Number(_root.vr.timer_margin_left);
+	if(_root.vr.dimm_noregister_by == undefined) {
+		dimm_noregister = 20;
+	} else {
+		dimm_noregister = Number(_root.vr.dimm_noregister_by);
+	}
+	if(_root.vr.dimm_lagged_by == undefined) {
+		dimm_lagged = 60;
+	} else {
+		dimm_lagged = Number(_root.vr.dimm_lagged_by);
+	}
+	if(_root.vr.label_font_color == undefined) {
+         _root.vr.label_font_color='000000';
+    }
+	if(_root.vr.label_shadow_color == undefined) {
+         _root.vr.label_shadow_color='dddddd';
+    }
+	label_font_color = parseInt(_root.vr.label_font_color, 16);
+	label_shadow_color = parseInt(_root.vr.label_shadow_color, 16);
+	clid_font_color = parseInt(_root.vr.clid_font_color, 16);
+	timer_font_color = parseInt(_root.vr.timer_font_color, 16);
+	label_font_size = Number(_root.vr.label_font_size);
+	arrow_margin_left = Number(vr.arrow_margin_left);
+	arrow_margin_top = Number(vr.arrow_margin_top);
+	led_scale = Number(_root.vr.led_scale);
+	arrow_scale = Number(_root.vr.arrow_scale);
+	// phone_scale = Number(phone_scale);
+	mail_margin_left = Number(_root.vr.mail_margin_left);
+	mail_margin_top = Number(_root.vr.mail_margin_top);
+	mail_scale = Number(_root.vr.mail_scale);
+	show_security_code = Number(_root.vr.show_security_code);
+	show_clid_info = Number(_root.vr.show_clid_info);
+	show_btn_help = Number(_root.vr.show_btn_help);
+	show_btn_debug = Number(_root.vr.show_btn_debug);
+	show_btn_reload = Number(_root.vr.show_btn_reload);
+	show_status = Number(_root.vr.show_status);
+	use_embed_fonts = Number(_root.vr.use_embed_fonts);
+	enable_animation = Number(_root.vr.enable_animation);
+	label_shadow = Number(_root.vr.label_shadow);
+	_level0.detail.duration_label = _root.vr.detail_duration;
+	_level0.detail.title = _root.vr.detail_title;
+	_level0.codebox.title = _root.vr.security_code_title;
+	_level0.superdetails.titlefs2 = _root.vr.tab_call_text;
+	_level0.superdetails.titlefs3 = _root.vr.tab_queue_text;
+    _level0.log.title = _root.vr.debug_window_title;
+	orden_barra = [["security", vr.show_security_code], ["clid", vr.show_clid_info], ["status", vr.show_status], ["help", vr.show_btn_help], ["debug", vr.show_btn_debug], ["reload", vr.show_btn_reload]];
+	orden_barra.sort(ordenaArray);
+	// cuantas_filas = math.floor((alto_pantalla_real-30)/(alto_boton+separacion));
+	cuantas_filas = (alto_pantalla_real-30)/(alto_boton+separacion);
+	cuantas_filas = Math.floor(_root.cuantas_filas);
+	// cuantas_columnas = math.floor((ancho_pantalla_real+separacion)/(ancho_boton+separacion));
+	cuantas_columnas = (ancho_pantalla_real+separacion)/(ancho_boton+separacion);
+	cuantas_columnas = Math.floor(Number(_root.cuantas_columnas));
+
+	max_en_pantalla = cuantas_columnas * cuantas_filas;
+
+	if(_root.vr.highestpos == undefined) {
+		_root.vr.highestpos = 2;
+	}
+    _global.highpos = Number(_root.vr.highestpos);
+	cuantas_columnas = Math.ceil(_global.highpos / cuantas_filas);
+	_global.max_scroll_left = 996 - ( cuantas_columnas * (ancho_boton+separacion)) + separacion;
+	if(_global.highpos <= max_en_pantalla) {
+		_global.scrolling = 0;
+	} else {
+		_global.scrolling = 1;
+	}
+
+
+	fmtLabel = new TextFormat();
+	fmtLabel.size = vr.label_font_size;
+	if(use_embed_fonts==1) {
+		fmtLabel.font = "$fuente_nombre";
+	} else {
+		fmtLabel.font = vr.label_font_family;
+	}
+	fmtLabel.color = label_font_color;
+
+	fmtLabelsh = new TextFormat();
+	fmtLabelsh.color = label_shadow_color;
+	fmtLabelsh.size = vr.label_font_size;
+	if(use_embed_fonts==1) {
+		fmtLabelsh.font = "$fuente_nombre";
+	} else {
+		fmtLabelsh.font = vr.label_font_family;
+	}
+	fmtLabelsh._alpha = 90;
+
+	fmtClid = new TextFormat();
+	fmtClid.size = vr.clid_font_size;
+	fmtClid.color = clid_font_color;
+	if(use_embed_fonts==1) {
+		fmtClid.font = "$fuente_nombre";
+	} else {
+		fmtClid.font = vr.clid_font_family;
+	}
+
+	fmtTimer = new TextFormat();
+	fmtTimer.size = vr.timer_font_size;
+	fmtTimer.color = timer_font_color;
+	if(use_embed_fonts==1) {
+		fmtTimer.font = "$fuente_nombre";
+	} else {
+		fmtTimer.font = vr.timer_font_family;
+	}
+
+	_global.ancho_a_centrar = vr.btn_width - clid_margin_left * 2;
+
+	timer_type = new Array();
+	inicio_timer = new Array();
+	/* Custom context menu is not working in MING
+		var myMenu;
+		myMenu = new ContextMenu();
+		myMenu.customItems.push(new ContextMenuItem("Toggle DND", setDND));
+		myMenu.hideBuiltInItems();
+	*/
+
+
+	var i=0;
+	while (++i < orden_barra.length) {
+//	for (i=0; i<orden_barra.length; i++) {
+		if (orden_barra[i][1]>0) {
+			if (orden_barra[i][0] == "security") {
+				Barra_SecurityCode();
+			}
+			if (orden_barra[i][0] == "clid") {
+				Barra_InfoText();
+			}
+			if (orden_barra[i][0] == "help") {
+				Barra_BotonHelp();
+			}
+			if (orden_barra[i][0] == "debug") {
+				Barra_BotonDebug();
+			}
+			if (orden_barra[i][0] == "reload") {
+				Barra_BotonReload();
+			}
+			if (orden_barra[i][0] == "status") {
+				Barra_Status();
+			}
+		}
+	}
+
+
+
+_global.opcionesTimeout = new Array();
+_global.opcionesTimeoutSecs = new Array();
+var a=0;
+while (++a <= vr.totaltimes) {
+//for (a=1; a<=vr.totaltimes; a++) {
+	v = eval("vr.timeout_"+a);
+		if (v != undefined) {
+			var datos = v.split(",");
+			_global.opcionesTimeoutSecs.push(Number(datos[0]));
+			_global.opcionesTimeout.push(datos[1]);
+		}
+
+}
+
+datosnod = vr.nodraw.split(',');
+for (var elem in datosnod) {
+	_root["nodraw_"+datosnod[elem]] = 1;
+}
+};
+
+
+function ordenaArray(a, b) {
+	return a[1]>b[1];
+}
+
+
+function SecurityCode_Locked() {
+    if(show_security_code != 0) {
+		var x=_root.claveinput._x;
+		var mydepth = _level0.claveinput.getDepth();
+		// _level0.claveinput.unloadMovie();
+		mymc = attachMovie("boton_security", "claveinput", mydepth);
+		mymc.gotoAndStop(1);
+		mymc._x = x;
+		mymc._y = 1;
+		mymc.onPress = function() {
+			_root.codebox._visible = true;
+			Selection.setFocus(_root.codebox.claveform);
+			_root.codebox.swapDepths(_root.log);
+		};
+		mymc.onRollOver = function() {
+			_root.statusbar.status.text = "Open Security Code Input Box";
+			mymc.gotoAndStop(2);
+		};
+		mymc.onRollOut = function() {
+			_root.statusbar.status.text = _global.statusline;
+			mymc.gotoAndStop(1);
+		};
+	}
+}
+
+function SecurityCode_Unlocked() {
+    if(show_security_code != 0) {
+		var x=_root.claveinput._x;
+		var mydepth = _level0.claveinput.getDepth();
+		// _level0.claveinput.unloadMovie();
+		mymc = attachMovie("boton_security_unlock", "claveinput", mydepth);
+		mymc._x = x;
+		mymc._y = 1;
+		mymc.onPress = function() {
+			_root.codebox._visible = true;
+			Selection.setFocus(_root.codebox.claveform);
+			_root.codebox.swapDepths(_root.log);
+		};
+		mymc.onRollOver = function() {
+			_level0.statusbar.status.text = "Open Security Code input box";
+			mymc.gotoAndStop(2);
+		};
+		mymc.onRollOut = function() {
+			_level0.statusbar.status.text = _global.statusline;
+			mymc.gotoAndStop(1);
+		};
+	}
+}
+
+function Barra_SecurityCode() {
+	attachMovie("boton_security_unlock", "claveinput", getNextHighestDepth());
+	claveinput.gotoAndStop(1);
+	claveinput._x = _global.margenbar;
+	_global.margen_claveinput = _global.margenbar;
+	claveinput._y = 1;
+	claveinput._visible = true;
+	claveinput.onPress = function() {
+		_root.codebox._visible = true;
+		Selection.setFocus(_root.codebox.claveform);
+		_root.codebox.swapDepths(_root.log);
+	};
+	claveinput.onRollOver = function() {
+		_level0.statusbar.status.text = vr.btn_security_text;
+		claveinput.gotoAndStop(2);
+	};
+	claveinput.onRollOut = function() {
+		_level0.statusbar.status.text = _global.statusline;
+		claveinput.gotoAndStop(1);
+	};
+	_global.margenbar = _global.margenbar+claveinput._width;
+}
+
+function Barra_BotonReload() {
+	attachMovie("boton_reload", "buttonreload", getNextHighestDepth());
+	buttonreload.gotoAndStop(1);
+	_global.margen_buttonreload = _global.margenbar;
+	buttonreload._x = _global.margenbar;
+	buttonreload._y = 1;
+	buttonreload._visible = true;
+	buttonreload.label.text = vr.btn_reload_label;
+	buttonreload.onRelease = function() {
+		_root.recarga();
+	};
+	buttonreload.onRollOver = function() {
+		if(_global.restart == 1) {
+			_level0.statusbar.status.text = vr.btn_restart_text;
+		} else {
+			_level0.statusbar.status.text = vr.btn_reload_text;
+		}
+		buttonreload.gotoAndStop(2);
+	};
+	buttonreload.onRollOut = function() {
+		_level0.statusbar.status.text = _global.statusline;
+		buttonreload.gotoAndStop(1);
+	};
+	_global.margenbar = _global.margenbar+buttonreload._width;
+}
+
+
+function Barra_BotonDebug() {
+	attachMovie("boton_debug", "buttondebug", getNextHighestDepth()); 
+	buttondebug.gotoAndStop(1);
+	_global.margen_buttondebug = _global.margenbar;
+	buttondebug._x = _global.margenbar;
+	buttondebug._y = 1;
+	buttondebug._visible = true;
+	buttondebug.label.text = vr.btn_log_label;
+	buttondebug.onPress = function() {
+		MuestraLog();
+	};
+	buttondebug.onRollOver = function() {
+		_level0.statusbar.status.text = vr.btn_debug_text + " (" +_global.swfversion + ")";
+		buttondebug.gotoAndStop(2);
+	};
+	buttondebug.onRollOut = function() {
+		_level0.statusbar.status.text = _global.statusline;
+		buttondebug.gotoAndStop(1);
+	};
+	_global.margenbar = _global.margenbar+buttondebug._width;
+}
+
+function Barra_BotonHelp() {
+	attachMovie("boton_ayuda", "buttonhelp", getNextHighestDepth()); 
+	buttonhelp.gotoAndStop(1);
+	_global.margen_buttonhelp = _global.margenbar;
+	buttonhelp._x = _global.margenbar;
+	buttonhelp._y = 1;
+	buttonhelp._visible = true;
+	buttonhelp.label.text = vr.btn_help_label;
+	buttonhelp.onPress = function() {
+		buttonhelp.gotoAndStop(2);
+		url = "help_"+vr.lang+".html";
+		winName = "fophelp";
+		w = 400;
+		h = 300;
+		toolbar = 0;
+		location = 0;
+		directories = 0;
+		status = 0;
+		menubar = 0;
+		scrollbars = 1;
+		resizable = 0;
+		getURL("javascript:var myWin1;if (!myWin1 || myWin1.closed){myWin1=window.open('"+url+"', '"+winName+"', '"+"width="+w+", height="+h+", toolbar="+toolbar+", location="+location+", directories="+directories+", status="+status+", menubar="+menubar+", scrollbars="+scrollbars+", resizable="+resizable+", top='+((screen.height/2)-("+h/2+"))+', left='+((screen.width/2)-("+w/2+"))+'"+"')} else{myWin1.focus();};void(0);",''); 
+	};
+	buttonhelp.onRollOver = function() {
+		_level0.statusbar.status.text = vr.btn_help_text;
+		buttonhelp.gotoAndStop(2);
+	};
+	buttonhelp.onRollOut = function() {
+		_level0.statusbar.status.text = _global.statusline;
+		buttonhelp.gotoAndStop(1);
+	};
+	_global.margenbar = _global.margenbar+buttonhelp._width;
+}
+
+
+function Barra_Status() {
+	ancho = 0;
+	var j=0;
+	while (++j < orden_barra.length) {
+//	for (j=0; j<orden_barra.length; j++) {
+		if (orden_barra[j][1]>0) {
+			if (orden_barra[j][0] == "security") {
+				ancho = ancho+32.5;
+			}
+			if (orden_barra[j][0] == "clid") {
+				ancho = ancho+272.5;
+			}
+			if (orden_barra[j][0] == "help") {
+				ancho = ancho+32.5;
+			}
+			if (orden_barra[j][0] == "debug") {
+				ancho = ancho+32.5;
+			}
+			if (orden_barra[j][0] == "reload") {
+				ancho = ancho+32.5;
+			}
+		}
+	}
+	ancho_status = ancho_pantalla_real-(ancho+2);
+
+	bar = createEmptyMovieClip("statusbar",30000);
+	_global.margen_statusbar = _global.margenbar;
+	bar._visible = true;
+	bar._border = true;
+	createSquare(_level0.statusbar, ancho_status, 30, 0, "0x999999", "0xcccccc", "0xcccccc", 0);
+	bar._x = _global.margenbar;
+	bar._y = 16;
+
+    fmtStatus = new TextFormat();
+    fmtStatus.size = 16;
+	if(use_embed_fonts==1) {
+	    fmtStatus.font = "$fuente_nombre";
+	} else {
+		fmtStatus.font = vr.label_font_family;
+	}
+
+	statusTextExtent = fmtStatus.getTextExtent ( "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" );
+    statusWidth  = statusTextExtent.textFieldWidth;
+    statusHeight = statusTextExtent.textFieldHeight;
+    bar.createTextField("status", getNextHighestDepth(), 3, 3, statusWidth, statusHeight);
+    bar.status.setNewTextFormat(fmtStatus);
+    bar.status.text = "Asterisk Flash Operator Panel";
+    bar.status.border = false;
+	bar.status._y = -10;
+    bar.status.selectable = false;
+	if(use_embed_fonts==1) {
+	    bar.status.embedFonts = true;
+	} 
+
+}
+
+function Barra_InfoText() {
+    fmtInfo = new TextFormat();
+    fmtInfo.size = 16;
+	if(use_embed_fonts==1) {
+	    fmtInfo.font = "$fuente_nombre";
+	} else {
+		fmtInfo.font = vr.label_font_family;
+	}
+	attachMovie("infotext", "infotext1", getNextHighestDepth());
+	_global.margen_infotext1 = _global.margenbar;
+	infotext1._x = _global.margenbar;
+	infotext1._y = 1;
+	infotext1._visible = true;
+	infoTextExtent = fmtInfo.getTextExtent ( vr.clid_label );
+    infoWidth  = infoTextExtent.textFieldWidth + 20;
+    infoHeight = infoTextExtent.textFieldHeight;
+    infotext1.createTextField("cclid", getNextHighestDepth(), 3, 3, infoWidth, infoHeight);
+	infotext1.cclid.setNewTextFormat(fmtInfo);
+	infotext1.cclid.text = vr.clid_label;
+	infotext1.cclid.border = false;
+	if(use_embed_fonts==1) {
+	    infotext1.cclid.embedFonts = true;
+	} 
+    inputtext = "XXXXXXXXXXXXXXXXXXX";
+	infoTextExtent = fmtInfo.getTextExtent ( inputtext );
+    infoWidth  = infoTextExtent.textFieldWidth;
+    infoHeight = infoTextExtent.textFieldHeight;
+    infotext1.createTextField("clid_text", getNextHighestDepth()+1, 74, 3, 195, infoHeight);
+	infotext1.clid_text.setNewTextFormat(fmtInfo);
+	infotext1.clid_text.text = "";
+	infotext1.clid_text.border = false;
+	infotext1.clid_text.type = "input";
+	if(use_embed_fonts==1) {
+	    infotext1.clid_text.embedFonts = true;
+	} 
+
+	_global.margenbar = _global.margenbar+infotext1._width;
+}
+
+recarga = function () {
+  	if(_global.restart == 1) {
+		// Send command to restart Asterisk
+		envia_comando("restart","1","1");
+	} else {
+		// Reloads FLASH client
+		delete _global.key;
+		var incontext = context;
+		var inbutton = mybutton;
+		var inrestrict = _global.restrict;
+		var indial = dial;
+		var innohighlight = nohighlight;
+		for (var a in _root) {
+			if (typeof (_root[a]) == "object") {
+				removeMovieClip(_root[a]);
+			}
+			if (typeof (_root[a]) == "movieclip") {
+				removeMovieClip(_root[a]);
+			}
+		}
+		_global.context = incontext;
+		_global.mybutton = inbutton;
+		_global.restrict = inrestrict;
+		_global.dial = indial;
+		_global.nohighlight = inhighlight;
+		stop();
+		gotoAndPlay(1);
+		}
+};
+
+
+Detiene_Peliculas = function () {	
+	// Detiene todos las peliculas al inicio
+ 	selectbox1.gotoAndStop(1);
+	for (a in _root) {
+		if (typeof (a) == "movieclip") {
+			_root[a].stop();
+			if (a.substring(0, 10) == "rectangulo") {
+				for (b in _root[a]) {
+					if (typeof (_root[a][b]) == "movieclip") {
+						_root[a][b].stop();
+					}
+					if(b.substring(0,7) == "casicol") {
+						var numero = b.substring(7,8);
+						_root[a][b].changeledcolor(0,_global.colorlibre[numero],_global.color[1],numero);
+					}
+				}
+			}
+		}
+	}
+  _root._y = _root.margintop;
+  _root._x = _root.marginleft;
+};
+
+_root.onEnterFrame = function() {
+
+		if(_global.scrolling == 1) {
+		// _level0.statusbar.status.text = _xmouse+":"+_ymouse;
+		// Nico SCROLL
+		var limite_der = 986 + (_root._x * -1);
+		var limite_der_top = 986 + (_root._x * -1) + 10;
+		var limite_izq = 10 + (_root._x * -1);
+		var limite_izq_top = 10 + (_root._x * -1) - 10;
+		if(_xmouse > limite_der && _xmouse <= limite_der_top) {
+			_root._x -= _global.step;
+			claveinput._x += _global.step;
+			infotext1._x += _global.step;
+			_level0.statusbar._x += _global.step;
+			buttonhelp._x += _global.step;
+			buttondebug._x += _global.step;
+			buttonreload._x += _global.step;
+			optionselected._x += _global.step;
+			selectbox1._x += _global.step;
+			_root.fondo.mihijo._x += _global.step;
+			_root.option0._x += _global.step;
+			_root.option1._x += _global.step;
+			_root.option2._x += _global.step;
+			_root.option3._x += _global.step;
+			_root.option4._x += _global.step;
+			_root.codebox._x += _global.step;
+			_root.superdetails._x += _global.step;
+			_global.step+=2;
+		} else if (_xmouse < limite_izq && _xmouse>= limite_izq_top) {
+			_root._x += _global.step;
+			claveinput._x -= _global.step;
+			infotext1._x -= _global.step;
+			_level0.statusbar._x -= _global.step;
+			buttonhelp._x -= _global.step;
+			buttondebug._x -= _global.step;
+			buttonreload._x -= _global.step;
+			optionselected._x -= _global.step;
+			selectbox1._x -= _global.step;
+			_root.fondo.mihijo._x -= _global.step;
+			_root.option0._x -= _global.step;
+			_root.option1._x -= _global.step;
+			_root.option2._x -= _global.step;
+			_root.option3._x -= _global.step;
+			_root.option4._x -= _global.step;
+			_root.codebox._x -= _global.step;
+			_root.superdetails._x -= _global.step;
+			_global.step+=2;
+		} else {
+			_global.step=2;
+		}
+		if(_root._x>0) {
+			_root._x = 0; 
+			buttondebug._x  = _global.margen_buttondebug;
+			buttonreload._x = _global.margen_buttonreload;
+			buttonhelp._x = _global.margen_buttonhelp;
+			claveinput._x   = _global.margen_claveinput;
+			infotext1._x   = _global.margen_infotext1;
+			_level0.statusbar._x   = _global.margen_statusbar;
+			optionselected._x   = 800;
+			selectbox1._x   = 800;
+			_root.option0._x = 800;
+			_root.option1._x = 800;
+			_root.option2._x = 800;
+			_root.option3._x = 800;
+			_root.option4._x = 800;
+
+			_root.codebox._x = 240;
+			_root.superdetails._x = 490;
+			_root.fondo.mihijo._x = 1;
+		} else if(_root._x < _global.max_scroll_left) {
+			_root._x = _global.max_scroll_left;
+			buttondebug._x  = _global.margen_buttondebug + ( _global.max_scroll_left * -1);
+			buttonreload._x = _global.margen_buttonreload + ( _global.max_scroll_left * -1);
+			buttonhelp._x = _global.margen_buttonhelp + (_global.max_scroll_left * -1);
+			claveinput._x   = _global.margen_claveinput + (_global.max_scroll_left * -1);
+			infotext1._x   = _global.margen_infotext1 + (_global.max_scroll_left * -1);
+			_level0.statusbar._x   = _global.margen_statusbar + (_global.max_scroll_left * -1);
+			optionselected._x   = 800 + (_global.max_scroll_left * -1);
+			selectbox1._x   = 800 + (_global.max_scroll_left * -1);
+			_root.option0._x = 800 + (_global.max_scroll_left * -1);
+			_root.option1._x = 800 + (_global.max_scroll_left * -1);
+			_root.option2._x = 800 + (_global.max_scroll_left * -1);
+			_root.option3._x = 800 + (_global.max_scroll_left * -1);
+			_root.option4._x = 800 + (_global.max_scroll_left * -1);
+//	 		for (var a=0; a<5; a++) {
+//			 	var v = eval("_root.option"+a);
+//				v._x = 800 + (_global.max_scroll_left * -1);
+//			}
+			_root.codebox._x = 240 + (_global.max_scroll_left * -1);
+			_root.superdetails._x = 490 + (_global.max_scroll_left * -1);
+			_root.fondo.mihijo._x = 1 + (_global.max_scroll_left * -1);
+		}
+		}
+
+  if (lastclick>0) {
+    if ((getTimer()-lastclick)>doubleclickduration) {
+      lastclick = 0;
+      logea ("single click "+lastclip);
+	  var clip=lastclip;
+	  var numeroclip = ExtraeNumeroClip(clip);
+
+		/* new_way op_actions 
+  		if (_global.authorized == true) {
+		    envia_comando("singleclick",clip,"");
+		} else {
+	   	    _root.codebox._visible = true;
+		    Selection.setFocus(_root.codebox.claveform);
+		    _root.codebox.swapDepths(_root.log);
+		    return;
+		}
+		*/
+		// Un solo click
+		if (clip._name.substring(0, 7) != "casilla") {
+			if (_global.meetmemember[numeroclip]>0) {
+				if (_global.authorized == true) {
+					var statusclid = eval("rectangulo"+numeroclip+".statusprint"+numeroclip);
+					if (_root.context.length>0) {
+				        boton_numero_con_contexto = numeroclip+"@"+context;
+				    } else {
+				        boton_numero_con_contexto = numeroclip;
+					}
+					if (_global.meetmemute[numeroclip]>0) {
+						logea("envio meetmemute");
+						envia_comando("meetmemute"+boton_numero_con_contexto+"-", _global.meetmemember[numeroclip], _global.meetmeroom[numeroclip]);
+						//statusclid.text = "Conference "+_global.meetmeroom[numeroclip]+" muted";
+						_global.meetmemute[numeroclip]=0;
+					} else {
+						logea("envio meetmeunmute");
+						envia_comando("meetmeunmute"+boton_numero_con_contexto+"-", _global.meetmemember[numeroclip], _global.meetmeroom[numeroclip]);
+						//statusclid.text = "Conference "+_global.meetmeroom[numeroclip];
+						_global.meetmemute[numeroclip]=1;
+					}
+				} else {
+					// Not authorized
+					envia_comando("bogus", 0, 0);
+					logea("no esta autorizado");
+				}
+			} else {
+				logea("no es meetmemember");
+			} 
+		} else {
+			logea("single click en led no hace nada");
+		}
+	}
+  }
+};
+
+Timers = function () {
+
+	
+	if (_global.reconecta == 1) {
+		delete setInterval;
+		delete _global.key;
+		if (_global.wait5seconds>9) {
+			_global.wait5seconds = 0;
+			recarga();
+		} else {
+			_global.wait5seconds += 1;
+		}
+		return;
+	}
+	var floor = Math.floor;
+	for (var a in timer_type) {
+		var v = eval("texto"+a);
+		if (v != "") {
+			if (timer_type[a] == "UP" || timer_type[a] == "IDLE") {
+				// calculate values
+				var elapsedTime = getTimer()-inicio_timer[a];
+				// hours
+				var elapsedHours = floor(elapsedTime/3600000);
+				var remaining = elapsedTime-(elapsedHours*3600000);
+				// minutes
+				var elapsedM = floor(remaining/60000);
+				remaining = remaining-(elapsedM*60000);
+				// seconds
+				var elapsedS = floor(remaining/1000);
+
+				if (elapsedHours<0) {
+					elapsedHours = Math.abs(elapsedHours);
+				}
+				if (elapsedM<0) {
+					elapsedM = Math.abs(elapsedM);
+				}
+				if (elapsedS<0) {
+					elapsedS = Math.abs(elapsedS);
+				}
+
+				if (elapsedHours<10) {
+					var hours = "0"+elapsedHours.toString();
+				} else {
+					var hours = elapsedHours.toString();
+				}
+				if (elapsedM<10) {
+					var minutes = "0"+elapsedM.toString();
+				} else {
+					var minutes = elapsedM.toString();
+				}
+				if (elapsedS<10) {
+					var seconds = "0"+elapsedS.toString();
+				} else {
+					var seconds = elapsedS.toString();
+				}
+				var statusclid = eval("rectangulo"+a+".timer"+a);
+				statusclid.text = hours+":"+minutes+":"+seconds;
+			} else if (timer_type[a] == "DOWN") {
+				// calculate values
+				var elapsedTime = inicio_timer[a]-getTimer();
+				if(elapsedTime < 0) {
+					elapsedTime=0;
+				}
+				// hours
+				var elapsedHours = floor(elapsedTime/3600000);
+				var remaining = elapsedTime-(elapsedHours*3600000);
+				// minutes
+				var elapsedM = floor(remaining/60000);
+				remaining = remaining-(elapsedM*60000);
+				// seconds
+				var elapsedS = floor(remaining/1000);
+				// output to text box
+				// add a 0 on the front of the numbers if the number is less than 10
+				if (elapsedHours<10) {
+					var hours = "0"+elapsedHours.toString();
+				} else {
+					var hours = elapsedHours.toString();
+				}
+				if (elapsedM<10) {
+					var minutes = "0"+elapsedM.toString();
+				} else {
+					var minutes = elapsedM.toString();
+				}
+				if (elapsedS<10) {
+					var seconds = "0"+elapsedS.toString();
+				} else {
+					var seconds = elapsedS.toString();
+				}
+				var statusclid = eval("rectangulo"+a+".timer"+a);
+				statusclid.text = hours+":"+minutes+":"+seconds;
+			}
+		}
+	}
+};
+
+setInterval(Timers, 1000);
+
+function LocalSave(record,field,value) {
+    var so = Object(SharedObject.getLocal(record));
+    so.data[field] = value;
+    so.flush();
+};
+
+function LocalLoad(record,field) {
+    return Object(SharedObject.getLocal(record)).data[field];
+};
+
+
+MovieClip.prototype.changeledcolor = function(value,color1,color2,nroboton) {
+    this.start = 1;
+	this.color = 0;
+	var button_number = ExtraeNumeroClip(this);
+
+	_global.valorchangeledcolor[nroboton] = value+1-1;
+    colorhex1 = color1;
+    colorhex2 = color2;
+    color1 = parseInt(color1, 16);
+    color2 = parseInt(color2, 16);
+	this.arraycolor = new Array();
+	this.arraycolor[0] = color1;
+	this.arraycolor[1] = color2;
+    var myColor = new Color(this);
+    if (value==3) {
+        this.onEnterFrame = function() {
+		    this.start+=1;
+            myColor.setRGB(this.arraycolor[this.color]);
+			if(_global.enable_label_background == 1) {
+		    	_root["rectangulo"+button_number]["textobg"].background = 1;
+			    _root["rectangulo"+button_number]["textobg"].backgroundColor = this.arraycolor[this.color];
+			}
+			if(this.start>10) { 
+				this.color = this.color +1;
+				if(this.color > 1) {
+					this.color = 0;
+				}
+				this.start = 0; 
+			}
+        };
+    } else if (value==0 || value==1) {
+        myColor.setRGB(this.arraycolor[value]);
+		if(_global.enable_label_background == 1) {
+		    _root["rectangulo"+button_number]["textobg"].background = 1;
+		    _root["rectangulo"+button_number]["textobg"].backgroundColor = this.arraycolor[value];
+		}
+        delete this.onEnterFrame ;
+	} else {
+        myColor.setRGB(_global.color[0]);
+		if(_global.enable_label_background == 1) {
+	    	_root["rectangulo"+button_number]["textobg"].background = 1;
+		    _root["rectangulo"+button_number]["textobg"].backgroundColor = _global.color[0];
+		}
+        delete this.onEnterFrame ;
+    }
+};
+
+
+MovieClip.prototype.beginDrag = function(target, lock, l, t, r, b) {
+	if (typeof(target) == "string") {
+		target = eval(target);
+	} else if (!(target instanceof MovieClip)) {
+		b = r;
+		r = t;
+		t = l;
+		l = lock;
+		lock = target;
+		target = this;
+	}
+	if (target.dragMethod) {
+		target.endDrag();
+	}
+	target.dragMethod = {MM:target.onMouseMove};
+	ASSetPropFlags(target, "dragMethod", 1, 1);
+	target.addProperty("onMouseMove", arguments.callee.getMM, arguments.callee.setMM);
+	ASSetPropFlags(target, "onMouseMove", 3);
+	var constrain = (arguments.length>1);
+	var off_x = 0, off_y = 0;
+	if (!lock) {
+		off_x = target._parent._xmouse-target._x;
+		off_y = target._parent._ymouse-target._y;
+	}
+	target.dragMethod.drag = function() {
+		target._x = target._parent._xmouse-off_x;
+		target._y = target._parent._ymouse-off_y;
+		if (constrain) {
+			if (typeof(l) == "object") {
+				t = l.ymin;
+				r = l.xmax;
+				b = l.ymax;
+				l = l.xmin;
+			}
+			if (target._x<l) {
+				target._x = l;
+			} else if (target._x>r) {
+				target._x = r;
+			}
+			if (target._y<t) {
+				target._y = t;
+			} else if (target._y>b) {
+				target._y = b;
+			}
+		}
+		updateAfterEvent();
+	};
+};
+
+MovieClip.prototype.beginDrag.getMM = function() {
+	this.dragMethod.drag();
+	return this.dragMethod.MM;
+};
+
+MovieClip.prototype.beginDrag.setMM = function(f) {
+	this.dragMethod.MM = f;
+};
+
+MovieClip.prototype.endDrag = function(target) {
+	if (arguments.length) {
+		if (typeof(target) == "string") {
+			target = eval(target);
+		}
+	} else {
+		target = this;
+	}
+	ASSetPropFlags(target, "onMouseMove", 0, 3);
+	delete target.onMouseMove;
+	if (target.dragMethod.MM) {
+		target.onMouseMove = target.dragMethod.MM;
+	}
+	delete target.dragMethod;
+	target.startDrag();
+	// for _droptarget
+	target.stopDrag();
+};
+
+MovieClip.prototype.flip = function(value) {
+	this.TCG = 100;
+	if (value) {
+		this.onEnterFrame = function() {
+			this._yscale = this._xscale*Math.sin(this.TCG/180*Math.PI);
+			this.TCG += 10;
+			if (this._yscale == this._xscale*-1) {
+				this.stop();
+				delete this.onEnterFrame;
+				this._yscale = this._xscale;
+			}
+		};
+	} else {
+		delete this.onEnterFrame ;
+		this._yscale = this.originalScale;
+	}
+};
+
+MovieClip.prototype.shake = function(value) {
+	if (value) {
+		this.orgX = this._x;
+		this.orgY = this._y;
+		this.toggle = -1;
+		this.onEnterFrame = function() {
+			this.seconds = getTimer();
+			this.modulo = this.seconds%2000;
+			if (this.modulo<100) {
+				if (this.viejotoggle == this.toggle) {
+					this.toggle = this.toggle*-1;
+				} else {
+					this.viejotoggle = this.toggle;
+				}
+			}
+			if (this.toggle>0) {
+				this._x = this.orgX+Math.random()*(value*2)-value;
+				this._y = this.orgY+Math.random()*(value*2)-value;
+				this._rotation = this._rotation-Math.random()*3+Math.random()*3;
+				updateAfterEvent();
+			} else {
+				this._x = this.orgX;
+				this._y = this.orgY;
+				this._rotation = 0;
+			}
+		};
+	} else {
+		delete this.onEnterFrame;
+		this._x = this.orgX;
+		this._y = this.orgY;
+		this._rotation = 0;
+	}
+};
+
+function makeStatusMail(origen) {
+	if(_global.texto_mail[origen]!=undefined) {
+		_level0.statusbar.status.text = _global.texto_mail[origen];
+	}
+}
+function makeStatus(nroboton) {
+	if (_global.texto_tip[nroboton] == undefined) {
+		_global.texto_tip[nroboton] = _global.statusline;
+	}
+	_level0.statusbar.status.text = _global.texto_tip[nroboton];
+}
+
+function displaydetails(clip) {
+	var button_number = ExtraeNumeroClip(clip);
+	//		  _root["rectangulo"+pepe].flip(1);
+	// 		  _root["resaltado"+pepe].flip(1);
+	if (clip._currentframe>=3) {
+		_root.detail._x = clip._parent._x;
+		// FIXME get actual screen width or canvas size and
+		// details windows widht to perform calculation of x asis.
+		if ((_root.detail._x+200)>960) {
+			_root.detail._x = 960-200;
+		}
+		_root.detail._y = clip._parent._y;
+		if ((_root.detail._y+100)>600) {
+			_root.detail._y = 600-100;
+		}
+	
+		_root.detail._alpha = 90;
+		_root.detail._visible = true;
+		ind = clip._name.substring(6);
+		ind = ExtraeNumeroClip(clip);
+		if (st_originclid[ind] != undefined) {
+			_level0.detail.label = vr.detail_from;
+			_level0.detail.clid = st_originclid[ind];
+		} else if (st_destinationclid[ind] != undefined) {
+			_level0.detail.label = vr.detail_to;
+			_level0.detail.clid = st_destinationclid[ind];
+		} else {
+			_root.detail.label = "Status:";
+			_root.detail.clid = "none";
+			_root.detail._visible = false;
+			_root.superdetails.texto = _global.st_direction[ind];
+			_root.superdetails._visible = true;
+			_root.detail._visible = false;
+		}
+		if (st_duration[ind] != "") {
+			_root.detail.duration = st_duration[ind];
+		} else if (st_duration[ind] == "" && (st_originclid[ind] != "" || st_destinationclid[ind] != "")) {
+			_root.detail.duration = "not answered";
+		} else {
+			_root.detail.duration = "";
+		}
+
+		var id = eval("queuemember." + ind);
+		_global.superdetailstexttab2 = ""; 
+		for (var a in id) {
+			_global.superdetailstexttab2 += _global.queuemember[ind][a];
+		} 
+		_global.superdetailstexttab1 = _global.st_direction[ind];
+		if (_global.superdetailstexttab1 == undefined)
+        {
+			_global.superdetailstexttab1 = vr.no_data_text;
+			_root.superdetails.tab1.gotoAndStop(2);
+			_root.superdetails.tab2.gotoAndStop(1);
+			_root.superdetails.texto = _global.superdetailstexttab2;
+		} else {
+			_root.superdetails.tab1.gotoAndStop(1);
+			_root.superdetails.tab2.gotoAndStop(2);
+			_root.superdetails.texto = _global.superdetailstexttab1;
+		}
+	} // end if currentframe>=3
+}
+
+function doubleClick(clip) {
+	// Funcion que detecta doble click y corta llamada
+
+	if (lastclick == 0) {
+
+        lastclick = getTimer();
+	    lastclip = clip;
+
+    } else {
+
+        if(lastclip == clip) {
+
+           logea ("double click "+clip);
+           lastclick = 0;
+
+		   if (_global.claveingresada == undefined) {
+		   	  _root.codebox._visible = true;
+			  Selection.setFocus(_root.codebox.claveform);
+			  _root.codebox.swapDepths(_root.log);
+			  return;
+		   }
+
+		   var numeroclip = ExtraeNumeroClip(clip);
+
+	
+		   if (defined(_global.restrict)) {
+		   	  if (_global.restrict == numeroclip) {
+				  logea("Authorized double click"+_global.restrict);
+			  } else {
+				  logea("Button Restriction in effect "+_global.restrict);
+				  return;
+			  }
+		   }
+
+			/* op_actions new_way 
+	  		if (_global.authorized == true) {
+			    envia_comando("doubleclick",clip,"");
+			} else {
+		   	    _root.codebox._visible = true;
+			    Selection.setFocus(_root.codebox.claveform);
+			    _root.codebox.swapDepths(_root.log);
+			    return;
+			}
+			*/
+
+ 		   /* old_way */
+		   if (clip._name.substring(0, 7) == "casilla") {
+	 		   envia_comando("cortar",clip,"");
+		   } else if (clip._name.substring(0,9)=="sobrecito") {
+			   envia_comando("voicemail",clip,"0");
+		   } else {
+			   displaydetails(clip);
+		   }
+		   /* end */
+	    }
+    }
+}
+
+function dragStop(clip, x, y) {
+    clip_arrastrado = undefined;
+	clip._parent.swapDepths("_level0.tele"+masalto);
+	//	clip.stopDrag();
+	clip.endDrag();
+	clip._x = x;
+	clip._y = y;
+	var destino = "";
+	var origen = "";
+	var origencompleto = "";
+	//var origen = "" + eval(clip._name);
+	//origen = origen.substring(12);
+	origen = ExtraeNumeroClip(clip);
+
+
+    var columna = int((_xmouse+ancho_boton+separacion)/(ancho_boton+separacion));
+    var fila = int((_ymouse-30-separacion)/(alto_boton+separacion))+1;
+    if (columna<1) {
+            columna = 0;
+    }
+    if (columna>cuantas_columnas) {
+         columna = 0;
+    }
+    if (fila>cuantas_filas) {
+         fila = 0;
+    }
+    if (fila<1) {
+         fila = 0;
+    }
+	if(columna>0 && fila>0) {
+    	destino = ((columna*cuantas_filas)-cuantas_filas)+fila;
+    }
+
+    logea("droptarget "+clip._droptarget+" clip "+clip);
+    logea("sobrehit  "+_global.sobrehit);
+    /* USANDO DROPTARGET 
+	for (s=1; s<clip._droptarget.length; s++) {
+		var c = clip._droptarget.charAt(s);
+		if (c == "/") {
+			break;
+		}
+		if (c<"0" || c>"9") {
+		} else {
+			destino = destino+""+c;
+		}
+	}
+    */
+
+
+	clip._x = x;
+	clip._y = y;
+	flechita_frame = _root["rectangulo"+origen]["flecha"+origen]._currentframe;
+
+	if(timer_type[origen]=="UP"||timer_type[origen]=="DOWN")
+	{
+		f_origen = 0;
+	} else {
+		f_origen = 1;
+	}
+
+	if(timer_type[destino]=="UP"||timer_type[destino]=="DOWN")
+	{
+		f_destino = 0;
+	} else {
+		f_destino = 1;
+	}
+//	f_origen       = timer_type[origen];
+//	f_destino      = timer_type[destino];
+	var extraclid = Trim(infotext1.clidvalue);
+	if (extraclid == undefined) {
+		extraclid = "";
+	}
+	logea("f_origen "+f_origen+" f_destino "+f_destino);
+	logea("origen "+origen+" destino "+destino);
+	if (_global.sobrehit != undefined) {
+		destino = ExtraeNumeroClip(_global.sobrehit);
+		logea("transfiero "+origen+" a destino voicemail "+destino);
+		envia_comando("tovoicemail", origen, destino);
+	} else {
+	if (destino!="" && origen!=destino) {
+		if (f_origen==1 && f_destino==0) {
+			// tranferencia 3 way a meetme
+			logea("Attempt to conference "+origen+" with "+destino);
+			envia_comando("conference", origen, destino);
+		} else if ((f_origen==0 || flechita_frame == 1 || f_origen==-1) && (f_destino==1 || f_destino == 0)) {
+			// transferencia normal
+			logea("Attempt to transfer "+origen+" to "+destino);
+			if (extraclid != "" && extraclid != "undefined") {
+				extraclid = only_allowed_chars(extraclid);
+				var comando = "ctransferir-"+extraclid+"-";
+				infotext1.clidvalue = "";
+			} else {
+				var comando = "transferir";
+			}
+			if(_global.timeout_value>0) {
+				comando= comando+"+"+_global.timeout_value+"+";
+				logea("transfiero con timeout "+_global.timeout_value);
+			}
+			logea("comando "+comando);
+			envia_comando(comando, origen, destino);
+		} else {
+			// originar llamado
+			logea("Attempt to origin call from "+origen+" to "+destino);
+			logea("f_origen "+f_origen+" f_destino "+f_destino);
+			logea("timeout "+_global.timeout_value);
+			if (extraclid != "" && extraclid != "undefined") {
+				extraclid = only_allowed_chars(extraclid);
+				var comando = "coriginate-"+extraclid+"-";
+				infotext1.clidvalue = "";
+			} else {
+				var comando = "originate";
+			}
+			if(_global.timeout_value > 0) {
+				comando= comando+"+"+_global.timeout_value+"+";
+				logea("origino con timeout "+_global.timeout_value);
+			}
+			envia_comando(comando, origen, destino);
+		}
+	} else {
+		logea("drag to itself or single click");
+    }
+	}
+}
+
+function only_allowed_chars(str) {
+	allowed = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789)(,";
+	var temp = new String("");
+	for (a=0; a<str.length; a++) {
+		var letra = str.substr(a, 1);
+		var pepe = allowed.IndexOf(letra);
+		if (allowed.indexof(letra) == -1) {
+			temp += " ";
+		} else {
+			temp += letra;
+		}
+	}
+	return temp;
+}
+
+function MuestraLog() {
+	if (log._visible == true) {
+		log._visible = false;
+//		_root.soundHolder.mySound.stop();
+		//delete _root.soundHolder.mySound.stop();
+	} else {
+		log._visible = true;
+		log.swapDepths(_root.codebox);
+//		_root.soundHolder.mySound.start();
+	}
+}
+
+function ExtraeNumeroClip(name) {
+	var destino = "";
+	name = name._name;
+	for (var s = 0; s<name.length; s++) {
+		var c = name.charAt(s);
+		if (c<"0" || c>"9") {
+		} else {
+			destino = destino+""+c;
+		}
+		if (c == ".") {
+			destino = "";
+		}
+	}
+	return destino;
+}
+
+function dragClip(clip) {
+    clip_arrastrado = clip;
+	var numeroclip = ""+eval(clip._name);
+	numeroclip = numeroclip.substring(12);
+	startX = clip._x;
+	startY = clip._y;
+	clip._parent.swapDepths("_level0.tele"+masalto);
+	clip.beginDrag(true);
+	clip.onRelease = function() {
+		dragStop(clip, startX, startY);
+	};
+	clip.onReleaseOutside = function() {
+		dragStop(clip, startX, startY);
+	};
+}
+
+envia_comando = function (comando, origen, destino) {
+	if (comando != "bogus" && comando != "contexto" && comando != "restrict") {
+		if (_global.restrict!=0) {
+			if(comando == "cortar") {
+				origen_number = ExtraeNumeroClip(origen);
+			} else {
+				origen_number = origen;
+			}
+			//logea("Origen "+origen_number);
+			//logea("Destino "+destino);
+			//logea("Restrict "+_global.restrict);
+			if(_global.restrict != undefined) {
+			    if (_global.restrict == origen_number ) {
+				    logea("Authorized envia_comando");
+   			    } else {
+				    logea("Button restriction in effect envia_comando "+_global.restrict);
+				return;
+			    }
+			} else {
+				// logea("global_restrict not defined?");
+			}
+		}
+	}
+	message = new XML();
+	message_data = message.createElement("msg");
+	if (_root.context.length>0) {
+		agrega_contexto = "@"+context;
+	}
+	if (agrega_contexto == undefined) {
+		agrega_contexto = "";
+	}
+	if (_level0.claveinput.secret == undefined) {
+		_level0.claveinput.secret = "";
+	}
+	if (_global.claveingresada == undefined && ( comando != "contexto" && comando != "bogus" && comando != "dial" && comando != "restrict")) {
+		_root.codebox._visible = true;
+		Selection.setFocus(_root.codebox.claveform);
+		_root.codebox.swapDepths(_root.log);
+		return;
+	}
+	// var clave=_level0.claveinput.secret+_global.key;
+	var clave = _global.claveingresada+_global.key;
+	var md5clave = "";
+	var md5clave = calcMD5(clave);
+	if (comando == "contexto" || comando == "restrict") {
+		md5clave = "";
+	}
+	message_data.attributes.data = origen+agrega_contexto+"|"+comando+destino+"|"+md5clave;
+	message.appendChild(message_data);
+	_global.sock.send(message);
+	var clave = "";
+};
+
+function LTrim(str) {
+	var whitespace = new String(" \t\n\r");
+	var s = new String(str);
+	if (whitespace.indexOf(s.charAt(0)) != -1) {
+		var j = 0, i = s.length;
+		while (j<i && whitespace.indexOf(s.charAt(j)) != -1) {
+			j++;
+		}
+		s = s.substring(j, i);
+	}
+	return s;
+}
+
+function RTrim(str) {
+	var whitespace = new String(" \t\n\r");
+	var s = new String(str);
+	if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {
+		var i = s.length-1;
+		// Get length of string
+		while (i>=0 && whitespace.indexOf(s.charAt(i)) != -1) {
+			i--;
+		}
+		s = s.substring(0, i+1);
+	}
+	return s;
+}
+
+function Trim(str) {
+	return RTrim(LTrim(str));
+}
+
+function setDND(obj, item) {
+	var nroboton = ExtraeNumeroClip(obj);
+	logea(item.caption+" for button "+nroboton);
+	envia_comando("dnd", nroboton, nroboton);
+}
+
+function genera_selecttimeout() {
+
+	_global.positionselect = 0;
+	test = attachMovie("option","optionselected", getNextHighestDepth(),  {_x:800, _y:6});
+	test._visible = true;
+	test.legend = "No timeout";
+
+	test.onPress = function() {
+	     _root.despliega_select();
+	};
+
+
+	 for (a=0; a<5; a++) {
+		var b=a+1;
+		if (_global.opcionesTimeout[a] != undefined) {
+
+			testa = attachMovie("option","option"+a, getNextHighestDepth(),  {_x:800, _y:(b*22)+6});
+			testa.legend = _global.opcionesTimeout[a];
+			testa._visible = false;
+
+
+			testa.onRollOver = function() {
+           	 	this.legend = "* "+this.legend;
+        	};
+
+   		 	testa.onRollOut = function() {
+	            this.legend = this.legend.substring(2, this.legend.length);
+    		};
+
+			testa.onPress = function() {
+	            this.legend = this.legend.substring(2, this.legend.length);
+				var posicion = ExtraeNumeroClip(this);
+				_global.timeout_value = _global.opcionesTimeoutSecs[posicion];
+				_root.logea("timeout "+_global.timeout_value);
+				_root.muestra_selecttimeout(0);
+				_root.selectbox1.gotoAndStop(1);
+				_root.optionselected._visible=true;
+				_root.optionselected.legend = this.legend;
+			};
+		}
+	}
+};
+
+function muestra_selecttimeout(value) {
+	 for (a=0; a<5; a++) {
+	 	var v = eval("_root.option"+a);
+		if(value) {
+			v._visible = true;
+		} else {
+			v._visible = false;
+		}
+	 }
+};
+
+function despliega_select() {
+	_root.optionselected._visible=false;
+	_root.selectbox1.gotoAndStop(2);
+	_root.muestra_selecttimeout(1);
+
+};
+
+function base64_decode(opString) {
+	if ( opString == undefined ) {
+		return;
+	} 
+	var str = opString;
+	var base64s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	var bits, bit1, bit2, bit3, bit4, i = 0;
+	var decOut = "";
+	for (i=0; i<str.length; i += 4) {
+		bit1 = (base64s.indexOf(str.charAt(i)) & 0xff) << 18 ;
+		bit2 = (base64s.indexOf(str.charAt(i+1)) & 0xff) << 12 ;
+		bit3 = (base64s.indexOf(str.charAt(i+2)) & 0xff) << 6 ;
+		bit4 = (base64s.indexOf(str.charAt(i+3)) & 0xff);
+		bits = bit1 | bit2 | bit3 | bit4;
+		decOut += String.fromCharCode((bits & 0xff0000) >> 16, (bits & 0xff00) >> 8, bits & 0xff);
+	}
+	if (str.charCodeAt(i-2) == 61) {
+		return decOut.substring(0, decOut.length-2);
+	} else if (str.charCodeAt(i-1) == 61) {
+		return decOut.substring(0, decOut.length-1);
+	} else {
+		return decOut.substring(0, decOut.length);
+	}
+};
+
+
+
+// MD5 ROUTINE
+/*
+ * Convert a 32-bit number to a hex string with ls-byte first
+ */
+var hex_chr = "0123456789abcdef";
+// 
+// somehow the expression (bitAND(b, c) | bitAND((~b), d)) didn't return coorect results on Mac
+// for: 
+// b&c = a8a20450, ((~b)&d) = 0101c88b, (bitAND(b, c) | bitAND((~b), d)) = a8a20450 <-- !!!
+// looks like the OR is not executed at all.
+//
+// let's try to trick the P-code compiler into working with us... Prayer beads are GO!
+// 
+function bitOR(a, b) {
+	var lsb = (a & 0x1) | (b & 0x1);
+	var msb31 = (a >>> 1) | (b >>> 1);
+	return (msb31 << 1) | lsb;
+}
+//  
+// will bitXOR be the only one working...?
+// Nope. XOR fails too if values with bit31 set are XORed. 
+//
+// Note however that OR (and AND and XOR?!) works alright for the statement
+//   (msb31 << 1) | lsb
+// even if the result of the left-shift operation has bit 31 set.
+// So there might be an extra condition here (Guessmode turned on):
+// Mac Flash fails (OR, AND and XOR) if either one of the input operands has bit31 set
+// *and* both operands have one or more bits both set to 1. In other words: when both
+// input bit-patterns 'overlap'.
+// Stuff to munch on for the MM guys, I guess...
+//
+function bitXOR(a, b) {
+	var lsb = (a & 0x1) ^ (b & 0x1);
+	var msb31 = (a >>> 1) ^ (b >>> 1);
+	return (msb31 << 1) | lsb;
+}
+// 
+// bitwise AND for 32-bit integers. This uses 31 + 1-bit operations internally
+// to work around bug in some AS interpreters. (Mac Flash!)
+// 
+function bitAND(a, b) {
+	var lsb = (a & 0x1) & (b & 0x1);
+	var msb31 = (a >>> 1) & (b >>> 1);
+	return (msb31 << 1) | lsb;
+	// return (a & b);
+}
+// 
+// Add integers, wrapping at 2^32. This uses 16-bit operations internally
+// to work around bugs in some AS interpreters. (Mac Flash!)
+// 
+function addme(x, y) {
+	var lsw = (x & 0xFFFF)+(y & 0xFFFF);
+	var msw = (x >> 16)+(y >> 16)+(lsw >> 16);
+	return (msw << 16) | (lsw & 0xFFFF);
+}
+function rhex(num) {
+	str = "";
+	for (j=0; j<=3; j++) {
+		str += hex_chr.charAt((num >> (j*8+4)) & 0x0F)+hex_chr.charAt((num >> (j*8)) & 0x0F);
+	}
+	return str;
+}
+/*
+ * Convert a string to a sequence of 16-word blocks, stored as an array.
+ * Append padding bits and the length, as described in the MD5 standard.
+ */
+function str2blks_MD5(str) {
+	nblk = ((str.length+8) >> 6)+1;
+	// 1 + (len + 8)/64
+	blks = new Array(nblk*16);
+	for (i=0; i<nblk*16; i++) {
+		blks[i] = 0;
+	}
+	/*
+				Input: 
+				
+				'willi' without the quotes.
+				
+				trace() Output on Intel (and MAC now?):
+				
+				see TXT files: *.Output.txt
+				
+				*/
+	for (i=0; i<str.length; i++) {
+		blks[i >> 2] |= str.charCodeAt(i) << (((str.length*8+i)%4)*8);
+	}
+	blks[i >> 2] |= 0x80 << (((str.length*8+i)%4)*8);
+	var l = str.length*8;
+	blks[nblk*16-2] = (l & 0xFF);
+	blks[nblk*16-2] |= ((l >>> 8) & 0xFF) << 8;
+	blks[nblk*16-2] |= ((l >>> 16) & 0xFF) << 16;
+	blks[nblk*16-2] |= ((l >>> 24) & 0xFF) << 24;
+	return blks;
+}
+/*
+ * Bitwise rotate a 32-bit number to the left
+ */
+function rol(num, cnt) {
+	return (num << cnt) | (num >>> (32-cnt));
+}
+/*
+ * These functions implement the basic operation for each round of the
+ * algorithm.
+ */
+function cmn(q, a, b, x, s, t) {
+	return addme(rol((addme(addme(a, q), addme(x, t))), s), b);
+}
+
+function ff(a, b, c, d, x, s, t) {
+	return cmn(bitOR(bitAND(b, c), bitAND((~b), d)), a, b, x, s, t);
+}
+
+function gg(a, b, c, d, x, s, t) {
+	return cmn(bitOR(bitAND(b, d), bitAND(c, (~d))), a, b, x, s, t);
+}
+
+function hh(a, b, c, d, x, s, t) {
+	return cmn(bitXOR(bitXOR(b, c), d), a, b, x, s, t);
+}
+
+function ii(a, b, c, d, x, s, t) {
+	return cmn(bitXOR(c, bitOR(b, (~d))), a, b, x, s, t);
+}
+/*
+ * Take a string and return the hex representation of its MD5.
+ */
+function calcMD5(str) {
+	x = str2blks_MD5(str);
+	a = 1732584193;
+	b = -271733879;
+	c = -1732584194;
+	d = 271733878;
+	var step;
+	for (i=0; i<x.length; i += 16) {
+		olda = a;
+		oldb = b;
+		oldc = c;
+		oldd = d;
+		step = 0;
+		a = ff(a, b, c, d, x[i+0], 7, -680876936);
+		d = ff(d, a, b, c, x[i+1], 12, -389564586);
+		c = ff(c, d, a, b, x[i+2], 17, 606105819);
+		b = ff(b, c, d, a, x[i+3], 22, -1044525330);
+		a = ff(a, b, c, d, x[i+4], 7, -176418897);
+		d = ff(d, a, b, c, x[i+5], 12, 1200080426);
+		c = ff(c, d, a, b, x[i+6], 17, -1473231341);
+		b = ff(b, c, d, a, x[i+7], 22, -45705983);
+		a = ff(a, b, c, d, x[i+8], 7, 1770035416);
+		d = ff(d, a, b, c, x[i+9], 12, -1958414417);
+		c = ff(c, d, a, b, x[i+10], 17, -42063);
+		b = ff(b, c, d, a, x[i+11], 22, -1990404162);
+		a = ff(a, b, c, d, x[i+12], 7, 1804603682);
+		d = ff(d, a, b, c, x[i+13], 12, -40341101);
+		c = ff(c, d, a, b, x[i+14], 17, -1502002290);
+		b = ff(b, c, d, a, x[i+15], 22, 1236535329);
+		a = gg(a, b, c, d, x[i+1], 5, -165796510);
+		d = gg(d, a, b, c, x[i+6], 9, -1069501632);
+		c = gg(c, d, a, b, x[i+11], 14, 643717713);
+		b = gg(b, c, d, a, x[i+0], 20, -373897302);
+		a = gg(a, b, c, d, x[i+5], 5, -701558691);
+		d = gg(d, a, b, c, x[i+10], 9, 38016083);
+		c = gg(c, d, a, b, x[i+15], 14, -660478335);
+		b = gg(b, c, d, a, x[i+4], 20, -405537848);
+		a = gg(a, b, c, d, x[i+9], 5, 568446438);
+		d = gg(d, a, b, c, x[i+14], 9, -1019803690);
+		c = gg(c, d, a, b, x[i+3], 14, -187363961);
+		b = gg(b, c, d, a, x[i+8], 20, 1163531501);
+		a = gg(a, b, c, d, x[i+13], 5, -1444681467);
+		d = gg(d, a, b, c, x[i+2], 9, -51403784);
+		c = gg(c, d, a, b, x[i+7], 14, 1735328473);
+		b = gg(b, c, d, a, x[i+12], 20, -1926607734);
+		a = hh(a, b, c, d, x[i+5], 4, -378558);
+		d = hh(d, a, b, c, x[i+8], 11, -2022574463);
+		c = hh(c, d, a, b, x[i+11], 16, 1839030562);
+		b = hh(b, c, d, a, x[i+14], 23, -35309556);
+		a = hh(a, b, c, d, x[i+1], 4, -1530992060);
+		d = hh(d, a, b, c, x[i+4], 11, 1272893353);
+		c = hh(c, d, a, b, x[i+7], 16, -155497632);
+		b = hh(b, c, d, a, x[i+10], 23, -1094730640);
+		a = hh(a, b, c, d, x[i+13], 4, 681279174);
+		d = hh(d, a, b, c, x[i+0], 11, -358537222);
+		c = hh(c, d, a, b, x[i+3], 16, -722521979);
+		b = hh(b, c, d, a, x[i+6], 23, 76029189);
+		a = hh(a, b, c, d, x[i+9], 4, -640364487);
+		d = hh(d, a, b, c, x[i+12], 11, -421815835);
+		c = hh(c, d, a, b, x[i+15], 16, 530742520);
+		b = hh(b, c, d, a, x[i+2], 23, -995338651);
+		a = ii(a, b, c, d, x[i+0], 6, -198630844);
+		d = ii(d, a, b, c, x[i+7], 10, 1126891415);
+		c = ii(c, d, a, b, x[i+14], 15, -1416354905);
+		b = ii(b, c, d, a, x[i+5], 21, -57434055);
+		a = ii(a, b, c, d, x[i+12], 6, 1700485571);
+		d = ii(d, a, b, c, x[i+3], 10, -1894986606);
+		c = ii(c, d, a, b, x[i+10], 15, -1051523);
+		b = ii(b, c, d, a, x[i+1], 21, -2054922799);
+		a = ii(a, b, c, d, x[i+8], 6, 1873313359);
+		d = ii(d, a, b, c, x[i+15], 10, -30611744);
+		c = ii(c, d, a, b, x[i+6], 15, -1560198380);
+		b = ii(b, c, d, a, x[i+13], 21, 1309151649);
+		a = ii(a, b, c, d, x[i+4], 6, -145523070);
+		d = ii(d, a, b, c, x[i+11], 10, -1120210379);
+		c = ii(c, d, a, b, x[i+2], 15, 718787259);
+		b = ii(b, c, d, a, x[i+9], 21, -343485551);
+		a = addme(a, olda);
+		b = addme(b, oldb);
+		c = addme(c, oldc);
+		d = addme(d, oldd);
+	}
+	return rhex(a)+rhex(b)+rhex(c)+rhex(d);
+}
+
+
+// TEA2
+
+c2b = new Object();
+c2b['\\000'] = 0;
+c2b["\001"] = 1;
+c2b["\002"] = 2;
+c2b["\003"] = 3;
+c2b["\004"] = 4;
+c2b["\005"] = 5;
+c2b["\006"] = 6;
+c2b["\007"] = 7;
+c2b["\010"] = 8;
+c2b["\011"] = 9;
+c2b["\012"] = 10;
+c2b["\013"] = 11;
+c2b["\014"] = 12;
+c2b["\015"] = 13;
+c2b["\016"] = 14;
+c2b["\017"] = 15;
+c2b["\020"] = 16;
+c2b["\021"] = 17;
+c2b["\022"] = 18;
+c2b["\023"] = 19;
+c2b["\024"] = 20;
+c2b["\025"] = 21;
+c2b["\026"] = 22;
+c2b["\027"] = 23;
+c2b["\030"] = 24;
+c2b["\031"] = 25;
+c2b["\032"] = 26;
+c2b["\033"] = 27;
+c2b["\034"] = 28;
+c2b["\035"] = 29;
+c2b["\036"] = 30;
+c2b["\037"] = 31;
+c2b["\040"] = 32;
+c2b["\041"] = 33;
+c2b['\042'] = 34;
+c2b["\043"] = 35;
+c2b["\044"] = 36;
+c2b["\045"] = 37;
+c2b["\046"] = 38;
+c2b["\047"] = 39;
+c2b["\050"] = 40;
+c2b["\051"] = 41;
+c2b["\052"] = 42;
+c2b["\053"] = 43;
+c2b["\054"] = 44;
+c2b["\055"] = 45;
+c2b["\056"] = 46;
+c2b["\057"] = 47;
+c2b["\060"] = 48;
+c2b["\061"] = 49;
+c2b["\062"] = 50;
+c2b["\063"] = 51;
+c2b["\064"] = 52;
+c2b["\065"] = 53;
+c2b["\066"] = 54;
+c2b["\067"] = 55;
+c2b["\070"] = 56;
+c2b["\071"] = 57;
+c2b["\072"] = 58;
+c2b["\073"] = 59;
+c2b["\074"] = 60;
+c2b["\075"] = 61;
+c2b["\076"] = 62;
+c2b["\077"] = 63;
+c2b["\100"] = 64;
+c2b["\101"] = 65;
+c2b["\102"] = 66;
+c2b["\103"] = 67;
+c2b["\104"] = 68;
+c2b["\105"] = 69;
+c2b["\106"] = 70;
+c2b["\107"] = 71;
+c2b["\110"] = 72;
+c2b["\111"] = 73;
+c2b["\112"] = 74;
+c2b["\113"] = 75;
+c2b["\114"] = 76;
+c2b["\115"] = 77;
+c2b["\116"] = 78;
+c2b["\117"] = 79;
+c2b["\120"] = 80;
+c2b["\121"] = 81;
+c2b["\122"] = 82;
+c2b["\123"] = 83;
+c2b["\124"] = 84;
+c2b["\125"] = 85;
+c2b["\126"] = 86;
+c2b["\127"] = 87;
+c2b["\130"] = 88;
+c2b["\131"] = 89;
+c2b["\132"] = 90;
+c2b["\133"] = 91;
+var pepe="\";
+c2b[pepe] = 92;
+var pepe="]";
+c2b[pepe] = 93;
+c2b["\136"] = 94;
+c2b["\137"] = 95;
+c2b["\140"] = 96;
+c2b["\141"] = 97;
+c2b["\142"] = 98;
+c2b["\143"] = 99;
+c2b["\144"] = 100;
+c2b["\145"] = 101;
+c2b["\146"] = 102;
+c2b["\147"] = 103;
+c2b["\150"] = 104;
+c2b["\151"] = 105;
+c2b["\152"] = 106;
+c2b["\153"] = 107;
+c2b["\154"] = 108;
+c2b["\155"] = 109;
+c2b["\156"] = 110;
+c2b["\157"] = 111;
+c2b["\160"] = 112;
+c2b["\161"] = 113;
+c2b["\162"] = 114;
+c2b["\163"] = 115;
+c2b["\164"] = 116;
+c2b["\165"] = 117;
+c2b["\166"] = 118;
+c2b["\167"] = 119;
+c2b["\170"] = 120;
+c2b["\171"] = 121;
+c2b["\172"] = 122;
+c2b["\173"] = 123;
+c2b["\174"] = 124;
+c2b["\175"] = 125;
+c2b["\176"] = 126;
+c2b["\177"] = 127;
+c2b["\200"] = 128;
+c2b["\201"] = 129;
+c2b["\202"] = 130;
+c2b["\203"] = 131;
+c2b["\204"] = 132;
+c2b["\205"] = 133;
+c2b["\206"] = 134;
+c2b["\207"] = 135;
+c2b["\210"] = 136;
+c2b["\211"] = 137;
+c2b["\212"] = 138;
+c2b["\213"] = 139;
+c2b["\214"] = 140;
+c2b["\215"] = 141;
+c2b["\216"] = 142;
+c2b["\217"] = 143;
+c2b["\220"] = 144;
+c2b["\221"] = 145;
+c2b["\222"] = 146;
+c2b["\223"] = 147;
+c2b["\224"] = 148;
+c2b["\225"] = 149;
+c2b["\226"] = 150;
+c2b["\227"] = 151;
+c2b["\230"] = 152;
+c2b["\231"] = 153;
+c2b["\232"] = 154;
+c2b["\233"] = 155;
+c2b["\234"] = 156;
+c2b["\235"] = 157;
+c2b["\236"] = 158;
+c2b["\237"] = 159;
+c2b["\240"] = 160;
+c2b["\241"] = 161;
+c2b["\242"] = 162;
+c2b["\243"] = 163;
+c2b["\244"] = 164;
+c2b["\245"] = 165;
+c2b["\246"] = 166;
+c2b["\247"] = 167;
+c2b["\250"] = 168;
+c2b["\251"] = 169;
+c2b["\252"] = 170;
+c2b["\253"] = 171;
+c2b["\254"] = 172;
+c2b["\255"] = 173;
+c2b["\256"] = 174;
+c2b["\257"] = 175;
+c2b["\260"] = 176;
+c2b["\261"] = 177;
+c2b["\262"] = 178;
+c2b["\263"] = 179;
+c2b["\264"] = 180;
+c2b["\265"] = 181;
+c2b["\266"] = 182;
+c2b["\267"] = 183;
+c2b["\270"] = 184;
+c2b["\271"] = 185;
+c2b["\272"] = 186;
+c2b["\273"] = 187;
+c2b["\274"] = 188;
+c2b["\275"] = 189;
+c2b["\276"] = 190;
+c2b["\277"] = 191;
+c2b["\300"] = 192;
+c2b["\301"] = 193;
+c2b["\302"] = 194;
+c2b["\303"] = 195;
+c2b["\304"] = 196;
+c2b["\305"] = 197;
+c2b["\306"] = 198;
+c2b["\307"] = 199;
+c2b["\310"] = 200;
+c2b["\311"] = 201;
+c2b["\312"] = 202;
+c2b["\313"] = 203;
+c2b["\314"] = 204;
+c2b["\315"] = 205;
+c2b["\316"] = 206;
+c2b["\317"] = 207;
+c2b["\320"] = 208;
+c2b["\321"] = 209;
+c2b["\322"] = 210;
+c2b["\323"] = 211;
+c2b["\324"] = 212;
+c2b["\325"] = 213;
+c2b["\326"] = 214;
+c2b["\327"] = 215;
+c2b["\330"] = 216;
+c2b["\331"] = 217;
+c2b["\332"] = 218;
+c2b["\333"] = 219;
+c2b["\334"] = 220;
+c2b["\335"] = 221;
+c2b["\336"] = 222;
+c2b["\337"] = 223;
+c2b["\340"] = 224;
+c2b["\341"] = 225;
+c2b["\342"] = 226;
+c2b["\343"] = 227;
+c2b["\344"] = 228;
+c2b["\345"] = 229;
+c2b["\346"] = 230;
+c2b["\347"] = 231;
+c2b["\350"] = 232;
+c2b["\351"] = 233;
+c2b["\352"] = 234;
+c2b["\353"] = 235;
+c2b["\354"] = 236;
+c2b["\355"] = 237;
+c2b["\356"] = 238;
+c2b["\357"] = 239;
+c2b["\360"] = 240;
+c2b["\361"] = 241;
+c2b["\362"] = 242;
+c2b["\363"] = 243;
+c2b["\364"] = 244;
+c2b["\365"] = 245;
+c2b["\366"] = 246;
+c2b["\367"] = 247;
+c2b["\370"] = 248;
+c2b["\371"] = 249;
+c2b["\372"] = 250;
+c2b["\373"] = 251;
+c2b["\374"] = 252;
+c2b["\375"] = 253;
+c2b["\376"] = 254;
+c2b["\377"] = 255;
+b2c = new Object();
+for (b in c2b) {
+	b2c[c2b[b]] = b;
+}
+
+
+// ascii to 6-bit bin to ascii
+a2b = new Object();
+a2b["A"] = 0;
+a2b["B"] = 1;
+a2b["C"] = 2;
+a2b["D"] = 3;
+a2b["E"] = 4;
+a2b["F"] = 5;
+a2b["G"] = 6;
+a2b["H"] = 7;
+a2b["I"] = 8;
+a2b["J"] = 9;
+a2b["K"] = 10;
+a2b["L"] = 11;
+a2b["M"] = 12;
+a2b["N"] = 13;
+a2b["O"] = 14;
+a2b["P"] = 15;
+a2b["Q"] = 16;
+a2b["R"] = 17;
+a2b["S"] = 18;
+a2b["T"] = 19;
+a2b["U"] = 20;
+a2b["V"] = 21;
+a2b["W"] = 22;
+a2b["X"] = 23;
+a2b["Y"] = 24;
+a2b["Z"] = 25;
+a2b["a"] = 26;
+a2b["b"] = 27;
+a2b["c"] = 28;
+a2b["d"] = 29;
+a2b["e"] = 30;
+a2b["f"] = 31;
+a2b["g"] = 32;
+a2b["h"] = 33;
+a2b["i"] = 34;
+a2b["j"] = 35;
+a2b["k"] = 36;
+a2b["l"] = 37;
+a2b["m"] = 38;
+a2b["n"] = 39;
+a2b["o"] = 40;
+a2b["p"] = 41;
+a2b["q"] = 42;
+a2b["r"] = 43;
+a2b["s"] = 44;
+a2b["t"] = 45;
+a2b["u"] = 46;
+a2b["v"] = 47;
+a2b["w"] = 48;
+a2b["x"] = 49;
+a2b["y"] = 50;
+a2b["z"] = 51;
+a2b["0"] = 52;
+a2b["1"] = 53;
+a2b["2"] = 54;
+a2b["3"] = 55;
+a2b["4"] = 56;
+a2b["5"] = 57;
+a2b["6"] = 58;
+a2b["7"] = 59;
+a2b["8"] = 60;
+a2b["9"] = 61;
+a2b["+"] = 62;
+a2b["_"] = 63;
+b2a = new Object();
+for (b in a2b) {
+	b2a[a2b[b]] = ''+b;
+}
+
+function binary2ascii(s) {
+	return bytes2ascii(blocks2bytes(s));
+}
+function binary2str(s) {
+	return bytes2str(blocks2bytes(s));
+}
+function ascii2binary(s) {
+	return bytes2blocks(ascii2bytes(s));
+}
+function str2binary(s) {
+	return bytes2blocks(str2bytes(s));
+}
+function str2bytes(s) {
+	var is = 0;
+	var ls = s.length;
+	var b = new Array();
+	while (1) {
+		if (is>=ls) {
+			break;
+		}
+		var pepe=s.charAt(is);
+		if (c2b[s.charAt(is)] == null) {
+			b[is] = 0xF7;
+		} else {
+			b[is] = c2b[s.charAt(is)];
+		}
+		is++;
+	}
+	return b;
+}
+function bytes2str(b) {
+	var ib = 0;
+	var lb = b.length;
+	var s = '';
+	while (1) {
+		if (ib>=lb) {
+			break;
+		}
+		if (b2c[0xFF & b[ib]]!=undefined) {
+			s += b2c[0xFF & b[ib]];
+		}
+		ib++;
+	}
+	return s;
+}
+function ascii2bytes(a) {
+	var ia = -1;
+	var la = a.length;
+	var ib = 0;
+	var b = new Array();
+	var carry;
+	while (1) {
+		// reads 4 chars and produces 3 bytes
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		b[ib] = a2b[a.charAt(ia)] << 2;
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		carry = a2b[a.charAt(ia)];
+		b[ib] |= carry >>> 4;
+		ib++;
+		carry = 0xF & carry;
+		if (carry == 0 && ia == (la-1)) {
+			return b;
+		}
+		b[ib] = carry << 4;
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		carry = a2b[a.charAt(ia)];
+		b[ib] |= carry >>> 2;
+		ib++;
+		carry = 3 & carry;
+		if (carry == 0 && ia == (la-1)) {
+			return b;
+		}
+		b[ib] = carry << 6;
+		while (1) {
+			ia++;
+			if (ia>=la) {
+				return b;
+			}
+			if (a2b[a.charAt(ia)] != null) {
+				break;
+			}
+		}
+		b[ib] |= a2b[a.charAt(ia)];
+		ib++;
+	}
+	return b;
+}
+function bytes2ascii(b) {
+	var ib = 0;
+	var lb = b.length;
+	var s = '';
+	var b1;
+	var b2;
+	var b3;
+	var carry;
+	while (1) {
+		// reads 3 bytes and produces 4 chars
+		if (ib>=lb) {
+			break;
+		}
+		b1 = 0xFF & b[ib];
+		s += b2a[63 & (b1 >>> 2)];
+		carry = 3 & b1;
+		ib++;
+		if (ib>=lb) {
+			s += b2a[carry << 4];
+			break;
+		}
+		b2 = 0xFF & b[ib];
+		s += b2a[(0xF0 & (carry << 4)) | (b2 >>> 4)];
+		carry = 0xF & b2;
+		ib++;
+		if (ib>=lb) {
+			s += b2a[carry << 2];
+			break;
+		}
+		b3 = 0xFF & b[ib];
+		s += b2a[(60 & (carry << 2)) | (b3 >>> 6)]+b2a[63 & b3];
+		ib++;
+		if (ib%36 == 0) {
+			s += "\n";
+		}
+	}
+	return s;
+}
+function bytes2blocks(bytes) {
+	var blocks = new Array();
+	var ibl = 0;
+	var iby = 0;
+	var nby = bytes.length;
+	while (1) {
+		blocks[ibl] = (0xFF & bytes[iby]) << 24;
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		blocks[ibl] |= (0xFF & bytes[iby]) << 16;
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		blocks[ibl] |= (0xFF & bytes[iby]) << 8;
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		blocks[ibl] |= 0xFF & bytes[iby];
+		iby++;
+		if (iby>=nby) {
+			break;
+		}
+		ibl++;
+	}
+	return blocks;
+}
+function blocks2bytes(blocks) {
+	var bytes = new Array();
+	var iby = 0;
+	var ibl = 0;
+	var nbl = blocks.length;
+	while (1) {
+		if (ibl>=nbl) {
+			break;
+		}
+		bytes[iby] = 0xFF & (blocks[ibl] >>> 24);
+		iby++;
+		bytes[iby] = 0xFF & (blocks[ibl] >>> 16);
+		iby++;
+		bytes[iby] = 0xFF & (blocks[ibl] >>> 8);
+		iby++;
+		bytes[iby] = 0xFF & blocks[ibl];
+		iby++;
+		ibl++;
+	}
+	return bytes;
+}
+function digest_pad(bytearray) {
+	var newarray = new Array();
+	var ina = 0;
+	var iba = 0;
+	var nba = bytearray.length;
+	var npads = 15-(nba%16);
+	newarray[ina] = npads;
+	ina++;
+	while (iba<nba) {
+		newarray[ina] = bytearray[iba];
+		ina++;
+		iba++;
+	}
+	var ip = npads;
+	while (ip>0) {
+		newarray[ina] = 0;
+		ina++;
+		ip--;
+	}
+	return newarray;
+}
+function pad(bytearray) {
+	var newarray = new Array();
+	var ina = 0;
+	var iba = 0;
+	var nba = bytearray.length;
+	var npads = 7-(nba%8);
+	newarray[ina] = (0xF8 & rand_byte()) | (7 & npads);
+	ina++;
+	while (iba<nba) {
+		newarray[ina] = bytearray[iba];
+		ina++;
+		iba++;
+	}
+	var ip = npads;
+	while (ip>0) {
+		newarray[ina] = rand_byte();
+		ina++;
+		ip--;
+	}
+	return newarray;
+}
+function rand_byte() {
+	return Math.floor(256*Math.random());
+	if (!rand_byte_already_called) {
+		var now = new Date();
+		seed = now.milliseconds;
+		rand_byte_already_called = true;
+	}
+	seed = (1029*seed+221591)%1048576;
+	return Math.floor(seed/4096);
+}
+function unpad(bytearray) {
+	var iba = 0;
+	var newarray = new Array();
+	var ina = 0;
+	var npads = 0x7 & bytearray[iba];
+	iba++;
+	var nba = bytearray.length-npads;
+	while (iba<nba) {
+		newarray[ina] = bytearray[iba];
+		ina++;
+		iba++;
+	}
+	return newarray;
+}
+function asciidigest(str) {
+	return binary2ascii(binarydigest(str));
+}
+function binarydigest(str, keystr) {
+	var key = new Array();
+	key[0] = 0x61626364;
+	key[1] = 0x62636465;
+	key[2] = 0x63646566;
+	key[3] = 0x64656667;
+	var c0 = new Array();
+	c0[0] = 0x61626364;
+	c0[1] = 0x62636465;
+	var c1 = new Array();
+	c1 = c0;
+	var v0 = new Array();
+	var v1 = new Array();
+	var swap;
+	var blocks = new Array();
+	blocks = bytes2blocks(digest_pad(str2bytes(str)));
+	var ibl = 0;
+	var nbl = blocks.length;
+	while (1) {
+		if (ibl>=nbl) {
+			break;
+		}
+		v0[0] = blocks[ibl];
+		ibl++;
+		v0[1] = blocks[ibl];
+		ibl++;
+		v1[0] = blocks[ibl];
+		ibl++;
+		v1[1] = blocks[ibl];
+		ibl++;
+		c0 = tea_code(xor_blocks(v0, c0), key);
+		c1 = tea_code(xor_blocks(v1, c1), key);
+		swap = c0[0];
+		c0[0] = c0[1];
+		c0[1] = c1[0];
+		c1[0] = c1[1];
+		c1[1] = swap;
+	}
+	var concat = new Array();
+	concat[0] = c0[0];
+	concat[1] = c0[1];
+	concat[2] = c1[0];
+	concat[3] = c1[1];
+	return concat;
+}
+function encrypt(str, keystr) {
+	var key = new Array();
+	key = binarydigest(keystr);
+	var blocks = new Array();
+	blocks = bytes2blocks(pad(str2bytes(str)));
+	var ibl = 0;
+	var nbl = blocks.length;
+	// Initial Value for CBC mode = "abcdbcde". Retain for interoperability.
+	var c = new Array();
+	c[0] = 0x61626364;
+	c[1] = 0x62636465;
+	var v = new Array();
+	var cblocks = new Array();
+	var icb = 0;
+	while (1) {
+		if (ibl>=nbl) {
+			break;
+		}
+		v[0] = blocks[ibl];
+		ibl++;
+		v[1] = blocks[ibl];
+		ibl++;
+		c = tea_code(xor_blocks(v, c), key);
+		cblocks[icb] = c[0];
+		icb++;
+		cblocks[icb] = c[1];
+		icb++;
+	}
+	return binary2ascii(cblocks);
+}
+function decrypt(ascii, keystr) {
+	var key = new Array();
+	key = binarydigest(keystr);
+	var cblocks = new Array();
+	cblocks = ascii2binary(ascii);
+	var icbl = 0;
+	var ncbl = cblocks.length;
+	var lastc = new Array();
+	lastc[0] = 0x61626364;
+	lastc[1] = 0x62636465;
+	var v = new Array();
+	var c = new Array();
+	var blocks = new Array();
+	var ibl = 0;
+	while (1) {
+		if (icbl>=ncbl) {
+			break;
+		}
+		c[0] = cblocks[icbl];
+		icbl++;
+		c[1] = cblocks[icbl];
+		icbl++;
+		v = xor_blocks(lastc, tea_decode(c, key));
+		blocks[ibl] = v[0];
+		ibl++;
+		blocks[ibl] = v[1];
+		ibl++;
+		lastc[0] = c[0];
+		lastc[1] = c[1];
+	}
+	return bytes2str(unpad(blocks2bytes(blocks)));
+}
+function xor_blocks(blk1, blk2) {
+	var blk = new Array();
+	blk[0] = blk1[0] ^ blk2[0];
+	blk[1] = blk1[1] ^ blk2[1];
+	return blk;
+}
+function tea_code(v, k) {
+	var v0 = v[0];
+	var v1 = v[1];
+	var k0 = k[0];
+	var k1 = k[1];
+	var k2 = k[2];
+	var k3 = k[3];
+	var sum = 0;
+	var n = 32;
+	while (n-->0) {
+		sum -= 1640531527;
+		// TEA magic number 0x9e3779b9 
+		sum = sum | 0;
+		v0 += ((v1 << 4)+k0) ^ (v1+sum) ^ ((v1 >>> 5)+k1);
+		v1 += ((v0 << 4)+k2) ^ (v0+sum) ^ ((v0 >>> 5)+k3);
+	}
+	var w = new Array();
+	w[0] = v0 | 0;
+	w[1] = v1 | 0;
+	return w;
+}
+function tea_decode(v, k) {
+	var v0 = v[0];
+	var v1 = v[1];
+	var k0 = k[0];
+	var k1 = k[1];
+	var k2 = k[2];
+	var k3 = k[3];
+	var sum = 0;
+	var n = 32;
+	sum = -957401312;
+	while (n-->0) {
+		v1 -= ((v0 << 4)+k2) ^ (v0+sum) ^ ((v0 >>> 5)+k3);
+		v0 -= ((v1 << 4)+k0) ^ (v1+sum) ^ ((v1 >>> 5)+k1);
+		sum += 1640531527;
+		sum = sum | 0;
+	}
+	var w = new Array();
+	w[0] = v0 | 0;
+	w[1] = v1 | 0;
+	return w;
+}
+
+Key.addListener(Key);
+
+Key.onKeyDown = function(){
+	var incremento = 1;
+	var tecla = Key.getCode();
+
+	if(tecla == 16) {
+		_global.shift = 1;
+	}
+
+	if(tecla == 40) // DOWN
+	{
+		// Select next button DOWN
+    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+       	dif1 = (_global.rectanguloprendido) % _root.cuantas_filas;
+		incremento = 1;
+		if(dif1 == 0) {
+			// It changed the column, increment it again
+			incremento = incremento - _root.cuantas_filas;
+		}
+        proximo = _global.rectanguloprendido + incremento;
+        var myresa = eval('_root.resaltado'+proximo);
+		if(_global.rectanguloprendido != _global.restrict) {
+        myapaga._visible = false;
+		}
+        myresa._visible = true;
+        _global.rectanguloprendido = proximo;
+        _root.makeStatus(proximo);
+	}
+	if(tecla == 38) // UP
+	{
+		// Select next button UP
+    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+       	dif1 = (_global.rectanguloprendido-1) % _root.cuantas_filas;
+		incremento = -1;
+		if(dif1 == 0) {
+			// It changed the column, increment it again
+			incremento = incremento + _root.cuantas_filas;
+		}
+        proximo = _global.rectanguloprendido + incremento;
+        var myresa = eval('_root.resaltado'+proximo);
+		if(_global.rectanguloprendido != _global.restrict) {
+        myapaga._visible = false;
+		}
+        myresa._visible = true;
+        _global.rectanguloprendido = proximo;
+        _root.makeStatus(proximo);
+	}
+	if(tecla == 37) // LEFT
+	{
+
+		if (_root.superdetails._visible == true) {
+			var tab = _root.superdetails.tab1._currentframe;
+		    if(tab == 2) {
+		        _root.superdetails.tab1.gotoAndStop(1);
+		        _root.superdetails.tab2.gotoAndStop(2);
+		        _root.superdetails.texto = _global.superdetailstexttab1;
+		    } else {
+		        _root.superdetails.tab1.gotoAndStop(2);
+		        _root.superdetails.tab2.gotoAndStop(1);
+		        _root.superdetails.texto = _global.superdetailstexttab2;
+		    }
+		} else {
+			// Select next button on the LEFT
+	    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+	       	incremento = _root.cuantas_filas;
+			diferencia = _global.rectanguloprendido % _root.cuantas_filas;
+	        proximo = _global.rectanguloprendido - incremento;
+
+        	if(proximo < 1) {
+				proximo = ((_root.cuantas_columnas - 1) * _root.cuantas_filas)+diferencia;
+       	 	}
+        	var myresa = eval('_root.resaltado'+proximo);
+			if(_global.rectanguloprendido != _global.restrict) {
+        	myapaga._visible = false;
+			}
+        	myresa._visible = true;
+        	_global.rectanguloprendido = proximo;
+        	_root.makeStatus(proximo);
+		}
+	}
+
+	if(tecla == 39) // RIGHT
+	{
+		if(_root.detail._visible == true) {
+			_root.superdetails._visible = true;
+			_root.detail._visible = false;
+		} else if (_root.superdetails._visible == true) {
+			var tab = _root.superdetails.tab1._currentframe;
+		    if(tab == 2) {
+		        _root.superdetails.tab1.gotoAndStop(1);
+		        _root.superdetails.tab2.gotoAndStop(2);
+		        _root.superdetails.texto = _global.superdetailstexttab1;
+		    } else {
+		        _root.superdetails.tab1.gotoAndStop(2);
+		        _root.superdetails.tab2.gotoAndStop(1);
+		        _root.superdetails.texto = _global.superdetailstexttab2;
+		    }
+		} else {
+			// Select next button on the RIGHT
+	    	myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+	        total = _root.cuantas_filas * _root.cuantas_columnas;
+        	incremento = _root.cuantas_filas;
+			diferencia = _global.rectanguloprendido % _root.cuantas_filas;
+	        proximo = _global.rectanguloprendido + incremento;
+
+	        if(proximo > total) {
+	            proximo = 1+diferencia-1;
+	        }
+	        var myresa = eval('_root.resaltado'+proximo);
+			if(_global.rectanguloprendido != _global.restrict) {
+	        myapaga._visible = false;
+			}
+	        myresa._visible = true;
+	        _global.rectanguloprendido = proximo;
+	        _root.makeStatus(proximo);
+		}
+	}
+	if(tecla == 9) // TAB
+	{
+		myapaga = eval('_root.resaltado'+_global.rectanguloprendido);
+		total = _root.cuantas_filas * _root.cuantas_columnas;
+		if(_global.shift == 1) {
+			incremento = -1;
+		} else {
+			incremento = 1;
+		}
+		proximo = _global.rectanguloprendido + incremento;
+
+	 	if(proximo > total) {
+			proximo = 1;
+		}
+		if(proximo < 1) {
+			proximo = total;
+		}
+		var myresa = eval('_root.resaltado'+proximo);
+		if(_global.rectanguloprendido == _global.restrict) {
+	  	myapaga._visible = false;
+		}
+	   	myresa._visible = true;
+	   	_global.rectanguloprendido = proximo;
+	   	_root.makeStatus(proximo);
+	}
+
+	if(tecla == 27)	// ESC
+	{
+		_root.codebox._visible = false;
+		_root.log._visible = false;
+		_root.detail._visible = false;
+		_root.superdetails._visible = false;
+	}
+
+	if(tecla == 18) // ALT
+	{
+		var myon = _global.rectanguloprendido;
+		if(myon>0) {
+			var myclip = eval('_level0.rectangulo'+myon+'.flecha'+myon);
+			_root.displaydetails(myclip);
+		}
+	}
+
+	if(tecla == 13) // ENTER
+	{
+		if(_root.codebox._visible == true) {
+			// The security code box is visible, sends code and hides it
+			_global.claveingresada = _root.codebox.claveform.text;
+			_root.codebox._visible = false;
+			_root.envia_comando('bogus', 0, 0);
+		} else {
+			// The security code is not visible, open detail windows of
+			// highlighted button
+			var myon = _global.rectanguloprendido;
+			if(myon>0) {
+				var myclip = eval('_level0.rectangulo'+myon+'.flecha'+myon);
+				_root.displaydetails(myclip);
+			}
+		}
+	}
+
+
+};
+
+Key.onKeyUp = function(){
+	var tecla = Key.getCode();
+	if(tecla == 16) {
+		_global.shift = 0;
+	}
+};
+
+
+
+
+// loadMovieNum("icono1.swf",1);
+
+Inicia_Variables();
+dibuja();
+Detiene_Peliculas();
+conecta();
+
+EndOfActionScript
+
+# Saves the movie
+$movie->nextFrame();
+$movie->save("operator_panel.swf",9);
+
+
+
+
+
+

Added: op-panel/branches/upstream/current/op_astdb.cfg
===================================================================
--- op-panel/branches/upstream/current/op_astdb.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_astdb.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,30 @@
+; FOP will ask for the value of the asterisk database families
+; specified between brackets. If the value is non empty, it will
+; send the commands to the flash client. Note that the family
+; is case sensitive!
+
+;[dnd]
+;settext=DND: ${value}
+;setalpha=70
+;flip=1
+;fopledcolor=0x001020
+
+;[cfb]
+;settext=CFB: ${value}
+;status=busy              ; free, busy, ringing
+;fopledcolor=0x102030
+
+# How it works: when the panel is first started, it will check
+# for every family defined in op_astdb.cfg between brakets. The
+# key is the channel name, as defined between brackets in op_buttons.cfg
+# If a value is found and non empty it will perform the actions
+# specified in op_astdb.cfg, those actions modify the button for
+# that channel in FOP, they are:
+#
+# settext  = sets the text where the callerid is displayed
+# setlabel = sets the label for the button
+# setalpha = sets the alpha blending for the whole button (0-100)
+# flip     = flips the button (1)
+# state    = set the state of the led to: free, busy or ringing
+# fopledcolor = sets the led color using hex values like 0x2030a0
+

Added: op-panel/branches/upstream/current/op_buttons.cfg
===================================================================
--- op-panel/branches/upstream/current/op_buttons.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_buttons.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,261 @@
+[SIP/10]              ; Channel name
+Position=1            ; Button number in the console
+Label="10 Fax"        ; Text label for the button
+Extension=10          ; Extension to reach that channel
+Context=sip           ; Context where that extension is defined
+Mailbox=10 at sip        ; The voicemail mailbox to monitor
+Icon=1                ; There are 6 icons available
+Url=http://www.asternic.org  ; Optional, add link to button label
+Target=_new                  ; Optional, open link in this target
+No_Rectangle=0        ; Optional: If enabled, it will not draw the button
+                      ; rectangle, only the icons inside
+Background=bg.jpg     ; Optional: it will load that jpg as the button 
+                      ; background. It should match the size as specified
+                      ; in op_style.cfg btn_width and btn_height.
+VoiceMailExt=910 at vm   ; extension at context to use for transferring a call
+                      ; directly to voicemail
+Privacy=false         ; if set to true, it will hide callerid info for
+                      ; the button
+
+[SIP/11]
+Position=n            ; Position 'n' will be the next available
+Label="Multiline%0aLabel"  ; %0a is the new line character
+Extension=11
+Context=sip
+Icon=1
+Server=1              ; If you omit the Server, it will default to 1
+
+[SIP/12]
+Position=n
+Label="12 Ernest"
+Extension=11
+Context=sip
+Icon=1
+Server=2            ; If you monitor more than one server change this
+
+[_SIP/.*]           ; You can use REGEXP. Prefix the button with an
+Position=1,2        ; underscore followed by your expression
+                    ; (you cannot use & and = as they are reserved)
+Label="SIP Guest"
+Extension=-1        ; If set to -1 you will not be able to transfer
+                    ; to this button
+Context=internos
+Icon=1
+
+[PARK/701]
+Position=17
+Icon=3
+Extension=700
+Label="Park 701"
+
+[SIP/16]
+Position=6
+Label="16 Nicolás"       ; you can use unicode for extended characters
+Extension=16
+Context=internos
+Icon=1
+Mailbox=16 at internos
+
+[CAPI[contr1/NNNNNNNNN]] ; where NNNN is the ISDN number. If you
+Position=22,23             ; specify more than one position, the button
+                         ; will be considered a 'trunk', each call will be
+                         ; displayed in a separate button
+Label="External CAPI"        
+Extension=-1
+Context=in-extern
+Icon=4 
+
+[SIP/17]
+Position=7
+Label="17 Martin"
+Extension=17
+Context=internos
+Icon=1
+Mailbox=17 at internos
+
+[IAX2/3002]
+Position=3
+Label="3002 IAX Client"
+Extension=3002
+Context=iaxcontext
+Icon=1
+
+[901]                ; Meetme must be defined by its room number
+Position=8
+Label="Meetme 901"
+Extension=901
+Context=conferences
+Icon=5
+
+[902]
+Position=9
+Label="Meetme 902"
+Extension=902
+Icon=5
+
+[Zap/1]
+Position=10
+Label="External 1"
+Extension=-1
+Icon=2
+
+[Zap/2]
+Position=11
+Label="External 2"
+Extension=-1
+Icon=2
+
+[QUEUE/SALES]                 ; queues must be defined by its name
+Position=12
+Label="Sales Queue"
+Extension=-1            ; -1 to disable transfers to this button
+Icon=3
+
+[QUEUE/SUPPORT]
+Position=13-18          ; each position will be used by users waiting
+                        ; on that position number
+Label="Support Queue"
+Extension=-1            ; -1 to disable transfers to this button
+Icon=3
+
+[Local/5555555 at sip]
+Position=26
+Label="Speed Dial"
+Extension=5555555
+Context=sip
+Icon=2
+
+[IAX2/iaxtel]
+Position=15,16
+Label="Iaxtel"
+Extension=-1
+Icon=2
+
+; buttons with panel context will be displayed in their
+; own panel, you have to append ?context=NAME when loading
+; the swf file
+;
+;[IAX2/iaxtel]
+;Position=15,16
+;Label="Iaxtel"
+;Extension=-1
+;Icon=2
+;Panel_context=sip      
+
+; You can draw rectangles anywhere in the screen. The canvas sixe is 996x600
+;
+
+[rectangle]
+x=748
+y=35
+width=252
+height=370
+line_width=3
+line_color=ffff10
+fade_color1=ffff10
+fade_color2=ffff3F
+rnd_border=2
+alpha=30
+layer=top       ; top    = above buttons
+                ; bottom = below buttons
+
+[rectangle]
+x=498
+y=35
+width=252
+height=220
+line_width=3
+line_color=ff1010
+fade_color1=ff1010
+fade_color2=a01000
+rnd_border=2
+alpha=20
+layer=top
+panel_context=*   ; The item will be persistant across contexts
+
+[rectangle]
+x=498
+y=255
+width=252
+height=295
+line_width=3
+line_color=10ff10
+fade_color1=10ff10
+fade_color2=10ff00
+rnd_border=2
+alpha=20
+layer=top
+
+[rectangle]
+x=-1
+y=35
+width=502
+height=515
+line_width=3
+line_color=1010ff
+fade_color1=1010ff
+fade_color2=1010ff
+rnd_border=2
+alpha=10
+layer=top
+
+; you can include configuration files
+;
+;include => more_rectangles.cfg
+
+[LEGEND]
+x=800
+y=50
+text=Zap Lines
+font_size=32
+font_color=000000
+font_family=Times New Roman  ; only used when use_embed_fonts=0
+use_embed_fonts=1            ; if set to 1 it will use an embeded Arial type font
+                             ; that looks consistently between platforms/os
+
+[LEGEND]
+x=535
+y=50
+text=Conferences
+font_size=32
+font_color=FF0000
+font_family=Arial
+use_embed_fonts=1
+
+[LEGEND]
+x=555
+y=270
+text=Queues
+font_size=32
+font_color=000000
+font_family=Arial
+use_embed_fonts=1
+
+[LEGEND]
+x=160
+y=40
+text=Extensions
+font_color=000000
+font_size=32
+font_family=Arial    
+use_embed_fonts=1
+
+[LEGEND]
+x=75
+y=75
+text=Local
+font_size=24
+font_family=Arial    
+font_color=000000
+use_embed_fonts=1
+
+[LEGEND]
+x=315
+y=75
+text=Remote
+font_color=000000
+font_size=24
+font_family=Arial
+use_embed_fonts=1
+
+;include => more_legends.cfg

Added: op-panel/branches/upstream/current/op_lang_ca.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_ca.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_ca.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,31 @@
+; Language configuration file
+dialing=Marcant
+calling=Trucant a $1
+incoming=Rebent una trucada de $1
+parked=Aparcat a $1
+registered=Registrat
+notregistered=No registrat
+reachable =Assolible $1
+unreachable=No assolible $1
+lagged=Enderrarit $1
+newold=Nous $1, Vells $2
+waitingonqueue=$1 usuari$2 a l'espera
+memberonconference=$1 participant$2
+version_mismatch=Versio incorrecte entre Client i Servidor!
+; client side
+clid_label=CLID
+detail_title=Detalls ultima trucada
+detail_from=De:
+detail_to=Per:
+detail_duration=Duracio:
+security_code_title=Introdueixi el codi de seguretat
+btn_security_text=Obrir finestra d'ingres de codi
+btn_restart_text=Reinicia Asterisk
+btn_reload_text=Recarrega la configuracio
+btn_debug_text=Obrir/Tancar finestra de Debug
+btn_help_text=Obrir ajuda
+tab_call_text=Trucada
+tab_queue_text=Cua
+calls_taken_text=Trucades ateses
+no_data_text=No hi ha dades
+debug_window_title=Finestra de Debug

Added: op-panel/branches/upstream/current/op_lang_de.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_de.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_de.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,31 @@
+; German Language configuration file
+dialing=Waehlt
+calling=Ruft $1
+incoming=Eingehendes Gespraech von $1
+parked=Gehalten auf $1
+registered=Registriert
+notregistered=Nicht registriert
+reachable=$1 erreichbar
+unreachable=$1 nicht erreichbar
+lagged=$1 verzoegert
+newold=$1 neue, $2 alte
+waitingonqueue=$1 Nutzer warten
+memberonconference=$1 Teilnehmer
+version_mismatch=Client/Server Versionsfehler!
+; client side
+clid_label=Info
+detail_title=Letzte Anrufdetails
+detail_from=Von:
+detail_to=An:
+detail_duration=Dauer:
+security_code_title=Bitte den Sicherheitscode eingeben
+btn_security_text=Eingabe Sicherheitscode
+btn_restart_text=Asterisk-Neustart
+btn_reload_text=Konfiguration neu laden
+btn_debug_text=Debug-Fenster ein/aus
+btn_help_text=Hilfefenster oeffnen
+tab_call_text=Anruf
+tab_queue_text=Warteschlange
+calls_taken_text=Angenommene Anrufe
+no_data_text=Keine Daten vorhanden
+debug_window_title=Debug-Fenster

Added: op-panel/branches/upstream/current/op_lang_en.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_en.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_en.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,31 @@
+; Language configuration file
+dialing=Dialing
+calling=Calling $1
+incoming=Incoming call from $1
+parked=Parked on $1
+registered=Registered
+notregistered=Not registered
+reachable=Reachable $1
+unreachable=Not reachable $1
+lagged=Lagged $1
+newold=New $1, Old $2
+waitingonqueue=$1 user$2 waiting
+memberonconference=$1 participant$2
+version_mismatch=Client/Server version mismatch!
+; client side
+clid_label=Info
+detail_title=Last call details
+detail_from=From:
+detail_to=To:
+detail_duration=Duration:
+security_code_title=Please enter the security code
+btn_security_text=Open Security Code Input Box
+btn_restart_text=Restarts Asterisk
+btn_reload_text=Reloads configuration
+btn_debug_text=Open/Close Debug Window
+btn_help_text=Open Help Window
+tab_call_text=Call
+tab_queue_text=Queue
+calls_taken_text=Calls taken
+no_data_text=No data available
+debug_window_title=Debug Window

Added: op-panel/branches/upstream/current/op_lang_es.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_es.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_es.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,31 @@
+; Language configuration file
+dialing=Marcando
+calling=Llamando a $1
+incoming=Recibiendo llamada de $1
+parked=Aparcado en $1
+registered=Registrado
+notregistered=No registrado
+reachable =Alcanzable $1
+unreachable=No alcanzable $1
+lagged=Demorado $1
+newold=Nuevos $1, Viejos $2
+waitingonqueue=$1 usuario$2 esperando
+memberonconference=$1 participante$2
+version_mismatch=Version incorrecta entre Cliente  y Servidor!
+; client side
+clid_label=CLID
+detail_title=Detalles ultimo llamado
+detail_from=De:
+detail_to=A:
+detail_duration=Duracion:
+security_code_title=Ingrese el codigo de seguridad
+btn_security_text=Abre ventana de ingreso de codigo
+btn_restart_text=Reinicia Asterisk
+btn_reload_text=Recarga la configuracion
+btn_debug_text=Abre/Cierra ventana de Debug
+btn_help_text=Abre ayuda
+tab_call_text=Llamada
+tab_queue_text=Cola
+calls_taken_text=Llamados atendidos
+no_data_text=No hay datos
+debug_window_title=Ventana de Debug

Added: op-panel/branches/upstream/current/op_lang_fr.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_fr.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_fr.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,35 @@
+; Language configuration file
+;
+; Laurent Mele - lmele at infoclip.fr
+; 2005
+;
+dialing=Numérotation
+calling=Appel de $1
+incoming=Appel entrant du $1
+parked=Parqué au $1
+registered=Enregistré
+notregistered=Non enregistré
+reachable=Disponible. $1
+unreachable=Indisponible $1
+lagged=Lenteur $1
+newold=Nouveau $1, Ancien $2
+waitingonqueue=$1 utilisateur$2 en attente
+memberonconference=$1 participant$2
+version_mismatch=Incohérence de version Client/Serveur!
+; client side
+clid_label=Information
+detail_title=Détails du dernier appel
+detail_from=De:
+detail_to=Vers:
+detail_duration=Durée:
+security_code_title=Entrez le code de sécurité
+btn_security_text=Authentification de l'administrateur
+btn_restart_text=Redémarre Asterisk
+btn_reload_text=Recharge la configuration
+btn_debug_text=Ouvre/Ferme la fenêtre de déverminage
+btn_help_text=Ouvre la fenêtre d'aide
+tab_call_text=Appel
+tab_queue_text=File d'attente
+calls_taken_text=Appels pris
+no_data_text=Pas d'informations disponibles
+debug_window_title=Fenêtre de déverminage

Added: op-panel/branches/upstream/current/op_lang_it.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_it.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_it.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,31 @@
+; Archivio di localizzazione nazionale
+dialing=Componendo
+calling=Chiamando $1
+incoming=Chiamata in arrivo da $1
+parked=Parcheggiata su $1
+registered=Registrato
+notregistered=Non registrato
+reachable=Raggiungibile $1
+unreachable=Non raggiungibile $1
+lagged=Trattenuto $1
+newold=Attuale $1, Precedente $2
+waitingonqueue=$1 utente$2 in attesa
+memberonconference=$1 partecipanti$2
+version_mismatch=Versione disallineata tra Client e Server!
+; client side
+clid_label=Info
+detail_title=Dettagli ultima chiamata
+detail_from=Da:
+detail_to=A:
+detail_duration=Durata:
+security_code_title=Introdurre il codice di sicurezza
+btn_security_text=Attiva richiesta Codice di sicurezza
+btn_restart_text=Riavvia Asterisk
+btn_reload_text=Ricarica la configurazione
+btn_debug_text=Apre/Chiude la finestra di debug
+btn_help_text=Attiva l'aiuto online
+tab_call_text=Chiama
+tab_queue_text=Coda
+calls_taken_text=Chiamate trattenute
+no_data_text=Non ci sono dati disponibili
+debug_window_title=Finestra di debug

Added: op-panel/branches/upstream/current/op_lang_se.cfg
===================================================================
--- op-panel/branches/upstream/current/op_lang_se.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_lang_se.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,32 @@
+; Swedish language configuration file
+; Courtesy Daniel Nylander
+dialing=Kopplar
+calling=Ringer $1
+incoming=Inkommande samtal från $1
+parked=Parkerad på $1
+registered=Registrerad
+notregistered=Inte registrerad
+reachable=Tillgänglig $1
+unreachable=Inte tillgänglig $1
+lagged=Fördröjd $1
+newold=Nya $1, Gamla $2
+waitingonqueue=$1 användare$2 väntar
+memberonconference=$1 deltagare$2
+version_mismatch=Klient/Server ej samma version!
+; client side
+clid_label=Info
+detail_title=Detaljer om senaste samtal
+detail_from=Från:
+detail_to=Till:
+detail_duration=Längd:
+security_code_title=Vänligen tryck in säkerhetskoden
+btn_security_text=Öppna inmatning för säkerhetskod
+btn_restart_text=Startar om Asterisk
+btn_reload_text=Läser om konfigurationen
+btn_debug_text=Öppna/Stäng debugfönstret
+btn_help_text=Öppna hjälpfönstret
+tab_call_text=Samtal
+tab_queue_text=Kö
+calls_taken_text=Samtal tagna
+no_data_text=Ingen data tillgänglig
+debug_window_title=Debugfönster

Added: op-panel/branches/upstream/current/op_server.cfg
===================================================================
--- op-panel/branches/upstream/current/op_server.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_server.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,207 @@
+[general]
+; host or ip address of asterisk
+manager_host=192.168.0.1
+manager_port=5038
+; user and secret for connecting to * manager
+manager_user=user
+manager_secret=secret
+; The optional event_mask for filtering manager events.
+; Asterisk will send only the events you request
+; with this parameter. Possible values are:
+; on, off, system, call, log, verbose
+;event_mask=call
+;
+; You can specify many asterisk servers to
+; monitor. Just repeat the manager_host, manager_user
+; and manager_secret parameters in order. The first
+; one will be server number 1, and so on.
+;
+; manager_host=1.2.3.4
+; manager_user=john
+; manager_secret=doe
+
+; Enable MD5 auth to Asterisk manager
+auth_md5=1
+
+
+; you can use astmanproxy, if you enable it, all of the above
+; connections and settings will be overriden. You have to define
+; the host and port
+; astmanproxy_host = 127.0.0.1
+; astmanproxy_port = 1234
+
+; You will also have to define the servers that are monitored trough
+; astmanproxy, you have to enumerate them using the astmanproxy_server.
+; astmanproxy_server = 192.168.10.1
+; astmanproxy_server = 192.168.10.2
+; astmanproxy_server = 192.168.10.3
+;
+; ip address to listen for inbound connections, default all
+;listen_addr=127.0.0.1
+
+; port to listen for inbound flash connections, default 4445
+;listen_port=4445
+
+; hostname or ip address used to connect to the webserver where
+; the flash movie resides (just the hostname, without directories)
+; This value might be omited. In that case the flash movie will
+; try to connect to the same host as the web page.
+; web_hostname=www.myexample.com
+
+; location of the .swf file in your disk (must reside somewhere
+; inside your web root)
+flash_dir=/var/www/html/panel
+
+; secret code for performing hangups and transfers
+security_code=dkd4393kld
+
+; Frequency in second to poll for sip and iax status
+poll_interval=120
+
+; Poll for voicemail status (only necesary when you access the
+; voicemail directories outside asterisk itself - eg. web access)
+poll_voicemail=0
+
+; 1 Enable automatic hangup of zombies
+; 0 Disable
+kill_zombies=0
+
+; Debug level to stdout (bitmap)
+; 1   Manager Events Received
+; 2   Manager Commands Sent
+; 4   Show Flash events Received
+; 8   Show events sent to Flash Clients
+; 16  Server 1st Debug Level
+; 32  Server 2nd Debug Level
+; 64  Server 3rd Debug Level
+;
+; Eg: to display manager events and
+; commands sent set it to 3 (1+2)
+;
+; Maximum debug level 255
+debug=0
+
+; Default language to use (op_lang_XX.cfg file)
+language=en
+
+; Context in your diaplan where you have the conferences for barge in
+; Example:
+;
+; meetme.conf
+; [rooms]
+; conf => 900
+; conf => 901
+; conf => 902
+;
+; extensions.conf
+; [conferences]
+; exten => 900,1,MeetMe(900)
+; exten => 901,1,MeetMe(901)
+; exten => 902,1,MeetMe(902)
+conference_context=conferences
+
+; Meetme room numbers to use for barge in. The room number must match
+; the extension number (see above).
+barge_rooms=900-902
+
+; When doing barge ins, you can make the 3rd party to start
+; the meetme muted, so the other parties wont notice they are
+; now being monitored
+barge_muted=1
+
+; Formatting of the callerid field
+; where 'x' is a number
+clid_format=(xxx)xxx-xxxx
+
+; If you want not to show the callerid on the buttons, set this
+; to one
+clid_privacy=0
+
+; To display the ip address of sip or iax peer inside the button
+; set this to 1
+show_ip=0
+
+; It will hide queue position buttons and show only the active ones
+queue_hide=0
+
+; Will change the button label on AgentLogin
+rename_label_agentlogin=0
+
+; Will change the button label on Agentcallbacklogin
+rename_label_callbacklogin=0
+
+; Will rename the label for a wildcard button
+rename_label_wildcard=0
+
+; Will rename to the name specified in agents.conf
+; If disabled the renaming will be Agent/XXXX
+rename_to_agent_name=1
+
+; Will display IDLE time for agents, as well as
+; update the queue status after an agent hangs up
+; the call, so you don't need to reload to get
+; queue statistics
+agent_status=0
+
+; Will rename labels for queuemembers
+; If you use addqueuemember in your dialplan, you
+; can fake an AgengLogin event by sending it with
+; the UserEvent application. Eg:
+;
+; exten => 25,1,AddQueueMember(sales|SIP/${CALLERIDNUM}
+; exten => 25,2,UserEvent(Agentlogin|Agent: ${CALLERIDNUM});
+; exten => 25,3,Answer
+; exten => 25,4,Playback(added-to-sales-queue)
+; exten => 25,5,Hangup
+;
+; exten => 26,1,RemoveQueueMember(sales|SIP/${CALLERIDNUM})
+; exten => 26,2,UserEvent(RefreshQueue);
+; exten => 26,3,Answer
+; exten => 26,4,Playback(removed-from-sales-queue)
+; exten => 26,5,Hangup
+rename_queue_member=0
+
+; Will change the led color when the agent logs in
+; The color is configurable in op_style.cfg
+change_led_agent=1
+
+; If set to 1, you will transfer the linked channel instead
+; of the current channel when you drag the icon on a button
+reverse_transfer=0
+
+; If enabled, it will not ask forthe  security code
+; when performing a click to dial
+clicktodial_insecure=1
+
+; Enable select box with absolutetimeout for the call after
+; a transfer is performed within the panel
+transfer_timeout= "0,No timeout|300,5 minutes|600,10 minutes|1200,20 minutes|2400,40 minutes|3000,50 minutes"
+
+; If set to 1, when hitting the reload button on the flash
+; client it will instead restart the 1st asterisk box
+; (For asterisk to restart you have to start it with
+; safe_asterisk, if you dont do that, asterisk will just
+; shut down)
+enable_restart     = 0
+
+; If you set this parameter to your voicemailmain
+; extension at context, it will originate a call to
+; voicemailmain when double clicking on the MWI icon
+; for any button.
+voicemail_extension = 3000 at features
+
+; You can have panel contexts with their own
+; button layout and configuration. The following entry
+; will create a context called sip with a different
+; security code. In the online documentation you will
+; find how to use contexts
+;
+;[sip]
+;security_code=djdjdi43
+;web_hostname=www.virtualwebserver.com
+;flash_dir=/var/www/virtualwebserver/html/panel
+;barge_rooms=800-802
+;conference_context=otherconferences
+;transfer_timeout="0,No timeout|60,1 minute"
+;voicemail_extension=1000 at nine
+;language=es

Added: op-panel/branches/upstream/current/op_server.pl
===================================================================
--- op-panel/branches/upstream/current/op_server.pl	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_server.pl	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,9156 @@
+#!/usr/bin/perl -w
+
+#  Flash Operator Panel.    http://www.asternic.org
+#
+#  Copyright (c) 2004 Nicolás Gudiño.  All rights reserved.
+#
+#  Nicolás Gudiño <nicolas at house.com.ar>
+#
+#  This program is free software, distributed under the terms of
+#  the GNU General Public License.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+#  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
+#  EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use integer;
+
+use constant DEBUG         => 1;
+use constant BYTES_TO_READ => 256;
+
+use IO::Socket;
+use IO::Select;
+use Getopt::Long;
+use Pod::Usage;
+use Fcntl;
+use POSIX qw(setsid EWOULDBLOCK);
+
+my $FOP_VERSION                = "026.001";
+my %datos                      = ();
+my %sesbot                     = ();
+my %linkbot                    = ();
+my %cache_hit                  = ();
+my %estadoboton                = ();
+my %botonled                   = ();
+my %botonalpha                 = ();
+my %botonregistrado            = ();
+my %boton_ip                   = ();
+my %botonlabel                 = ();
+my %botonlabelonly             = ();
+my %botonsetlabel              = ();
+my %botontimer                 = ();
+my %botontimertype             = ();
+my %botonpark                  = ();
+my %botonmeetme                = ();
+my %botonclid                  = ();
+my %botonqueue                 = ();
+my %botonqueue_count           = ();
+my %botonqueuemember           = ();
+my %botonvoicemail             = ();
+my %botonvoicemailcount        = ();
+my %botonlinked                = ();
+my %parked                     = ();
+my %meetme_pos                 = ();
+my %laststatus                 = ();
+my %autenticado                = ();
+my %auto_conference            = ();
+my %buttons                    = ();
+my %buttons_queue              = ();
+my %buttons_queue_reverse      = ();
+my %buttons_preserve_case      = ();
+my %button_server              = ();
+my %buttons_reverse            = ();
+my %textos                     = ();
+my %iconos                     = ();
+my %urls                       = ();
+my %targets                    = ();
+my %remote_callerid            = ();
+my %remote_callerid_name       = ();
+my %extension_transfer         = ();
+my %extension_transfer_reverse = ();
+my %max_queue_waiting_time_for = ();
+my %flash_contexto             = ();
+my %saved_clidnum              = ();
+my %saved_clidname             = ();
+my %keys_socket                = ();
+my %manager_socket             = ();
+my %start_muted                = ();
+my %timeouts                   = ();
+my %no_rectangle               = ();
+my %background                 = ();
+my %astdbcommands              = ();
+my %client_queue               = ();
+my %manager_queue              = ();
+my %client_queue_nocrypt       = ();
+my %ip_addy                    = ();
+my %count_queue                = ();
+my %is_agent                   = ();
+my %agents_on_queue            = ();
+my %max_lastcall               = ();
+my $config                     = {};
+my $cola                       = {};
+my $language                   = {};
+my $global_verbose             = 1;
+my $help                       = 0;
+my $version                    = 0;
+my $counter_servers            = -1;
+my %bloque_completo;
+my %buferbloque;
+my $bloque_final;
+my $todo;
+my $regexp_buttons     = 0;
+my $queueagent_buttons = 0;
+my $defaultlanguage;
+my @bloque;
+my @respuestas;
+my @all_flash_files;
+my @masrespuestas;
+my @fake_bloque;
+my @flash_clients;
+my @status_active;
+my @panel_contexts;
+my %mailbox;
+my %tovoicemail;
+my %instancias;
+my %agent_to_channel;
+my %agent_label;
+my %togle_action;
+my %togle_response;
+my %channel_to_agent;
+my %reverse_agents;
+my %agents_name;
+my @p;
+my $m;
+my $O;
+my @S;
+my @key;
+my @manager_host        = ();
+my @manager_port        = ();
+my @manager_user        = ();
+my @manager_secret      = ();
+my @event_mask          = ();
+my @astmanproxy_servers = ();
+my @manager_conectado   = ();
+my %manager_desconectado;
+my %mask_hash;
+my $web_hostname;
+my $listen_port;
+my $listen_addr;
+my $security_code;
+my $flash_dir;
+my $astmanproxy_server = "";
+my $restrict_channel   = "";
+my $socketpolicy;
+my $poll_interval;
+my $poll_voicemail;
+my $kill_zombies;
+my $ren_agentlogin;
+my $ren_cbacklogin;
+my $ren_agentname;
+my $agent_status;
+my $ren_queuemember;
+my $ren_wildcard;
+my $clid_privacy;
+my %clid_private;
+my $show_ip;
+my $queue_hide;
+my $enable_restart;
+my $change_led;
+my $cdial_nosecure;
+my $barge_muted;
+my $debuglevel       = -1;
+my $debuglevel_cache = "";
+my $cont_debug_cache = 0;
+my $flash_file;
+my %barge_rooms;
+my %barge_context;
+my $first_room;
+my $last_room;
+my $meetme_context;
+my $clid_format;
+my $directorio       = "";
+my $auth_md5         = 1;
+my $astmanproxy_host = "";
+my $astmanproxy_port = "5038";
+my $md5challenge;
+my $reverse_transfer;
+my %shapes;
+my %legends;
+my %no_encryption = ();
+my %total_shapes;
+my %total_legends;
+my @btninclude   = ();
+my @styleinclude = ();
+my $command      = "";
+my $daemonized   = 0;
+my $pidfile      = "/var/run/op_panel.pid";
+my $logdir       = "";
+my $confdir      = "";
+my $tab          = "";
+
+my $PADDING = join(
+    '',
+    map( chr,
+        (
+            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+          ) )
+);
+my %a2b = (
+    A   => 000,
+    B   => 001,
+    C   => 002,
+    D   => 003,
+    E   => 004,
+    F   => 005,
+    G   => 006,
+    H   => 007,
+    I   => 010,
+    J   => 011,
+    K   => 012,
+    L   => 013,
+    M   => 014,
+    N   => 015,
+    O   => 016,
+    P   => 017,
+    Q   => 020,
+    R   => 021,
+    S   => 022,
+    T   => 023,
+    U   => 024,
+    V   => 025,
+    W   => 026,
+    X   => 027,
+    Y   => 030,
+    Z   => 031,
+    a   => 032,
+    b   => 033,
+    c   => 034,
+    d   => 035,
+    e   => 036,
+    f   => 037,
+    g   => 040,
+    h   => 041,
+    i   => 042,
+    j   => 043,
+    k   => 044,
+    l   => 045,
+    m   => 046,
+    n   => 047,
+    o   => 050,
+    p   => 051,
+    q   => 052,
+    r   => 053,
+    s   => 054,
+    t   => 055,
+    u   => 056,
+    v   => 057,
+    w   => 060,
+    x   => 061,
+    y   => 062,
+    z   => 063,
+    '0' => 064,
+    '1' => 065,
+    '2' => 066,
+    '3' => 067,
+    '4' => 070,
+    '5' => 071,
+    '6' => 072,
+    '7' => 073,
+    '8' => 074,
+    '9' => 075,
+    '+' => 076,
+    '_' => 077,
+);
+my %b2a                      = reverse %a2b;
+my $rand_byte_already_called = 0;
+
+$SIG{PIPE} = 'IGNORE';
+$SIG{ALRM} = 'alarma_al_minuto';
+$SIG{INT}  = 'close_all';
+$SIG{HUP}  = 'generate_configs_onhup';
+$SIG{USR1} = 'dump_internal_hashes_to_stdout';
+
+GetOptions(
+    'p|pidfile=s'    => \$pidfile,
+    'l|logdir=s'     => \$logdir,
+    'c|confdir=s'    => \$confdir,
+    'd|daemon'       => \$daemonized,
+    'V|version'      => \$version,
+    'x|debuglevel=i' => \$debuglevel,
+    'help|?'         => \$help
+);
+
+pod2usage(1) if $help;
+
+if ( $version == 1 ) {
+    print "op_server.pl version $FOP_VERSION\n";
+    exit 0;
+}
+
+if ( $confdir eq "" ) {
+
+    # if there is no config directory supplied at the command line
+    # use the same directory where op_server.pl lives
+    $directorio = $0;
+    $directorio =~ s/(.*)\/(.*)/$1/g;
+}
+else {
+    $directorio = $confdir;
+}
+
+if ( $logdir ne "" ) {
+    open( STDOUT, ">>$logdir/output.log" )
+      or die "Can't open output log $logdir/error.log";
+    open( STDERR, ">>$logdir/error.log" )
+      or die "Can't open output log $logdir/error.log";
+}
+
+if ( $daemonized == 1 ) {
+    defined( my $pid = fork ) or die "Can't Fork: $!";
+    exit if $pid;
+    setsid or die "Can't start a new session: $!";
+    open MYPIDFILE, ">$pidfile";
+    print MYPIDFILE $$;
+    close MYPIDFILE;
+
+    close(STDIN);
+    if ( $logdir eq "" ) {
+        close STDOUT;
+        close STDERR;
+    }
+}
+
+sub read_language_config() {
+    $/ = "\n";
+
+    # tries to read and parse every language file needed
+    foreach my $ctx (@panel_contexts) {
+        if ( !defined( $config->{$ctx}{language} ) ) {
+            $config->{"$ctx"}{language} = $defaultlanguage;
+        }
+
+        my $lang = $config->{$ctx}{language};
+        $lang =~ tr/A-Z/a-z/;
+        $lang =~ s/\W//g;
+        $config->{$ctx}{language} = $lang;
+
+        open( CONFIG, "<$directorio/op_lang_$lang.cfg" )
+          or die("Could not open $directorio/op_lang_$lang.cfg. Aborting...");
+
+        while (<CONFIG>) {
+            chop;
+            $_ =~ s/^\s+//g;
+            $_ =~ s/([^;]*)[;](.*)/$1/g;
+            $_ =~ s/\s+$//g;
+            next unless $_ ne "";
+            my ( $variable_name, $value ) = split( /=/, $_ );
+            $variable_name =~ tr/A-Z/a-z/;
+            $variable_name =~ s/\s+//g;
+            $value         =~ s/^\s+//g;
+            $value         =~ s/\s+$//g;
+            $value         =~ s/\"//g;
+            $language->{$ctx}{$variable_name} = $value;
+        }
+        close(CONFIG);
+    }
+    $/ = "\0";
+}
+
+sub read_server_config() {
+    my $context = "";
+    $counter_servers = -1;
+
+    $/ = "\n";
+
+    open( CONFIG, "<$directorio/op_server.cfg" )
+      or die("Could not open op_server.cfg. Aborting...");
+
+    while (<CONFIG>) {
+        chomp;
+        $_ =~ s/^\s+//g;
+        $_ =~ s/([^;]*)[;](.*)/$1/g;
+        $_ =~ s/\s+$//g;
+
+        if ( /^#/ || /^;/ || /^$/ ) {
+            next;
+        }    # Ignores comments and empty lines
+
+        if (/^\Q[\E/) {
+            s/\[(.*)\]/$1/g;
+            tr/a-z/A-Z/;
+            $context = $_;
+        }
+        else {
+            if ( $context ne "" ) {
+                my ( $variable_name, $value ) = split( /=/, $_ );
+                $variable_name =~ tr/A-Z/a-z/;
+                $variable_name =~ s/\s+//g;
+                $value         =~ s/^\s+//g;
+                $value         =~ s/\s+$//g;
+                $value         =~ s/\"//g;
+                $config->{$context}{$variable_name} = $value;
+
+                if ( $variable_name eq "manager_host" ) {
+                    $counter_servers++;
+                    $manager_host[$counter_servers] = $value;
+                }
+
+                if ( $variable_name eq "manager_user" ) {
+                    $manager_user[$counter_servers] = $value;
+                }
+
+                if ( $variable_name eq "manager_secret" ) {
+                    $manager_secret[$counter_servers] = $value;
+                }
+
+                if ( $variable_name eq "manager_port" ) {
+                    $manager_port[$counter_servers] = $value;
+                }
+
+                if ( $variable_name eq "event_mask" ) {
+                    $event_mask[$counter_servers] = $value;
+                }
+
+                if ( $variable_name eq "astmanproxy_server" ) {
+                    push @astmanproxy_servers, $value;
+                }
+
+            }
+        }
+    }
+    close(CONFIG);
+
+    $web_hostname     = $config->{GENERAL}{web_hostname};
+    $listen_port      = $config->{GENERAL}{listen_port};
+    $listen_addr      = $config->{GENERAL}{listen_addr};
+    $security_code    = $config->{GENERAL}{security_code};
+    $flash_dir        = $config->{GENERAL}{flash_dir};
+    $poll_interval    = $config->{GENERAL}{poll_interval};
+    $poll_voicemail   = $config->{GENERAL}{poll_voicemail};
+    $kill_zombies     = $config->{GENERAL}{kill_zombies};
+    $reverse_transfer = $config->{GENERAL}{reverse_transfer};
+    $auth_md5         = $config->{GENERAL}{auth_md5};
+    $astmanproxy_host = $config->{GENERAL}{astmanproxy_host};
+    $astmanproxy_port = $config->{GENERAL}{astmanproxy_port};
+    $ren_agentlogin   = $config->{GENERAL}{rename_label_agentlogin};
+    $ren_cbacklogin   = $config->{GENERAL}{rename_label_callbacklogin};
+    $ren_wildcard     = $config->{GENERAL}{rename_label_wildcard};
+    $ren_agentname    = $config->{GENERAL}{rename_to_agent_name};
+    $agent_status     = $config->{GENERAL}{agent_status};
+    $ren_queuemember  = $config->{GENERAL}{rename_queue_member};
+    $change_led       = $config->{GENERAL}{change_led_agent};
+    $cdial_nosecure   = $config->{GENERAL}{clicktodial_insecure};
+    $barge_muted      = $config->{GENERAL}{barge_muted};
+    $clid_privacy     = $config->{GENERAL}{clid_privacy};
+    $show_ip          = $config->{GENERAL}{show_ip};
+    $queue_hide       = $config->{GENERAL}{queue_hide};
+    $enable_restart   = $config->{GENERAL}{enable_restart};
+    $defaultlanguage  = $config->{GENERAL}{language};
+
+    if ( $debuglevel == -1 ) {
+        $debuglevel = $config->{GENERAL}{debug};
+    }
+
+    my @todos_los_rooms;
+    foreach my $val ($config) {
+        while ( my ( $aa, $bb ) = each( %{$val} ) ) {
+            while ( my ( $cc, $dd ) = each( %{$bb} ) ) {
+                if ( $cc eq "barge_rooms" ) {
+                    ( $first_room, $last_room ) = split( /-/, $dd );
+                    if ( !defined($last_room) ) {
+                        $last_room = $first_room;
+                    }
+                    my @arrayroom = $first_room .. $last_room;
+                    foreach (@arrayroom) {
+                        $barge_context{"$_"} = $aa;
+                    }
+                    push( @todos_los_rooms, @arrayroom );
+                }
+            }
+        }
+    }
+    %barge_rooms = map { $todos_los_rooms[$_], 0 } 0 .. $#todos_los_rooms;
+
+    $meetme_context = $config->{GENERAL}{conference_context};
+    $clid_format    = $config->{GENERAL}{clid_format};
+
+    $flash_file = $flash_dir . "/variables.txt";
+    push @all_flash_files, $flash_file;
+
+    if ( !defined $web_hostname ) {
+        $web_hostname = "";
+    }
+    if ( !defined $listen_port ) {
+        $listen_port = 4445;
+    }
+    if ( !defined $listen_addr ) {
+        $listen_addr = "0.0.0.0";
+    }
+    if ( !defined $astmanproxy_host ) {
+        $astmanproxy_host = "";
+    }
+    else {
+        @manager_host   = ();
+        @manager_user   = ();
+        @manager_secret = ();
+        push @manager_host,   $astmanproxy_host;
+        push @manager_user,   "astmanproxy";
+        push @manager_secret, "astmanproxy";
+    }
+
+    if ( defined $astmanproxy_port ) {
+        @manager_port = ();
+        push @manager_port, $astmanproxy_port;
+    }
+
+    if ( !defined $security_code ) {
+        die("Missing security_code in op_server.cfg!");
+    }
+
+    if ( !defined $flash_dir ) { die("Missing flash_dir in op_server.cfg!"); }
+
+    if ( !defined $poll_interval ) {
+        die("Missing poll_interval in op_server.cfg!");
+    }
+
+    if ( !defined $ren_agentlogin ) {
+        $ren_agentlogin = 0;
+    }
+
+    if ( !defined $defaultlanguage ) {
+        $defaultlanguage = "en";
+        $config->{DEFAULT}{language} = "en";
+    }
+
+    if ( !defined $clid_privacy ) {
+        $clid_privacy = 0;
+    }
+
+    if ( !defined $show_ip ) {
+        $show_ip = 0;
+    }
+
+    if ( !defined $queue_hide ) {
+        $queue_hide = 0;
+    }
+
+    if ( !defined $ren_wildcard || $ren_wildcard eq "" ) {
+        $ren_wildcard = 1;
+    }
+
+    if ( !defined $reverse_transfer || $reverse_transfer eq "" ) {
+        $reverse_transfer = 0;
+    }
+
+    if ( !defined $barge_muted || $barge_muted eq "" ) {
+        $barge_muted = 0;
+    }
+
+    if ( !defined $enable_restart || $enable_restart eq "" ) {
+        $enable_restart = 0;
+    }
+
+    if ( !defined $cdial_nosecure || $cdial_nosecure eq "" ) {
+        $cdial_nosecure = 0;
+    }
+
+    if ( !defined $agent_status || $agent_status eq "" ) {
+        $agent_status = 0;
+    }
+
+    if ( !defined $ren_agentname || $ren_agentname eq "" ) {
+        $ren_agentname = 0;
+    }
+
+    if ( !defined $ren_cbacklogin || $ren_cbacklogin eq "" ) {
+        $ren_cbacklogin = 0;
+    }
+
+    if ( !defined $ren_queuemember || $ren_queuemember eq "" ) {
+        $ren_queuemember = 0;
+    }
+
+    if ( !defined $change_led || $change_led eq "" ) {
+        $change_led = 0;
+    }
+
+    if ( !defined $kill_zombies || $kill_zombies eq "" ) {
+        $kill_zombies = 0;
+    }
+
+    if ( !defined $poll_voicemail || $poll_voicemail eq "" ) {
+        $poll_voicemail = 0;
+    }
+
+    if ( !defined $clid_format ) {
+        $clid_format = "(xxx) xxx-xxxx";
+    }
+
+    if ( !defined $debuglevel ) {
+        $debuglevel = 0;
+    }
+    else {
+        if ( $daemonized == 1 && $logdir eq "" ) {
+            $debuglevel = 0;
+        }
+    }
+    $/ = "\0";
+}
+
+sub collect_includes {
+    my $filename = shift;
+    my $tipo     = shift;
+    my $archivo  = $directorio . "/" . $filename;
+
+    if ( !-r $archivo ) {
+        log_debug( "** $archivo not readable... skipping", 16 ) if DEBUG;
+        return;
+    }
+
+    if ( $tipo eq "buttons" ) {
+        if ( !inArray( $filename, @btninclude ) ) {
+            push( @btninclude, $filename );
+        }
+        else {
+            log_debug( "** $filename already included", 16 ) if DEBUG;
+            return;
+        }
+    }
+    if ( $tipo eq "style" ) {
+        if ( !inArray( $filename, @styleinclude ) ) {
+            push( @styleinclude, $filename );
+        }
+        else {
+            log_debug( "** $filename already included", 16 ) if DEBUG;
+            return;
+        }
+    }
+
+    open( CONFIG, "< $archivo" )
+      or die("Could not open $filename. Aborting...\n\n");
+
+    my @lineas  = <CONFIG>;
+    my $cuantos = @lineas;
+    foreach my $linea (@lineas) {
+        $linea =~ s/^\s+//g;
+        $linea =~ s/([^;]*)[;](.*)/$1/g;
+        $linea =~ s/\s+$//g;
+        if ( $linea =~ /^include/ ) {
+
+            # store include lines in an array so we can
+            # process them later excluding duplicates
+            $linea =~ s/^include//g;
+            $linea =~ s/^\s+//g;
+            $linea =~ s/^=>//g;
+            $linea =~ s/^\s+//g;
+            $linea =~ s/\s+$//g;
+            collect_includes( $linea, $tipo );
+        }
+    }
+    close CONFIG;
+}
+
+sub read_astdb_config() {
+    $/ = "\n";
+    if ( -e "$directorio/op_astdb.cfg" ) {
+        open( ASTDB, "<$directorio/op_astdb.cfg" )
+          or die("Could not open op_astdb.cfg. Aborting...");
+        my $contador = 0;
+        my $key      = "";
+        while (<ASTDB>) {
+            chomp;
+            $_ =~ s/^\s+//g;
+            $_ =~ s/([^;]*)[;](.*)/$1/g;
+            $_ =~ s/\s+$//g;
+
+            if ( /^#/ || /^;/ || /^$/ ) {
+                next;
+            }    # Ignores comments and empty lines
+
+            if (/^\Q[\E/) {
+                s/\[(.*)\]/$1/g;
+                $key = $_;
+            }
+            else {
+                push @{ $astdbcommands{$key} }, $_;
+            }
+        }
+    }
+    close(ASTDB);
+
+    $/ = "\0";
+}
+
+sub read_buttons_config() {
+    my @btn_cfg  = ();
+    my $contador = -1;
+    my @distinct_files;
+    my $no_counter   = 0;
+    my @contextos    = ();
+    my %lastposition = ();
+
+    $/ = "\n";
+
+    @distinct_files = unique(@btninclude);
+
+    foreach my $archivo (@distinct_files) {
+        open( CONFIG, "< $directorio/$archivo" )
+          or die("Could not open $directorio/$archivo. Aborting...");
+
+        # Read op_buttons.cfg loading it into a hash for easier processing
+
+        while (<CONFIG>) {
+            chomp;
+            $_ =~ s/^\s+//g;
+            $_ =~ s/([^;]*)[;](.*)/$1/g;
+            $_ =~ s/\s+$//g;
+            if ( /^#/ || /^;/ || /^$/ ) {
+                next;
+            }    # Ignores comments and empty lines
+
+            if (/^\Q[\E/) {
+                $contador++;
+                s/\[(.*)\]/$1/g;
+                my $channel = $_;
+                $btn_cfg[$contador]{'channel_preserve_case'} = $channel;
+                $btn_cfg[$contador]{'channel'}               = $channel;
+
+            }
+            else {
+                next unless ( $contador >= 0 );
+                my ( $key, $val ) = split( /=/, $_, 2 );
+                $key =~ tr/A-Z/a-z/;
+                $key =~ s/^\s+//g;
+                $key =~ s/(.*)\s+/$1/g;
+                if (   $key ne "label"
+                    && $key ne "font_family"
+                    && $key ne "text"
+                    && $key ne "mailbox"
+                    && $key ne "voicemail_context" )
+                {
+                    $val =~ s/^\s+//g;
+                    $val =~ s/(.*)\s+/$1/g;
+                }
+                $btn_cfg[$contador]{$key} = $val;
+                if ( $key eq "panel_context" ) {
+                    push @contextos, $val;
+                }
+            }
+        }
+
+        close(CONFIG);
+    }
+
+    my @uniq2 = unique(@contextos);
+    @contextos = @uniq2;
+    @uniq2     = grep { !/\*/ } @contextos;
+    @contextos = @uniq2;
+    push @contextos, "DEFAULT";
+    push @contextos, "GENERAL";
+
+    # Convert every element to uppercase
+    @panel_contexts = map { uc } @contextos;
+
+    # Pass to replicate panel_context=* configuration
+    my @copy_cfg = ();
+    @copy_cfg = @btn_cfg;
+    foreach (@copy_cfg) {
+        my %tmphash = %$_;
+        if ( defined( $tmphash{panel_context} ) ) {
+            if ( $tmphash{panel_context} eq "*" ) {
+                foreach my $contextoahora (@contextos) {
+                    $contador++;
+                    while ( my ( $key, $val ) = each(%tmphash) ) {
+                        if ( $key eq "panel_context" ) {
+                            $val = $contextoahora;
+                        }
+                        $btn_cfg[$contador]{$key} = $val;
+                    }
+                }
+            }
+        }
+    }
+
+    # We finished reading the file, now we populate our
+    # structures with the relevant data
+    my %rectangles_counter;
+    my %legends_counter;
+
+  CONFIG:
+    foreach (@btn_cfg) {
+        my @positions = ();
+        my %tmphash   = %$_;
+
+        if ( defined( $tmphash{panel_context} ) ) {
+            if ( $tmphash{panel_context} eq "*" ) {
+
+                # We skip the * panel_context because we already
+                # expand them to every context possible before
+                next CONFIG;
+            }
+        }
+        if ( $tmphash{channel} =~ /^_/ ) {
+            $regexp_buttons = 1;
+        }
+        elsif ( $tmphash{channel} =~ /^QUEUEAGENT\//i ) {
+            $queueagent_buttons = 1;
+        }
+        elsif ( $tmphash{channel} =~ /^legend$/i ) {
+
+            # Legend config primitive
+
+            if ( defined( $tmphash{panel_context} ) ) {
+                $tmphash{panel_context} =~ tr/a-z/A-Z/;
+                $tmphash{panel_context} =~ s/^DEFAULT$//xms;
+            }
+            else {
+                $tmphash{panel_context} = "";
+            }
+            my $conttemp = $tmphash{panel_context};
+            if ( $conttemp eq "" ) { $conttemp = "GENERAL"; }
+
+            if ( !defined( $tmphash{text} ) ) {
+                $tmphash{text} = "LEGEND";
+            }
+            if ( !defined( $tmphash{x} ) ) {
+                $tmphash{x} = 1;
+            }
+            if ( !defined( $tmphash{y} ) ) {
+                $tmphash{y} = 1;
+            }
+            if ( !defined( $tmphash{font_size} ) ) {
+                $tmphash{font_size} = 16;
+            }
+            if ( !defined( $tmphash{font_color} ) ) {
+                $tmphash{font_color} = "000000";
+            }
+            if ( !defined( $tmphash{use_embed_fonts} ) ) {
+                $tmphash{use_embed_fonts} = 1;
+            }
+            if ( !defined( $tmphash{font_family} ) ) {
+                $tmphash{font_family} = "Arial";
+            }
+            if ( !defined( $tmphash{no_base64} ) ) {
+                $tmphash{no_base64} = 0;
+            }
+            if ( $tmphash{no_base64} == 0 ) {
+                $tmphash{text} = encode_base64( $tmphash{text} );
+            }
+            if ( !defined( $tmphash{url} ) ) {
+                $tmphash{url} = "no";
+            }
+            if ( !defined( $tmphash{target} ) ) {
+                $tmphash{target} = "NONTARFOP";
+            }
+            $legends_counter{$conttemp}++;
+            if ( $legends_counter{$conttemp} > 1 ) {
+                $legends{$conttemp} .= "&";
+            }
+            $total_legends{$conttemp}++;
+            $legends{$conttemp} .= "legend_$legends_counter{$conttemp}=" . $tmphash{x} . ",";
+            $legends{$conttemp} .= $tmphash{y} . ",";
+            $legends{$conttemp} .= $tmphash{text} . ",";
+            $legends{$conttemp} .= $tmphash{font_size} . ",";
+            $legends{$conttemp} .= $tmphash{font_family} . ",";
+            $legends{$conttemp} .= $tmphash{font_color} . ",";
+            $legends{$conttemp} .= $tmphash{use_embed_fonts} . ",";
+            $legends{$conttemp} .= $tmphash{no_base64} . ",";
+            $legends{$conttemp} .= $tmphash{url} . ",";
+            $legends{$conttemp} .= $tmphash{target};
+            next CONFIG;
+        }
+        elsif ( $tmphash{channel} =~ /^RECTANGLE$/i ) {
+
+            # Rectangle config primitive
+            if ( defined( $tmphash{panel_context} ) ) {
+                $tmphash{panel_context} =~ tr/a-z/A-Z/;
+                $tmphash{panel_context} =~ s/^DEFAULT$//;
+            }
+            else {
+                $tmphash{panel_context} = "";
+            }
+            my $conttemp = $tmphash{panel_context};
+            if ( $conttemp eq "" ) { $conttemp = "GENERAL"; }
+
+            if ( !defined( $tmphash{x} ) ) {
+                $tmphash{x} = 1;
+            }
+            if ( !defined( $tmphash{y} ) ) {
+                $tmphash{y} = 1;
+            }
+            if ( !defined( $tmphash{width} ) ) {
+                $tmphash{width} = 1;
+            }
+            if ( !defined( $tmphash{height} ) ) {
+                $tmphash{height} = 1;
+            }
+            if ( !defined( $tmphash{line_width} ) ) {
+                $tmphash{line_width} = 1;
+            }
+            if ( !defined( $tmphash{line_color} ) ) {
+                $tmphash{line_color} = "0x000000";
+            }
+            if ( !defined( $tmphash{fade_color1} ) ) {
+                $tmphash{fade_color1} = "0xd0d0d0";
+            }
+            if ( !defined( $tmphash{fade_color2} ) ) {
+                $tmphash{fade_color2} = "0xd0d000";
+            }
+            if ( !defined( $tmphash{rnd_border} ) ) {
+                $tmphash{rnd_border} = 3;
+            }
+            if ( !defined( $tmphash{alpha} ) ) {
+                $tmphash{alpha} = 100;
+            }
+            if ( !defined( $tmphash{layer} ) ) {
+                $tmphash{layer} = "bottom";
+            }
+
+            $rectangles_counter{$conttemp}++;
+            if ( $rectangles_counter{$conttemp} > 1 ) {
+                $shapes{$conttemp} .= "&";
+            }
+            $total_shapes{$conttemp}++;
+            $shapes{$conttemp} .= "rect_$rectangles_counter{$conttemp}=" . $tmphash{x} . ",";
+            $shapes{$conttemp} .= $tmphash{y} . ",";
+            $shapes{$conttemp} .= $tmphash{width} . ",";
+            $shapes{$conttemp} .= $tmphash{height} . ",";
+            $shapes{$conttemp} .= $tmphash{line_width} . ",";
+            $shapes{$conttemp} .= $tmphash{line_color} . ",";
+            $shapes{$conttemp} .= $tmphash{fade_color1} . ",";
+            $shapes{$conttemp} .= $tmphash{fade_color2} . ",";
+            $shapes{$conttemp} .= $tmphash{rnd_border} . ",";
+            $shapes{$conttemp} .= $tmphash{alpha} . ",";
+            $shapes{$conttemp} .= $tmphash{layer};
+            next CONFIG;
+        }
+
+        if ( !defined( $tmphash{position} ) ) {
+            log_debug( "** Ignored button $tmphash{'channel'}, position?", 16 ) if DEBUG;
+            next CONFIG;
+        }
+
+        if ( !defined( $tmphash{url} ) ) {
+            $tmphash{url} = "0";
+        }
+
+        if ( !defined( $tmphash{target} ) ) {
+            $tmphash{target} = "0";
+        }
+
+        if ( !defined( $tmphash{server} ) ) {
+            $tmphash{server} = 0;
+        }
+        else {
+            $tmphash{server} = $tmphash{server} - 1;
+        }
+
+        if ( !defined( $tmphash{label} ) ) {
+            $tmphash{label} = $tmphash{channel};
+        }
+
+        if ( !defined( $tmphash{icon} ) ) {
+            $tmphash{icon} = "0";
+        }
+
+        # Local channels are case sensitive
+        my $canal_key = "";
+
+        if ( $tmphash{channel} =~ m/^local/i ) {
+            $canal_key = $tmphash{channel};
+        }
+        else {
+            $canal_key = uc( $tmphash{channel} );
+        }
+
+        my $canal_key_case = $tmphash{channel_preserve_case};
+
+        if ( $canal_key =~ m/^PARK\d/ ) {
+
+            # Change the PARKXXX tu PARK/XXX
+            $canal_key      =~ s/PARK(.*)/PARK\/$1/g;
+            $canal_key_case =~ s/PARK(.*)/PARK\/$1/gi;
+        }
+
+        if ( defined( $tmphash{panel_context} ) ) {
+            $tmphash{panel_context} =~ tr/a-z/A-Z/;
+            $tmphash{panel_context} =~ s/^DEFAULT$//;
+        }
+        else {
+            $tmphash{panel_context} = "";
+        }
+
+        if ( $tmphash{panel_context} ne "" ) {
+
+            # We want to add the context in case we have the same button
+            # repeated in several panel_contexts. If we do not add it, then
+            # only the last panel context will prevail.
+            $canal_key      .= "&" . $tmphash{panel_context};
+            $canal_key_case .= "&" . $tmphash{panel_context};
+        }
+
+        if (   ( $tmphash{position} !~ /,/ )
+            && ( $tmphash{position} !~ /-/ )
+            && ( $canal_key =~ /^_/ ) )
+        {
+
+            # If it's a regexp button with just one position
+            # we fake the same position number to populate
+            # the array and make the button work anyways.
+            my $pos = $tmphash{position};
+            $pos =~ s/(\d+),(\d+)/$1/g;
+            $tmphash{position} = "$pos,$pos";
+            $no_counter = 1;
+        }
+        else {
+            $no_counter = 0;
+        }
+
+        if ( $tmphash{position} =~ /[,-]/ ) {
+
+            my $canalidx = $tmphash{server} . "^" . $tmphash{channel};
+
+            if ( defined( $tmphash{panel_context} )
+                && $tmphash{panel_context} ne "" )
+            {
+                $canalidx .= "&" . $tmphash{panel_context};
+            }
+            $instancias{ uc($canalidx) }{""} = 0;
+
+            my @ranges = split( /,/, $tmphash{position} );
+            foreach my $valu (@ranges) {
+                if ( $valu !~ m/-/ ) {
+                    if ( $valu eq "n" ) {
+                        my $lastpos = $lastposition{ $tmphash{panel_context} };
+                        if ( is_number($lastpos) ) {
+                            $lastpos++;
+                            $lastposition{ $tmphash{panel_context} } = $lastpos;
+                            $valu = $lastpos;
+                            push @positions, $valu;
+                            last;
+                        }
+                    }
+                    push @positions, $valu;
+                }
+                else {
+                    my @range2 = split( /-/, $valu );
+                    my $menor = $range2[0] < $range2[1] ? $range2[0] : $range2[1];
+                    my $mayor = $range2[0] > $range2[1] ? $range2[0] : $range2[1];
+                    my @newrange = $menor .. $mayor;
+                    foreach my $valevale (@newrange) {
+                        push @positions, $valevale;
+                    }
+                }
+            }
+
+            my $count = 0;
+            foreach my $pos (@positions) {
+                $count++;
+                my $indice_contexto = $pos;
+                my $chan_trunk      = $tmphash{channel} . "=" . $count;
+                my $chan_trunk_case = $tmphash{channel_preserve_case} . "=" . $count;
+                if ( $tmphash{panel_context} ne "" ) {
+                    $chan_trunk      .= "&" . $tmphash{panel_context};
+                    $chan_trunk_case .= "&" . $tmphash{panel_context};
+                    $indice_contexto .= "@" . $tmphash{panel_context};
+                    $pos             .= "@" . $tmphash{panel_context};
+                }
+                if ( $chan_trunk =~ m/^QUEUE/i ) {
+                    $buttons_queue{ uc("$tmphash{server}^$chan_trunk") } = $pos;
+                }
+                $buttons_preserve_case{"$tmphash{server}^$chan_trunk_case"} = $pos;
+                $buttons{ uc("$tmphash{server}^$chan_trunk") }              = $pos;
+                $textos{$indice_contexto}                                   = $tmphash{label};
+                if ( $no_counter == 0 ) {
+                    $textos{$indice_contexto} .= " " . $count;
+                }
+                $iconos{$indice_contexto}  = $tmphash{icon};
+                $urls{$indice_contexto}    = $tmphash{url};
+                $targets{$indice_contexto} = $tmphash{target};
+                $button_server{$pos}       = $tmphash{server};
+
+                # Saves last position for the button at context
+                $lastposition{ $tmphash{panel_context} } = $pos;
+                log_debug( qq[** $tmphash{server}^$chan_trunk in position $pos], 16 ) if DEBUG;
+            }
+        }
+        else {
+            my $lastpos = 0;
+            $lastpos = $lastposition{ $tmphash{panel_context} }
+              if defined( $lastposition{ $tmphash{panel_context} } );
+            if ( $tmphash{position} eq "n" ) {
+                if ( is_number($lastpos) ) {
+                    $lastpos++;
+                    $lastposition{ $tmphash{panel_context} } = $lastpos;
+                }
+            }
+            else {
+                $lastpos = $tmphash{position};
+                $lastposition{ $tmphash{panel_context} } = $lastpos;
+            }
+
+            log_debug( qq[** $tmphash{channel} in next position $lastpos], 16 ) if DEBUG;
+
+            if ( $tmphash{panel_context} ne "" ) {
+
+                if ( $canal_key =~ m/^QUEUE/i ) {
+                    $buttons_queue{ uc("$tmphash{server}^$canal_key") } = $lastpos . "\@" . $tmphash{panel_context};
+                }
+                $buttons{"$tmphash{server}^$canal_key"}                    = $lastpos . "\@" . $tmphash{panel_context};
+                $buttons_preserve_case{"$tmphash{server}^$canal_key_case"} = $lastpos . "\@" . $tmphash{panel_context};
+
+                $textos{"$lastpos\@$tmphash{panel_context}"}              = $tmphash{label};
+                $iconos{"$lastpos\@$tmphash{panel_context}"}              = $tmphash{icon};
+                $urls{"$lastpos\@$tmphash{panel_context}"}                = $tmphash{url};
+                $targets{"$lastpos\@$tmphash{panel_context}"}             = $tmphash{target};
+                $button_server{ $buttons{"$tmphash{server}^$canal_key"} } = $tmphash{server};
+            }
+            else {
+                if ( $canal_key =~ /^_/ ) {
+                    $canal_key .= "=1";
+                }
+
+                if ( $canal_key =~ m/^QUEUE/i ) {
+                    $buttons_queue{ uc("$tmphash{server}^$canal_key") } = $lastpos;
+                }
+                $buttons{"$tmphash{server}^$canal_key"}                    = $lastpos;
+                $buttons_preserve_case{"$tmphash{server}^$canal_key_case"} = $lastpos;
+                $textos{$lastpos}                                          = $tmphash{label};
+                $iconos{$lastpos}                                          = $tmphash{icon};
+                $urls{$lastpos}                                            = $tmphash{url};
+                $targets{$lastpos}                                         = $tmphash{target};
+                $button_server{ $buttons{"$tmphash{server}^$canal_key"} }  = $tmphash{server};
+            }
+        }
+
+        @positions = unique(@positions);
+
+        if ( defined( $tmphash{privacy} ) ) {
+            my $count = @positions;
+            if ( $count == 0 ) {
+                push @positions, $lastposition{ $tmphash{panel_context} };
+            }
+            if ( $tmphash{privacy} eq "true" || $tmphash{privacy} eq "1" ) {
+                my $agre_context = "";
+                if ( $tmphash{panel_context} ne "" ) {
+                    $agre_context = "\@" . $tmphash{panel_context};
+                }
+                foreach my $pos (@positions) {
+                    $clid_private{"$pos$agre_context"} = 1;
+                }
+            }
+        }
+
+        if ( defined( $tmphash{no_rectangle} ) ) {
+            my $count = @positions;
+            if ( $count == 0 ) {
+                push @positions, $lastposition{ $tmphash{panel_context} };
+            }
+
+            if ( $tmphash{no_rectangle} eq "true" || $tmphash{no_rectangle} eq "1" ) {
+                my $pcont = $tmphash{panel_context};
+                if ( $pcont eq "" ) { $pcont = "GENERAL"; }
+                foreach my $pos (@positions) {
+                    $pos =~ s/\@$pcont//g;
+                    $no_rectangle{$pcont}{$pos} = 1;
+                }
+            }
+        }
+
+        if ( defined( $tmphash{background} ) ) {
+            my $count = @positions;
+            if ( $count == 0 ) {
+                push @positions, $lastposition{ $tmphash{panel_context} };
+            }
+
+            my $pcont = $tmphash{panel_context};
+            if ( $pcont eq "" ) { $pcont = "GENERAL"; }
+            foreach my $pos (@positions) {
+                $pos =~ s/\@$pcont//g;
+                $background{$pcont} .= "&bg$pos=$tmphash{background}";
+            }
+        }
+
+        if ( defined( $tmphash{extension} ) ) {
+            if ( defined( $tmphash{context} ) ) {
+
+                $extension_transfer{"$tmphash{server}^$canal_key"} = $tmphash{server} . "^" . $tmphash{extension} . "@" . $tmphash{context};
+
+            }
+            else {
+                $extension_transfer{"$tmphash{server}^$canal_key"} = $tmphash{server} . "^" . $tmphash{extension};
+            }
+            if ( defined( $tmphash{voicemail_context} ) ) {
+                $mailbox{"$tmphash{server}^$canal_key"} = $tmphash{extension} . "@" . $tmphash{voicemail_context};
+            }
+        }
+        if ( defined( $tmphash{mailbox} ) ) {
+            $mailbox{"$tmphash{server}^$canal_key"} = $tmphash{mailbox};
+        }
+        if ( defined( $tmphash{voicemailext} ) ) {
+            my $indicevm = $lastposition{ $tmphash{panel_context} };
+            if ( $tmphash{panel_context} ne "" ) {
+                $indicevm .= "\@$tmphash{panel_context}";
+            }
+            $tovoicemail{$indicevm} = $tmphash{voicemailext};
+        }
+        $/ = "\0";
+    }
+    %extension_transfer_reverse = reverse %extension_transfer;
+    %buttons_reverse            = reverse %buttons;
+    %buttons_queue_reverse      = reverse %buttons_queue;
+}
+
+sub genera_config {
+
+    # This sub generates the file variables.txt that is read by the
+    # swf movie on load, with info about buttons, layout, etc.
+
+    my @textsclients = (
+        'detail_title',      'detail_from',        'detail_to',       'security_code_title',
+        'btn_security_text', 'btn_restart_text',   'btn_reload_text', 'btn_debug_text',
+        'btn_help_text',     'tab_call_text',      'tab_queue_text',  'calls_taken_text',
+        'no_data_text',      'debug_window_title', 'detail_duration', 'clid_label',
+        'version_mismatch'
+    );
+
+    $/ = "\n";
+    my %style_variables;
+    my @contextos        = ();
+    my @unique_contexts  = ();
+    my $contextoactual   = "";
+    my $highest_position = 0;
+    my @style_include    = ();
+
+    foreach my $archi (@styleinclude) {
+        open( STYLE, "<$directorio/$archi" )
+          or die("Could not open $archi for reading");
+        while (<STYLE>) {
+            chomp($_);
+            $_ =~ s/^\s+//g;
+            $_ =~ s/([^;]*)[;](.*)/$1/g;
+            $_ =~ s/\s+$//g;
+            next unless $_ ne "";
+
+            if (/^\Q[\E/) {
+                s/\[(.*)\]/$1/g;
+                $contextoactual = $_;
+                $contextoactual =~ tr/A-Z/a-z/;
+                next;
+            }
+            if (/^include/i) {
+
+                # Skip include lines
+                next;
+            }
+            $style_variables{$contextoactual} .= $_ . "&";
+        }
+        close(STYLE);
+    }
+
+    for ( keys %textos ) {
+        if ( $_ =~ /\@/ ) {
+            my @partes = split(/\@/);
+            if ( $partes[1] ne "*" ) {
+                push( @contextos, $partes[1] );
+            }
+        }
+    }
+
+    push @contextos, "GENERAL";
+    @unique_contexts = unique(@contextos);
+
+    # Writes variables.txt for each context defined
+    foreach my $contexto_iterate (@unique_contexts) {
+
+        my $directorio   = "";
+        my $host_web     = "";
+        my $contextlower = $contexto_iterate;
+        $contextlower =~ tr/A-Z/a-z/;
+
+        if ( defined( $config->{$contexto_iterate}{flash_dir} ) ) {
+            $directorio = $config->{$contexto_iterate}{flash_dir};
+        }
+        else {
+            $directorio = $config->{GENERAL}{flash_dir};
+        }
+
+        if ( defined( $config->{$contexto_iterate}{web_hostname} ) ) {
+            $host_web = $config->{$contexto_iterate}{web_hostname};
+        }
+        else {
+            $host_web = $web_hostname;
+        }
+
+        my $append_filename = "";
+        if ( $contexto_iterate ne "GENERAL" ) {
+            $append_filename = $contexto_iterate;
+        }
+        my $flash_context_file = $directorio . "/variables" . $append_filename . ".txt";
+        push @all_flash_files, $flash_context_file;
+        open( VARIABLES, ">$flash_context_file" )
+          or die("Could not write configuration data $flash_context_file.\nCheck your file permissions\n");
+
+        if ( $host_web ne "" ) {
+            print VARIABLES "server=$host_web&";
+        }
+        if ( $listen_port ne "4445" ) {
+            print VARIABLES "port=$listen_port&";
+        }
+        print VARIABLES "restart=$enable_restart";
+
+        if ( defined( $config->{$contexto_iterate}{security_code} ) ) {
+            if ( $config->{"$contexto_iterate"}{security_code} eq "" ) {
+                print VARIABLES "&nosecurity=1";
+            }
+        }
+
+        if ( defined( $config->{"$contexto_iterate"}{transfer_timeout} ) ) {
+            my @partes = split( /\|/, $config->{"$contexto_iterate"}{transfer_timeout} );
+            my $cuantos = @partes;
+            print VARIABLES "&totaltimes=$cuantos";
+            my $contador = 1;
+            foreach my $item_timeout (@partes) {
+                print VARIABLES "&timeout_$contador=$item_timeout";
+                $contador++;
+            }
+        }
+        else {
+            print VARIABLES "&totaltimes=0";
+        }
+
+        if ( $no_rectangle{$contexto_iterate} ) {
+            my $pos_no_dibujar = "";
+            while ( my ( $key, $val ) = each( %{ $no_rectangle{$contexto_iterate} } ) ) {
+                $pos_no_dibujar .= "$key,";
+            }
+            $pos_no_dibujar = substr( $pos_no_dibujar, 0, -1 );
+            print VARIABLES "&nodraw=$pos_no_dibujar";
+        }
+
+        if ( $background{$contexto_iterate} ) {
+            my $pos_no_dibujar = $background{$contexto_iterate};
+            print VARIABLES "$pos_no_dibujar";
+        }
+
+        while ( my ( $key, $val ) = each(%shapes) ) {
+            if ( $key eq $contexto_iterate ) {
+                print VARIABLES "&$val";
+            }
+        }
+        while ( my ( $key, $val ) = each(%legends) ) {
+            if ( $key eq $contexto_iterate ) {
+                print VARIABLES "&$val";
+            }
+        }
+        $highest_position = 0;
+        while ( my ( $key, $val ) = each(%textos) ) {
+            $val =~ s/\"(.*)\"/$1/g;
+            my $contextoboton = $key;
+            if ( $contextoboton =~ m/\@/ ) {
+                my @parte = split( /\@/, $contextoboton, 2 );
+                $contextoboton = $parte[1];
+                $contextoboton =~ tr/a-z/A-Z/;
+            }
+            else {
+                $contextoboton = "GENERAL";
+            }
+            if ( $contextoboton eq $contexto_iterate ) {
+                $key =~ s/(\d+)\@.+/$1/g;
+                print VARIABLES "&texto$key=$val";
+                if ( $key > $highest_position ) { $highest_position = $key; }
+            }
+        }
+        print VARIABLES "&highestpos=$highest_position";
+        while ( my ( $key, $val ) = each(%iconos) ) {
+            $val =~ s/\"(.*)\"/$1/g;
+
+            my $contextoboton = $key;
+            if ( $contextoboton =~ m/\@/ ) {
+                my @parte = split( /\@/, $contextoboton, 2 );
+                $contextoboton = $parte[1];
+                $contextoboton =~ tr/a-z/A-Z/;
+            }
+            else {
+                $contextoboton = "GENERAL";
+            }
+
+            if ( $contextoboton eq $contexto_iterate ) {
+                $key =~ s/(\d+)\@.+/$1/g;
+                print VARIABLES "&icono$key=$val";
+            }
+        }
+        while ( my ( $key, $val ) = each(%urls) ) {
+            $val =~ s/\"(.*)\"/$1/g;
+            if ( $val ne "0" ) {
+                my $base64_url    = encode_base64($val);
+                my $contextoboton = $key;
+                if ( $contextoboton =~ m/\@/ ) {
+                    my @parte = split( /\@/, $contextoboton, 2 );
+                    $contextoboton = $parte[1];
+                    $contextoboton =~ tr/a-z/A-Z/;
+                }
+                else {
+                    $contextoboton = "GENERAL";
+                }
+
+                if ( $contextoboton eq $contexto_iterate ) {
+                    $key =~ s/(\d+)\@.+/$1/g;
+                    print VARIABLES "&url$key=$base64_url";
+                }
+            }
+        }
+        while ( my ( $key, $val ) = each(%targets) ) {
+            $val =~ s/\"(.*)\"/$1/g;
+
+            if ( $val ne "0" ) {
+                my $contextoboton = $key;
+                if ( $contextoboton =~ m/\@/ ) {
+                    my @parte = split( /\@/, $contextoboton, 2 );
+                    $contextoboton = $parte[1];
+                    $contextoboton =~ tr/a-z/A-Z/;
+                }
+                else {
+                    $contextoboton = "GENERAL";
+                }
+
+                if ( $contextoboton eq $contexto_iterate ) {
+                    $key =~ s/(\d+)\@.+/$1/g;
+                    print VARIABLES "&target$key=$val";
+                }
+            }
+        }
+        if ( !defined( $style_variables{$contextlower} ) ) {
+            $style_variables{$contextlower} = $style_variables{"general"};
+        }
+        print VARIABLES "&" . $style_variables{$contextlower};
+        if ( !defined( $total_shapes{$contexto_iterate} ) ) {
+            $total_shapes{$contexto_iterate} = 0;
+        }
+        print VARIABLES "total_rectangles=" . $total_shapes{$contexto_iterate};
+        if ( !defined( $total_legends{$contexto_iterate} ) ) {
+            $total_legends{$contexto_iterate} = 0;
+        }
+        print VARIABLES "&total_legends=" . $total_legends{$contexto_iterate};
+
+        foreach my $val (@textsclients) {
+            if ( defined( $language->{$contexto_iterate}{$val} ) ) {
+                print VARIABLES "&$val=" . $language->{$contexto_iterate}{$val};
+            }
+            else {
+                log_debug( "Language string $val in context $contexto_iterate does not exists", 64 ) if DEBUG;
+                print("Language string $val in context $contexto_iterate does not exists\n");
+            }
+        }
+        print VARIABLES "&lang=" . $config->{$contexto_iterate}{language};
+        close(VARIABLES);
+    }
+    $/ = "\0";
+}
+
+sub dump_internal_hashes_to_stdout {
+
+    &print_botones(1);
+
+    &print_instancias(1);
+
+    if ( keys(%datos) ) {
+        &print_datos(1);
+    }
+    else {
+        print "No data blocks in memory\n";
+    }
+
+    if ( keys(%sesbot) ) {
+        &print_sesbot(1);
+    }
+    else {
+        print "No data sesiones botones\n";
+    }
+
+    if ( keys(%linkbot) ) {
+        &print_linkbot();
+    }
+
+    &print_cachehit();
+
+    print "\n";
+    while ( my ( $key, $val ) = each(%timeouts) ) {
+        print "Timer($key)=$val\n";
+    }
+    print "\n";
+
+    &print_status();
+
+    &print_clients();
+
+    &print_cola_write();
+
+    &print_timers();
+
+}
+
+sub generate_configs_onhup {
+    %buttons            = ();
+    %background         = ();
+    %sesbot             = ();
+    %linkbot            = ();
+    %instancias         = ();
+    %textos             = ();
+    %iconos             = ();
+    %urls               = ();
+    %targets            = ();
+    %extension_transfer = ();
+    %shapes             = ();
+    %legends            = ();
+    %total_shapes       = ();
+    %total_legends      = ();
+    @all_flash_files    = ();
+    %astdbcommands      = ();
+
+    %estadoboton         = ();
+    %botonled            = ();
+    %botonvoicemail      = ();
+    %botonvoicemailcount = ();
+    %botonalpha          = ();
+    %botonqueue          = ();
+    %botonqueuemember    = ();
+    %botonpark           = ();
+    %botonlinked         = ();
+    %botonclid           = ();
+    %botonmeetme         = ();
+    %botontimer          = ();
+    %botontimertype      = ();
+    %botonlabel          = ();
+    %botonsetlabel       = ();
+    %botonregistrado     = ();
+    @astmanproxy_servers = ();
+
+    &read_buttons_config();
+    &read_server_config();
+    &read_language_config();
+    &read_astdb_config();
+    &genera_config();
+    &send_initial_status();
+}
+
+sub get_next_trunk_button {
+    my $canalid        = shift;
+    my $contexto       = shift;
+    my $server         = shift;
+    my $canalsesion    = shift;
+    my $canal_tipo_fop = "";
+    my $canal;
+    my $sesion;
+    my $return = "";
+    my @uniq;
+    my $trunk_pos;
+    my $heading = "** GET_NEXT_TRUNK";
+
+    # This routine mantains and returns the position of each channel inside
+    # a trunk button.
+
+    log_debug( "$heading START SUB canalid $canalid contexto $contexto server $server canalsesion $canalsesion", 16 ) if DEBUG;
+
+    if ( $canalid eq "" ) {
+        log_debug( "!! ERROR empty canalid ", 64 ) if DEBUG;
+        return;
+    }
+
+    if ( $canalsesion =~ /</ ) {
+
+        # We want to remove <ZOMBIE> or <MASQ>
+        $canalsesion =~ s/([^<]*).*/$1/g;
+    }
+
+    if ( $canalid !~ /\^/ ) {
+        $canal_tipo_fop = $server . "^" . $canalid;
+    }
+    else {
+        $canal_tipo_fop = $canalid;
+        $canalid =~ s/(.*)\^(.*)/$2/g;
+    }
+
+    if ( $canal_tipo_fop =~ /\QCAPI[\E/ ) {
+        $canal_tipo_fop =~ tr/a-z/A-Z/;
+        $canalid        =~ tr/a-z/A-Z/;
+    }
+    $canal_tipo_fop =~ s/(.*)<(.*)>/$1/g;
+    $canal_tipo_fop =~ s/\s+//g;
+    $canal_tipo_fop =~ s/(.*)[-\/](.*)/$1/g;
+    if ( defined($2) ) {
+        $sesion = $2;
+    }
+    else {
+        $sesion = "XXXX";
+    }
+    $sesion         =~ s/(.*)\&(.*)/$1/g;                               # removes context if it has any
+    $canal_tipo_fop =~ s/(\d+\^IAX2\/)([^@]*)(.*)/$1\U$2\E/g;
+    $canal_tipo_fop =~ s/(\d+\^IAX2)\[(.*)?@?(.*)?\]?/$1\[\U$2\E\]/g;
+    log_debug( "$heading canal_tipo_fop 1 $canal_tipo_fop", 64 ) if DEBUG;
+
+    if ( $canalid =~ /^_.*/ ) {
+        $canal_tipo_fop = $canalid;
+        if ( $canal_tipo_fop =~ /=/ ) {
+            $canal_tipo_fop =~ /([^=].*)(=\d+)(.*)/;
+            $canal_tipo_fop = $1;
+            if ( defined($3) ) {
+                $contexto = $3;
+            }
+        }
+        log_debug( "$heading contexto $contexto", 32 ) if DEBUG;
+        my ( $nada, $ses ) = separate_session_from_channel($canalsesion);
+        $sesion = $ses;
+    }
+    $canal_tipo_fop =~ tr/a-z/A-Z/;
+    log_debug( "$heading canal_tipo_fop 2 $canal_tipo_fop", 64 ) if DEBUG;
+
+    my $canalconcontexto = "";
+    if ( $contexto ne "" ) {
+        $canalconcontexto = "$canal_tipo_fop$contexto";
+    }
+    else {
+        $canalconcontexto = $canal_tipo_fop;
+        $contexto         = "";
+    }
+
+    if ( $sesion eq "XXXX" ) {
+
+        # Si la sesion es XXXX devuelve siempre el 1er boton
+        log_debug( "$heading return $canal_tipo_fop=1$contexto (1st one)", 64 ) if DEBUG;
+        return "$canal_tipo_fop=1$contexto";
+    }
+
+    my $canalconcontextosinserver = $canalconcontexto;
+    $canalconcontextosinserver =~ s/(\d+)\^(.*)/$2/g;
+    if ( $canalconcontexto !~ /\^/ ) {
+        $canalconcontexto = $server . "^" . $canalconcontexto;
+    }
+    if ( exists( $instancias{"$canalconcontexto"} ) ) {
+        if ( exists( $instancias{"$canalconcontexto"}{"$server^$canalsesion"} ) ) {
+            log_debug(
+"$heading Found instancias($canalconcontexto)($server^$canalsesion)=$instancias{\"$canalconcontexto\"}{\"$server^$canalsesion\"}",
+                64
+              )
+              if DEBUG;
+            $trunk_pos = $instancias{"$canalconcontexto"}{"$server^$canalsesion"};
+        }
+        else {
+            log_debug( "$heading Not Found instancias($canalconcontexto)($server^$canalsesion)", 64 ) if DEBUG;
+            my %busy_slots = ();
+            foreach my $key1 ( sort ( keys(%instancias) ) ) {
+                if ( $key1 eq $canalconcontexto ) {
+                    foreach my $key2 ( sort ( keys( %{ $instancias{$key1} } ) ) ) {
+                        my $indice = $instancias{$key1}{$key2};
+                        $busy_slots{$indice} = 1;
+                    }
+                }
+            }
+            for ( $trunk_pos = 1 ; ; $trunk_pos++ ) {
+                last if ( !exists( $busy_slots{$trunk_pos} ) );
+            }
+            $instancias{"$canalconcontexto"}{"$server^$canalsesion"} = $trunk_pos;
+        }
+        $return = "$canal_tipo_fop=${trunk_pos}$contexto";
+    }
+    return $return;
+}
+
+sub separate_session_from_channel {
+    my $elemento = shift;
+    my $heading  = "** SEPARATE_SESSION_FROM_CHAN";
+    log_debug( "$heading elemento1 $elemento", 32 ) if DEBUG;
+    if ( $elemento !~ /.*[-\/].*[-\/].+$/ ) {
+        if ( $elemento =~ /^OH323/ || $elemento =~ /^\QMODEM[I4l]\E/i ) {
+            $elemento =~ s/(.*)\/(.*)/\U$1\E\/${2}-${2}/g;
+        }
+        elsif ( $elemento =~ m/^\d+/ ) {
+
+            # If the channel is a meetme, do nothing;
+        }
+        else {
+            $elemento .= "-XXXX";
+        }
+    }
+    if ( $elemento =~ /^mISDN/i ) {
+        $elemento .= "-XXXX";
+
+        #    $elemento =~ s/(.*)\/(.*)/\U$1\E\/${2}-${2}/g;
+    }
+    if ( $elemento =~ /^SRX/i ) {
+        $elemento =~ s/(.*)\/(.*)/\U$1\E\/${2}-1/g;
+    }
+    $elemento =~ s/(.*)[-\/](.*)/$1\t$2/g;
+    log_debug( "$heading elemento2 $elemento", 32 ) if DEBUG;
+    my $canal  = $1;
+    my $sesion = $2;
+    log_debug( "$heading canal $canal sesion $sesion", 32 ) if DEBUG;
+
+    if ( defined($canal) && defined($sesion) ) {
+        $canal =~ tr/a-z/A-Z/;
+        $elemento = $canal . "\t" . $sesion;
+    }
+    $elemento =~ s/IAX2\[(.*)@(.*)\]\t(.*)/IAX2\[$1\]\t$3/;
+    $elemento =~ s/IAX2\/(.*)@(.*)\t(.*)/IAX2\/$1\t$3/;
+
+    my @partes = split( /\t/, $elemento );
+    return @partes;
+}
+
+sub peerinfo {
+    my $sock  = shift;
+    my $short = shift;
+    if ( $sock eq "" ) {
+        return "";
+    }
+    if ( defined( $sock->peeraddr ) ) {
+        if ( defined($short) ) {
+            return $sock->peerhost;
+        }
+        else {
+            return sprintf( "%s:%s", $sock->peerhost, $sock->peerport );
+        }
+
+    }
+    else {
+        return "";
+    }
+}
+
+sub erase_instances_for_trunk_buttons {
+    my $canalid          = shift;
+    my $canal            = shift;
+    my $server           = shift;
+    my $canalidsinserver = "";
+    my $canalglobal;
+    my $valor;
+    my @new     = ();
+    my $heading = "** ERASE_INSTANCE_TRUNK";
+
+    $canalidsinserver = $canalid;
+    $canalid          = "$server^$canalid";
+    $canalid =~ s/(.*)<(.*)>/$1/g;    #discards ZOMBIE or MASQ
+
+    log_debug( "$heading canalid $canalid canal $canal", 16 ) if DEBUG;
+
+    $canalglobal = $canalid;
+    $canalglobal =~ s/(.*)[-\/](.*)/$1/g;
+    $canalglobal =~ s/IAX2\/(.*)@(.*)/IAX2\/$1/g;
+    $canalglobal =~ s/IAX2\[(.*)@(.*)\]/IAX2\[$1\]/g;
+
+    my ( $nada, $contexto ) = split( /\&/, $canal );
+    if ( !defined($contexto) ) { $contexto = ""; }
+
+    my $canalconcontexto = "";
+    if ( $contexto ne "" ) {
+        $canalconcontexto = "$canalglobal&$contexto";
+        $contexto         = "&$contexto";
+    }
+    else {
+        $canalconcontexto = $canalglobal;
+        $contexto         = "";
+    }
+
+    my $sesiontemp = $canalid;
+    if ( $canalid =~ /^Zap/i && $canal =~ /\*/ ) {
+
+        # Si es un Zap y ademas wildcard, cambio el canalid para
+        # que tenga la sesion modificada
+        # $sesiontemp =~ s/Zap/ZAP/g;
+        $sesiontemp =~ s/(.*)\/(.*)-(.*)/\U$1\/$2-${2}\E${3}/g;
+    }
+    if ( $canalid =~ /^MGCP/i && $canal =~ /\*/ ) {
+
+        # Si es un MGCP y ademas wildcard, cambio el canalid para
+        # que tenga la sesion modificada
+        my $sesiontemp2 = $sesiontemp;
+        $sesiontemp2 =~ s/(.*)\@(.*)-(.*)/$2/g;
+        $sesiontemp2 = substr( $sesiontemp2, -3 );
+        $sesiontemp =~ s/(.*)\/(.*)-(.*)/\U$1\E\/${2}-${sesiontemp2}${3}/g;
+    }
+
+    log_debug( "$heading looking for $canalid on instancias to erase it", 128 ) if DEBUG;
+
+    foreach my $key1 ( sort ( keys(%instancias) ) ) {
+        foreach my $key2 ( sort ( keys( %{ $instancias{$key1} } ) ) ) {
+            if ( $key2 eq $canalid ) {
+                delete $instancias{$key1}{$key2};
+                log_debug( "$heading Erasing $canalid from instanacias!", 128 ) if DEBUG;
+            }
+        }
+    }
+}
+
+sub generate_linked_buttons_list {
+    my $nroboton     = shift;
+    my $server       = shift;
+    my @botonas      = ();
+    my $listabotones = "";
+    my $heading      = "** GEN_LINK_LIST ";
+
+    log_debug( "$heading canal $nroboton server $server", 16 ) if DEBUG;
+
+    if ( $nroboton !~ /\^/ ) {
+        $nroboton = "$server^$nroboton";
+    }
+
+    my ( $nada1, $contexto1 ) = split( /\&/, $nroboton );
+    if ( !defined($contexto1) ) { $contexto1 = ""; }
+
+    if ( defined( @{ $linkbot{"$nroboton"} } ) ) {
+        log_debug( "$heading Esta definido linkbot {$nroboton}", 32 ) if DEBUG;
+        foreach ( @{ $linkbot{"$nroboton"} } ) {
+            log_debug( "$heading y contiene $_", 32 ) if DEBUG;
+            my ( $canal1, $sesion1 ) = separate_session_from_channel($_);
+            log_debug( "$heading luego de separate canal1 = $canal1 y sesion1 = $sesion1", 128 ) if DEBUG;
+            my $canalsesion = $_;
+            if ( !defined($sesion1) ) {
+                $canalsesion = $canal1 . "-XXXX";
+            }
+            log_debug( "$heading canal1 = $canal1 y sesion1 = $sesion1 canalsesion=$canalsesion", 128 ) if DEBUG;
+            my @linkbotones = find_panel_buttons( $canal1, $canalsesion, $server );
+            foreach my $cual (@linkbotones) {
+                my ( $nada2, $contexto2 ) = split( /\&/, $cual );
+                if ( !defined($contexto2) ) { $contexto2 = ""; }
+                if ( $contexto1 eq $contexto2 ) {
+                    if ( defined( $buttons{"$server^$cual"} ) ) {
+                        my $botinro = $buttons{"$server^$cual"};
+                        push @botonas, $botinro;
+                        log_debug( "$heading Agrego $botinro", 64 ) if DEBUG;
+                    }
+                }
+            }
+        }
+
+        #my %seen2 = ();
+        #my @uniq2 = grep { !$seen2{$_}++ } @botonas;
+        #@botonas = \@uniq2;
+        @botonas = unique(@botonas);
+
+        foreach my $val (@botonas) {
+            if ( defined($val) ) {
+                $listabotones .= "$val,";
+                log_debug( "$heading devuelve $val", 128 ) if DEBUG;
+            }
+        }
+        $listabotones = substr( $listabotones, 0, -1 );
+    }
+    else {
+        log_debug( "$heading NO ESTA DEFINIDO linkbot {$nroboton}", 32 ) if DEBUG;
+    }
+    return $listabotones;
+}
+
+sub erase_all_sessions_from_queues {
+    my $canalid     = shift;
+    my $canal       = shift;
+    my $server      = shift;
+    my $canalsesion = $canalid;
+    my $heading     = "** ERASE SESSION QUEUE ";
+    log_debug( "$heading erase queue $canalid $canal $server", 64 ) if DEBUG;
+
+    for my $mnroboton ( keys %sesbot ) {
+        if ( !exists( $buttons_queue_reverse{$mnroboton} ) ) {
+            next;
+        }
+        my @final = ();
+        foreach my $msesion ( @{ $sesbot{$mnroboton} } ) {
+            log_debug( "$heading $msesion ne $canalsesion?", 64 ) if DEBUG;
+            if ( $msesion ne $canalsesion ) {
+                log_debug( "$heading sesbot es distinto dejo $msesion en sesbot($mnroboton)", 64 ) if DEBUG;
+                push @final, $msesion;
+            }
+        }
+        $sesbot{$mnroboton} = [@final];
+    }
+}
+
+sub erase_all_sessions_from_channel {
+    my $canalid     = shift;
+    my $canal       = shift;
+    my $server      = shift;
+    my $canalsesion = $canalid;
+    my @final;
+    my @return;
+    my $heading = "** ERASE_ALL_SESS_FROM";
+    log_debug( "$heading canal $canal canalid $canalid", 16 ) if DEBUG;
+
+    my $indice_cache = $canalid . "-" . $canal . "-" . $server;
+    log_debug( "$heading borro cache_hit($indice_cache)", 128 ) if DEBUG;
+    delete $cache_hit{$indice_cache};
+    if ( keys(%cache_hit) ) {
+        for ( keys %cache_hit ) {
+            if ( defined( @{ $cache_hit{$_} } ) ) {
+                foreach my $val ( @{ $cache_hit{$_} } ) {
+                    if ( $val eq $canal ) {
+                        log_debug( "$heading borro cache $_", 128 ) if DEBUG;
+                        delete $cache_hit{$_};
+                    }
+                }
+            }
+        }
+    }
+
+    if ( $canal =~ /^QUEUE/ ) {
+
+        # QUEUE buttons have a special treatment with sessions (sesbot).
+        # we dont want to remove a session (sesbot) from a real button when
+        # the channel leaves the queue
+        erase_all_sessions_from_queues( $canalid, $canal, $server );
+        return;
+    }
+    else {
+
+        if ( $canal =~ /=/ ) {
+
+            # If its a trunk button, erase instances
+            erase_instances_for_trunk_buttons( $canalsesion, $canal, $server );
+        }
+        $canalsesion =~ s/\t/-/g;
+        $canalid     =~ s/(.*)<(.*)>/$1/g;    # Removes <zombie><masq>
+
+        for my $mnroboton ( keys %sesbot ) {
+            @final = ();
+            foreach my $msesion ( @{ $sesbot{$mnroboton} } ) {
+                log_debug( "$heading $msesion ne $canalsesion?", 64 ) if DEBUG;
+                if ( $msesion ne $canalsesion ) {
+                    log_debug( "$heading sesbot es distinto dejo $msesion a \@final", 64 ) if DEBUG;
+                    push @final, $msesion;
+                }
+            }
+            $sesbot{$mnroboton} = [@final];
+        }
+
+        if ( keys(%linkbot) ) {
+            for ( keys %linkbot ) {
+                if ( defined( @{ $linkbot{$_} } ) ) {
+                    my @final = ();
+                    foreach my $val ( @{ $linkbot{$_} } ) {
+                        log_debug( "$heading linkbot($_) ne $val ?", 64 ) if DEBUG;
+                        if ( $val ne $canalsesion ) {
+                            push @final, $val;
+                            log_debug( "$heading No es igual lo dejo $_", 64 ) if DEBUG;
+                        }
+                        else {
+                            push @return, $_;
+                            log_debug( "$heading Es igual lo AGREGO RETURN $_", 64 ) if DEBUG;
+                        }
+                    }
+
+                    log_debug( "$heading delete linkbot($_)", 64 ) if DEBUG;
+                    delete $linkbot{$_};
+                    $linkbot{$_} = [@final];
+                }
+            }
+        }
+
+        my $quehay = "";
+        for $quehay ( keys %datos ) {
+            while ( my ( $key, $val ) = each( %{ $datos{$quehay} } ) ) {
+                if ( $key eq "Channel" ) {
+                    $val =~ s/(.*)[-\/](.*)/$1\t$2/g;
+                    $val =~ tr/a-z/A-Z/;
+                    if ( $canalid eq $val ) {
+                        log_debug( "** Found a match $canalid=$val ($quehay) - Cleared!", 16 ) if DEBUG;
+                        delete $datos{$quehay};
+                    }
+                }
+            }
+        }
+        for my $valores (@return) {
+            log_debug( "$heading devuleve $valores", 64 ) if DEBUG;
+        }
+        return @return;
+    }
+}
+
+sub extraer_todas_las_sesiones_de_un_canal {
+    my $canal         = shift;
+    my $canalbase     = "";
+    my $sesion_numero = "";
+    my $sesion        = "";
+    my $key           = "";
+    my $val           = "";
+    my $quehay        = "";
+    my @result        = ();
+    my $heading       = "** EXTRAER_TODAS ";
+    log_debug( "$heading from the channel $canal", 16 ) if DEBUG;
+
+    # Removes the context if its set
+
+    my @pedazos = split( /&/, $canal );
+    $canal = $pedazos[0];
+
+    # Checks if the channel name has an equal sign
+    # (its a trunk button channel)
+
+    if ( $canal =~ /(.*)=(\d+)/ ) {
+        ( $canalbase, $sesion_numero ) = split( /\=/, $canal );
+        log_debug( "** Its a trunk $canalbase button number $sesion_numero!", 16 ) if DEBUG;
+
+        foreach my $key1 ( sort ( keys(%instancias) ) ) {
+            foreach my $key2 ( sort ( keys( %{ $instancias{$key1} } ) ) ) {
+                if ( $key2 eq $canalbase ) {
+                    push @result, $key2;
+                    log_debug( "$heading encontro sesion $canalbase", 16 ) if DEBUG;
+                }
+            }
+        }
+    }
+
+    my $cuantos = @result;
+    if ( $cuantos == 0 ) {
+
+        # If there is no results for a trunk button, look into the %datos
+        # hash.
+
+        for $quehay ( keys %datos ) {
+            while ( ( $key, $val ) = each( %{ $datos{$quehay} } ) ) {
+                if ( defined($val) ) {
+                    my $vel = $val;
+                    if ( $vel =~ /^IAX2/ ) {
+                        $vel =~ s/IAX2\/(.*)@(.*)\/(.*)/IAX2\/$1\/$3/g;
+                        $vel =~ s/IAX2\[(.*)@(.*)\](.*)/IAX2\[$1\]$3/g;
+                    }
+                    if ( $vel =~ /^\Q$canal\E[-\/]/i && $key eq "Channel" ) {
+                        push( @result, $val );
+                        log_debug( "** Sesion: $val", 16 ) if DEBUG;
+                    }
+                }
+            }
+        }
+    }
+    return @result;
+}
+
+sub extracts_exten_from_active_channel {
+    my $canal   = shift;
+    my $quehay  = "";
+    my @result  = ();
+    my $heading = "** EXTRACT_EXTEN ";
+    my $server  = "";
+
+    my @pedazos = split( /&/, $canal );
+    $canal = $pedazos[0];
+
+    if ( $canal =~ /\^/ ) {
+        @pedazos = split( /\^/, $canal );
+        $server  = $pedazos[0];
+        $canal   = $pedazos[1];
+    }
+
+    for $quehay ( keys %datos ) {
+        log_debug( "$heading turno de $quehay", 64 ) if DEBUG;
+        my $canalaqui  = 0;
+        my $serveraqui = 0;
+        my $linkeado   = "";
+        while ( my ( $key, $val ) = each( %{ $datos{$quehay} } ) ) {
+
+            if ( $val =~ /^$canal-/i && ( $key =~ /^Chan/i || $key =~ /^Link/i ) ) {
+                $canalaqui = 1;
+            }
+            if ( $key =~ /^Server/i && $val == $server ) {
+                $serveraqui = 1;
+            }
+            if ( $key =~ /^Exten/i ) {
+                $linkeado = $val;
+            }
+        }
+        if ( $canalaqui == 1 && $linkeado ne "" && $serveraqui == 1 ) {
+            log_debug( "$heading devuelvo $linkeado\n", 64 ) if DEBUG;
+            push( @result, $linkeado );
+        }
+    }
+    return @result;
+}
+
+sub extraer_todos_los_enlaces_de_un_canal {
+    my $canal   = shift;
+    my $server  = shift;
+    my $quehay  = "";
+    my @result  = ();
+    my $heading = "** EXTRACT_LINKS_CHAN";
+
+    print_datos(1);
+
+    my @pedazos = split( /&/, $canal );
+    $canal = $pedazos[0];
+
+    if ( $canal =~ /\^/ ) {
+        @pedazos = split( /\^/, $canal );
+        $server  = $pedazos[0];
+        $canal   = $pedazos[1];
+    }
+
+    log_debug( "$heading canal $canal server $server", 1 ) if DEBUG;
+
+    for $quehay ( keys %datos ) {
+        my $canalaqui  = 0;
+        my $serveraqui = 0;
+        my $linkeado   = "";
+        my $todo       = "";
+        my $eventob    = "";
+
+        log_debug( "$heading turno de $quehay", 128 ) if DEBUG;
+        log_debug( "",                          128 ) if DEBUG;
+        while ( my ( $key, $val ) = each( %{ $datos{$quehay} } ) ) {
+            $todo .= "$key = $val\n";
+            log_debug( "$heading buscando $canal en $key=$val", 128 ) if DEBUG;
+            if ( ( $val =~ /^$canal-/i || $val =~ /^$canal$/ ) && $key =~ /^Chan/i ) {
+                log_debug( "$heading canal coincide $canal = $val\n", 16 ) if DEBUG;
+                $canalaqui = 1;
+            }
+            if ( $key =~ /^Server/i && $val eq $server ) {
+                $serveraqui = 1;
+                log_debug( "$heading server coincide $server = $val\n", 16 ) if DEBUG;
+            }
+            if ( $key =~ /^Link/i ) {
+                $linkeado = $val;
+            }
+            if ( $key =~ /^Event/i ) {
+                $eventob = $val;
+                log_debug( "$heading eventob = $val\n", 16 ) if DEBUG;
+            }
+        }
+        if ( $canalaqui == 1 && $linkeado ne "" && $serveraqui == 1 && $eventob !~ /agent/i ) {
+            push( @result, $linkeado );
+            log_debug( "$heading Agrego $linkeado a la lista", 16 ) if DEBUG;
+            log_debug( $todo, 16 ) if DEBUG;
+        }
+    }
+    return @result;
+}
+
+sub find_panel_buttons {
+
+    # *****************************************************************
+    # Based on a CHANNEL name returned by Asterisk, we try to match
+    # one or more of our buttons to show status. Returns array with list
+    # of channel names as set in op_buttons.cfg
+
+    my $canal       = shift;
+    my $canalsesion = shift;
+    my $server      = shift;
+    my $pos         = 0;
+    my $sesion      = "";
+    my @canales     = ();
+    my @multicanal;
+    my $quehay        = "";
+    my $canalfinal    = "";
+    my $contextoindex = "";
+    my $server_boton  = 0;
+    my $heading       = "** FIND_PANEL_BUT";
+    my $calleridnum   = "noexiste";
+    my %trunk_matched = ();
+
+    $tab = $tab . "\t" if DEBUG;
+    log_debug( "$heading canal $canal canalsesion $canalsesion server $server", 32 ) if DEBUG;
+
+    if ( $canal eq "" ) {
+        $tab = substr( $tab, 0, -1 ) if DEBUG;
+        return;
+    }
+
+    my $uniqueid = find_uniqueid( $canalsesion, $server );
+    if ( $uniqueid ne "" ) {
+        if ( defined( $datos{$uniqueid}{"CallerID"} ) ) {
+            $calleridnum = $datos{$uniqueid}{"CallerID"};
+        }
+    }
+
+    # XXXXX We have to try hard to find a match for the channel
+    # There are several posibilities:
+    #
+    # Exact match:      SIP/jo       (no panel context, not trunk, no wildcard)
+    # Panel Ctxt match: SIP/jo&SIP   (exact name, not trunk, no wildcard, panel context)
+    # Trunk match:      SIP/jo=1     (exact name, trunk, no wildcard, no panel context)
+    # Ctxt&Trunk match: SIP/jo=1&SIP (exact name, trunk, no wildcard, panel context)
+    # Wildcard          SIP/*=1      (wildcard name, trunk)
+    #
+    # The key to match syntax is server^[chan_name|wildcard](=trunk_position)(&panel_context)
+    #
+    # Here I first will try to match any $buttons that might match the given channel name
+
+    if ( $canalsesion =~ /</ ) {
+
+        # "<" Is an invalid character for a channel name, unless its a zombie
+        # or masq, in that case we should discard them
+        log_debug( "$heading canalsesion $canalsesion (Se supone que no debo tratar zombies?)", 32 ) if DEBUG;
+    }
+
+    $canal = uc($canal);
+
+    # Pass for QUEUEAGENT buttons
+    # We should check it no matter the cache because we match also on queue, not only channel
+    push @multicanal, $canal;
+
+    if ( defined( $channel_to_agent{"$server^$canal"} ) ) {
+        $canal = uc( $channel_to_agent{"$server^$canal"} );
+    }
+
+    if ( $queueagent_buttons == 1 ) {
+
+        my $canalsindumy = $canal;
+        $canalsindumy =~ s/-FOPdummy$//g;
+
+        log_debug( "$heading trying with QUEUEAGENT buttons", 64 ) if DEBUG;
+
+        if ( keys(%agents_on_queue) ) {
+            foreach my $valor ( keys(%agents_on_queue) ) {
+                my $cont = 0;
+                foreach my $vvalor ( @{ $agents_on_queue{$valor} } ) {
+                    $cont++;
+                    log_debug( "$heading in queue $valor is '$vvalor' equal to '$server^$canalsindumy'?", 64 ) if DEBUG;
+
+                    if ( uc("$server^$canalsindumy") eq uc($vvalor) ) {
+                        my $queuename = $valor;
+                        $queuename =~ s/(\d+)\^(.*)/$2/g;
+                        my $fake_channel_agent = uc("QUEUEAGENT/$queuename=$cont");
+
+                        foreach my $ctx (@panel_contexts) {
+                            my $ctxp = "";
+                            if ( $ctx eq "DEFAULT" ) {
+                                $ctxp = "";
+                            }
+                            else {
+                                $ctxp = "&$ctx";
+                            }
+                            my $idx = "$server^$fake_channel_agent" . $ctxp;
+                            if ( exists( $buttons{$idx} ) ) {
+
+                                # We have a match! add to return canales
+                                push @canales, "$fake_channel_agent$ctxp";
+                                log_debug( "$heading we have a winner! $fake_channel_agent $ctxp", 64 ) if DEBUG;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    push @multicanal, $canal;
+
+    if ( $canal =~ /^AGENT/i ) {
+        my $canalag = $canal;
+        $canalag =~ s/^AGENT/Agent/g;
+        if ( defined( $agent_to_channel{"$server^$canalag"} ) ) {
+            push @multicanal, uc( $agent_to_channel{"$server^$canalag"} );
+            log_debug( "$heading HAY UN AGENTE " . $agent_to_channel{"$server^$canalag"}, 32 );
+        }
+        else {
+            if ( $canal =~ /-FOPdummy$/ ) {
+                $canal =~ s/-FOPdummy$//g;
+                @multicanal = ($canal);
+            }
+            print_agents();
+        }
+    }
+    else {
+        if ( defined( $channel_to_agent{"$server^$canal"} ) ) {
+            push @multicanal, $channel_to_agent{"$server^$canal"};
+        }
+    }
+
+    if ( $canal =~ m/^Local/i ) {
+        my $canalsinlocal = $canal;
+        $canalsinlocal =~ s/^LOCAL\///gi;
+        $canalsinlocal =~ s/(,*)\/n$/$1/gi;
+        while ( my ( $key, $val ) = each(%extension_transfer_reverse) ) {
+            if ( uc($key) eq "$server^$canalsinlocal" ) {
+                my $canalfin = $val;
+                $canalfin =~ s/\d+\^(.*)/$1/g;
+                push @multicanal, $canalfin;
+            }
+        }
+    }
+
+    my $indice_cache = "";
+    @multicanal = unique(@multicanal);
+
+    foreach my $canal (@multicanal) {
+
+        # Attemp to match a button from cache
+        $indice_cache = $canalsesion . "-" . $canal . "-" . $server;
+        if ( !defined( $cache_hit{$indice_cache} ) ) {
+            log_debug( "$heading CACHE MISS $indice_cache", 32 ) if DEBUG;
+            for ( keys %buttons ) {
+                $canalfinal = "";
+                my ( $nada, $contexto ) = split( "\&", $_ );
+                if ( !defined($contexto) ) { $contexto = ""; }
+                if ( $contexto ne "" ) { $contexto = "&" . $contexto; }
+                if ( $_ =~ /^\Q$server^$canal\E$/i ) {
+
+                    log_debug( "$heading exact match buttons ( $_ )  $canal $contexto", 32 ) if DEBUG;
+                    $canalfinal = $canal;
+                }
+                elsif ( $_ =~ /^\Q$server^$canal\E\&/i ) {
+
+                    log_debug( "$heading context match buttons ( $_ )  $canal $contexto", 32 ) if DEBUG;
+                    $canalfinal = $canal;
+                }
+                elsif ( $_ =~ /^\Q$server^$canal\E=/i ) {
+                    if ( !exists( $trunk_matched{"$server^$canal"} ) ) {
+                        $canalfinal = get_next_trunk_button( $canalsesion, $contexto, $server, $canalsesion );
+                        if ( $canalfinal ne "" ) {
+                            log_debug( "$heading trunk match ( $_ )  $canal $contexto", 32 ) if DEBUG;
+                            $trunk_matched{"$server^$canal"} = 1;
+                            $canalfinal =~ s/(.*)\^(.*)/$2/g;
+                        }
+                    }
+                }
+                elsif ( $_ =~ /^$server\^CLID\/\Q$calleridnum\E\&?/ ) {
+
+                    log_debug( "$heading clid match ( $_ )  $canal $contexto", 32 ) if DEBUG;
+                    $canalfinal = "CLID/$calleridnum";
+                }
+
+                if ( $canalfinal ne "" ) {
+                    my $indicefin             = "";
+                    my $canalfinalconcontexto = $canalfinal;
+
+                    if ( $canalfinal =~ /\^/ ) {
+                        $indicefin = "${canalfinal}";
+                    }
+                    else {
+                        $indicefin = "$server^${canalfinal}";
+                    }
+                    if ( $indicefin !~ /(.*)\&(.*)$/ ) {
+                        $indicefin             = "$indicefin$contexto";
+                        $canalfinalconcontexto = "${canalfinal}${contexto}";
+                    }
+
+                    if ( exists( $buttons{$indicefin} ) ) {
+                        my $posicion = $buttons{$indicefin};
+                        $server_boton = $button_server{$posicion};
+                        log_debug( "$heading server para $canalfinal = $server_boton", 64 ) if DEBUG;
+                    }
+                    push @canales, "${canalfinalconcontexto}";
+                }
+            }
+            $canalfinal = "";
+
+            my $nada1      = "";
+            my $contextemp = "";
+            my %contextosencontrados;
+            for my $val (@canales) {
+                ( $nada1, $contextemp ) = split( "&", $val );
+                if ( !defined($contextemp) ) { $contextemp = ""; }
+                $contextosencontrados{"&$contextemp"} = 1;
+            }
+
+            # Pass for REGEXP buttons
+            my $canal_sin_server_ni_contexto = $canal;
+            $canal_sin_server_ni_contexto =~ s/(^\d+\^)(.*)(\&.*)?(=\d+)?/$2/;
+
+            if ( $regexp_buttons == 1 ) {
+                for ( keys %buttons_preserve_case ) {
+                    my $regexp = "";
+                    if ( $_ =~ /^\d+\^_/ ) {
+                        $regexp = $_;
+                        $regexp =~ /^(\d+)\^_([^=&]*)(=[^&]*)?(\&.*)?/;
+                        my $serverb = $1;
+                        $regexp = $2;
+                        my $posicion = $3;
+                        my $contexto = "";
+                        if ( defined($4) ) {
+                            $contexto = $4;
+                            if ( defined( $contextosencontrados{$contexto} ) ) {
+                                next;
+                            }
+                        }
+
+                        if ( $canal_sin_server_ni_contexto =~ m/$regexp/i
+                            && !exists( $trunk_matched{"$canal_sin_server_ni_contexto^$regexp"} ) )
+                        {
+                            if ( defined($posicion) ) {
+
+                                # Es un trunk
+                                $canalfinal = get_next_trunk_button( $_, $contexto, $server, $canalsesion );
+                            }
+                            else {
+
+                                # No es un trunk
+                                $canalfinal = $_;
+                            }
+                            if ( $canalfinal ne "" ) {
+                                $trunk_matched{"$canal_sin_server_ni_contexto^$regexp"} = 1;
+                                push @canales, $canalfinal;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else {
+
+            # We have a cache match, retrieve the buttons from cache
+            my @canales2 = @{ $cache_hit{$indice_cache} };
+
+            # and add the matches from queueagents we might have
+            push @canales, @canales2;
+            log_debug( "$heading CACHE HIT Retrieving buttons from cache ($indice_cache)", 32 ) if DEBUG;
+        }
+    }    # end foreach multicanal
+    @canales = unique(@canales);
+
+    my $cuantoscanales = @canales;
+    if ( $cuantoscanales > 0 ) {
+        $cache_hit{$indice_cache} = [@canales];
+    }
+
+    my $cuantos = $#canales + 1;
+    log_debug( "$heading returns $cuantos", 16 ) if DEBUG;
+    foreach (@canales) {
+        log_debug( "$heading cache button $_", 32 ) if DEBUG;
+    }
+    $tab = substr( $tab, 0, -1 );
+    return @canales;
+}
+
+sub procesa_bloque {
+    my $blaque             = shift;
+    my $socket             = shift;
+    my $astmanproxy_server = shift;
+    my %bloque             = %$blaque if defined(%$blaque);
+
+    my %hash_temporal = ();
+    my $evento        = "";
+    my $canal         = "";
+    my $sesion        = "";
+    my $texto         = "";
+    my $estado_final  = "";
+    my $unico_id      = "";
+    my $exten         = "";
+    my $clid          = "";
+    my $clidnum       = "";
+    my $clidname      = "";
+    my $canalid       = "";
+    my $key           = "";
+    my $val           = "";
+    my @return        = ();
+    my $conquien      = "";
+    my $enlazado      = "";
+    my $viejo_nombre  = "";
+    my $nuevo_nombre  = "";
+    my $quehay        = "";
+    my $elemento      = "";
+    my $state         = "";
+    my $exists        = 0;
+    my $fakecounter   = 1;
+    my $fill_datos    = 0;
+    my $server        = 0;
+    my $timeout       = 0;
+    my $heading       = "** PROCESA_BLOQUE";
+
+    $tab = $tab . "\t";
+    $hash_temporal{"Event"} = "";
+
+    while ( my ( $key, $val ) = each(%bloque) ) {
+        if ( defined($val) ) {
+            $val =~ s/(.*)\s+$/$1/g;
+        }
+        else {
+            $val = "";
+        }
+        $hash_temporal{$key} = $val;
+    }
+
+    if ( defined( $hash_temporal{Channel} ) ) {
+        if ( $hash_temporal{Channel} =~ /^Agent/ ) {
+
+            # If the channel is Agent/XXXX and we have a real channel
+            # in memory, duplicate the event using the real channel
+            my $uniagentid = "YYYY";
+
+            my $canalcompara = $hash_temporal{"Channel"};
+            $canalcompara =~ s/Agent\/(.*)/$1/g;
+            for $quehay ( keys %agent_to_channel ) {
+                my $conque = $quehay;
+                $conque =~ s/(\d+)\^(.*)/$2/g;
+                if ( $canalcompara eq $conque ) {
+                    while ( my ( $key, $val ) = each(%hash_temporal) ) {
+                        if ( $key ne "Channel" ) {
+                            $fake_bloque[$fakecounter]{$key} = $val;
+                        }
+                    }
+                    $fake_bloque[$fakecounter]{"Channel"} = $agent_to_channel{$quehay} . "-XXXX";    # We dont want to add a sesbot
+                    $fakecounter++;
+                }
+            }
+        }
+    }
+
+    if ( $hash_temporal{"Event"} =~ /^UserEvent/ ) {
+
+        # This blocks checks if we have an UserEvent
+        # and splits every key value pair if it haves
+        # a caret as a delimiter
+        while ( my ( $key, $val ) = each(%hash_temporal) ) {
+            if ( defined($val) && $val =~ /\^/ ) {
+                my @partes = split( /\^/, $val, 2 );
+                $hash_temporal{$key} = $partes[0];
+                my $resto_de_parametros = $partes[1];
+                @partes = split( /\^/, $resto_de_parametros );
+                foreach my $value (@partes) {
+                    my @partes2 = split( /: /, $value );
+                    if ( !defined( $partes2[0] ) ) { next; }
+                    if ( !defined( $partes2[1] ) ) { $partes2[1] = ""; }
+                    $hash_temporal{ $partes2[0] } = $partes2[1];
+                }
+            }
+        }
+    }
+
+    $canalid = "";
+    $canalid = $hash_temporal{"Channel"}
+      if defined( $hash_temporal{"Channel"} );
+
+    $server = 0;
+    $server = $hash_temporal{"Server"}
+      if defined( $hash_temporal{"Server"} );
+
+    if ( defined( $hash_temporal{"Uniqueid"} ) ) {
+        $unico_id   = $hash_temporal{"Uniqueid"};
+        $fill_datos = 1;
+    }
+    else {
+        $unico_id = "YYYY";
+    }
+
+    $enlazado = "";
+    if ( exists( $datos{$unico_id} ) ) {
+
+        if ( exists( $datos{$unico_id}{"Link"} ) ) {
+            $enlazado = $datos{$unico_id}{"Link"};
+        }
+
+        if ( exists( $datos{$unico_id}{"Application"} ) ) {
+            $enlazado .= " - " . $datos{$unico_id}{"Application"};
+        }
+
+        if ( exists( $datos{$unico_id}{"AppData"} ) ) {
+            $enlazado .= ":" . $datos{$unico_id}{"AppData"};
+        }
+
+    }
+
+    if ( $unico_id !~ /-\d+$/ ) {
+
+        # Add the server at the end of the uniqueid
+        # if its not already there
+        $unico_id .= "-" . $server;
+    }
+
+    $evento = "";
+    if ( defined( $hash_temporal{"Event"} ) ) {
+        $evento = $hash_temporal{"Event"};
+    }
+
+    if ( defined( $hash_temporal{"ActionID"} ) ) {
+        if ( $hash_temporal{"ActionID"} =~ /^timeout/i ) {
+            my @partes = split( /\|/, $hash_temporal{"ActionID"} );
+            $canalid  = $partes[1];
+            $timeout  = $partes[2];
+            $evento   = "Timeout";
+            $unico_id = "YYYY-$server";
+        }
+    }
+
+    log_debug( "$heading canalid $canalid unico_id $unico_id evento $evento enlazado $enlazado", 128 ) if DEBUG;
+
+    # Populates a global hash to keep track of
+    # 'active' channels, the ones that are not
+    # state down.
+    if ( defined($unico_id) ) {
+        if ( $unico_id !~ /^YYYY/ ) {
+
+            if ($fill_datos) {    # Ignores blocks without Uniqueid
+                log_debug( "$heading LLENANDO el global datos $unico_id", 64 ) if DEBUG;
+                delete $datos{$unico_id}{"State"};
+                while ( my ( $key, $val ) = each(%hash_temporal) ) {
+                    if ( $key eq "Uniqueid" ) {
+                        if ( $val !~ /-/ ) {
+                            $val .= "-" . $server;
+                        }
+                    }
+                    if ( !defined($val) ) {
+                        $val = "";
+                    }
+                    $datos{$unico_id}{"$key"} = $val;
+                    log_debug( "$heading POPULATES datos($unico_id){ $key } = $val", 128 ) if DEBUG;
+                }
+            }
+        }
+        else {
+            log_debug( "$heading NO LLENO el global datos $unico_id", 64 ) if DEBUG;
+        }
+    }
+
+    $evento =~ s/UserEvent//g;
+    if    ( $evento =~ /Newchannel/ )           { $evento = "newchannel"; }
+    elsif ( $evento =~ /Newcallerid/ )          { $evento = "newcallerid"; }
+    elsif ( $evento =~ /^Status$/ )             { $evento = "status"; }
+    elsif ( $evento =~ /^StatusComplete/ )      { $evento = "statuscomplete"; }
+    elsif ( $evento =~ /Newexten/ )             { $evento = "newexten"; }
+    elsif ( $evento =~ /^ParkedCall$/ )         { $evento = "parkedcall"; }
+    elsif ( $evento =~ /^UnParkedCall$/ )       { $evento = "unparkedcall"; }
+    elsif ( $evento =~ /Newstate/ )             { $evento = "newstate"; }
+    elsif ( $evento =~ /Hangup/ )               { $evento = "hangup"; }
+    elsif ( $evento =~ /Rename/ )               { $evento = "rename"; }
+    elsif ( $evento =~ /MessageWaiting/ )       { $evento = "voicemail"; }
+    elsif ( $evento =~ /Regstatus/ )            { $evento = "regstatus"; }
+    elsif ( $evento =~ /^Unlink/ )              { $evento = "unlink"; }
+    elsif ( $evento =~ /QueueParams/ )          { $evento = "queueparams"; }
+    elsif ( $evento =~ /QueueEntry/ )           { $evento = "queueentry"; }
+    elsif ( $evento =~ /^QueueMember$/ )        { $evento = "queuemember"; }
+    elsif ( $evento =~ /^QueueMemberStatus$/ )  { $evento = "queuememberstatus"; }
+    elsif ( $evento =~ /QueueMemberAdded/ )     { $evento = "queuememberadded"; }
+    elsif ( $evento =~ /QueueMemberRemoved/ )   { $evento = "queuememberremoved"; }
+    elsif ( $evento =~ /QueueMemberPaused/ )    { $evento = "queuememberpaused"; }
+    elsif ( $evento =~ /QueueStatus$/ )         { $evento = "queuestatus"; }
+    elsif ( $evento =~ /QueueStatusComplete/ )  { $evento = "queuestatuscomplete"; }
+    elsif ( $evento =~ /^Link/ )                { $evento = "link"; }
+    elsif ( $evento =~ /^Join/ )                { $evento = "join"; }
+    elsif ( $evento =~ /^MeetmeJoin/ )          { $evento = "meetmejoin"; }
+    elsif ( $evento =~ /^MeetmeLeave/ )         { $evento = "meetmeleave"; }
+    elsif ( $evento =~ /^meetmemute/ )          { $evento = "meetmemute"; }
+    elsif ( $evento =~ /^meetmeunmute/ )        { $evento = "meetmeunmute"; }
+    elsif ( $evento =~ /^Agentlogin/ )          { $evento = "agentlogin"; }
+    elsif ( $evento =~ /^RefreshQueue/ )        { $evento = "refreshqueue"; }
+    elsif ( $evento =~ /^Timeout/ )             { $evento = "timeout"; }
+    elsif ( $evento =~ /^AgentCalled/ )         { $evento = "agentcalled"; }
+    elsif ( $evento =~ /^AgentConnect/ )        { $evento = "agentconnect"; }
+    elsif ( $evento =~ /^AgentComplete/ )       { $evento = "agentcomplete"; }
+    elsif ( $evento =~ /^Agentcallbacklogin/ )  { $evento = "agentcblogin"; }
+    elsif ( $evento =~ /^Agentcallbacklogoff/ ) { $evento = "agentlogoff"; }
+    elsif ( $evento =~ /^Agentlogoff/ )         { $evento = "agentlogoff"; }
+    elsif ( $evento =~ /^IsMeetmeMember/ )      { $evento = "fakeismeetmemember"; }
+    elsif ( $evento =~ /^PeerStatus/ )          { $evento = "peerstatus"; }
+    elsif ( $evento =~ /^Leave/ )               { $evento = "leave"; }
+    elsif ( $evento =~ /^FOP_Popup/i )          { $evento = "foppopup"; }
+    elsif ( $evento =~ /^FOP_LedColor/i )       { $evento = "fopledcolor"; }
+    elsif ( $evento =~ /^Dial/ )                { $evento = "dial"; }
+    elsif ( $evento =~ /^ASTDB/ )               { $evento = "astdb"; }
+    elsif ( $evento =~ /^DNDState/ )            { $evento = "zapdndstate"; }
+    elsif ( $evento =~ /^ZapShowChannels$/ )    { $evento = "zapdndstate"; }
+    elsif ( $evento =~ /^ExtensionStatus$/ )    { $evento = "extensionstatus"; }
+    else { log_debug( "$heading No event match ($evento)", 32 ); }
+
+    if ( defined( $hash_temporal{"Link"} ) ) {
+        if ( defined( $hash_temporal{"Seconds"} ) ) {
+            my $unid = find_uniqueid( $hash_temporal{"Link"}, $server ) if DEBUG;
+            $fake_bloque[$fakecounter]{Event}    = "Newexten";
+            $fake_bloque[$fakecounter]{Channel}  = $hash_temporal{Link};
+            $fake_bloque[$fakecounter]{State}    = "Up";
+            $fake_bloque[$fakecounter]{Seconds}  = $hash_temporal{Seconds};
+            $fake_bloque[$fakecounter]{CallerID} = $hash_temporal{CallerID};
+            $fake_bloque[$fakecounter]{Uniqueid} = $unid;
+            $fake_bloque[$fakecounter]{Server}   = $hash_temporal{Server};
+            $fakecounter++;
+            log_debug( "$heading Fake bloque canal $hash_temporal{Link} con seconds $hash_temporal{Seconds}", 128 )
+              if DEBUG;
+        }
+    }
+
+    if ( $evento eq "agentcomplete" ) {
+
+        # Hook for queue statistics?
+        #Event: AgentComplete
+        #Privilege: agent,all
+        #Queue: soporte
+        #Uniqueid: 1130872017.1364
+        #Channel: SIP/16-6b1b
+        #HoldTime: 17
+        #TalkTime: 557
+        #Reason: agent
+        my ( $canal, $nada ) = separate_session_from_channel( $hash_temporal{Channel} );
+        request_queue_status( $socket, $canal );
+    }
+
+    if ( $evento eq "agentcalled" ) {
+
+        # We use this event to send the ringing state for an Agent
+        $estado_final = "ringing";
+        $canal        = $hash_temporal{"AgentCalled"};
+        $canal =~ tr/a-z/A-Z/;
+        $canalid  = $canal . "-XXXX";
+        $clidnum  = $hash_temporal{"CallerID"};
+        $clidname = $hash_temporal{"CallerIDName"};
+        $texto    = "&incoming,[" . format_clid( $clidnum, $clid_format ) . "]";
+        my $base64_clidnum  = encode_base64( $clidnum . " " );
+        my $base64_clidname = encode_base64( $clidname . " " );
+        push @return, "$canal|clidnum|$base64_clidnum|$canalid-$server|$canalid";
+        push @return, "$canal|clidname|$base64_clidname|$canalid-$server|$canalid";
+        push @return, "$canal|$estado_final|$texto|$canalid-$server|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "agentconnect" ) {
+
+        # We use this event to fake the ringing state
+        $estado_final = "ocupado";
+        $texto        = "Taking call from $hash_temporal{\"Queue\"}";
+        $canal        = $hash_temporal{"Channel"};
+        $canal =~ tr/a-z/A-Z/;
+        $canalid = $canal . "-XXXX";
+        push @return, "$canal|$estado_final|$texto|$canalid-$server|$canalid";    #NEW
+        $evento = "";
+    }
+
+    if ( $evento eq "dial" ) {
+
+        # We use this hashes to store the remote callerid for CVS-HEAD
+        my $key      = "$server^$hash_temporal{'Destination'}";
+        my $dorigen  = "";
+        my $ddestino = "";
+        my $dnada    = "";
+        $remote_callerid{$key}      = $hash_temporal{"CallerID"};
+        $remote_callerid_name{$key} = $hash_temporal{"CallerIDName"};
+
+        # We also look for Dial from Local/XX at context to TECH/XX for
+        # matching agentcallbacklogins exten at context to real channels
+        # so we can map outgoing calls to Agent buttons
+        # It will only work after the agent receives at least one call
+        ( $dorigen,  $dnada ) = separate_session_from_channel( $hash_temporal{'Source'} );
+        ( $ddestino, $dnada ) = separate_session_from_channel( $hash_temporal{'Destination'} );
+        if ( exists( $channel_to_agent{"$server^$dorigen"} ) ) {
+            my $agente = $channel_to_agent{"$server^$dorigen"};
+
+            # delete $channel_to_agent{$dorigen};
+            $channel_to_agent{"$server^$ddestino"} = $agente;
+        }
+    }
+
+    if ( $evento eq "zapdndstate" ) {
+        $canal = $hash_temporal{"Channel"};
+        my $zstatus = "";
+        if ( $canal !~ m/Zap/i ) {
+            $canal = "Zap/$canal";
+        }
+        if ( defined( $hash_temporal{Status} ) ) {
+            $zstatus = $hash_temporal{Status};
+        }
+        if ( defined( $hash_temporal{DND} ) ) {
+            $zstatus = $hash_temporal{DND};
+        }
+        if ( $zstatus =~ /disabled/i ) {
+            $zstatus = "";
+        }
+
+        # If we receive a zap dnd state, we fake the ASTDB
+        # event with family 'dnd'. So it will execute the
+        # actions listed on op_astdb.cfg inside [dnd]
+        $fake_bloque[$fakecounter]{Event}   = "ASTDB";
+        $fake_bloque[$fakecounter]{Channel} = $canal;
+        $fake_bloque[$fakecounter]{Family}  = "dnd";
+        $fake_bloque[$fakecounter]{Server}  = $hash_temporal{Server};
+        $fake_bloque[$fakecounter]{Value}   = $zstatus;
+        $fakecounter++;
+
+        $evento = "";
+    }
+
+    if ( $evento eq "astdb" ) {
+        my $valor = "";
+        $estado_final = "astdb";
+        ( $canal, my $nada ) = separate_session_from_channel( $hash_temporal{"Channel"} );
+        $canalid = $hash_temporal{"Channel"} . "-XXXX";
+        my $clave = $hash_temporal{"Family"};
+        if ( !defined( $hash_temporal{"State"} ) ) {
+            $valor = "";
+        }
+        else {
+            $valor = $hash_temporal{"State"};
+        }
+
+        foreach my $item ( @{ $astdbcommands{$clave} } ) {
+            my $item_temp = $item;
+            $item_temp =~ s/\${value}/$valor/g;
+            my ( $comando, $datos ) = split( /=/, $item_temp );
+            if ( $valor ne "" ) {
+                push @return, "$canal|$comando|$datos|$canalid-$server|$canalid";
+            }
+            else {
+                push @return, "$canal|$comando||$canalid-$server|$canalid";
+            }
+        }
+        $evento = "";
+    }
+
+    if ( $evento eq "timeout" ) {
+        $estado_final = "timeout";
+        $texto        = $timeout;
+        my $ahora = time();
+        my $unique = find_uniqueid( $canalid, $server );
+        $datos{$unique}{"Timeout"} = $ahora + $timeout;
+        $timeouts{$canalid} = $ahora + $timeout;
+        push @return, "$canal|$estado_final|$texto|$unique|$canalid";    #NEW
+        $evento = "";
+    }
+
+    if ( $evento eq "regstatus" ) {
+
+        # Sends the IP address of the peer to the flash client
+        # XXXX It will have to store this value internally in future version
+        # to avoid polling asterisk every time
+        ( $canal, my $nada ) = separate_session_from_channel( $hash_temporal{"Channel"} );
+        $texto = $hash_temporal{"IP"};
+        my $serv = $hash_temporal{"Server"};
+        if ($show_ip) {
+
+            # $estado_final = "ip";
+            $estado_final = "settext";
+            $boton_ip{$canalid} = $texto;
+            push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+
+            # $evento = "";
+        }
+    }
+
+    if ( $evento eq "fopledcolor" ) {
+        my $color = "";
+        my $state = "";
+        ( $canal, my $nada ) = separate_session_from_channel( $hash_temporal{"Channel"} );
+        $color        = $hash_temporal{"Color"};
+        $state        = $hash_temporal{"State"};
+        $estado_final = "fopledcolor";
+        push @return, "$canal|$estado_final|$color^$state|$unico_id|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "foppopup" ) {
+        ( $canal, my $nada ) = separate_session_from_channel( $hash_temporal{"Channel"} );
+        my $url    = $hash_temporal{"URL"};
+        my $target = $hash_temporal{"Target"};
+        my $button = $hash_temporal{"Button"};
+        if ( !defined($button) ) { $button = ""; }
+        my $data = "$url^$target^$button";
+        $estado_final = "foppopup";
+        push @return, "$canal|$estado_final|$data|$unico_id|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "refreshqueue" ) {
+        ( $canal, my $nada ) = separate_session_from_channel( $hash_temporal{"Channel"} );
+
+        # Turns off led of the agent that generated the refresh
+        if ( $change_led == 1 ) {
+            $estado_final = "changelabel" . $change_led;
+            push @return, "$canal|$estado_final|original|$unico_id|$canalid";
+        }
+        request_queue_status( $socket, $hash_temporal{"Channel"} );
+        $evento = "";
+    }
+
+    if ( $evento eq "agentcblogin" ) {
+        my $canal      = "";
+        my $canallocal = "";
+        my $labeltext  = ".";
+        my $texto      = $hash_temporal{"Agent"};
+
+        if ( $canalid eq "" ) {
+            $canalid = "Agent/$texto-XXXX";
+        }
+
+        if ( defined( $agent_to_channel{"$server^Agent/$texto"} ) ) {
+
+            # The agent was already logged in, fake a logout event
+
+            if ( $ren_agentlogin == 1 || $ren_cbacklogin == 1 || $change_led == 1 ) {
+
+                $canal        = $agent_to_channel{"$server^Agent/$texto"};
+                $estado_final = "changelabel" . $change_led;
+                if ( $canal =~ /^AGENT/i ) {
+                    push @return, "AGENT/$texto|setalpha|100|$unico_id|$canalid";
+                }
+                else {
+                    push @return, "$canal|$estado_final|original|$unico_id|$canalid";
+
+                    # Change back the label to the old localtion/button
+                }
+                delete $agent_to_channel{"$server^Agent/$texto"};
+                delete $channel_to_agent{"$server^$canal"};
+            }
+        }
+
+        if ( defined( $datos{$unico_id}{"Channel"} ) ) {
+
+            # If we have this defined, its a REAL and LIVE event!
+            # so we populate some internal structures. If not, its a fake
+            # callbacklogin from the show agents cli command
+            ( $canal, my $nada ) = separate_session_from_channel( $datos{$unico_id}{Channel} );
+            $canal =~ tr/a-z/A-Z/;
+        }
+        else {
+
+            # It is a fake login, probably from a first run (show agents)
+            # or a queuemember event. We have the extension at context but not
+            # the real channel. In order to monitor OUTBOUND calls, we need
+            # to find out the real channel. There is no easy way around this
+            # problem. We have to make some assumptions.
+
+            my $ext_transf_key = $hash_temporal{"Server"} . "^" . $hash_temporal{"Loginchan"};
+
+            if ( defined( $extension_transfer_reverse{$ext_transf_key} ) ) {
+
+                # Our first assumption would be to look for a button definition
+                # that has the same extension at context and extract the channel name
+                # from there. Drawback: there has to be a butotn with the same exten at context
+                # in op_buttons.cfg.
+                $canal = $extension_transfer_reverse{$ext_transf_key};
+                $canal =~ s/(.*)&(.*)/$1/g;
+                if ( $canal =~ /\^/ ) {
+                    my @pedacete = split( /\^/, $canal );
+                    $canal = $pedacete[1];
+                }
+            }
+        }
+
+        # We also add a Local channel just in case. It will be used to match but
+        # not to keep track of sessions. We skip the agent_to_channel, we dont
+        # mind on local channels as monitoring buttons.
+
+        $canallocal = "Local/$hash_temporal{'Loginchan'}";
+        $canallocal =~ tr/a-z/A-Z/;
+        $channel_to_agent{"$server^$canallocal"} = "Agent/$texto";
+
+        if ( $canal ne "" ) {
+
+            # So, we find a channel. Lets send the responses and fill the hashes
+
+            $channel_to_agent{"$server^$canal"}       = "Agent/$texto";
+            $agent_to_channel{"$server^Agent/$texto"} = $canal;
+
+            print_agents();
+
+            $estado_final = "changelabel" . $change_led;
+            if ( $ren_cbacklogin == 1 ) {
+                $labeltext = "Agent/$texto";
+                if ( $ren_agentname == 1 ) {
+                    if ( defined( $agents_name{"$server^$texto"} ) ) {
+                        $labeltext = $agents_name{"$server^$texto"};
+                    }
+                }
+                push @return, "$canal|$estado_final|$labeltext|$unico_id|$canalid";
+            }
+            if ( $agent_status == 1 ) {
+                push @return, "$canal|isagent|0|$unico_id|$canalid";
+                push @return, "$canal|settimer|0\@IDLE|$unico_id|$canalid";
+                push @return, "$canal|settext|Idle|$unico_id|$canalid";
+            }
+        }
+
+        # Now send AGENT/ events
+        if ( $ren_cbacklogin == 1 ) {
+            $labeltext = "Agent/$texto";
+            if ( $ren_agentname == 1 ) {
+                if ( defined( $agents_name{"$server^$texto"} ) ) {
+                    $labeltext = $agents_name{"$server^$texto"};
+                }
+            }
+        }
+        push @return, "AGENT/$texto|changelabel$change_led|$labeltext|$unico_id|$canalid";
+
+        if ( $agent_status == 1 ) {
+            push @return, "AGENT/$texto|isagent|0|$unico_id|$canalid";
+        }
+
+        $evento = "";
+    }
+
+    if ( $evento eq "queuememberpaused" && $agent_status == 1 ) {
+        my $canal   = $hash_temporal{Location};
+        my $cola    = $hash_temporal{Queue};
+        my $canalid = $canal . "-XXXX";
+
+        # Paused
+        #  Event: QueueMemberPaused
+        #  Privilege: agent,all
+        #  Queue: soporte
+        #  Location: SIP/17
+        #  Paused: 1
+        #  Server: 0
+
+        # Unpaused
+        #  Event: QueueMemberPaused
+        #  Privilege: agent,all
+        #  Queue: soporte
+        #  Location: SIP/17
+        #  Paused: 0
+        #  Server: 0
+
+        my $color = "";
+        if ( $hash_temporal{Paused} eq "1" ) {
+            my ( $text, $textriginal, $buttontext ) = translate( $canal, "&paused", "", "" );
+            $texto = $text;
+            $texto = "&paused";
+            $color = "ledcolor_paused";
+        }
+        else {
+            my ( $text, $textriginal, $buttontext ) = translate( $canal, "&idle", "", "" );
+            $texto = $text;
+            $texto = "&idle";
+            $color = "ledcolor_agent";
+        }
+        $boton_ip{$canalid} = $texto;
+        push @return, "$canal|settext|$texto|$unico_id|$canalid";
+        push @return, "$canal|settimer|1\@UP|$unico_id|$canalid";
+        push @return, "$canal|settimer|0\@IDLE|$unico_id|$canalid";
+        push @return, "$canal|fopledcolor|$color^2|$unico_id|$canalid";
+        push @return, "$canal|state|free|$unico_id|$canalid";
+        $evento = "";
+
+    }
+
+    if ( $evento eq "queuememberremoved" ) {
+        my $cola  = $hash_temporal{Queue};
+        my $canal = $hash_temporal{Location};
+        $fake_bloque[$fakecounter]{Event}   = "Agentlogoff";
+        $fake_bloque[$fakecounter]{Channel} = $canal . "-XXXX";
+        $fake_bloque[$fakecounter]{Agent}   = $canal;
+        $fake_bloque[$fakecounter]{Queue}   = $cola;
+        $fake_bloque[$fakecounter]{Fake}    = "removed";
+        $fake_bloque[$fakecounter]{Server}  = $hash_temporal{Server};
+        $fakecounter++;
+        $evento = "";
+    }
+
+    if ( $evento eq "queuememberadded" ) {
+
+        my $cola  = $hash_temporal{Queue};
+        my $canal = $hash_temporal{Location};
+
+        $fake_bloque[$fakecounter]{Event}   = "Agentlogin";
+        $fake_bloque[$fakecounter]{Channel} = $canal . "-XXXX";
+        $fake_bloque[$fakecounter]{Agent}   = $canal;
+        $fake_bloque[$fakecounter]{Queue}   = $cola;
+        $fake_bloque[$fakecounter]{Server}  = $hash_temporal{Server};
+        $fake_bloque[$fakecounter]{Addhash} = 1;
+        $fakecounter++;
+
+        $evento = "";
+
+        # Add the channel to the agents_on_queue hash
+        ( $server, $canal ) = local_channels_are_driving_me_mad( $server, $canal );
+        reserve_next_available_agent_button( $server, $canal, $hash_temporal{Queue} );
+
+        # Remove cache hit to force find panel buttons to look for new positions
+        foreach my $kkey ( keys %cache_hit ) {
+            if ( $kkey =~ /^$canal/ ) {
+                delete $cache_hit{$kkey};
+            }
+        }
+
+    }
+
+    if ( $evento eq "agentlogin" ) {
+
+        my $labeltext = ".";
+        my $texto     = $hash_temporal{"Agent"};
+
+        if ( defined( $datos{$unico_id}{Channel} ) ) {
+
+            # This catches a live real Agentlogin event
+            ( my $canalreal, my $nada ) = separate_session_from_channel( $datos{$unico_id}{Channel} );
+            $canalreal =~ tr/a-z/A-Z/;
+            $channel_to_agent{"$server^$canalreal"}   = "Agent/$texto";
+            $agent_to_channel{"$server^Agent/$texto"} = $canalreal;
+            log_debug( "channel_to_agent($server^$canalreal) = " . $channel_to_agent{"$server^$canalreal"}, 64 ) if DEBUG;
+        }
+
+        ( $canal, my $sess ) = separate_session_from_channel( $hash_temporal{Channel} );
+        $estado_final = "changelabel" . $change_led;
+
+        if ( $sess ne "XXXX" ) {
+
+            # If we have a real session, its an agentlogin on op_server startup (from show agents)
+            $channel_to_agent{"$server^$canal"}       = "Agent/$texto";
+            $agent_to_channel{"$server^Agent/$texto"} = $canal;
+        }
+
+        if ( defined( $agent_label{$canal} ) && ( $ren_agentlogin == 1 || $ren_cbacklogin == 1 ) ) {
+            $labeltext = $agent_label{$canal};
+        }
+
+        if ( $canalid eq "" ) {
+            $canalid = "AGENT/$texto-XXXX";
+        }
+
+        if ( $ren_agentlogin == 1 && !defined( $hash_temporal{'Fake'} ) ) {
+            if ( $texto !~ /\// ) {
+                $labeltext = "Agent/$texto";
+            }
+            else {
+                $labeltext = $texto;
+            }
+            if ( $ren_agentname == 1 ) {
+                if ( defined( $agents_name{"$server^$texto"} ) ) {
+                    $labeltext = $agents_name{"$server^$texto"};
+                }
+            }
+        }
+
+        if ( $ren_queuemember == 1 ) {
+            if ( $texto !~ /\// ) {
+                $labeltext = "Agent/$texto";
+            }
+            else {
+                $labeltext = $texto;
+            }
+            if ( $ren_agentname == 1 ) {
+                if ( defined( $agents_name{"$server^$texto"} ) ) {
+                    $labeltext = $agents_name{"$server^$texto"};
+                }
+            }
+        }
+
+        if ( $labeltext eq "original" ) {
+            $labeltext = ".";
+        }
+
+        if ( $canal =~ m/^AGENT/i ) {
+            push @return, "$canal-FOPdummy|setalpha|100|$unico_id|$canalid";
+
+            my $agent_num = $texto;
+            $agent_num =~ s/^Agent\///gi;
+            if ( $ren_agentname == 1 ) {
+                if ( defined( $agents_name{"$server^$agent_num"} ) ) {
+                    $labeltext = $agents_name{"$server^$agent_num"};
+                }
+                else {
+                    $labeltext = $texto;
+                }
+            }
+            else {
+
+                # If its an Agent channel, and rename to agent name is not
+                # set, rename it anyways to Agent/XXXX
+                $labeltext = "Agent/$agent_num";
+            }
+
+            # push @return, "$canal-FOPdummy|setlabel|$labeltext|$unico_id|$canalid";
+
+        }
+        else {
+            push @return, "$canal|$estado_final|$labeltext|$unico_id|$canalid";
+            push @return, "$canal|corto||$unico_id|$canalid";
+        }
+
+        if ( $agent_status == 1 ) {
+            my $textopaused = "&idle";
+            if ( defined( $hash_temporal{Paused} ) ) {
+                $textopaused = $hash_temporal{Paused};
+            }
+            if ( defined( $hash_temporal{LastCall} ) ) {
+                if ( $hash_temporal{LastCall} > 0 ) {
+
+                    # Max_lastcall saves the maximum epoch time, so I can
+                    # show only the lowest lastcall time if an agent is member
+                    # or more than one queue
+                    if ( !defined( $max_lastcall{$canal} ) ) {
+                        $max_lastcall{$canal} = $hash_temporal{LastCall};
+                    }
+                    if ( $hash_temporal{LastCall} > $max_lastcall{$canal} ) {
+                        $max_lastcall{$canal} = $hash_temporal{LastCall} + 0;
+                    }
+                }
+            }
+            push @return, "$canal|isagent|0|$unico_id|$canalid";
+            push @return, "$canal|settext|$textopaused|$unico_id|$canalid";
+        }
+
+        $evento = "";
+
+        $is_agent{ uc("$server^$texto") } = 1;
+
+        if ( defined( $hash_temporal{Queue} ) ) {
+            if ( keys(%count_queue) ) {
+                my $contaconta = 0;
+                my %temp_queue = ();
+                my $valor      = "$server^$hash_temporal{Queue}";
+
+                push @{ $count_queue{$valor} }, "$server^$texto";
+
+                my %count;
+                my @unique_queues = grep { ++$count{$_} < 2 } @{ $count_queue{$valor} };
+                @{ $count_queue{$valor} } = @unique_queues;
+
+                if ( exists( $count_queue{$valor} ) && $count_queue{$valor} ne "" ) {
+                    my $texto3 = "";
+                    foreach my $qmem ( @{ $count_queue{$valor} } ) {
+                        $texto3 .= "$qmem\n";
+                    }
+                    $contaconta = @{ $count_queue{$valor} };
+                    my $texto2 = "Agents Logged: $contaconta\n" . $texto3 . "  ";
+                    $texto2 = encode_base64($texto2);
+                    push @return, "QUEUE/" . uc( $hash_temporal{Queue} ) . "|infoqstat2|$texto2|$unico_id|$canalid";
+                    print_countqueue("final de agentlogin tenia queue");
+                }
+            }
+        }
+    }
+
+    if ( $evento eq "agentlogoff" ) {
+
+        $canal = "Agent/" . $hash_temporal{Agent};
+        if ( $hash_temporal{Agent} !~ /^Agent/ ) {
+            $canal = $hash_temporal{Agent};
+        }
+
+        my $texto = $hash_temporal{Agent};
+        $canalid = $canal . "-XXXX";
+
+        if ( $ren_agentlogin == 1 || $ren_cbacklogin == 1 || $change_led == 1 ) {
+            $estado_final = "changelabel" . $change_led;
+
+            if ( defined( $agent_to_channel{"$server^Agent/$canal"} ) || defined( $channel_to_agent{"$server^$canal"} ) ) {
+                if ( defined( $agent_to_channel{"$server^Agent/$canal"} ) ) {
+
+                    #                    ( $canal, my $nada ) = separate_session_from_channel( $agent_to_channel{"$server^Agent/$canal"} );
+                    $canal = $agent_to_channel{"$server^Agent/$canal"};
+                }
+                else {
+
+                    #                    ( $canal, my $nada ) = separate_session_from_channel( $channel_to_agent{"$server^$canal"} );
+                    $canal = $channel_to_agent{"$server^$canal"};
+                }
+
+                if ( defined( $agent_label{$canal} ) ) {
+                    delete $agent_label{$canal};
+                }
+
+                if ( $canalid eq "" ) {
+                    $canalid = "AGENT/$texto-XXXX";
+                }
+
+                #delete $agent_to_channel{"$server^$canal"};
+                #delete $agent_to_channel{"$server^$agente"};
+                delete $reverse_agents{$texto};
+                delete $reverse_agents{$canal};
+
+                push @return, "$canal|$estado_final|original|$unico_id|$canalid";
+                push @return, "$canal|agentlogoff|original|$unico_id|$canalid";
+            }
+            else {
+                log_debug( "No esta definido agente $server^$canal", 32 ) if DEBUG;
+                push @return, "$canal|$estado_final|original|$unico_id|$canalid";
+                push @return, "$canal|agentlogoff|original|$unico_id|$canalid";
+            }
+
+            #    if ( defined( $hash_temporal{Fake} ) ) {
+
+            # We dont want queueagent buttons to be renamed back to the orignal label
+            #       push @return, "AGENT/$texto|$estado_final|original|$unico_id|$canalid";
+            #  }
+
+            if ( $agent_status == 1 ) {
+                push @return, "$canal|isagent|-1|$unico_id|$canalid" if ( $canal ne "" );
+                push @return, "AGENT/$texto|isagent|-1|$unico_id|$canalid";
+            }
+
+            # Its form a removequeuemember, we have to mantain the agents_on_queue hash
+            # after finding buttons in digest_event_block, so the led and label go back
+            # to normal. If we do it here, we will always have the AGENTQUEUE button marked
+            # as an agent even if its removed
+            if ( defined( $hash_temporal{Fake} ) && $canal ne "" ) {
+                if ( $hash_temporal{Fake} eq "removed" ) {
+                    push @return, "$canal|queueremoved|$hash_temporal{Queue}|$unico_id|$canalid";
+                }
+            }
+
+            $evento = "";
+        }
+
+        delete( $is_agent{ uc("$server^$texto") } );
+
+        if ( keys(%count_queue) ) {
+            print_countqueue("agentlogoff principio count_queue");
+            my $contaconta = 0;
+            my %temp_queue = ();
+            my $valor      = "";
+            foreach $valor ( sort ( keys(%count_queue) ) ) {
+                foreach my $vvalor ( @{ $count_queue{$valor} } ) {
+                    if ( $vvalor !~ /^$server\^$canal$/i && $vvalor !~ /^$server\^AGENT\/$texto$/i ) {
+                        push @{ $temp_queue{$valor} }, $vvalor;
+                    }
+                    my %count;
+                    my @unique_queues = grep { ++$count{$_} < 2 } @{ $temp_queue{$valor} };
+                    @{ $temp_queue{$valor} } = @unique_queues;
+                }
+            }
+            %count_queue = %temp_queue;
+            if ( defined( $hash_temporal{Queue} ) ) {
+                $valor = $hash_temporal{Queue};
+                if ( exists( $count_queue{"$server^$valor"} ) && $count_queue{"$server^$valor"} ne "" ) {
+                    my $texto3 = "";
+                    foreach my $qmem ( @{ $count_queue{"$server^$valor"} } ) {
+                        $texto3 .= "$qmem\n";
+                    }
+                    $contaconta = @{ $count_queue{"$server^$valor"} };
+                    my $texto2 = "Agents Logged: $contaconta\n" . $texto3 . "  ";
+                    $texto2 = encode_base64($texto2);
+                    push @return, "QUEUE/" . uc( $hash_temporal{Queue} ) . "|infoqstat2|$texto2|$unico_id|$canalid";
+                    print_countqueue("al final");
+                }
+            }
+        }
+
+    }
+
+    if ( $evento eq "queueentry" ) {
+
+        if ( defined( $max_queue_waiting_time_for{"$hash_temporal{Queue}-$hash_temporal{Server}"} ) ) {
+            if ( $hash_temporal{Wait} > $max_queue_waiting_time_for{"$hash_temporal{Queue}-$hash_temporal{Server}"} ) {
+                $max_queue_waiting_time_for{"$hash_temporal{Queue}-$hash_temporal{Server}"} = $hash_temporal{Wait};
+            }
+        }
+        else {
+            $max_queue_waiting_time_for{"$hash_temporal{Queue}-$hash_temporal{Server}"} = $hash_temporal{Wait};
+        }
+        foreach my $keyh ( keys(%hash_temporal) ) {
+            if ( $keyh eq "Event" ) {
+                $fake_bloque[$fakecounter]{$keyh} = "Join";
+            }
+            elsif ( $keyh eq "Position" ) {
+                $fake_bloque[$fakecounter]{Count}    = $hash_temporal{$keyh};
+                $fake_bloque[$fakecounter]{Position} = $hash_temporal{$keyh};
+            }
+            else {
+                $fake_bloque[$fakecounter]{$keyh} = $hash_temporal{$keyh};
+            }
+        }
+        $fakecounter++;
+    }
+
+    if ( $evento eq "queuestatuscomplete" ) {
+        for my $cola_server ( keys %max_queue_waiting_time_for ) {
+            my ( $cola, $server ) = ( $cola_server =~ m/(.*)-(.*)/ );
+            push @return, "QUEUE/$cola|settimer|" . $max_queue_waiting_time_for{"$cola-$server"} . "|$cola-$server|QUEUE/$cola-XXXX";
+        }
+
+        # Sends the lowest lastcall time of all possible queues
+        for my $canala ( keys %max_lastcall ) {
+            my $idleseconds = time() - $max_lastcall{$canala};
+            push @return, "$canala|settimer|$idleseconds\@IDLE|$unico_id|$canala-XXXX";
+        }
+        $evento = "";
+    }
+
+    if ( $evento eq "queuemember" || $evento eq "queuememberstatus" ) {
+
+        my $canalag = $hash_temporal{"Location"};
+        $canalag =~ tr/a-z/A-Z/;
+        my $canalagid  = $canalag . "-XXXX";
+        my $unicoag_id = "$canalag-$server";
+        $canal = $hash_temporal{"Location"};
+
+        ( $server, $canal ) = local_channels_are_driving_me_mad( $server, $canal );
+
+        if ( $canal =~ /^AGENT/i ) {
+            my $temp = $canal;
+            $temp =~ s/^AGENT\///gi;
+
+            if ( defined( $hash_temporal{Status} ) && $evento eq "queuemember" ) {
+                if ( $hash_temporal{Status} == 5 ) {
+
+                    # If its logged off, fake the event, but only for queuemember
+                    $fake_bloque[$fakecounter]{Event}  = "Agentlogoff";
+                    $fake_bloque[$fakecounter]{Agent}  = $temp;
+                    $fake_bloque[$fakecounter]{Server} = $server;
+                    $fake_bloque[$fakecounter]{Fake}   = "1";
+                    $fakecounter++;
+
+                    push @return, "$canalag|changelabel$change_led|original|$unicoag_id|$canal-XXXX";
+                }
+                else {
+
+                    # Generates Fake Agent Login to change led color and label renaming
+                    $fake_bloque[$fakecounter]{Event}   = "Agentlogin";
+                    $fake_bloque[$fakecounter]{Channel} = $canal . "-XXXX";
+                    $fake_bloque[$fakecounter]{Agent}   = $canal;
+                    $fake_bloque[$fakecounter]{Fake}    = "1";
+                    $fake_bloque[$fakecounter]{Server}  = $server;
+                    $fakecounter++;
+
+                    #    push @return, "$canalag|changelabel$change_led|.|$unicoag_id|$canal-XXXX";
+                }
+            }
+        }
+
+        if ( $evento eq "queuemember" ) {
+
+            # We only want to reserve positions on queuemember (initial query status) and
+            # to AGENT channels
+            reserve_next_available_agent_button( $server, $canal, $hash_temporal{Queue} );
+            $is_agent{ uc("$server^$canalag") } = 1;
+
+            #if ( $agent_status == 1 ) {
+            #    if ( $hash_temporal{Paused} eq "1" ) {
+            #        push @return, "$canal|settext|&paused|$unico_id|$canalid";
+            #        push @return, "$canal|settimer|0\@IDLE|$unico_id|$canalid";
+            #    }
+            #    else {
+            #        push @return, "$canal|settext|&idle|$unico_id|$canalid";
+            #        push @return, "$canal|settimer|0\@IDLE|$unico_id|$canalid";
+            #    }
+            #}
+
+        }
+        if ( $canal !~ /^Local/ ) {
+            $canal =~ tr/a-z/A-Z/;
+        }
+        $estado_final = "info";
+        $texto        = "";
+
+        my $contaconta        = 0;
+        my $vval              = $hash_temporal{Queue};
+        my $has_status_ast_12 = 0;
+
+        while ( ( $key, $val ) = each(%hash_temporal) ) {
+            if ( !defined($val) ) { $val = " "; }
+            $texto .= "$key = $val\n";
+            if ( $key eq "Status" && $val != 5 ) {
+                $estado_final .= $vval;
+                push @{ $count_queue{"$server^$vval"} }, "$server^$canal";
+                $has_status_ast_12 = 1;
+            }
+        }
+        if ( $has_status_ast_12 == 0 ) {
+
+            # If there is no status on the events, is asterisk stable, count the agent in
+            $estado_final .= $vval;
+            push @{ $count_queue{"$server^$vval"} }, "$server^$canal";
+        }
+        my %count;
+        my @unique_queues = grep { ++$count{$_} < 2 } @{ $count_queue{"$server^$vval"} };
+        @{ $count_queue{"$server^$vval"} } = @unique_queues;
+        $contaconta = @{ $count_queue{"$server^$vval"} };
+
+        my $texto3 = "";
+        foreach my $qmem ( @{ $count_queue{"$server^$vval"} } ) {
+            $texto3 .= "$qmem\n";
+        }
+        $unico_id = "$canal-$server";
+        my $texto2 = "Agents Logged: $contaconta\n" . $texto3 . "  ";
+        $texto .= " ";
+        $texto = encode_base64($texto);
+        print_countqueue("en queuemember");
+        $texto2  = encode_base64($texto2);
+        $canalid = $canal . "-XXXX";
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+
+        if ( $canal !~ /$canalag/i ) {
+            push @return, "$canalag|$estado_final|$texto|$unicoag_id|$canalagid";
+        }
+        push @return, "QUEUE/" . uc( $hash_temporal{Queue} ) . "|infoqstat2|$texto2|$unico_id|$canalid";
+
+        if ( $canal !~ /^Local/i && $canal !~ /^Agent/i && $evento eq "queuemember" ) {
+
+            #if (!exists($is_agent{"$server^$canal"})) {
+            # If we have a queuemember event and is not recorded as agent, fake login
+            my $pausetext = "";
+            if ( $hash_temporal{Paused} eq "1" ) {
+                $pausetext = "&paused";
+            }
+            else {
+                $pausetext = "&idle";
+            }
+
+            # Generates Fake Agent Login to change led color and label renaming
+            $fake_bloque[$fakecounter]{Event}   = "Agentlogin";
+            $fake_bloque[$fakecounter]{Channel} = $canal . "-XXXX";
+            $fake_bloque[$fakecounter]{Agent}   = $canal;
+            $fake_bloque[$fakecounter]{Fake}    = "1";
+            $fake_bloque[$fakecounter]{Server}  = $server;
+
+            # we sent the folowing two headers (paused,lastcall) to the fake agentlogin
+            $fake_bloque[$fakecounter]{Paused}   = $pausetext;
+            $fake_bloque[$fakecounter]{LastCall} = $hash_temporal{LastCall};
+            $fakecounter++;
+        }
+
+        #}
+        $evento = "";
+    }
+
+    if ( $evento eq "queuestatus" ) {
+        $canal   = $hash_temporal{Queue};
+        $canalid = $canal . "-XXXX";
+        print_countqueue("en queuestatus");
+        $canal =~ tr/a-z/A-Z/;
+        $canal        = "QUEUE/$canal";
+        $estado_final = "infoqstat";
+        $texto        = "";
+        while ( ( $key, $val ) = each(%hash_temporal) ) {
+            $texto .= "$key = $val\n";
+        }
+        $unico_id = "$canal-$server";
+        $texto .= " ";
+        $texto = encode_base64($texto);
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "meetmemute" || $evento eq "meetmeunmute" ) {
+        my ( $canal, $nada ) = separate_session_from_channel($canalid);
+        $estado_final = $evento;
+        push @return, "$canal|$evento||$unico_id|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "queueparams" ) {
+        $canal = $hash_temporal{Queue};
+        $canal =~ tr/a-z/A-Z/;
+        $estado_final = "ocupado";
+        my $plural = "";
+        if ( $hash_temporal{Calls} > 0 ) {
+            if ( $hash_temporal{Calls} > 1 ) { $plural = "s"; }
+            $texto    = "&waitingonqueue," . $hash_temporal{Calls} . ",$plural&";
+            $unico_id = "$canal-$server";
+            push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        }
+        else {
+
+            # If the queue has no users waiting, delete the hash element
+            delete $max_queue_waiting_time_for{"$hash_temporal{Queue}-$hash_temporal{Server}"};
+        }
+
+        # Generates a Fake Block/Event for sending info status to queues
+        while ( ( $key, $val ) = each(%hash_temporal) ) {
+            $fake_bloque[$fakecounter]{$key} = $val;
+        }
+        $fake_bloque[$fakecounter]{Event} = "QueueStatus";
+        $fakecounter++;
+        $evento = "";
+    }
+
+    if ( $evento eq "join" ) {
+        my $qclidnum  = "";
+        my $qclidname = "";
+        $canal = "QUEUE/" . $hash_temporal{Queue};
+        my $position = $hash_temporal{Position};
+        $canal =~ tr/a-z/A-Z/;
+        $estado_final = "ocupado1";
+        my $plural = "";
+        if ( $hash_temporal{Count} > 1 ) { $plural = "s"; }
+        $texto    = "&waitingonqueue," . $hash_temporal{Count} . ",$plural&";
+        $unico_id = "$canal-$server";
+
+        if ( defined( $hash_temporal{CallerIDName} ) ) {
+            $qclidnum  = $hash_temporal{CallerID};
+            $qclidname = $hash_temporal{CallerIDName};
+        }
+        elsif ( defined( $hash_temporal{CalleridName} ) ) {
+            $qclidnum  = $hash_temporal{Callerid};
+            $qclidname = $hash_temporal{CalleridName};
+        }
+        else {
+            ( $qclidnum, $qclidname ) = split_callerid( $hash_temporal{CallerID} );
+        }
+        my $texto_pos = "[$qclidname $qclidnum]";
+
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        push @return, "$canal=$position|$estado_final|$texto_pos|$unico_id|$canalid";
+        push @return, "$canal=$position|setalpha|100|$unico_id|$canalid";
+        $evento = "";
+
+        my $tiempo = time();
+        if ( defined( $hash_temporal{Wait} ) ) {
+            $tiempo = $tiempo - $hash_temporal{Wait};
+            push @return, "$canal=$position|settimer|$hash_temporal{Wait}\@UP|$unico_id|$canalid";
+        }
+        $cola->{$canalid}{POSITION} = $position;
+        $cola->{$canalid}{QUEUE}    = $canal;
+        $cola->{$canalid}{CLID}     = $qclidnum;
+        $cola->{$canalid}{CLIDNAME} = $qclidname;
+        $cola->{$canalid}{SERVER}   = $server;
+        $cola->{$canalid}{TIME}     = $tiempo;
+
+    }
+
+    if ( $evento eq "meetmejoin" ) {
+        my $originate = "no";
+        my $nada      = "";
+        my $contexto  = "";
+
+        if ( $hash_temporal{Channel} =~ /^Local/ ) {
+
+            # We have to ignore Local channels when counting users
+            $hash_temporal{Fake} = 1;
+        }
+
+        $canal = $hash_temporal{Meetme};
+        my $uni_id = $hash_temporal{Uniqueid} . "-" . $server;
+        log_debug( "$heading MEETMEJOIN uni_id = $uni_id y canal = $canal", 128 ) if DEBUG;
+        $datos{$uni_id}{Extension} = $canal;
+        log_debug( "$heading 2 BORRO datos $uni_id { link }", 128 ) if DEBUG;
+        delete $datos{$uni_id}{Link};
+
+        $canal =~ tr/a-z/A-Z/;
+
+        for $quehay ( keys %auto_conference ) {
+
+            if ( $quehay eq $hash_temporal{Channel} ) {
+                $originate = $auto_conference{"$quehay"};
+                $contexto  = $barge_context{$canal};
+            }
+        }
+
+        if ( $originate ne "no" ) {
+            log_debug( "$heading origino a meetme en el contexto $contexto!", 128 ) if DEBUG;
+            my $comando = "Action: Originate\r\n";
+            $comando .= "Channel: $originate\r\n";
+            $comando .= "Exten: $canal\r\n";
+            $comando .= "Context: " . $config->{$contexto}{'conference_context'} . "\r\n";
+            $comando .= "Priority: 1\r\n";
+            $comando .= "\r\n";
+            send_command_to_manager( $comando, $socket, 0, $astmanproxy_server );
+
+            if ($barge_muted) {
+                $start_muted{"$server^$originate"} = 1;
+            }
+        }
+
+        $estado_final = "ocupado9";    # 9 for conference
+        my $plural = "";
+
+        if ( !defined( $hash_temporal{Fake} ) ) {
+            if ( !defined( $datos{"$canal-$server"}{Count} ) ) {
+                $datos{"$canal-$server"}{Count} = 0;
+                log_debug( "$heading POPULATES datos($canal-$server){ count } = 0", 64 ) if DEBUG;
+            }
+            if ( exists( $meetme_pos{"$server^$canal"}{ $hash_temporal{Usernum} } ) ) {
+
+                # Already logged in, buggy channed driver! (SCCP?)
+                log_debug( "$heading ignoring already joined channel", 16 );
+            }
+            else {
+                $datos{"$canal-$server"}{Count}++;
+            }
+            log_debug( "$heading pongo DATOS ($canal-$server) {count} en $datos{\"$canal-$server\"}{Count}", 16 )
+              if DEBUG;
+        }
+
+        # Its a fake meetmejoin generated from the meetme status at startup
+        my ( $canalsinses, $pedses ) = separate_session_from_channel( $hash_temporal{Channel} );
+        push @return, "$hash_temporal{Meetme}|setlink|$hash_temporal{Channel}|YYYY-$server|$hash_temporal{Channel}";
+        push @return, "$canalsinses|setlink|$hash_temporal{Meetme}|$hash_temporal{Meetme}-$server|$hash_temporal{Channel}";
+        push @return, "$canalsinses|meetmeuser|$hash_temporal{Usernum},$hash_temporal{Meetme}|YYYY-$server|$hash_temporal{Channel}";
+
+        if ( defined( $hash_temporal{Total} ) ) {
+            $datos{"$canal-$server"}{Count} = $hash_temporal{Total};
+            log_debug( "$heading pongo DATOS de ($canal-$server) {count} en $hash_temporal{Total}", 64 ) if DEBUG;
+        }
+
+        $barge_rooms{"$canal"} = $datos{"$canal-$server"}{"Count"};
+
+        if ( defined( $datos{"$canal-$server"}{"Count"} ) ) {
+            if ( $datos{"$canal-$server"}{"Count"} > 1 ) { $plural = "s"; }
+            $texto = "&memberonconference," . $datos{"$canal-$server"}{"Count"} . ",$plural&";
+        }
+
+        if ( exists( $start_muted{"$server^$canalsinses"} ) ) {
+            my $boton_con_contexto = $buttons{"$server^$canalsinses"};
+            my $comando            = "Action: Command\r\n";
+            $comando .= "ActionID: meetmemute$boton_con_contexto\r\n";
+            $comando .= "Command: meetme mute $hash_temporal{Meetme} $hash_temporal{Usernum}\r\n\r\n";
+            send_command_to_manager( $comando, $socket, 0, $astmanproxy_server );
+            delete $start_muted{"$server^$canalsinses"};
+        }
+
+        $unico_id = $canal . "-" . $server;
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        $evento = "";
+
+        # From here we send MEETME=POS button responses
+        my $position   = $hash_temporal{Usernum};
+        my $realunique = "";
+        if ( $hash_temporal{Uniqueid} =~ m/(.*)-\d+/ ) {
+            $realunique = $hash_temporal{Uniqueid};
+        }
+        else {
+            $realunique = $hash_temporal{Uniqueid} . "-" . $server;
+        }
+        my $qclidnum  = "";
+        my $qclidname = "";
+        if ( defined( $datos{$realunique}{CallerIDName} ) ) {
+            $qclidname = $datos{$realunique}{CallerIDName};
+            $qclidnum  = $datos{$realunique}{CallerID};
+        }
+        elsif ( defined( $datos{$realunique}{CalleridName} ) ) {
+            $qclidname = $datos{$realunique}{CalleridName};
+            $qclidnum  = $datos{$realunique}{Callerid};
+        }
+        else {
+            print_datos(99);
+            ( $qclidnum, $qclidname ) = split_callerid( $datos{$realunique}{CallerID} );
+        }
+        my $texto_pos = "[$qclidnum]";
+        if ( $qclidnum ne $qclidname ) {
+            $texto_pos = "[$qclidname $qclidnum]";
+        }
+        my $canalfin = get_meetme_pos( $server, $canal, $position );
+        push @return, "$canalfin|$estado_final|$texto_pos|YYYY-$server|$hash_temporal{Channel}";
+        push @return, "$canalfin|meetmeuser|$hash_temporal{Usernum},$hash_temporal{Meetme}|YYYY-$server|$hash_temporal{Channel}";
+    }
+
+    if ( $evento eq "meetmeleave" ) {
+        $canal = $hash_temporal{Meetme};
+        $canal =~ tr/a-z/A-Z/;
+        $estado_final = "ocupado9";    # 9 for meetme
+        my $plural = "";
+        $datos{"$canal-$server"}{"Count"}--;
+        log_debug( "$heading pongo DATOS ( $canal-$server) (count) en $datos{\"$canal-$server\"}{'Count'} leave", 64 )
+          if DEBUG;
+        $barge_rooms{$canal} = $datos{"$canal-$server"}{Count};
+        if ( $datos{"$canal-$server"}{Count} > 1 )  { $plural       = "s"; }
+        if ( $datos{"$canal-$server"}{Count} <= 0 ) { $estado_final = "corto"; }
+        $texto    = "&memberonconference," . $datos{"$canal-$server"}{Count} . ",$plural&";
+        $unico_id = $canal . "-" . $server;
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        my $canaleja = $hash_temporal{Channel};
+        delete $auto_conference{$canaleja};
+        log_debug( "$heading Erasing auto_conference $canaleja", 64 ) if DEBUG;
+
+        for $quehay ( keys %auto_conference ) {
+            log_debug( "$heading Remaining conferences: $quehay", 64 ) if DEBUG;
+        }
+
+        my ( $canal1, $nada1 ) = separate_session_from_channel($canaleja);
+        push @return, "$canal1|unsetlink|$canal|$unico_id|$canalid";
+        $evento = "";
+
+        my $canalfin = get_meetme_pos( $server, $canal, $hash_temporal{Usernum} );
+        delete $meetme_pos{"$server^$canal"}{ $hash_temporal{Usernum} };
+        push @return, "$canalfin|corto||$hash_temporal{Uniqueid}-$server|$canaleja";
+    }
+
+    if ( $evento eq "leave" ) {
+        $canal = "QUEUE/" . $hash_temporal{"Queue"};
+        $canal =~ tr/a-z/A-Z/;
+        $estado_final = "ocupado";
+        my $plural = "";
+        if ( $hash_temporal{"Count"} > 1 )  { $plural       = "s"; }
+        if ( $hash_temporal{"Count"} == 0 ) { $estado_final = "corto"; }
+        $texto    = "&waitingonqueue," . $hash_temporal{"Count"} . ",$plural&";
+        $unico_id = "$canal-$server";
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        $evento = "";
+
+        print_sesbot(1);
+        my @queue_events = recompute_queues($canalid);
+        foreach my $valor (@queue_events) {
+            push @return, $valor;
+        }
+        print_sesbot(2);
+    }
+
+    if ( $evento eq "voicemail" ) {
+        my @canalesvoicemail = ();
+
+        while ( my ( $ecanal, $eextension ) = each(%mailbox) ) {
+            if ( $eextension eq $hash_temporal{"Mailbox"} ) {
+                $canal = $ecanal;
+                $canal =~ s/(.*)\&(.*)/$1/g;    # Remove &context
+                $canal =~ s/(.*)\^(.*)/$2/g;    # Remove Server
+                push @canalesvoicemail, $canal;
+            }
+        }
+        foreach my $canal (@canalesvoicemail) {
+            $unico_id = $canal;
+            $canalid  = $canal . "-XXXX";
+            if ( defined( $hash_temporal{"Waiting"} ) ) {
+                $estado_final = "voicemail";
+                $texto        = $hash_temporal{"Waiting"};
+
+                #$texto        = 1;
+                if ( $texto eq "1" ) {
+
+                    # If it has new voicemail, ask for mailboxcount
+                    send_command_to_manager( "Action: MailboxCount\r\nMailbox: $hash_temporal{Mailbox}\r\n\r\n",
+                        $socket, 0, $astmanproxy_server );
+                }
+            }
+            else {
+                $estado_final = "voicemailcount";
+                my $nuevos = $hash_temporal{"NewMessages"};
+                my $viejos = $hash_temporal{"OldMessages"};
+                $texto   = "&newold,$nuevos,$viejos";
+                $canalid = $canal . "-XXXX";
+            }
+            push @return, "$canal|$estado_final|$texto|$unico_id-$server|$canalid";
+        }
+        $evento = "";
+    }
+
+    if ( $evento eq "link" ) {
+        my $uniqueid1 = $hash_temporal{"Uniqueid1"};
+        my $uniqueid2 = $hash_temporal{"Uniqueid2"};
+        if ( $uniqueid1 !~ /-\d+$/ ) {
+            $uniqueid1 .= "-" . $server;
+        }
+        if ( $uniqueid2 !~ /-\d+$/ ) {
+            $uniqueid2 .= "-" . $server;
+        }
+        my $channel1 = $hash_temporal{"Channel1"};
+        my $channel2 = $hash_temporal{"Channel2"};
+
+        log_debug( "$heading DATOS de $uniqueid1 { link } en $channel2", 64 ) if DEBUG;
+        log_debug( "$heading DATOS de $uniqueid2 { link } en $channel1", 64 ) if DEBUG;
+        $datos{$uniqueid1}{"Link"} = $channel2;
+        $datos{$uniqueid2}{"Link"} = $channel1;
+        my ( $canal1, $sesion1 ) = separate_session_from_channel($channel1);
+        my ( $canal2, $sesion2 ) = separate_session_from_channel($channel2);
+
+        my $channel1conses = $channel1;
+        if ( $channel1 !~ /${sesion1}$/ ) {
+            $channel1conses = "$canal1-$sesion1";
+        }
+
+        my $channel2conses = $channel2;
+        if ( $channel2 !~ /${sesion2}$/ ) {
+            my $channel2conses = "$canal2-$sesion2";
+        }
+
+        # push @return, "$canal1|link|$canal2|$uniqueid2|${canal1}-XXXX";
+        # delete $datos{$unico_id};
+        # print "3 BORRO datos $unico_id \n";
+        $evento       = "";
+        $canal        = $canal1;
+        $estado_final = "ocupado7";    # 7 for linked channel, start billing
+
+        if ( exists( $parked{"$server^$channel1"} ) ) {
+            log_debug( "$heading EXISTE parked{$server^$channel1} ", 128 ) if DEBUG;
+            my $parkexten = $parked{"$server^$channel1"};
+            delete $parked{"$server^$channel1"};
+            push @return, "PARK/$parkexten|corto||YYYY-$server|$channel1conses";
+            push @return, "$canal1|ocupado5||$uniqueid1|$channel1conses";
+        }
+        else {
+            log_debug( "$heading NO EXISTE parked{$server^$channel1}", 128 ) if DEBUG;
+        }
+
+        if ( exists( $parked{"$server^$channel2"} ) ) {
+            log_debug( "$heading EXISTE parked{$server^$channel2} ", 128 ) if DEBUG;
+            log_debug( "$heading SI EXISTE!",                        128 ) if DEBUG;
+            my $parkexten = $parked{"$server^$channel2"};
+            delete $parked{"$server^$channel2"};
+            push @return, "PARK/$parkexten|corto||YYYY-$server|$channel2conses";
+            push @return, "$canal2|ocupado5||$uniqueid2|$channel2conses";
+        }
+        else {
+            log_debug( "$heading NO EXISTE parked{$server^$channel2}", 128 ) if DEBUG;
+        }
+        my $clid1 = "";
+        my $clid2 = "";
+
+        if ( defined( $datos{$uniqueid2}{"Callerid"} ) ) {
+            $clid1 = $datos{$uniqueid2}{"Callerid"};
+        }
+        if ( defined( $datos{$uniqueid2}{"CallerID"} ) ) {
+            $clid1 = $datos{$uniqueid2}{"CallerID"};
+        }
+        if ( defined( $datos{$uniqueid1}{"Callerid"} ) ) {
+            $clid2 = $datos{$uniqueid1}{"Callerid"};
+        }
+        if ( defined( $datos{$uniqueid1}{"CallerID"} ) ) {
+            $clid2 = $datos{$uniqueid1}{"CallerID"};
+        }
+        if ( $clid1 ne "" && $channel2 ne "" ) {
+            my $clid_with_format = format_clid( $clid1, $clid_format );
+            push @return, "$canal1|settext|[$clid_with_format]|$uniqueid1|$channel1conses";
+        }
+        if ( $clid2 ne "" && $channel1 ne "" ) {
+            my $clid_with_format = format_clid( $clid2, $clid_format );
+            push @return, "$canal2|settext|[$clid_with_format]|$uniqueid2|$channel2conses";
+        }
+        push @return, "$canal1|setlink|$channel2|$uniqueid1|$channel1conses";
+        push @return, "$canal2|setlink|$channel1|$uniqueid2|$channel2conses";
+        $evento = "";    #NEW
+    }
+
+    if ( $evento eq "unlink" ) {
+        my $uniqueid1 = $hash_temporal{Uniqueid1};
+        my $uniqueid2 = $hash_temporal{Uniqueid2};
+        my $channel1  = $hash_temporal{Channel1};
+        my $channel2  = $hash_temporal{Channel2};
+        my ( $canal1, $sesion1 ) = separate_session_from_channel($channel1);
+        my ( $canal2, $sesion2 ) = separate_session_from_channel($channel2);
+
+        my $channel1conses = $channel1;
+        if ( $channel1 !~ /${sesion1}$/ ) {
+            my $channel1conses = "$canal1-$sesion1";
+        }
+
+        my $channel2conses = $channel2;
+        if ( $channel2 !~ /${sesion2}$/ ) {
+            my $channel2conses = "$canal2-$sesion2";
+        }
+
+        log_debug( "$heading Unlink $canal1 and $canal2", 64 ) if DEBUG;
+        $evento = "";
+
+        $estado_final = "unsetlink";
+        $canal        = $canal1;
+
+        my $boton1 = 0;
+        my $boton2 = 0;
+
+        for my $mnroboton ( keys %sesbot ) {
+            foreach my $msesion ( @{ $sesbot{$mnroboton} } ) {
+                if ( $msesion eq $channel1 ) {
+                    $boton1 = $mnroboton;
+                }
+                if ( $msesion eq $channel2 ) {
+                    $boton2 = $mnroboton;
+                }
+            }
+        }
+
+        #push @return, "$boton1|unsetlink|$boton2|$uniqueid1|$channel2";
+        #push @return, "$boton2|unsetlink|$boton1|$uniqueid2|$channel1";
+        push @return, "$canal1|unsetlink|$channel2|$uniqueid1-$server|$channel1conses";
+        push @return, "$canal2|unsetlink|$channel1|$uniqueid2-$server|$channel2conses";
+        $evento = "";    #NEW
+    }
+
+    if ( $evento eq "rename" ) {
+        my $nuevo_nombre = "";
+        my $viejo_nombre = "";
+        log_debug( "$heading RENAME Event", 32 ) if DEBUG;
+        $evento = "";
+        while ( ( $key, $val ) = each(%hash_temporal) ) {
+            if ( $key =~ /newname/i ) {
+                $nuevo_nombre = $val;
+            }
+            if ( $key =~ /oldname/i ) {
+                $viejo_nombre = $val;
+            }
+        }
+        log_debug( "$heading RENAME $viejo_nombre por $nuevo_nombre (id $unico_id)", 64 ) if DEBUG;
+
+        if ( $nuevo_nombre =~ /<ZOMBIE>/ ) {
+            log_debug( "$heading $nuevo_nombre, asterisk bug, sometimes misses the hangup, so we fake it", 64 ) if DEBUG;
+            my ( $canalnuevo, $nada ) = separate_session_from_channel($nuevo_nombre);
+            push @return, "$canalnuevo|corto||$unico_id|$nuevo_nombre";
+        }
+
+        # Directamente borra la sesion que se debe renombrar
+        #if ( ( $nuevo_nombre !~ /</ ) && ( $viejo_nombre !~ /</ ) ) {
+        my @final = ();
+
+        # A rename means that the channel was masqueraded, or going somewhere else
+        # we dont want to fiddle with sesbot variables. Because the new/old names
+        # maybe we want to REMOVE the old name from sesbot
+
+        for my $mnroboton ( keys %sesbot ) {
+            @final = ();
+            foreach my $msesion ( @{ $sesbot{$mnroboton} } ) {
+                if ( $msesion ne $viejo_nombre ) {
+                    push @final, $msesion;
+                }
+            }
+            $sesbot{$mnroboton} = [@final];
+        }
+
+        # We need to remove the channel from the cola hash
+        $cola->{$nuevo_nombre} = $cola->{$viejo_nombre};
+        delete $cola->{$viejo_nombre};
+
+        for my $mnroboton ( keys %linkbot ) {
+            @final = ();
+            foreach my $msesion ( @{ $linkbot{$mnroboton} } ) {
+                log_debug( "$heading RENAME iteracion cada linkbot($mnroboton)", 32 ) if DEBUG;
+                if ( $msesion ne $viejo_nombre ) {
+                    push @final, $msesion;
+                    log_debug( "$heading RENAME dejo $msesion en linkbot($mnroboton)", 32 ) if DEBUG;
+                }
+                else {
+                    &print_sesbot(20);
+                    log_debug( "$heading RENAME viejo $viejo_nombre no va, en realidad va $nuevo_nombre", 32 )
+                      if DEBUG;
+                    push @final, $nuevo_nombre;
+                    $estado_final = "setlink";
+                    my $botoncambiado = $buttons{"$mnroboton"};
+                    log_debug( "$heading RENAME buttons($mnroboton)",       32 ) if DEBUG;
+                    log_debug( "$heading RENAME sesbot($botoncambiado)[0]", 32 ) if DEBUG;
+                    my $canalcambiado = $sesbot{$botoncambiado}[0];
+
+                    if ( defined($canalcambiado) ) {
+                        my ( $canalito, $nada ) = separate_session_from_channel($canalcambiado);
+                        push @return, "$canalito|$estado_final|$nuevo_nombre|$unico_id|$canalcambiado";
+                        ( $canalito, $nada ) = separate_session_from_channel($nuevo_nombre);
+                        push @return, "$canalito|$estado_final|$canalcambiado|$unico_id|$nuevo_nombre";
+                        $canal = $canalito;
+                    }
+                }
+            }
+            $linkbot{$mnroboton} = [@final];
+        }
+
+        for $quehay ( keys %datos ) {
+            while ( ( $key, $val ) = each( %{ $datos{$quehay} } ) ) {
+                if ( ( $key eq "Channel" ) && ( $val eq $viejo_nombre ) ) {
+                    $datos{"$quehay"}{"$key"} = $nuevo_nombre;
+                    log_debug( "$heading POPULATES datos($quehay){ $key } = $nuevo_nombre", 32 ) if DEBUG;
+                }
+            }
+        }
+        for $quehay ( keys %parked ) {
+            if ( $quehay eq "$server^$viejo_nombre" ) {
+                $parked{"$server^$nuevo_nombre"} = $parked{"$quehay"};
+                delete $parked{"$quehay"};
+                my ( $rcanal, $rses ) = separate_session_from_channel($nuevo_nombre);
+                $texto = "&parked," . $parked{"$server^$nuevo_nombre"} . "&";
+                push @return, "$rcanal|ocupado3|$texto|$unico_id|$nuevo_nombre";
+            }
+        }
+        $evento = "";    #NEW
+    }
+
+    if ( $evento eq "peerstatus" ) {
+        my $tiempo = 0;
+        $canal = $hash_temporal{Peer};
+        $canal =~ tr/a-z/A-Z/;
+        $state = $hash_temporal{PeerStatus};
+
+        if ( defined $hash_temporal{Time} ) {
+            $tiempo = $hash_temporal{Time};
+        }
+
+        if ( $state eq "Registered" ) {
+            $estado_final = "registrado";
+            $texto        = "&registered";
+        }
+        elsif ( $state eq "Reachable" ) {
+            $estado_final = "registrado";
+            $texto        = "&reachable,$tiempo";
+        }
+        elsif ( $state eq "Unreachable" ) {
+            $estado_final = "unreachable";
+            $texto        = "&unreachable,$tiempo";
+        }
+        elsif ( $state eq "Lagged" ) {
+            $estado_final = "noregistrado";
+            $texto        = "&lagged,$tiempo";
+        }
+        $canalid = $canal . "-XXXX";
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "extensionstatus" ) {
+        $canal = $hash_temporal{"Exten"};
+        $canal =~ s/(\d+)/SCCP\/$1/g;
+        $state = $hash_temporal{"Status"};
+        if ( $hash_temporal{"Status"} == 0 ) {
+            $estado_final = "registrado";
+            $texto        = "&registered";
+        }
+        elsif ( $hash_temporal{"Status"} == 4 ) {
+            $estado_final = "unreachable";
+            $texto        = "&unreachable";
+        }
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+        $evento = "";
+    }
+
+    if ( $evento eq "status" ) {
+        $evento = "";
+    }
+
+    if ( $evento eq "statuscomplete" ) {
+
+        # When done with the status retrieval, generate events to send to
+        # flash clients. Do it only when finishing receiving status from
+        # all asterisk servers monitored
+
+        my @ids = ();
+        if ( keys(%datos) ) {
+            my $hay_activos = 0;
+
+            for ( keys %datos ) {
+                my $ignorame       = 0;
+                my @pedazote       = split( /-/, $_ );
+                my $current_server = $pedazote[1];
+                if ( "$server" ne "$current_server" ) {
+                    next;
+                }
+
+                log_debug( "$heading STATUSCOMPLETE datos { $_ }", 128 ) if DEBUG;
+                push @ids, $_;
+                my $myevent = "Newexten";
+                while ( my ( $key, $val ) = each( %{ $datos{$_} } ) ) {
+                    log_debug( "$heading STATUSCOMPLETE datos { $key } = $val", 128 ) if DEBUG;
+
+                    if ( defined($val) ) {
+                        $hay_activos = 1;
+                        $fake_bloque[$fakecounter]{$key} = $val;
+                        if ( $key eq "Extension" ) {
+                            $myevent = "Ring";
+                            $fake_bloque[$fakecounter]{Origin} = "true";
+                        }
+                        if ( $key eq "Channel" ) {
+                            if ( $timeouts{$val} ) {
+                                $datos{$_}{Timeout} = $timeouts{$val};
+                            }
+                        }
+                        if ( $key eq "Link" && $val =~ /^Agent/ ) {
+                            $ignorame = 1;
+                        }
+                    }
+                }
+                if ( $hay_activos == 1 ) {
+                    $fake_bloque[$fakecounter]{"Event"} = $myevent;
+                    if ( $ignorame == 1 ) {
+                        $fake_bloque[$fakecounter]{"Event"} = "Ignoreme-Bad-CLID";
+                        $fake_bloque[$fakecounter]{"State"} = "Ignoreme";
+                    }
+                    log_debug( "$heading fake bloque de $fakecounter (evento) lo pongo en $myevent", 128 ) if DEBUG;
+                    $fakecounter++;
+                }
+            }
+        }
+        else {
+            log_debug( "$heading En statuscomplete datos esta vacio!", 64 ) if DEBUG;
+        }
+
+        foreach my $valor (@ids) {
+            log_debug( "$heading foreach statuscomplete $valor", 32 ) if DEBUG;
+            if ( exists( $datos{"$valor"} ) ) {
+                if ( exists( $datos{"$valor"}{Link} ) ) {
+                    if ( $datos{"$valor"}{Link} !~ /^Agent/ ) {
+                        log_debug( "$heading datos de $valor tiene defined Link genero un Fake bloque", 128 ) if DEBUG;
+
+                        my $channel1 = $datos{$valor}{"Channel"};
+                        my $channel2 = $datos{$valor}{"Link"};
+                        my $unique1  = $datos{$valor}{"Uniqueid"};
+                        my $unique2  = find_uniqueid( $channel2, $server );
+
+                        $fake_bloque[$fakecounter]{"Event"}     = "Link";
+                        $fake_bloque[$fakecounter]{"Channel1"}  = $channel1;
+                        $fake_bloque[$fakecounter]{"Channel2"}  = $channel2;
+                        $fake_bloque[$fakecounter]{"Uniqueid1"} = $unique1;
+                        $fake_bloque[$fakecounter]{"Uniqueid2"} = $unique2;
+
+                        while ( my ( $quey, $vail ) = each( %{ $fake_bloque[$fakecounter] } ) ) {
+                            log_debug( "$heading FAKEBLOQUE contiene $quey = $vail", 128 ) if DEBUG;
+                        }
+
+                        $fakecounter++;
+                    }
+                    else {
+                        log_debug( "$heading datos de $valor linked to Agent, IGNORE", 128 ) if DEBUG;
+                    }
+                }
+                if ( exists( $datos{"$valor"}{"Timeout"} ) ) {
+                    my $calltimeout = $datos{"$valor"}{"Timeout"} - time();
+                    $fake_bloque[$fakecounter]{"ActionID"} = "timeout|$datos{$valor}{'Channel'}|$calltimeout";
+                    $fakecounter++;
+                }
+            }
+        }
+
+        $evento = "";    #NEW (estaba comentado)
+    }
+
+    if ( $evento eq "fakeismeetmemember" ) {
+        my @bot1 = ();
+        my $bot2 = 0;
+        $estado_final = "meetmeuser";
+        $texto        = $hash_temporal{"Usernum"} . "," . $hash_temporal{"Meetme"};
+        my ( $chan1, $nada1 ) = separate_session_from_channel( $hash_temporal{'Channel'} );
+        push @return, "$hash_temporal{'Meetme'}|setlink|$hash_temporal{'Channel'}||$hash_temporal{'Channel'}";
+        push @return, "$chan1|setlink|$hash_temporal{'Meetme'}||$hash_temporal{'Channel'}";
+        $evento = "";    #NEW
+    }
+
+    if ( $evento eq "newexten" ) {
+
+        # If its a new extension without state, defaults to 'Up'
+        if ( !defined( $datos{$unico_id}{'State'} ) && $fill_datos ) {
+            $datos{$unico_id}{'State'} = "Up";
+            log_debug( "$heading POPULATES datos($unico_id){ State } = Up", 128 ) if DEBUG;
+        }
+
+        # If its a parked channel, set the PARK button to 'Down'
+        if ( exists( $parked{"$server^$canalid"} ) ) {
+            log_debug( "$heading EXISTE parked{$server^$canalid}", 128 ) if DEBUG;
+            my $parkexten = $parked{"$server^$canalid"};
+            delete $parked{"$server^$canalid"};
+            push @return, "PARK/$parkexten|corto||YYYY-$server|$canalid";
+        }
+        else {
+            log_debug( "$heading NO EXISTE parked{$server^$canalid}", 128 ) if DEBUG;
+        }
+    }
+
+    if ( $evento eq "hangup" ) {
+        if ( exists( $datos{$unico_id} ) ) {
+            $datos{$unico_id}{'State'} = "Down";
+            log_debug( "$heading POPULATES datos($unico_id){ State } = down", 128 ) if DEBUG;
+        }
+        else {
+            $hash_temporal{'State'} = "Down";
+        }
+
+        # Look if the channel was parked and clear that button too
+        if ( exists( $parked{"$server^$canalid"} ) ) {
+            log_debug( "$heading 2 EXISTE parked{$server^$canalid}", 128 ) if DEBUG;
+            my $parkexten = $parked{"$server^$canalid"};
+            delete $parked{"$server^$canalid"};
+            push @return, "PARK/$parkexten|corto||YYYY-$server|$canalid";
+        }
+        else {
+            log_debug( "$heading NO EXISTE parked{$server^$canalid}", 128 ) if DEBUG;
+        }
+    }
+
+    if ( $evento eq "unparkedcall" ) {
+        my $channel1 = $hash_temporal{"Channel"};
+
+        if ( exists( $parked{"$server^$channel1"} ) ) {
+            my $unidchan = find_uniqueid( $hash_temporal{'Channel'}, $server );
+            log_debug( "$heading EXISTE parked{$server^$channel1} ", 128 ) if DEBUG;
+            my $parkexten = $parked{"$server^$channel1"};
+            delete $parked{"$server^$channel1"};
+            push @return, "PARK/$parkexten|corto||YYYY-$server|$channel1";
+            my ( $canal1, $sesion1 ) = separate_session_from_channel($channel1);
+            push @return, "$canal1|ocupado5||$unidchan|$channel1";
+        }
+    }
+
+    if ( $evento eq "parkedcall" ) {
+        $texto        = "&parked," . $hash_temporal{'Exten'} . "&";
+        $estado_final = "ocupado3";
+        my ( $canal, $nada ) = separate_session_from_channel( $hash_temporal{'Channel'} );
+        my $textid   = "";
+        my $timeout  = "";
+        my $unidchan = find_uniqueid( $hash_temporal{'Channel'}, $server );
+        $textid = $datos{$unidchan}{'Callerid'}
+          if ( defined( $datos{$unidchan}{'Callerid'} ) );
+        $textid = $datos{$unidchan}{'CallerID'}
+          if ( defined( $datos{$unidchan}{'CallerID'} ) );
+        $timeout = "(" . $hash_temporal{'Timeout'} . ")";
+        $textid =~ s/\"//g;
+        $textid =~ s/\<//g;
+        $textid =~ s/\>//g;
+        push @return, "$canal|ocupado3|$texto|$unidchan|$canalid";
+        push @return, "PARK/$hash_temporal{'Exten'}|park|[$textid]$timeout|$hash_temporal{'Timeout'}-$server|$hash_temporal{'Channel'}";
+
+        log_debug( "$heading pongo parked($server^$hash_temporal{'Channel'}) en $hash_temporal{'Exten'}", 64 ) if DEBUG;
+        $parked{"$server^$hash_temporal{'Channel'}"} = $hash_temporal{'Exten'};
+        $evento = "";    #NEW
+    }
+
+    if ( $evento eq "newcallerid" ) {
+        $estado_final = "setstatus";
+        $state        = "Newcallerid";
+        my $save_clidnum  = "";
+        my $save_clidname = "";
+        if ( defined( $hash_temporal{'CallerIDName'} ) ) {
+            $save_clidnum  = $hash_temporal{'CallerID'};
+            $save_clidname = $hash_temporal{'CallerIDName'};
+        }
+        elsif ( defined( $hash_temporal{'CalleridName'} ) ) {
+            $save_clidnum  = $hash_temporal{'Callerid'};
+            $save_clidname = $hash_temporal{'CalleridName'};
+        }
+        else {
+            ( $save_clidnum, $save_clidname ) = split_callerid( $hash_temporal{'CallerID'} );
+        }
+        $saved_clidnum{"$server^$hash_temporal{'Channel'}"}  = $save_clidnum;
+        $saved_clidname{"$server^$hash_temporal{'Channel'}"} = $save_clidname;
+    }
+
+    # From now on, we only look for the State of the datos block
+    # Dont check for $evento bellow this line!
+
+    if ( $evento ne "" ) {
+        log_debug( "$heading Event $evento, canal '$canal'", 32 ) if DEBUG;
+
+        # De acuerdo a los datos de la extension genera
+        # la linea con info para el flash
+
+        $elemento = $canalid;
+
+        if ( exists( $datos{$unico_id} ) ) {
+            if ( exists( $datos{$unico_id}{'Channel'} ) ) {
+                $elemento = $datos{$unico_id}{'Channel'};
+
+                # Old IAX naming convention
+                if ( $elemento =~ /^IAX2\[/ && $elemento =~ /\@/ ) {
+
+                    # The channel is IAX2 and has the @context
+                    # I will remove the @context/host because it varies
+                    $elemento =~ s/IAX2\[(.*)@(.*)\](.*)/IAX2\[$1\]$3/g;
+                }
+
+                if ( $elemento =~ /^IAX2\// && $elemento =~ /\@/ ) {
+                    $elemento =~ s/IAX2\/(.*)@(.*)\/(.*)/IAX2\/$1\/$3/g;
+                }
+            }
+        }
+        ( $canal, $sesion ) = separate_session_from_channel($elemento);
+
+        if ( defined($canal) ) {
+            $canal =~ tr/a-z/A-Z/;
+        }
+        else {
+            log_debug( "$heading canal not defined!! END $elemento", 32 ) if DEBUG;
+            while ( my ( $key, $val ) = each(%hash_temporal) ) {
+                log_debug( "$heading hash_temporal $key = $val", 128 ) if DEBUG;
+            }
+            return;
+        }
+
+        if ( $canal =~ m/^Local/i ) {    # ZZ nico
+                                         # return;
+        }
+
+        if ( defined($sesion) ) {
+            log_debug( "$heading canal $canal sesion $sesion", 128 ) if DEBUG;
+        }
+
+        if ( exists( $datos{$unico_id} ) ) {
+
+            log_debug( "$heading EXISTE datos($unico_id) ", 32 ) if DEBUG;
+
+            if ( exists( $datos{$unico_id}{'Extension'} ) ) {
+                $exten = $datos{$unico_id}{'Extension'};
+            }
+
+            if ( exists( $datos{$unico_id}{'State'} ) ) {
+                log_debug( "$heading EXISTE datos($unico_id){state}", 32 ) if DEBUG;
+                $state = $datos{$unico_id}{'State'};
+            }
+
+            if ( exists( $datos{$unico_id}{'Callerid'} ) ) {
+                $clid = $datos{$unico_id}{'Callerid'};
+            }
+
+            if ( exists( $datos{$unico_id}{'CallerID'} ) ) {
+                $clid = $datos{$unico_id}{'CallerID'};
+            }
+            if ( $clid ne "" ) {
+                ( $clidnum, $clidname ) = split_callerid($clid);
+            }
+            if ( exists( $datos{$unico_id}{'CallerIDName'} ) ) {
+                $clidname = $datos{$unico_id}{'CallerIDName'};
+            }
+
+            # The ones below are for catching the callerid from the
+            # Dial event on CVS-HEAD
+            if ( exists( $remote_callerid{"$server^$canalid"} ) ) {
+                $clidnum = $remote_callerid{"$server^$canalid"};
+            }
+            if ( exists( $remote_callerid_name{"$server^$canalid"} ) ) {
+                $clidname = $remote_callerid_name{"$server^$canalid"};
+            }
+        }
+        else {
+            log_debug( "$heading NO EXISTE datos($unico_id)", 32 ) if DEBUG;
+        }
+
+        if ( $state eq "" ) {
+            if ( defined( $hash_temporal{'State'} ) ) {
+                $state = $hash_temporal{'State'};
+            }
+            else {
+                $state = "";
+            }
+        }
+
+        my $clid_with_format = format_clid( $clidnum, $clid_format );
+
+        if ( $state eq "Ringing" ) {
+            my $ret = "";
+            if ( $clidnum ne "" ) {
+                my $base64_clidnum = encode_base64( $clidnum . " " );
+                $ret = "$canal|clidnum|$base64_clidnum|$unico_id|$hash_temporal{'Channel'}";
+                push @return, $ret;
+            }
+            if ( defined($clidname) ) {
+                my $base64_clidname = encode_base64( $clidname . " " );
+                $ret = "$canal|clidname|$base64_clidname|$unico_id|$hash_temporal{'Channel'}";
+                push @return, $ret;
+            }
+        }
+
+        if ( $state eq "Rsrvd" ) {
+            $state = "Ring";
+        }
+
+        if ( $state eq "Ring" ) {
+            $texto                      = "&calling";
+            $estado_final               = "ring";
+            $datos{$unico_id}{'Origin'} = "true";
+            log_debug( "$heading POPULATES datos($unico_id){ Origin } = true", 128 ) if DEBUG;
+        }
+
+        if ( $state eq "Dialing" ) {
+            $texto        = "&dialing";
+            $estado_final = "ring";
+            if ( $canal =~ /^OH323/ ) {
+
+                # OH323 use a random channel name when Dialing
+                # that later changes its name. So we just discard
+                # this event/name to avoid getting Dialing channels
+                # foerever (because we never receive a Down status)
+                $estado_final = "";
+            }
+        }
+
+        if ( $state eq "OffHook" ) {
+            $texto                      = "&calling";
+            $estado_final               = "ring";
+            $datos{$unico_id}{'Origin'} = "true";
+            log_debug( "$heading POPULATES datos($unico_id){ Origin } = true", 128 );
+        }
+
+        if ( $state =~ /^UNK/ ) {
+            $texto        = "&notregistered";
+            $estado_final = "noregistrado";
+            $unico_id     = "YYYY-$server";
+            if ( $canalid !~ /(.*)-XXXX$/ ) {
+                $canalid = $canalid .= "-XXXX";
+            }
+        }
+
+        if ( $state =~ /^UNR/ ) {
+            $texto        = "&unreachable";
+            $estado_final = "unreachable";
+            $unico_id     = "YYYY-$server";
+            if ( $canalid !~ /(.*)-XXXX$/ ) {
+                $canalid = $canalid .= "-XXXX";
+            }
+        }
+
+        if ( $state =~ /^Unm/ ) {
+            $texto        = "&registered";
+            $estado_final = "registrado";
+            $unico_id     = "YYYY-$server";
+            if ( $canalid !~ /(.*)-XXXX$/ ) {
+                $canalid = $canalid .= "-XXXX";
+            }
+        }
+
+        if ( $state =~ /^OK/ ) {
+            $texto        = "&registered";
+            $estado_final = "registrado";
+            $unico_id     = "YYYY-$server";
+            if ( $canalid !~ /(.*)-XXXX$/ ) {
+                $canalid = $canalid .= "-XXXX";
+            }
+        }
+
+        if ( $state eq "Newcallerid" ) {
+            $texto = "&incoming,[" . $clid_with_format . "]";
+        }
+
+        if ( $state eq "Ringing" ) {
+            $texto        = "&incoming,[" . $clid_with_format . "]";
+            $estado_final = "ringing";
+        }
+
+        if ( $state eq "Down" ) {
+
+            if ( $evento eq "hangup" ) {
+
+                # Solo nos interesa mandar a flash los down por hangup
+                # para evitar enviar eventos redundantes
+                $estado_final = "corto";
+                if ( $agent_status == 1 ) {
+                    if ( exists( $agent_to_channel{"$server^$canal"} ) || exists( $reverse_agents{$canal} ) ) {
+                        push @return, "$canal|isagent|0|$unico_id|$canalid";
+                    }
+                }
+            }
+            delete $timeouts{$canalid};
+            delete $remote_callerid{"$server^$canalid"};
+            delete $remote_callerid_name{"$server^$canalid"};
+            delete $saved_clidname{"$server^$canalid"};
+            delete $saved_clidnum{"$server^$canalid"};
+
+            #erase_instances_for_trunk_buttons($canalsesion);
+        }
+
+        my $exclude    = 0;
+        my $exten_clid = "";
+        if ( $state eq "Up" ) {
+            if ( $exten ne "" ) {
+                if ( is_number($exten) ) {
+                    $exten_clid = format_clid( $exten, $clid_format );
+                    if ( defined( $saved_clidnum{"$server^$canalid"} ) ) {
+                        $exten_clid = format_clid( $saved_clidnum{"$server^$canalid"}, $clid_format );
+                    }
+                    if ($clid_privacy) {
+                        $exten_clid = "n/a";
+                    }
+                    $conquien = "[" . $exten_clid . "]";
+                }
+                else {
+                    if ( length($exten) == 1 ) {
+                        $conquien = $exten;
+                        $exclude  = 1;        # We ignore events that have letter extensions 's', 'h', etc
+                        $exclude  = 0;        # Do we? UserEvent fake events dont work if we ignore them
+                        log_debug( "$heading CLID is not a number! $exten", 32 ) if DEBUG;
+                    }
+                    else {
+                        $conquien = $exten;
+                    }
+                }
+            }
+            else {
+                $conquien = $clid_with_format;
+            }
+
+            if ( defined( $hash_temporal{'Seconds'} ) ) {
+
+                # $conquien .= " (" . $hash_temporal{'Seconds'} . ")";
+                push @return, "$canal|settimer|$hash_temporal{'Seconds'}\@UP|$unico_id|$canalid";
+                push @return, "$canal|state|busy|$unico_id|$canalid";
+
+            }
+
+            if ( defined( $datos{$unico_id}{'Origin'} ) ) {
+                if ( $datos{$unico_id}{'Origin'} eq "true" ) {
+                    if ( $exclude == 1 ) {
+                        $texto = "skip";
+                    }
+                    else {
+                        $texto = "&calling,[$exten_clid]";
+                    }
+                    $estado_final = "ocupado2";    # 2 for origin button
+                }
+            }
+            else {
+
+                $texto        = "&incoming,[$conquien]";
+                $estado_final = "ocupado1";                # 1 for destination button
+            }
+        }
+
+        # Remove special character from Caller ID string
+        $texto =~ s/\"/'/g;
+        $texto =~ s/</[/g;
+        $texto =~ s/>/]/g;
+        $texto =~ s/\|/ /g;
+
+        push @return, "$canal|$estado_final|$texto|$unico_id|$canalid";
+
+    }
+
+    @return = unique(@return);
+
+    my $cuantos = $#return + 1;
+    log_debug( "$heading returns $cuantos", 16 ) if DEBUG;
+    foreach (@return) {
+        log_debug( "$heading END SUB returns $_", 32 ) if DEBUG;
+    }
+    $tab = substr( $tab, 0, -1 );
+    return @return;
+}
+
+sub local_channels_are_driving_me_mad {
+
+    # This tidbit checks if the channel is Local and we happen to have a regular
+    # channel button with the same ext @ context, if so, we replace the Local
+    # !$##@ channel to the regular/basic channel.
+
+    my $server = shift;
+    my $canal  = shift;
+    my @return = ();
+
+    log_debug( "** LOCAL_CHANNELS entra server $server canal $canal", 32 );
+
+    if ( $canal =~ /^Local/i ) {
+        my $local_channel = $canal;
+        $local_channel =~ s/Local\///gi;
+        if ( defined( $extension_transfer_reverse{"$server^$local_channel"} ) ) {
+            if ( $extension_transfer_reverse{"$server^$local_channel"} !~ /\d+\^CLID/ ) {
+
+                # We dont want to return CLID buttons
+                $canal = $extension_transfer_reverse{"$server^$local_channel"};
+                if ( $canal =~ /(\d+)\^(.*)/ ) {
+                    $server = $1;
+                    $canal  = $2;
+                }
+            }
+            else {
+                log_debug( "** LOCAL_CHANNELS ignoro el CLID button $canal", 32 ) if DEBUG;
+            }
+        }
+    }
+
+    # Remove &context from $canal
+    $canal =~ s/(.*)&(.*)/$1/g;
+
+    #	if( $canal =~ m/^CLID/ ) {
+    #   		my $extr = $extension_transfer{"$server^$canal"};
+    #		$extr =~ s/\d+\^(.*)/$1/g;
+    #		$canal = "Local/$extr";
+    #	}
+
+    log_debug( "** LOCAL_CHANNELS devuelvo $server canal $canal", 32 ) if DEBUG;
+    push @return, $server;
+    push @return, $canal;
+    return @return;
+}
+
+sub digest_event_block {
+    my $bleque             = shift;
+    my $tipo               = shift;
+    my $socket             = shift;
+    my $astmanproxy_server = shift;
+    my @blique             = @$bleque;
+    my @respuestas         = ();
+    my $canal              = "";
+    my $quehace            = "";
+    my $dos                = "";
+    my $uniqueid           = "";
+    my $canalid            = "";
+    my $quehay             = "";
+    my @mensajes           = ();
+    my $interno            = "";
+    my $todo               = "";
+    my @mensajefinal;
+    my $cuantas;
+    my $server = 0;
+    my %cambiaron;
+    my $heading = "** DIGEST_EVENT:";
+
+    $tab = $tab . "\t" if DEBUG;
+
+    log_debug( "$heading start", 16 ) if DEBUG;
+
+    @fake_bloque = ();
+    delete $datos{""};
+    foreach my $blaque (@blique) {
+
+        if (DEBUG) {
+            if ( $tipo eq "fake" ) {
+                $tab = substr( $tab, 0, -1 );
+                my $totdebug = "";
+                while ( my ( $key, $val ) = each( %{$blaque} ) ) {
+                    if ( $key ne "" ) {
+                        $totdebug .= sprintf( "%-15s <- %s\n", "fake", "$key: $val" );
+                    }
+                }
+                log_debug( $totdebug, 1 );
+                $tab = $tab . "\t";
+            }
+        }
+        @mensajes = procesa_bloque( $blaque, $socket, $astmanproxy_server );
+        foreach my $mensaje (@mensajes) {
+            if ( defined($mensaje) && $mensaje ne "" ) {
+                log_debug( "$heading GOT $mensaje", 32 ) if DEBUG;
+                delete $datos{""};    # Erase the hash with no uniqueid
+                ( $canal, $quehace, $dos, $uniqueid, $canalid ) =
+                  split( /\|/, $mensaje );
+
+                if ( !defined($dos) )     { $dos     = ""; }
+                if ( !defined($quehace) ) { $quehace = ""; }
+
+                if ( $canal =~ /\/PSEUDO/ ) {
+                    log_debug( "$heading Ignoring pseudo channel $canal", 32 ) if DEBUG;
+                    next;
+                }
+
+                if ( $dos eq "skip" ) {
+                    log_debug( "$heading SALTEO $canal tiene skip", 32 ) if DEBUG;
+                    next;
+                }
+                if ( $quehace eq "" ) {
+                    log_debug( "$heading SALTEO $canal no tiene quehace", 32 ) if DEBUG;
+                    next;
+                }
+
+                log_debug( "$heading canal:    $canal",    32 ) if DEBUG;
+                log_debug( "$heading quehace:  $quehace",  32 ) if DEBUG;
+                log_debug( "$heading dos:      $dos",      32 ) if DEBUG;
+                log_debug( "$heading uniqueid: $uniqueid", 32 ) if DEBUG;
+                log_debug( "$heading canalid:  $canalid",  32 ) if DEBUG;
+
+                #                if ( !defined($canal) )   { $canal   = ""; }
+                #                if ( !defined($quehace) ) { $quehace = ""; }
+                #                if ( !defined($dos) )     { $dos     = ""; }
+
+                $canalid =~ s/\s+//g;    # Removes whitespace from CHANNEL-ID
+                my $canalidzombie = $canalid;    # Removes whitespace from CHANNEL-ID
+                $canalid =~ s/(.*)<(.*)>/$1/g;   # discards ZOMBIE or MASQ
+
+                if ( $canal =~ /^vpb\//i ) {
+
+                    # For vpb channels, we fake a session number
+                    $canal = $canalid;
+                    $canal =~ tr/a-z/A-Z/;
+                    $canalid = $canalid .= "-VPB1";
+                }
+
+                $server = $uniqueid;
+                $server =~ s/(.*)-(.*)/$2/g;
+
+                log_debug( "$heading Quehace $quehace", 64 ) if DEBUG;
+
+                my $buttontext = $dos;
+                if ( $buttontext =~ /\Q[\E/ ) {
+                    $buttontext =~ s/.*\Q[\E(.*)\Q]\E.*/$1/g;
+                }
+                else {
+                    $buttontext = "";
+                }
+
+                my @canaleja = find_panel_buttons( $canal, $canalid, $server );
+                my $cuantos  = @canaleja;
+
+                if ( $quehace eq "corto" || $quehace eq "info" ) {
+
+                    # We collect the last state of the channel on hangup
+                    while ( my ( $key, $val ) = each( %{ $datos{$uniqueid} } ) ) {
+                        $todo .= "$key = $val\n"
+                          if ( $key ne "E" ) && ( defined($val) );
+                        log_debug( "$heading \tAgrego $key = $val", 128 ) if DEBUG;
+                    }
+                    $todo .= " ";
+                    $todo = encode_base64($todo);
+
+                    delete $datos{$uniqueid};
+                    delete $cola->{$canalidzombie};
+                    log_debug( "$heading erasing datos{$uniqueid}", 128 ) if DEBUG;
+
+                    if ( $cuantos == 0 ) {
+
+                        # We delete all appeareance in sesbot because the channel without
+                        # a button might occupy one slot in sesbot. If we have a button
+                        # match then skip this step for later
+                        erase_all_sessions_from_channel( $canalid, $canal, $server );
+                    }
+                }
+
+                if ( $quehace eq "queueremoved" ) {
+
+                    # Remove the agent from the agents_on_queue hash
+                    my $colita    = $dos;
+                    my @elementos = ();
+
+                    if ( keys(%agents_on_queue) ) {
+
+                        # remove from agents_on_queue hash only if it has anything on it
+                        foreach my $vvalor ( @{ $agents_on_queue{"$server^$colita"} } ) {
+                            if ( $vvalor ne "$server^$canal" ) {
+                                push @elementos, $vvalor;
+                            }
+                            else {
+                                push @elementos, "!" . $vvalor;
+                            }
+                        }
+                        @{ $agents_on_queue{"$server^$colita"} } = @elementos;
+                    }
+
+                    #Remove cache hit to force find panel buttons to look for new positions
+                    foreach my $kkey ( keys %cache_hit ) {
+                        if ( $kkey =~ /^$canal/ ) {
+                            delete $cache_hit{$kkey};
+                        }
+                    }
+                }
+
+                my $dosoriginal = "";
+
+                foreach $canal (@canaleja) {
+                    log_debug( "",                                       32 ) if DEBUG;
+                    log_debug( "$heading canaleja LOOP; is $canal turn", 32 ) if DEBUG;
+
+                    if ( $dosoriginal ne "" ) {
+                        $dos = $dosoriginal;
+                    }
+
+                    # Try to find the text string in the lang conf hash
+                    if ( $dos =~ m/^\&/ ) {
+                        ( $dos, $dosoriginal, $buttontext ) = translate( $canal, $dos, $dosoriginal, $buttontext );
+                    }
+
+                    if ( !defined( $buttons{"$server^$canal"} ) ) {
+                        log_debug( "$heading \tNo tengo botones para $server^$canal, END FUNCTION", 128 ) if DEBUG;
+                        for ( keys %buttons ) {
+                            log_debug( "$heading \t\tKey $_", 128 ) if DEBUG;
+                        }
+                        next;
+                    }
+
+                    # If its a REGEXP button, we have to ignore all events
+                    # except ocupado*, corto, setlink and unsetlink
+                    if ( $canal =~ /^_/ ) {
+                        log_debug( "$heading canal $canal es un WILD y quehace vale $quehace", 32 ) if DEBUG;
+
+                        if (   $quehace =~ /registr/
+                            || $quehace =~ /reacha/
+                            || $quehace =~ /^inf/ )
+                        {
+                            log_debug( "$heading IGNORO $quehace porque es un wildcard", 32 ) if DEBUG;
+                            next;
+                        }
+
+                        if (   $quehace !~ /^ocupado/
+                            && $quehace !~ /^corto/
+                            && $quehace !~ /^state/
+                            && $quehace !~ /^settext/
+                            && $quehace !~ /^setlabel/
+                            && $quehace !~ /^setlink/
+                            && $quehace !~ /^meetme/
+                            && $quehace !~ /^ring/
+                            && $quehace !~ /^settimer/
+                            && $quehace !~ /^clidnum/
+                            && $quehace !~ /^clidname/
+                            && $quehace !~ /^setstatus/
+                            && $quehace !~ /^unsetlink/ )
+                        {
+                            my ( $nada, $elcontexto ) = split( /\&/, $canal );
+                            if ( !defined($elcontexto) ) { $elcontexto = ""; }
+                            if ( $elcontexto ne "" ) {
+                                $elcontexto = "&" . $elcontexto;
+                            }
+                            my ( $canalsolo, $nrotrunk ) = split( /=/, $canal );
+                            $canal = $canalsolo . "=1" . $elcontexto;
+                            log_debug( "$heading quehace=$quehace, elijo el 1ero del trunk $canal", 32 ) if DEBUG;
+
+                            #next;
+                        }
+
+                        # If we have a wildcard button with changelabel
+                        # and change led_color (the 1 after changelabel)
+                        # change it so to not change the led color.
+                        if ( $quehace =~ /changelabel1/ ) {
+                            log_debug( "$heading el wildcard tiene changelabel1, lo cambio por changelabel0!", 32 )
+                              if DEBUG;
+                            $quehace = "changelabel0";
+                        }
+                    }
+
+                    if ( $canal ne "" ) {
+
+                        if ( $quehace eq 'corto' || $quehace eq 'info' ) {
+
+                            my @linked = erase_all_sessions_from_channel( $canalid, $canal, $server );
+                            push @linked, $canal;
+                            my $btnorinum = "";
+                            foreach my $canaleje (@linked) {
+                                if ( $canaleje =~ /\^/ ) {
+                                    $btnorinum = $buttons{$canaleje};
+                                }
+                                else {
+                                    $btnorinum = $buttons{"$server^$canaleje"};
+                                }
+                                log_debug( "$heading call GEN_LINKED 1", 32 ) if DEBUG;
+                                my $listabotones = generate_linked_buttons_list( $canaleje, $server );
+                                push @respuestas, "$btnorinum|linked|$listabotones";
+                            }
+
+                            delete $datos{$uniqueid};
+                            log_debug( "$heading REMOVING datos { $uniqueid }", 32 ) if DEBUG;
+                        }
+
+                        if ( $quehace eq "setlink" ) {
+                            log_debug( "$heading IF quehace = SETLINK", 32 ) if DEBUG;
+                            my ( $nada1, $contexto1 ) = split( /\&/, $canal );
+                            if ( !defined($contexto1) ) { $contexto1 = ""; }
+                            my $listabotones = "";
+
+                            if ( !defined( @{ $linkbot{"$server^$canal"} } ) ) {
+                                push @{ $linkbot{"$server^$canal"} }, "";
+                                pop @{ $linkbot{"$server^$canal"} };
+                                log_debug( "$heading DEFINIENDO linkbot ($server^$canal)", 32 ) if DEBUG;
+                            }
+
+                            my ( $canal1, $sesion1 ) = separate_session_from_channel($dos);
+                            my @linkbotones = find_panel_buttons( $canal1, $dos, $server );
+                            foreach (@linkbotones) {
+                                my ( $nada2, $contexto2 ) = split( /\&/, $_ );
+                                if ( !defined($contexto2) ) { $contexto2 = ""; }
+                                if ( $contexto1 eq $contexto2 ) {
+                                    push @{ $linkbot{"$server^$canal"} }, $dos;
+                                    log_debug( "$heading AGREGO a linkbot{ $server^$canal} el valor $dos", 32 )
+                                      if DEBUG;
+                                }
+                            }
+
+                            #my %seen = ();
+                            #my @uniq =
+                            #  grep { !$seen{$_}++ } @{ $linkbot{"$server^$canal"} };
+                            #$linkbot{"$server^$canal"} = \@uniq;
+                            my @uniq = unique( @{ $linkbot{"$server^$canal"} } );
+                            $linkbot{"$server^$canal"} = \@uniq;
+
+                            foreach my $valorad (@uniq) {
+                                log_debug( "$heading linkbot ($server^$canal) = $valorad", 32 ) if DEBUG;
+                            }
+                            my $btnorinum = $buttons{"$server^$canal"};
+                            log_debug( "$heading llamo a GENERATE_LINKED", 32 ) if DEBUG;
+                            $listabotones = generate_linked_buttons_list( $canal, $server );
+                            push @respuestas, "$btnorinum|linked|$listabotones";
+                            $botonlinked{$btnorinum} = $listabotones;
+                            log_debug( "$heading linkeado con $listabotones", 32 ) if DEBUG;
+                            log_debug( "$heading ENDIF quehace = SETLINK",    32 ) if DEBUG;
+                        }
+
+                        if ( $quehace eq "unsetlink" ) {
+                            log_debug( "$heading IF quehace = UNSETLINK", 32 ) if DEBUG;
+                            my @final = ();
+                            foreach my $msesion ( @{ $linkbot{"$server^$canal"} } ) {
+                                if ( $msesion ne $dos ) {
+                                    push @final, $msesion;
+                                }
+                            }
+                            $linkbot{"$server^$canal"} = [@final];
+                            log_debug( "$heading ENDIF quehace = UNSETLINK", 32 ) if DEBUG;
+                        }
+
+                        $interno = $buttons{"$server^$canal"};
+                        $interno = "" if ( !defined($interno) );
+
+                        if ( $interno ne "" ) {
+                            if ( defined( $clid_private{$interno} ) && $clid_private{$interno} == 1 ) {
+                                if ( $dos =~ m/\[/ ) {
+                                    $dos =~ s/([^\[]*)?(\[.*\])/$1 \[n\/a\]/g;
+                                }
+                            }
+                        }
+
+                        if ( $quehace eq "queueremoved" ) {
+                            delete $botonvoicemail{$interno};
+                            delete $botonvoicemailcount{$interno};
+                            delete $botonpark{$interno};
+                            delete $botonmeetme{$interno};
+                            delete $botonclid{$interno};
+                            delete $botonlinked{$interno};
+                            delete $botontimer{$interno};
+                            delete $botontimertype{$interno};
+                            delete $botonqueue_count{$interno};
+                            delete $botonqueue{$interno};
+                            delete $botonled{$interno};
+                            push @mensajefinal, "$interno|voicemail|0";
+                        }
+
+                        if ( $interno eq "" ) {
+                            log_debug( "$heading NO HAY INTERNO buttons($server^$canal), ABORTO", 32 ) if DEBUG;
+                            next;
+                        }
+                        log_debug( "$heading EL INTERNO es $interno", 32 ) if DEBUG;
+
+                        if ( !defined( $laststatus{$interno} ) ) {
+                            $laststatus{$interno} = "";
+                        }
+                        if ( !defined( $estadoboton{$interno} ) ) {
+                            $estadoboton{$interno} = "";
+                        }
+
+                        # Mantains hash of arrays with sessions for each button number
+                        # %sesbot{key}=value where:
+                        #
+                        # key is the button number (anything after '@' is the panel context)
+                        # value is an array containing the sessions Eg: SIP/mary-43xZ
+                        #
+                        # The rename manager event also modifies this hash
+                        #
+                        # There are other hashes to maintain a 'view' of the status:
+                        #
+                        # %estadoboton{key}   = shows busy, free or ringing
+                        #
+                        if ( $canalid eq "" || $canalid =~ /zombie/i || $canalid =~ /(.*)-XXXX$/ ) {
+                            log_debug( "$heading ATENCION canalid es $canalid, NO PROCESAR?", 32 ) if DEBUG;
+                        }
+                        else {
+
+                            if ( $quehace eq "corto" ) {
+
+                                log_debug( "$heading CORTO interno $interno canal $canal", 32 ) if DEBUG;
+
+                                delete $botonpark{$interno};
+                                delete $botonmeetme{$interno};
+                                delete $botonclid{$interno};
+                                delete $botonlinked{$interno};
+                                delete $botontimer{$interno};
+                                delete $botontimertype{$interno};
+                                delete $togle_action{$interno};
+                                delete $togle_response{$interno};
+
+                                my $canalbotonreverse = $buttons_reverse{$interno};
+
+                                if ( $canal =~ /^_/ && $ren_wildcard == 1 ) {
+                                    push @respuestas, "$interno|changelabel0|labeloriginal";
+                                }
+
+                                delete $linkbot{$interno};
+                                delete $linkbot{$canalbotonreverse};
+
+                                if ( !defined( $sesbot{$interno} ) ) {
+                                    push @{ $sesbot{$interno} }, "";
+                                    pop @{ $sesbot{$interno} };
+                                }
+                                my $cuantos = @{ $sesbot{$interno} };
+                                if ( $cuantos == 0 ) {
+                                    log_debug( "$heading CORTO y SE DESOCUPO estadoboton($interno) = free, sesbot($interno) esta vacio",
+                                        32 )
+                                      if DEBUG;
+                                    $cambiaron{$interno}   = 1;
+                                    $estadoboton{$interno} = "free";
+                                }
+                                else {
+                                    log_debug( "$heading CORTO y SIGUE OCUPADO estadoboton($interno) = busy, sesbot($interno) tiene algo",
+                                        32 )
+                                      if DEBUG;
+                                    &print_sesbot(3);
+                                    if ( $laststatus{$interno} ne "busy|${buttontext}" ) {
+                                        $cambiaron{$interno} = 1;
+
+                                        push @respuestas, "$interno|state|busy";
+
+                                        # Justin from Fry's has prolems with callerid being cleared while a call is connected
+                                        # from a queue using Local channels, so commnet these out
+                                        #push @respuestas, "$interno|settext|";
+                                        #push @respuestas, "$interno|setstatus|";
+                                        $laststatus{$interno} = "busy|${buttontext}";
+
+                                        log_debug(
+                                            "$heading Y es distinto al ultimo estado $laststatus{$interno} ne $estadoboton{$interno}", 32 )
+                                          if DEBUG;
+                                    }
+                                    $estadoboton{$interno} = "busy|${buttontext}";
+                                }
+
+                            }
+                            else {
+
+                                # quehace no es "corto"
+                                #
+
+                                # MAINTAINS SESBOT HASH
+                                if ( $canalid !~ /^Agent/ ) {
+
+                                    # settimer agent needs to be discarded
+                                    if ( !defined( @{ $sesbot{$interno} } ) ) {
+                                        push @{ $sesbot{$interno} }, "";
+                                        pop @{ $sesbot{$interno} };
+                                    }
+
+                                    push @{ $sesbot{$interno} }, "$canalid";
+
+                                    log_debug( "$heading AGREGO a sesbot($interno) el valor $canalid", 32 ) if DEBUG;
+
+                                    my @uniq = unique( @{ $sesbot{$interno} } );
+                                    $sesbot{$interno} = [@uniq];
+
+                                    foreach my $vavi ( @{ $sesbot{$interno} } ) {
+                                        log_debug( "$heading sesbot($interno) tiene $vavi", 32 ) if DEBUG;
+                                        log_debug( "$heading --------------------",         32 ) if DEBUG;
+                                    }
+                                }
+
+                                if ( $canal =~ /^_/ && $quehace =~ /^ring/ ) {
+                                    log_debug( "$heading TENGO UN WILDCARD ORIGINANDO LLAMADO! $canal $quehace $canalid", 32 )
+                                      if DEBUG;
+                                    if ( $quehace eq "ring" ) {
+
+                                        # $quehace = "ocupado1";
+                                    }
+                                    if ( $ren_wildcard == 1 ) {
+                                        push @respuestas, "$interno|changelabel0|$canalid";
+                                        $botonlabel{$interno} = $canalid;
+                                    }
+                                }
+
+                                if ( $quehace eq "ringing" ) {
+                                    if ( $laststatus{$interno} ne "ringing|${buttontext}" ) {
+                                        $cambiaron{$interno} = 1;
+                                    }
+                                    $estadoboton{$interno} = "ringing|${buttontext}";
+                                    if ( $dos =~ m/(.*)?\[(.*)\].*?/ ) {
+                                        my $clidtext = $2;
+                                        $botonclid{$interno} = $clidtext;
+                                    }
+
+                                    # We dont want a timer when ringing - Local channels
+                                    # generate a previous state and timer
+                                    push @mensajefinal, "$interno|settimer|0\@STOP";
+
+                                }
+                                elsif ( $quehace =~ /^ocupado/ ) {
+                                    if ( $laststatus{$interno} ne "busy|${buttontext}" ) {
+                                        $cambiaron{$interno} = 1;
+                                    }
+                                    $estadoboton{$interno} = "busy|${buttontext}";
+                                }
+                            }
+                        }
+
+                        log_debug( "$heading Continuo proceso...", 32 ) if DEBUG;
+                        if ( $quehace =~ /changelabel/ ) {
+                            log_debug( "$heading quehace = changelabel", 32 ) if DEBUG;
+
+                            # Mantains state of label and led
+                            my $cambia_el_led = $quehace;
+                            $cambia_el_led =~ s/changelabel//g;
+                            my $labdos = "";
+                            if ( $canal =~ /^QUEUEAGENT/ ) {
+                                $labdos = $canalid;
+                                $labdos = substr( $labdos, 0, -5 );
+                                $labdos =~ s/(.*)\&(.*)/$1/g;
+
+                                if ( $labdos =~ m/^Agent/i && $ren_agentname == 1 ) {
+                                    $labdos =~ s/^Agent\///g;
+                                    if ( defined( $agents_name{"$server^$labdos"} ) ) {
+                                        $labdos = $agents_name{"$server^$labdos"};
+                                    }
+                                }
+
+                                $botonled{$interno} = $cambia_el_led;
+                                if ( defined( $botonlabelonly{$interno} ) ) {
+                                    $labdos = $botonlabelonly{$interno};
+                                }
+                                $botonlabel{$interno}     = $dos;
+                                $botonlabelonly{$interno} = $labdos;
+                                $agent_label{$canal}      = $dos;
+                                push @mensajefinal, "$interno|setlabel|$labdos";
+                            }
+                            else {
+                                $botonled{$interno}   = $cambia_el_led;
+                                $botonlabel{$interno} = $dos;
+                                $agent_label{$canal}  = $dos;
+                            }
+
+                        }
+                        if ( $quehace eq "park" ) {
+                            log_debug( "$heading quehace = park", 32 ) if DEBUG;
+                            $dos =~ m/(.*)\((.*)\)/;
+                            my $texto   = $1;
+                            my $timeout = $2;
+                            $timeout = time() + $timeout;
+                            $botonpark{$interno} = "$texto|$timeout";
+                        }
+                        if ( $quehace eq "meetmeuser" ) {
+                            $botonmeetme{$interno} = $dos;
+                        }
+
+                        if ( $quehace eq "infoqstat" ) {
+                            $botonqueue{$interno} = $dos;
+                        }
+                        elsif ( $quehace eq "infoqstat2" ) {
+                            $botonqueue_count{$interno} = $dos;
+                        }
+                        elsif ( $quehace =~ /info/ ) {
+                            my $mcola = $quehace;
+                            $mcola =~ s/^info//g;
+                            push @{ $botonqueuemember{$interno} }, "$mcola|$dos";
+                        }
+
+                        if ( $quehace eq "settext" ) {
+                            $botonclid{$interno} = $dos;
+                            push @respuestas, "$interno|settext|$dos";
+                        }
+                        if ( $quehace eq "setalpha" ) {
+                            $botonalpha{$interno} = $dos;
+                            push @respuestas, "$interno|setalpha|$dos";
+                        }
+                        if ( $quehace eq "flip" ) {
+                            push @respuestas, "$interno|flip|$dos";
+                        }
+                        if ( $quehace eq "setlabel" ) {
+                            if (   $dos ne "."
+                                && $dos ne "original"
+                                && $dos ne "labeloriginal" )
+                            {
+                                $botonsetlabel{$interno} = $dos;
+                                push @respuestas, "$interno|setlabel|$dos";
+                            }
+                        }
+                        if ( $quehace eq "voicemail" ) {
+                            $botonvoicemail{$interno} = $dos;
+                        }
+                        if ( $quehace eq "voicemailcount" ) {
+                            $botonvoicemailcount{$interno} = $dos;
+                        }
+
+                        # linkbot{key} hash mantains the list of linked channels
+                        # for a button. key is the button number, the value is the
+                        # channel-session, like SIP/jose-AxiD
+
+                        if (   ( $quehace !~ /^corto/ )
+                            && ( $quehace !~ /^ocupado/ )
+                            && ( $quehace !~ /link/ ) )
+                        {
+                            $cambiaron{$interno} = 1;
+                            log_debug( "$heading es distinto de corto,ocupado,link pongo cambiaron=1", 32 ) if DEBUG;
+                        }
+
+                        if ( !defined( $sesbot{$interno} ) ) {
+                            push @{ $sesbot{$interno} }, "";
+                            pop @{ $sesbot{$interno} };
+                        }
+
+                        if ( @{ $sesbot{$interno} } > 0 && $quehace eq 'corto' ) {
+                            log_debug( "$heading Still busy...sesbot($interno) is not empty,  ignoring hangup", 32 )
+                              if DEBUG;
+                        }
+                        else {
+
+                            # This block is for the voicemail client
+                            if ( $quehace =~ "^voicemail" ) {
+                                my $canalsincontexto = $canal;
+                                $canalsincontexto =~ s/(.*)&(.*)/$1/g;
+                                push @mensajefinal, "$canalsincontexto\@$canalsincontexto|$quehace|$dos";
+                            }
+
+                            # This block is for the voicemail client, popups
+                            if ( $quehace =~ "^ringing" ) {
+                                my $canalsincontexto = $canal;
+                                $canalsincontexto =~ s/(.*)&(.*)/$1/g;
+                                my $calleridpop = $dos;
+                                $calleridpop =~ s/(.*)\Q[\E(.*)/$2/g;
+                                $calleridpop =~ s/\]//g;
+                                $calleridpop =~ s/\s+//g;
+                                push @mensajefinal, "$canalsincontexto\@$canalsincontexto|$quehace|$calleridpop";
+                            }
+                            if ( $quehace eq "corto" ) {
+                                my $canalsincontexto = $canal;
+                                $canalsincontexto =~ s/(.*)&(.*)/$1/g;
+                                push @mensajefinal, "$canalsincontexto\@$canalsincontexto|$quehace|corto!";
+                            }
+
+                            my $quehace2 = $quehace;
+
+                            if ( $quehace2 eq "ring" ) {
+
+                                #$quehace2 = "ocupado";
+                            }
+
+                            next unless ( $quehace2 ne "setlink" );
+                            next unless ( $quehace2 ne "unsetlink" );
+
+                            log_debug( "$heading sigo quehace quehace2", 32 ) if DEBUG;
+
+                            if ( $quehace2 eq "isagent" && $dos == -1 ) {
+                                log_debug( "$heading quehace2 = isagent", 32 ) if DEBUG;
+                                push @mensajefinal, "$interno|changelabel1|original";
+                                push @mensajefinal, "$interno|settimer|0\@STOP";
+                                push @mensajefinal, "$interno|settext|";
+                                push @mensajefinal, "$interno|corto|";
+                            }
+
+                            if ( $quehace2 eq "agentlogoff" ) {
+
+                                # clear the agent helper hashes. We do it here because we first need to map
+                                log_debug( "$heading quehace2 = agentlogoff", 32 ) if DEBUG;
+                                my $canalag = $canalid;
+                                $canalag = substr( $canalag, 0, -5 );
+                                if ( $canalag !~ /^Agent/ ) {
+                                    $canalag = "Agent/" . $canalag;
+                                }
+                                print_agents();
+
+                                my %temp_channel_to_agent = %channel_to_agent;
+                                while ( my ( $key, $val ) = each(%temp_channel_to_agent) ) {
+                                    if ( $val eq $canalag ) {
+                                        delete $channel_to_agent{$key};
+                                        log_debug( "$heading borro channel_to_agent($key)", 64 ) if DEBUG;
+                                    }
+                                }
+                                undef %temp_channel_to_agent;
+
+                                if ( defined( $agent_to_channel{"$server^$canalag"} ) ) {
+                                    delete $agent_to_channel{"$server^$canalag"};
+                                    log_debug( "$heading borro agent_to_channel($server^$canalag)", 64 ) if DEBUG;
+                                }
+
+                                $quehace2 = "corto";
+                                delete $estadoboton{$interno};
+                                delete $botonpark{$interno};
+                                delete $botonmeetme{$interno};
+                                delete $botonclid{$interno};
+                                delete $botonlinked{$interno};
+                                delete $botontimer{$interno};
+                                delete $botontimertype{$interno};
+                            }
+
+                            if ( $quehace2 !~ /isagent/ && $quehace2 !~ /^agentlogoff/ ) {
+                                log_debug( "$heading pushing respuestas $interno|$quehace2|$dos", 32 ) if DEBUG;
+
+                                # Discard events that we dont want to send
+                                # to flash clients
+                                # "isagent". "agentlogoff"
+                                # everything else is pushed
+                                push @respuestas, "$interno|$quehace2|$dos";
+                            }
+
+                            if ( $quehace2 =~ /ocupado/ ) {
+                                if ( $dos =~ m/(.*)?\[(.*)\].*?/ ) {
+                                    my $clidtext = $2;
+                                    $botonclid{$interno} = $clidtext;
+                                }
+
+                                #push @mensajefinal, "$interno|state|busy";
+                                push @mensajefinal, "$interno|settimer|0\@UP";
+                            }
+                            if ( $quehace2 eq "settimer" ) {
+                                my $tiempo = $dos;
+                                my $nada   = "";
+                                if ( $tiempo =~ /\@/ ) {
+                                    ( $tiempo, $nada ) = split( /\@/, $tiempo );
+                                }
+                                if ( $nada ne "" ) {
+                                    $botontimertype{$interno} = $nada;
+                                    $nada = "\@" . $nada;
+                                }
+                                $botontimer{$interno} = time() - $tiempo;
+                                push @mensajefinal, "$interno|settimer|$tiempo$nada";
+                            }
+
+                            if ( $quehace eq "ring" || $quehace eq "ocupado1" || $quehace eq "ocupado9" ) {
+                                push @mensajefinal, "$interno|settimer|0\@UP";
+                                if ( !defined( $botontimer{$interno} ) ) {
+                                    $botontimer{$interno}     = time();
+                                    $botontimertype{$interno} = "UP";
+                                }
+                            }
+                            if ( $quehace2 eq "ring" ) {
+                                push @mensajefinal, "$interno|state|busy";
+
+                                #push @mensajefinal, "$interno|settext|$dos";
+                            }
+                            if ( $quehace2 =~ /corto/ ) {
+                                log_debug( "$heading quehace2 corto", 32 ) if DEBUG;
+
+                                my $canalsincontexto = $canal;
+                                $canalsincontexto =~ s/(.*)&(.*)/$1/g;
+                                $canalsincontexto =~ s/^AGENT/Agent/g;
+                                if (
+                                    (
+                                           exists( $agent_to_channel{"$server^$canalsincontexto"} )
+                                        || exists( $channel_to_agent{"$server^$canalsincontexto"} )
+                                        || exists( $is_agent{"$server^$canalsincontexto"} )
+
+                                        #  || ( $canalsincontexto =~ /^QUEUEAGENT/i )
+                                    )
+                                    && $agent_status == 1
+                                  )
+                                {
+                                    my $valip    = "";
+                                    my $iniagent = "";
+                                    if ( defined( $agent_to_channel{"$server^$canalsincontexto"} ) ) {
+                                        $iniagent = $agent_to_channel{"$server^$canalsincontexto"};
+                                    }
+                                    elsif ( defined( $channel_to_agent{"$server^$canalsincontexto"} ) ) {
+                                        $iniagent = $channel_to_agent{"$server^$canalsincontexto"};
+                                    }
+                                    log_debug( "$heading quehace2 corto y es agente, pushing settimer y settext to idle", 1 ) if DEBUG;
+                                    $botontimer{$interno}     = time();
+                                    $botontimertype{$interno} = "IDLE";
+                                    push @mensajefinal, "$interno|settimer|0\@IDLE";
+                                    if ( exists( $boton_ip{"$iniagent-XXXX"} ) ) {
+                                        $valip = $boton_ip{"$iniagent-XXXX"};
+                                    }
+                                    if ( $valip eq "" ) { $valip = "Idle"; }
+                                    $botonclid{$interno} = $valip;
+                                    push @mensajefinal, "$interno|settext|$valip";
+                                }
+                                else {
+                                    my $valip = "";
+                                    log_debug( "$heading quehace2 corto, no es agente, pongo timer en cero", 1 ) if DEBUG;
+                                    print_agents();
+
+                                    push @mensajefinal, "$interno|settimer|0\@STOP";
+                                    if ( defined( $boton_ip{"$canal-XXXX"} ) ) {
+                                        $valip = $boton_ip{"$canal-XXXX"};
+                                        push @mensajefinal, "$interno|settext|$valip";
+                                        $botonclid{$interno} = $valip;
+                                    }
+                                    else {
+                                        $botonclid{$interno} = "";
+                                    }
+
+                                    if ( defined( $botonalpha{$interno} ) ) {
+                                        if ( $botonalpha{$interno} ne "" ) {
+                                            push @mensajefinal, "$interno|setalpha|$botonalpha{$interno}";
+                                        }
+                                    }
+                                }
+                            }
+
+                            if ( $quehace eq "registrado" ) {
+                                if ( defined( $botonalpha{$interno} ) ) {
+                                    if ( $botonalpha{$interno} ne "" ) {
+                                        push @mensajefinal, "$interno|setalpha|50";
+                                    }
+                                    else {
+                                        push @mensajefinal, "$interno|setalpha|100";
+                                    }
+                                }
+                            }
+
+                            if ( $quehace eq "registrado" || $quehace eq "noregistrado" || $quehace eq "unreachable" ) {
+                                $botonregistrado{$interno} = "$quehace|$dos";
+                            }
+
+                            log_debug( "$heading Agrego mensaje final $interno|$quehace2|$dos", 32 ) if DEBUG;
+
+                            #if (defined($mensajefinal) && $interno ne "")
+                            $cuantas = @mensajefinal;
+                            if ( $cuantas > 0 && $interno ne "" ) {
+                                if ( exists $cambiaron{$interno} ) {
+
+                                    log_debug( "$heading Existe cambiaron($interno) = $cambiaron{$interno}", 32 )
+                                      if DEBUG;
+
+                                    #push(@respuestas, $mensajefinal);
+                                    foreach (@mensajefinal) {
+                                        push @respuestas, $_;
+                                    }
+                                }
+                                else {
+
+                                    log_debug( "$heading No existe cambiaron($interno)", 32 ) if DEBUG;
+                                    foreach (@mensajefinal) {
+
+                                        # If the last status was not modified, avoid sending info
+                                        # push @respuestas, $_;
+                                    }
+                                }
+                                if ( $todo ne "" ) {
+                                    my $otromensajefinal = "$interno|info|$todo";
+                                    push( @respuestas, $otromensajefinal );
+                                }
+                            }
+                        }
+
+                        $laststatus{$interno} = $estadoboton{$interno};
+                    }
+                    else {    # endif canal distinto de nada
+                        log_debug( "$heading There is no command defined", 32 ) if DEBUG;
+                    }
+                }
+            }
+        }
+    }
+
+    @respuestas = unique(@respuestas);
+    $cuantas    = $#respuestas + 1;
+    log_debug( "$heading end, return $cuantas", 16 ) if DEBUG;
+    foreach my $valor (@respuestas) {
+        log_debug( "$heading END SUB: returns $valor", 32 ) if DEBUG;
+    }
+    $tab = substr( $tab, 0, -1 ) if DEBUG;
+    return @respuestas;
+}
+
+sub translate {
+
+    my $canal       = shift;
+    my $dos         = shift;
+    my $dosoriginal = shift;
+    my $buttontext  = shift;
+
+    my @return;
+
+    # Try to find the text string in the lang conf hash
+    my $ctx = "";
+    if ( $canal =~ m/.*\&(.*)/ ) {
+        $ctx = $1;
+    }
+    else {
+        $ctx = "DEFAULT";
+    }
+    my ( $partstring, $varsub ) = split( /,/, $dos, 2 );
+    $partstring =~ s/&(.*)/$1/g;
+    if ( !defined($varsub) ) { $varsub = ""; }
+    my $traduc = $language->{$ctx}{$partstring};
+    if ( $varsub =~ m/.*&/ ) {
+
+        # Horrible hack, if variable ends in &, set the text
+        # between brackets so it will be displayed as a whole in the
+        # button's clid area
+        $varsub = substr( $varsub, 0, -1 );
+        my ( $var1, $var2 ) = split( /,/, $varsub );
+        $traduc =~ s/\$1/$var1/g if defined $var1;
+        $traduc =~ s/\$2/$var2/g if defined $var2;
+        $traduc =~ s/\$1//g;
+        $traduc =~ s/\$2//g;
+        $dosoriginal = $dos;
+        $dos         = "[" . $traduc . "]";
+        $buttontext  = $dos;
+    }
+    else {
+        my ( $var1, $var2 ) = split( /,/, $varsub );
+        $traduc =~ s/\$1/$var1/g if defined $var1 && $var1 ne "";
+        $traduc =~ s/\$2/$var2/g if defined $var2 && $var1 ne "";
+        $traduc =~ s/\$1//g;
+        $traduc =~ s/\$2//g;
+        $dosoriginal = $dos;
+        $dos         = $traduc;
+    }
+
+    push @return, $dos;
+    push @return, $dosoriginal;
+    push @return, $buttontext;
+
+    return @return;
+}
+
+sub nonblock {
+    my $socket = shift;
+    my $flags;
+
+    $flags = fcntl( $socket, F_GETFL, 0 )
+      or die "Can't get flags for socket: $!\n";
+    fcntl( $socket, F_SETFL, $flags | O_NONBLOCK )
+      or die "Can't make socket nonblocking: $!\n";
+}
+
+sub clean_inmemory_state_for_server {
+    my $server = shift;
+    my @botones_a_limpiar;
+    log_debug( "CLEAN_INMEMORY from server $server)", 16 ) if DEBUG;
+    foreach ( keys(%buttons) ) {
+        my $btn_server = $_;
+        $btn_server =~ s/^(\d+)\^.*/$1/g;
+        if ( $btn_server eq $server ) {
+            push @botones_a_limpiar, $buttons{$_};
+        }
+    }
+
+    foreach (@botones_a_limpiar) {
+        delete $estadoboton{$_};
+        delete $botonled{$_};
+        delete $botonlabelonly{$_};
+        delete $botonvoicemail{$_};
+        delete $botonvoicemailcount{$_};
+        delete $botonalpha{$_};
+        delete $botonqueue{$_};
+        delete $botonqueuemember{$_};
+        delete $botonqueue_count{$_};
+        delete $botonpark{$_};
+    }
+}
+
+sub manager_connection {
+    my $host       = "";
+    my $user       = "";
+    my $pass       = "";
+    my $heading    = "** MANAGER CONNECTION";
+    my $temphandle = "";
+    my $contador   = 0;
+    my $port       = "5038";
+
+    foreach my $mhost (@manager_host) {
+        if ( defined($mhost) ) {
+            $host = $mhost;
+            $user = $manager_user[$contador];
+            $pass = $manager_secret[$contador];
+            $port = $manager_port[$contador] if defined( $manager_port[$contador] );
+
+            if ( defined( $manager_conectado[$contador] ) ) {
+                if ( $manager_conectado[$contador] == 1 ) {
+                    $contador++;
+                    next;
+                }
+            }
+
+            log_debug( "$heading Connecting to $mhost:$port (Server $contador)", 1 ) if DEBUG;
+
+            $p[$contador] = new IO::Socket::INET->new(
+                PeerAddr => $manager_host[$contador],
+                PeerPort => $port,
+                Proto    => "tcp",
+                Type     => SOCK_STREAM
+            );
+
+            if ( !$p[$contador] ) {
+                log_debug( "$heading Couldn't connect to $mhost:$port (Server $contador)", 1 ) if DEBUG;
+                $p[$contador]                    = "";
+                $manager_conectado[$contador]    = 0;
+                $manager_desconectado{$contador} = time();
+                $contador++;
+                next;
+            }
+            else {
+                log_debug( "$heading Connected  to $mhost:$port (Server $contador)", 1 ) if DEBUG;
+                $manager_conectado[$contador] = 1;
+                if ( defined( $manager_desconectado{$contador} ) ) {
+                    delete $manager_desconectado{$contador};
+                }
+                $p[$contador]->autoflush(1);
+                $ip_addy{ $p[$contador] } = peerinfo( $p[$contador], 1 );
+                clean_inmemory_state_for_server($contador);
+            }
+
+            my $mask = "";
+            if ( defined( $event_mask[$contador] ) ) {
+                $mask_hash{ $p[$contador] } = $event_mask[$contador];
+            }
+
+            $manager_socket{ $p[$contador] } = $manager_host[$contador] . "|" . $manager_user[$contador] . "|" . $manager_secret[$contador];
+            my $command = "";
+
+            # If using astmanproxy, override authentication
+            if ( $astmanproxy_host ne "" ) {
+                $autenticado{ $p[$contador] } = 1;
+                send_eventmask( $p[$contador] );
+                send_initial_status( $p[$contador] );
+            }
+            else {
+                if ( $auth_md5 == 1 ) {
+                    $command = "Action: Challenge\r\n";
+                    $command .= "AuthType: MD5\r\n\r\n";
+                }
+                else {
+                    $command = "Action: Login\r\n";
+                    $command .= "Username: $user\r\n";
+                    $command .= "Secret: $pass\r\n\r\n";
+                }
+                send_command_to_manager( $command, $p[$contador], 1 );
+            }
+
+        }
+        $contador++;
+    }
+
+    # Adds AMI handles into IO::Select
+    foreach (@p) {
+        if ( defined($_) ) {
+            $O->add($_);
+        }
+    }
+
+}
+
+sub send_eventmask {
+    my $socket = shift;
+    if ( defined( $mask_hash{$socket} ) ) {
+        my $comando = "Action: Events\r\n";
+        $comando .= "EventMask: " . $mask_hash{$socket} . "\r\n\r\n";
+        send_command_to_manager( $comando, $socket );
+    }
+}
+
+sub clean_socket {
+    my $socket  = shift;
+    my $heading = "** CLEAN SOCKET ";
+    log_debug( "$heading connection lost removing socket $socket", 1 ) if DEBUG;
+
+    $O->remove($socket);
+    $socket->close;
+    delete $ip_addy{$socket};
+    if ( exists( $manager_socket{$socket} ) ) {
+        delete $manager_queue{$socket};
+
+        # The closed connections belong to an asterisk manager port
+        my @partes  = split( /\|/, $manager_socket{$socket} );
+        my @pp      = ();
+        my $counter = 0;
+        foreach my $cual (@p) {
+            if ( defined($cual) ) {
+                if ( $cual eq $_ ) {
+                    log_debug( "$heading Connection lost to server $counter", 1 ) if DEBUG;
+                    $manager_conectado[$counter] = 0;
+                    $manager_desconectado{$counter} = time();
+                    delete $autenticado{$_};
+                    push @pp, "";
+                }
+                else {
+                    log_debug( "$heading still connected to $ip_addy{$cual}", 16 ) if DEBUG;
+                    push @pp, $cual;
+                }
+            }
+            $counter++;
+        }
+        @p = @pp;
+    }
+    else {
+
+        # The closed socket was from a client
+        log_debug( "$heading flash client connection lost", 1 ) if DEBUG;
+        delete $client_queue{$socket};
+        delete $client_queue_nocrypt{$socket};
+        my $cualborrar = $socket;
+        my @temp = grep( !/\Q$cualborrar\E/, @flash_clients );
+        @flash_clients = @temp;
+        delete $keys_socket{$socket};
+        &print_clients();
+    }
+}
+
+collect_includes( "op_buttons.cfg", "buttons" );
+collect_includes( "op_style.cfg",   "style" );
+read_buttons_config();
+read_server_config();
+read_language_config();
+read_astdb_config();
+genera_config();
+
+# Tries to open the listening socket
+$m = new IO::Socket::INET( Listen => 1, LocalAddr => $listen_addr, LocalPort => $listen_port, ReuseAddr => 1, Blocking => 0 )
+  or die "\nCan't listen to port $listen_port\n";
+$O = new IO::Select();
+$O->add($m);
+
+# Connects to the asterisk boxes
+manager_connection();
+
+$/ = "\0";
+
+# MAIN
+# Endless loop
+while (1) {
+    my $heading = "** MAIN";
+
+    # Attempt reconnections to dead asterisk servers  every 10 seconds
+    if (%manager_desconectado) {
+        while ( my ( $key, $val ) = each(%manager_desconectado) ) {
+            my $seconds_to_go = ( time() - $val ) % 10;
+            if ( $seconds_to_go == 9 ) {
+                manager_connection();
+            }
+        }
+    }
+
+    while ( @S = $O->can_read(0.1) )    # profile
+    {
+        foreach (@S) {
+            my $handle = $_;
+
+            if ( $_ == $m ) {
+
+                # New client connection
+                my $C = $m->accept;
+                $ip_addy{$C} = peerinfo( $C, 1 );
+                log_debug( "$heading New client connection $ip_addy{$C}", 1 ) if DEBUG;
+                push( @flash_clients, $C );
+                $O->add($C);
+                nonblock($C);
+            }
+            else {
+
+                # Its not a new client connection
+                my %i;
+                my $R;
+                $R = sysread( $_, $i{$handle}, BYTES_TO_READ );    # profile
+                if ( defined($R) && $R == 0 ) {
+
+                    # Could not read.. close the socket
+                    log_debug( "$heading closing $ip_addy{$_}", 1 ) if DEBUG;
+                    clean_socket($_);
+                }
+                else {
+                    $bloque_completo{$handle} = ""
+                      if ( !defined( $bloque_completo{$handle} ) );
+                    $buferbloque{$handle} = ""
+                      if ( !defined( $buferbloque{$handle} ) );
+                    if ( $buferbloque{$handle} ne "" ) {
+                        $bloque_completo{$handle} = $buferbloque{$handle};
+                        $buferbloque{$handle}     = "";
+                    }
+                    $bloque_completo{$handle} .= $i{$handle};
+
+                    next
+                      if ( $bloque_completo{$handle} !~ /\r\n\r\n/
+                        && $bloque_completo{$handle} !~ /\0/ );
+
+                    # From here we have one or more Event block
+                    # to process. The last one might be incomplete
+                    # so we have to buffer it for the next can_read
+
+                    my @event_blocks = ();
+                    if ( $bloque_completo{$handle} =~ /\0/ ) {
+                        $bloque_completo{$handle} =~ s/\0/\$\$\$\0/g;
+                        @event_blocks = split /\0/, $bloque_completo{$handle};
+                    }
+                    else {
+                        $bloque_completo{$handle} =~ s/\r\n\r\n/\$\$\$\r\n\r\n/g;
+                        @event_blocks = split /\r\n\r\n/, $bloque_completo{$handle};
+                    }
+
+                    foreach my $block (@event_blocks) {
+
+                        if ( $block !~ /\$\$\$/ ) {
+
+                            # if there is no end, buffer the block
+                            $buferbloque{$handle} = $block;
+                        }
+                        else {
+                            $block =~ s/\$\$\$/\n/g;
+
+                            # process an individual manager block stored in $block
+                            if ( exists( $manager_socket{$handle} ) ) {
+                                my @part = split( /\|/, $manager_socket{$handle} );
+                                log_debug( "$heading End of block from $part[0]", 16 ) if DEBUG;
+                            }
+
+                            $bloque_final = $block;
+                            $bloque_final =~ s/([^\r])\n/$1\r\n/g;    # Reemplaza \n solo por \r\n
+                            $bloque_final =~ s/\r\n\r\n/\r\n/g;
+                            $bloque_completo{$handle} = "";
+
+                            ##################################################
+                            # If we have a Server header, asume this is comming from astmanproxy
+                            # and replace the server address to the server index number that FOP uses
+                            # and that is specified in op_server.cfg file with the astmanproxy_server
+                            # keyword
+                            if ( $bloque_final =~ /.*?^Server: .*$/xms ) {
+                                $astmanproxy_server = $bloque_final;
+                                $astmanproxy_server =~ s/.*?^Server: \s ([\.\w]*) .*? \z/$1/xms;
+                                my $que_manager = 0;
+                                foreach my $address (@astmanproxy_servers) {
+                                    if ( $address eq $astmanproxy_server ) {
+                                        $bloque_final =~ s/(.*?^Server: \s)([\.\w]*)( .*? \z)/${1}${que_manager}${3}/xms;
+                                    }
+                                    $que_manager++;
+                                }
+                            }
+                            else {
+
+                                # Add the asterisk server number as a part of the event block
+                                my $que_manager = 0;
+                                foreach my $handle_manager_connected (@p) {
+                                    if ( $handle_manager_connected eq $handle ) {
+
+                                        $bloque_final = $bloque_final . "Server: $que_manager";
+                                    }
+                                    $que_manager++;
+                                }
+                            }
+
+                            ####################################################
+                            # This block is just for logging in the event
+                            # to stdout
+                            if ( ( $debuglevel & 1 ) && DEBUG ) {
+                                my @lineas = split( "\r\n", $bloque_final );
+                                foreach my $linea (@lineas) {
+                                    if ( exists( $manager_socket{$handle} ) ) {
+                                        my $linea_formato = sprintf( "%-15s <- %s", $ip_addy{$handle}, $linea );
+                                        log_debug( $linea_formato, 1 ) if DEBUG;
+                                    }
+                                }
+                                $global_verbose = 'separator';
+                            }
+                            ##################################################
+
+                            foreach my $C ( $O->handles ) {
+                                if ( $C == $handle ) {
+                                    log_debug( "$heading AST event received...", 16 ) if DEBUG;
+
+                                    # Asterisk event received
+                                    # Read the info and arrange it into blocks
+                                    # for processing in 'procesa_bloque'
+                                    if (   $bloque_final =~ /Event:/
+                                        || $bloque_final =~ /Message: Mailbox/
+                                        || $bloque_final =~ /Message: Timeout/ )
+                                    {
+                                        log_debug( "$heading There's an 'Event' in the event block", 32 ) if DEBUG;
+                                        my @lineas = split( /\r\n/, $bloque_final );
+                                        @bloque = ();
+                                        my $block_count = -1;
+                                        foreach my $p (@lineas) {
+                                            my $my_event = "";
+                                            if ( $p =~ /Event:/ ) {
+                                                $block_count++;
+                                                log_debug( "$heading Event detected block_count = $block_count", 128 )
+                                                  if DEBUG;
+                                            }
+                                            elsif ( $p =~ /Message: Mailbox/ ) {
+                                                $my_event = "MessageWaiting";    # Fake event
+                                                $block_count++;
+                                                log_debug( "$heading Event mailbox detected block_count = $block_count", 128 )
+                                                  if DEBUG;
+                                            }
+                                            my ( $atributo, $valor ) = split( /: /, $p, 2 );
+                                            if ( defined $atributo && $atributo ne "" ) {
+                                                if ( $my_event ne "" ) {
+                                                    $atributo = "Event";
+                                                    $valor    = $my_event;
+                                                    log_debug( "$heading Fake event generated $atributo=$valor", 128 )
+                                                      if DEBUG;
+                                                }
+                                                if ( length($atributo) >= 1 ) {
+                                                    if ( $block_count < 0 ) {
+                                                        $block_count = 0;
+                                                    }
+                                                    $bloque[$block_count]{"$atributo"} = $valor;
+                                                }
+                                            }
+                                        }
+                                        log_debug( "$heading There are $block_count blocks for processing", 128 )
+                                          if DEBUG;
+                                        @respuestas = ();
+                                        log_debug( "$heading Answer block cleared", 32 ) if DEBUG;
+                                        @respuestas = digest_event_block( \@bloque, "real", $C, $astmanproxy_server );
+                                        @masrespuestas = ();
+                                        while (@fake_bloque) {
+                                            my @respi = digest_event_block( \@fake_bloque, "fake", $C, $astmanproxy_server );
+                                            foreach (@respi) {
+                                                push @masrespuestas, $_;
+                                            }
+                                        }
+                                    }
+                                    elsif ( $bloque_final =~ /--END COMMAND--/ ) {
+                                        log_debug( "$heading There's an 'END' in the event block", 32 ) if DEBUG;
+                                        $todo .= $bloque_final;
+                                        process_cli_command($todo);
+                                        my $cuantos = @bloque;
+                                        log_debug( "$heading There are $cuantos blocks for processing", 128 ) if DEBUG;
+                                        @respuestas = digest_event_block( \@bloque, "real", $C, $astmanproxy_server );
+                                        @masrespuestas = ();
+                                        while (@fake_bloque) {
+                                            my @respi = digest_event_block( \@fake_bloque, "fake", $C, $astmanproxy_server );
+                                            foreach (@respi) {
+                                                push @masrespuestas, $_;
+                                            }
+                                        }
+                                        $todo = "";
+                                    }
+                                    elsif ( $bloque_final =~ /<msg/ ) {
+                                        $bloque_final =~ s/\n//g;
+                                        log_debug( "$heading Processing command received from flash clients...", 32 )
+                                          if DEBUG;
+                                        process_flash_command( $bloque_final, $_ );
+                                        @respuestas   = ();
+                                        $bloque_final = "";
+                                        $todo         = "";
+                                    }
+                                    elsif ( $bloque_final =~ /Challenge:/ ) {
+                                        my @lineas = split( /\r\n/, $bloque_final );
+                                        foreach my $p (@lineas) {
+                                            if ( $p =~ /Challenge:/ ) {
+                                                $p =~ s/^Challenge: (.*)/$1/g;
+                                                $md5challenge = $p;
+                                            }
+                                        }
+                                        manager_login_md5( $md5challenge, $C );
+                                    }
+                                    elsif ( $bloque_final =~ /Message: Authentication ac/i ) {
+
+                                        # Authentication Accepted, enable sending commands
+                                        $autenticado{$C} = 1;
+                                        send_eventmask($C);
+                                        send_initial_status($C);
+                                    }
+                                    else {
+                                        log_debug( "$heading No 'Event' nor 'End'. Erasing block...", 32 ) if DEBUG;
+
+                                        # No Event in the block. Lets clear it up...
+                                        @bloque = ();
+                                        $todo .= $bloque_final;
+                                    }
+                                }
+                                else {
+
+                                    # Send messages to Flash clients
+                                    @respuestas    = ( @respuestas, @masrespuestas );
+                                    @masrespuestas = ();
+                                    @respuestas    = unique(@respuestas);
+
+                                    if ( !defined( $autenticado{$C} ) ) {    # try to exclude manager connections
+                                        foreach my $valor (@respuestas) {
+                                            if ( defined( $flash_contexto{$C} ) ) {
+                                                send_status_to_flash( $C, $valor, 0 );
+                                            }
+                                        }                                    # end foreach respuestas
+                                    }
+                                }
+                            }    # end foreach handles
+
+                        }
+                    }
+
+                }    # end else the handle is readable
+            }    # end else for active connections
+        }    # end foreach @S -> can read
+    }    # while can read
+
+    foreach my $sacket ( $O->can_write(0.1) )    # profile
+    {
+        if ( defined( $client_queue{$sacket} ) ) {
+
+            # Loop through command buffer to send to  clients
+            while ( my $comd = shift @{ $client_queue{$sacket} } ) {
+                my $tolog = shift @{ $client_queue_nocrypt{$sacket} };
+                my $ret = actual_syswrite( $sacket, $comd, "isclient", $tolog );
+                if ( $ret == -1 ) {
+                    log_debug( "Partial syswrite, buffering for client $ip_addy{$sacket}", 1 ) if DEBUG;
+                    last;
+                }
+
+            }
+        }
+        if ( defined( $manager_queue{$sacket} ) ) {
+
+            # Loop through command buffer to send to managers
+            while ( my $comd = shift @{ $manager_queue{$sacket} } ) {
+                my $cuantos = @{ $manager_queue{$sacket} };
+
+                my $ret = actual_syswrite( $sacket, $comd, "ismanager", $comd );
+                if ( $ret == -1 ) {
+                    log_debug( "Partial syswrite, buffering for server $ip_addy{$sacket}", 1 ) if DEBUG;
+                    last;
+                }
+
+            }
+        }
+    }
+}    # endless loop
+
+sub actual_syswrite {
+    my ( $socket, $encriptadofinal, $whom, $log ) = @_;
+    my $largo = length($encriptadofinal);
+    my $res   = syswrite( $socket, $encriptadofinal, $largo );
+
+    if ( defined $res && $res > 0 ) {
+        if ( $res != $largo ) {
+
+            # Could not write the whole command, buffer
+            # the rest for later
+            my $offset = $largo - $res;
+            $offset = $offset * -1;
+            my $buf = substr( $encriptadofinal, $offset );
+            unshift( @{ $client_queue{$socket} },         $buf );
+            unshift( @{ $client_queue_nocrypt{$socket} }, $log );
+            log_debug( "Partial syswrite, len $res but $largo written", 1 ) if DEBUG;
+
+            my $cuantos = @{ $client_queue{$socket} };
+            if ( $cuantos > 200 ) {
+                &clean_socket($socket);
+            }
+            return -1;
+        }
+        else {
+
+            # Write succesfull, log to stdout
+            $log = substr( $log, 0, -1 );
+            if ( $debuglevel > 0 ) {
+                if ( $whom eq "isclient" ) {
+                    my $linea_formato = sprintf( "%-15s => %s", $ip_addy{$socket}, $log );
+                    log_debug( "$linea_formato", 8 ) if DEBUG;
+                    $global_verbose = "separador";
+                }
+                else {
+                    $log =~ s/\r//g;
+                    $log =~ s/\n//g;
+                    if ( $log ne "" ) {
+                        my $linea_formato = sprintf( "%-15s -> %s", $ip_addy{$socket}, $log );
+                        log_debug( "$linea_formato", 2 ) if DEBUG;
+                    }
+                    else {
+                        $global_verbose = "separador";
+                    }
+                }
+            }
+        }
+    }
+    elsif ( $! == EWOULDBLOCK ) {
+
+        # would block: not an error
+        # handle blocking, by trying again later
+        log_debug( "Write wouldblock, buffering for $ip_addy{$socket}", 1 ) if DEBUG;
+        push( @{ $client_queue{$socket} },         $encriptadofinal );
+        push( @{ $client_queue_nocrypt{$socket} }, $log );
+        my $cuantos = @{ $client_queue{$socket} };
+        if ( $cuantos > 200 ) {
+            &clean_socket($socket);
+        }
+    }
+    else {
+        log_debug( "Write error on $ip_addy{$socket}", 1 ) if DEBUG;
+        &clean_socket($socket);
+    }
+    return 0;
+}
+
+sub get_transfer_channel {
+
+    my $origin_channel = shift;
+    my $datosflash     = shift;
+
+    my @cuales_transferir = ();
+
+    my $local_reverse = $reverse_transfer;
+
+    if ( $origin_channel =~ m/^PARK/i || $origin_channel =~ m/^QUEUE/i || $origin_channel =~ m/^\d/ ) {
+        $local_reverse = 0;
+        log_debug("** GET TRANSFER Disable reverse transfer for $origin_channel!",16) if DEBUG;
+    }
+
+    if ( $local_reverse == 1 ) {
+        log_debug( "** !! REVERSE TRANSFER", 16 ) if DEBUG;
+
+        # Transfer the session from the *other* button
+        @cuales_transferir = extraer_todos_los_enlaces_de_un_canal( $origin_channel, $button_server{$datosflash} );
+		if (@cuales_transferir == 0) {
+        	log_debug( "** !! REVERSE TRANSFER No reverse available, using regular sesbot", 16 ) if DEBUG;
+        	if ( @{ $sesbot{$datosflash} } ) {
+            	@cuales_transferir = @{ $sesbot{$datosflash} };
+	        }
+		}
+    }
+    else {
+        log_debug( "** !! NORMAL TRANSFER", 16 ) if DEBUG;
+
+        # Transfer the session from the same button
+        if ( @{ $sesbot{$datosflash} } ) {
+            @cuales_transferir = @{ $sesbot{$datosflash} };
+        }
+        else {
+            @cuales_transferir = ();
+        }
+    }
+
+    return @cuales_transferir;
+
+}
+
+sub process_flash_command {
+
+    # This function process a command received from a Flash client
+    # Including request of transfers, hangups, etc
+    my $comando        = shift;
+    my $socket         = shift;
+    my $datosflash     = "";
+    my $accion         = "";
+    my $password       = "";
+    my $valor          = "";
+    my $origin_channel = "";
+    my $origin_server  = "";
+    my $canal_destino  = "";
+    my $destin_server  = "";
+    my $contexto       = "";
+    my $btn_destino    = "0";
+    my $extension_destino;
+    my $origin_context = "";
+    my $canal;
+    my $nroboton;
+    my $destino;
+    my $sesion;
+    my @partes;
+    my $ultimo;
+    my $clid;
+    my $myclave;
+    my $md5clave;
+    my @pedazos;
+    my $panelcontext;
+    my $auto_conf_exten;
+    my $conference_context;
+    my $bargerooms;
+    my $found_room;
+    my $servidor_dial = "";
+    my $heading       = "-- PROCESS_FLASH_COMMAND";
+    my $calltimeout   = 0;
+
+    my $linea_formato = sprintf( "%-15s <= %s", $ip_addy{$socket}, $comando );
+    log_debug( "$linea_formato", 4 ) if DEBUG;
+
+    $tab = $tab . "\t" if DEBUG;
+
+    $comando =~ s/<msg data=\"(.*)\"\s?\/>/$1/g;    # Removes XML markup
+    ( $datosflash, $accion, $password ) = split( /\|/, $comando );
+    chop $password;
+    log_debug( "$heading datosflash $datosflash accion $accion password $password", 16 ) if DEBUG;
+
+    if ( $accion =~ /\+/ ) {
+
+        # The command has a timeout for the call
+        $accion =~ s/(.*)\+(.*)\+(.*)/$1$3/g;
+        $calltimeout = $2;
+    }
+
+    my $elementname = $datosflash;
+    $elementname =~ s/(.*)\.(.*)/$2/g;
+    $elementname =~ s/([^\@]*)(.*)/$1/g;
+    $elementname =~ s/\d//g;
+
+    if ( $datosflash =~ /_level0\.casilla/ ) {
+        $datosflash =~ s/_level0\.casilla(\d+)/$1/g;
+    }
+    if ( $datosflash =~ /_level0\.rectangulo/ ) {
+        $datosflash =~ s/_level0\.rectangulo(\d+).*/$1/g;
+    }
+
+    log_debug( "$heading datosflash before context $datosflash", 128 ) if DEBUG;
+
+    # Appends context if defined because my crappy regexp only extracts digits
+    # FIXME make a regexp that extract digits and digits at context
+    if ( defined( $flash_contexto{$socket} ) ) {
+        if ( $flash_contexto{$socket} ne "" ) {
+            if ( $datosflash =~ /\@/ ) {
+
+                # No need to append context
+            }
+            else {
+                $datosflash .= "\@" . $flash_contexto{$socket};
+            }
+        }
+    }
+
+    log_debug( "$heading datosflash after context $datosflash", 128 ) if DEBUG;
+
+    undef $origin_channel;
+
+    # Flash clients send a "contexto" command on connect indicating
+    # the panel context they want to receive. We populate a hash with
+    # sockets/contexts in order to send only the events they want
+    # And because this is an initial connection, it triggers a status
+    # request to Asterisk
+
+    if ( $accion =~ /^contexto\d+/ ) {
+
+        my ( $nada, $contextoenviado ) = split( /\@/, $datosflash );
+
+        if ( defined($contextoenviado) ) {
+            $flash_contexto{$socket} = $contextoenviado;
+        }
+        else {
+            $flash_contexto{$socket} = "";
+        }
+        if ( $datosflash =~ /^1/ ) {
+            $no_encryption{$socket} = 1;
+        }
+        else {
+            $no_encryption{$socket} = 0;
+        }
+
+        sends_key($socket);
+        sends_version($socket);
+
+        # send_initial_status();
+        first_client_status($socket);
+        $tab = substr( $tab, 0, -1 ) if DEBUG;
+        return;
+    }
+    if ( defined( $flash_contexto{$socket} ) ) {
+        $panelcontext = $flash_contexto{$socket};
+    }
+    else {
+        $panelcontext = "";
+    }
+    if ( $panelcontext eq "" ) { $panelcontext = "GENERAL"; }
+
+    if ( defined( $config->{$panelcontext}{conference_context} ) ) {
+        $conference_context = $config->{$panelcontext}{conference_context};
+    }
+    else {
+        if ( defined( $config->{GENERAL}{conference_context} ) ) {
+            $conference_context = $config->{GENERAL}{conference_context};
+        }
+        else {
+            $conference_context = "";
+        }
+    }
+
+    if ( defined( $config->{$panelcontext}{barge_rooms} ) ) {
+        $bargerooms = $config->{$panelcontext}{barge_rooms};
+        ( $first_room, $last_room ) = split( /-/, $bargerooms );
+    }
+    else {
+        if ( defined( $config->{GENERAL}{barge_rooms} ) ) {
+            $bargerooms = $config->{GENERAL}{barge_rooms};
+            ( $first_room, $last_room ) = split( /-/, $bargerooms );
+        }
+        else {
+            $bargerooms = "";
+        }
+    }
+
+    # We have the origin button number from the drag&drop in the 'datos'
+    # variable. We need to traverse the %buttons hash in order to extract
+    # the channel name and the panel context, used to find the destination
+    # button of the command if any
+    if (   $accion =~ /^meetmemute/
+        || $accion =~ /^meetmeunmute/
+        || $accion =~ /^bogus/
+        || $accion =~ /^restart/ )
+    {
+        $origin_channel = "bogus";
+    }
+    else {
+        my $datosflash_sincontexto = $datosflash;
+        $datosflash_sincontexto =~ s/(.*)\@(.*)/$1/g;
+
+        if ( is_number($datosflash_sincontexto) ) {
+
+            # If the originator is a number, assume button position
+            # on fop, extract the channel name from the button_reverse hash
+
+            $canal = $buttons_reverse{$datosflash};
+
+            # A button key with an & is for a context channel
+            # A button key with an = is for a trunk   channel
+            # This bit of code just cleans the channel name and context
+            if ( $canal =~ m/&/ ) {
+                @pedazos = split( /&/, $canal );
+                $origin_context = $pedazos[1];
+                my @pedazos2 = split( /\^/, $pedazos[0] );
+                $origin_server  = $pedazos2[0];
+                $origin_channel = $pedazos2[1];
+            }
+            else {
+                my @pedazos2 = split( /\^/, $canal );
+                $origin_server  = $pedazos2[0];
+                $origin_channel = $pedazos2[1];
+            }
+        }
+        else {
+
+            # The origin has letters, assume its a channel name
+            # with a possible extensions.conf context after '@'
+            # (We have already removed the '@fop_context')
+
+            if ( $datosflash_sincontexto =~ /\@/ ) {
+                $contexto = $datosflash_sincontexto;
+                $datosflash_sincontexto =~ s/(.*)\@(.*)/$1/g;
+                $contexto               =~ s/(.*)\@(.*)/$2/g;
+            }
+
+            $origin_channel = $datosflash_sincontexto;
+
+            # If we receive a channel name for the dial command
+            # we default to server number 1 to send the command
+            $servidor_dial = "default";
+
+        }
+    }
+
+    if ( $origin_channel =~ m/^clid/i ) {
+        $contexto = $datosflash;
+
+        if ( $contexto =~ m/\@/ ) {
+            $contexto =~ s/(.*)\@(.*)/$2/g;
+            if ( defined($contexto) && $contexto ne "" ) {
+                $contexto = "&" . $contexto;
+            }
+        }
+        else {
+            $contexto = "";
+        }
+
+        my $local_channel_for_clid_buttons = $extension_transfer{"$origin_server^$origin_channel$contexto"};
+        $local_channel_for_clid_buttons =~ s/\d+\^(.*)/$1/g;
+        $origin_channel = "Local/" . $local_channel_for_clid_buttons;
+
+        # Add the reverse transfer extension to make the callerid in originate work
+        $extension_transfer{"$origin_server^$origin_channel$contexto"} = "Local/$local_channel_for_clid_buttons";
+    }
+
+    if ( $accion =~ /^restrict/ && defined($origin_channel) ) {
+        my $contextoaagregar = "";
+        if ( $panelcontext ne "GENERAL" ) {
+            $contextoaagregar = "&$panelcontext";
+        }
+        $restrict_channel = $origin_channel;
+        log_debug( "$heading RESTRICT commands to channel $restrict_channel", 32 ) if DEBUG;
+        my $indice = "0^$restrict_channel$contextoaagregar";
+        log_debug( "$heading RESTRICT indice $indice", 32 ) if DEBUG;
+        my $btn_num = "0";
+        if ( defined( $buttons{$indice} ) ) {
+            $btn_num = $buttons{$indice};
+            $btn_num =~ s/(.*)\@(.*)/$1/g;
+        }
+        if ( $btn_num ne "0" ) {
+            log_debug( "$heading RESTRICT btn_num $btn_num", 32 ) if DEBUG;
+            my $manda = "$btn_num|restrict|0";
+            send_status_to_flash( $socket, $manda, 0 );
+        }
+        else {
+            log_debug( "$heading RESTRICT channel not found $indice!", 32 ) if DEBUG;
+        }
+        $tab = substr( $tab, 0, -1 ) if DEBUG;
+        return;
+    }
+
+    if ( defined($origin_channel) ) {
+        log_debug( "$heading origin_channel = $origin_channel", 64 ) if DEBUG;
+
+        if ( defined( $config->{$panelcontext}{security_code} ) ) {
+            $myclave = $config->{$panelcontext}{security_code} . $keys_socket{$socket};
+            log_debug( "$heading usando key " . $keys_socket{$socket}, 16 ) if DEBUG;
+        }
+        else {
+            $myclave = "";
+            $myclave = $config->{GENERAL}{security_code} . $keys_socket{$socket};
+            log_debug( "$heading usando key " . $keys_socket{$socket}, 16 ) if DEBUG;
+        }
+
+        if ( $myclave ne "" ) {
+            $md5clave = MD5HexDigest($myclave);
+        }
+
+        if (   ( "$password" eq "$md5clave" )
+            || ( $accion =~ /^dial/ && $cdial_nosecure == 1 ) )
+        {
+            sends_correct($socket);
+            log_debug( "** The channel selected is $origin_channel and the security code matches", 16 ) if DEBUG;
+            sends_key($socket);
+            if ( $accion =~ /^restart/ ) {
+
+                $comando = "Action: Command\r\n";
+                $comando .= "Command: restart when convenient\r\n\r\n";
+                log_debug( "!! Command received: restart when convenient", 32 ) if DEBUG;
+                send_command_to_manager( $comando, $p[0], 0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+
+                # FIXME restart only works for the 1st server defined
+                alarm(10);
+                $tab = substr( $tab, 0, -1 ) if DEBUG;
+                return;
+            }
+
+            if ( $accion =~ /-/ ) {
+
+                #if action has an "-" the command has clid text to pass
+                @partes = split( /-/, $accion );
+                $ultimo = @partes;
+                $ultimo--;
+                $btn_destino = $partes[$ultimo];
+                $ultimo--;
+                $clid = $partes[$ultimo];
+
+                if ( defined($origin_context) ) {
+
+                    if ( length($origin_context) > 0 ) {
+                        $btn_destino = $btn_destino . "@" . $origin_context;
+                    }
+                }
+            }
+            else {
+
+                #strips the destination button (number at the end)
+                $btn_destino = $accion;
+                $btn_destino =~ s/[A-Za-z- ]//g;
+                if ( $btn_destino eq "" ) { $btn_destino = "0"; }
+
+                if ( defined($origin_context) ) {
+                    if ( length($origin_context) > 0 ) {
+                        $btn_destino = $btn_destino . "@" . $origin_context;
+                    }
+                }
+            }
+            if ( $btn_destino eq "" ) { $btn_destino = "0"; }
+            if ( $btn_destino eq "0" ) {
+                log_debug( "$heading btn_destino es igual a cero!", 32 ) if DEBUG;
+            }
+            else {
+
+                log_debug( "$heading btn_destino = $btn_destino", 32 ) if DEBUG;
+                if ( defined( $buttons_reverse{$btn_destino} ) ) {
+                    $canal = $buttons_reverse{$btn_destino};
+                    $canal =~ s/(.*)=(.*)/$1/g;
+                }
+                else {
+                    $canal = "";
+                }
+                $destino = $canal;
+            }
+
+            if ( defined($destino) && $destino ne "" ) {
+                if ( $destino ne "0" ) {
+                    log_debug( "$heading destino es igual a $destino", 32 ) if DEBUG;
+                    my @pedazos2 = split( /\^/, $destino );
+                    $destin_server = $pedazos2[0];
+                    $destino       = $pedazos2[1];
+                    ( $destino, my $nada ) = split( /\&/, $pedazos2[1] );
+                    log_debug( "$heading El boton de destino es $destino en el server $destin_server", 64 ) if DEBUG;
+                }
+            }
+
+            if ( $accion =~ /^tovoicemail/ ) {
+
+                my $keyext = "$origin_server^$origin_channel";
+                my $exttran = $tovoicemail{$btn_destino};
+                my ( $extx, $contextx ) = split( /\@/, $exttran, 2 );
+
+                my @cuales_transferir = get_transfer_channel( $origin_channel, $datosflash );
+                my $cuantos = @cuales_transferir;
+
+                if ( $cuantos > 0 ) {
+                    $comando = "Action: Redirect\r\n";
+                    $comando .= "Channel: $cuales_transferir[0]\r\n";
+                    $comando .= "Exten: $extx\r\n";
+                    $comando .= "ActionID: 1234\r\n";
+                    $comando .= "Context: $contextx\r\n";
+                    $comando .= "Priority: 1\r\n\r\n";
+                }
+                else {
+                    $comando = "Action: Originate\r\n";
+                    $comando .= "Channel: $origin_channel\r\n";
+                    $comando .= "Exten: $extx\r\n";
+                    $comando .= "ActionID: 1234\r\n";
+                    $comando .= "Context: $contextx\r\n";
+                    $comando .= "Priority: 1\r\n\r\n";
+                }
+                send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                    0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+
+                return;
+            }
+            if ( $accion =~ /^voicemail/ ) {
+                my $vext     = "";
+                my $vcontext = "";
+
+                if ( defined( $config->{$panelcontext}{voicemail_extension} ) ) {
+                    my $voicemailext = $config->{$panelcontext}{voicemail_extension};
+                    ( $vext, $vcontext ) = split( /\@/, $voicemailext );
+                }
+                else {
+                    log_debug( "There is no voicemail_extension defined in op_server.cfg!", 32 ) if DEBUG;
+                    $tab = substr( $tab, 0, -1 ) if DEBUG;
+                    return;
+                }
+
+                my $keyext = "$origin_server^$origin_channel";
+                if ( $contexto ne "" ) { $keyext .= "\&$contexto"; }
+                my $vclid = $extension_transfer{$keyext};
+                $vclid =~ s/\d+\^(.*)/$1/g;
+                $vclid =~ s/^Local\///g;
+                $vclid =~ s/(.*)\@(.*)/$1/g;
+
+                $comando = "Action: Originate\r\n";
+                $comando .= "Channel: $origin_channel\r\n";
+                $comando .= "Callerid: $vclid <$vclid>\r\n";
+                $comando .= "Async: True\r\n";
+                $comando .= "Exten: $vext\r\n";
+                if ( defined($vcontext) ) {
+                    $comando .= "Context: $vcontext\r\n";
+                }
+                $comando .= "Priority: 1\r\n";
+                $comando .= "\r\n";
+
+                send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                    0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+                $tab = substr( $tab, 0, -1 ) if DEBUG;
+                return;
+            }
+
+            if ( is_number($destino) ) {
+
+                # If the selected channel name is only digits, its a
+                # conference. So treat a conference command as a regular
+                # transfer or redirect. (We do not want to send into a
+                # meetme conference another ongoing meetme conference)
+                my @sesiones_del_canal = extraer_todas_las_sesiones_de_un_canal($origin_channel);
+                my $cuantos            = @sesiones_del_canal;
+
+                if ( $accion =~ /^conference/ ) {
+                    if ( $cuantos == 0 ) {
+                        $accion =~ s/conference/originate/g;
+                    }
+                    elsif ( $cuantos > 0 ) {
+                        $accion =~ s/conference/transferir/g;
+                    }
+                }
+            }
+
+            if ( $accion eq "cortar" ) {
+                my $buton_number = $datosflash;
+                log_debug( "$heading Will try to hangup channel para el boton $buton_number", 16 ) if DEBUG;
+
+                foreach ( @{ $sesbot{$buton_number} } ) {
+                    log_debug( "$heading hanging up channel $_", 16 ) if DEBUG;
+                    $comando = "Action: Hangup\r\n";
+                    $comando .= "Channel: $_\r\n\r\n";
+                    log_debug( "-- Command received: $accion chan $_", 32 ) if DEBUG;
+                    send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                        0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+
+                    # $comando = "Action: Command\r\n";
+                    # $comando .= "Command: soft hangup $_\r\n\r\n";
+                    # send_command_to_manager($comando, $p[$button_server{$datosflash}]);
+                }
+            }
+            elsif ( $accion =~ /^meetmemute/ ) {
+                my $conference   = $btn_destino;
+                my $meetmemember = $datosflash;
+                $conference   =~ s/(.*)\@(.*)/$1/g;
+                $meetmemember =~ s/(.*)\@(.*)/$1/g;
+                my $boton_con_contexto = $clid;
+                $boton_con_contexto =~ s/^meetmemute//g;
+                $comando = "Action: Command\r\n";
+                $comando .= "ActionID: meetmemute$boton_con_contexto\r\n";
+                $comando .= "Command: meetme mute $conference $meetmemember\r\n\r\n";
+                send_command_to_manager( $comando, $p[ $button_server{$boton_con_contexto} ],
+                    0, $astmanproxy_servers[ $button_server{$boton_con_contexto} ] );
+            }
+            elsif ( $accion =~ /^meetmeunmute/ ) {
+                my $conference   = $btn_destino;
+                my $meetmemember = $datosflash;
+                $conference   =~ s/(.*)\@(.*)/$1/g;
+                $meetmemember =~ s/(.*)\@(.*)/$1/g;
+                my $boton_con_contexto = $clid;
+                $boton_con_contexto =~ s/^meetmeunmute//g;
+                $comando = "Action: Command\r\n";
+                $comando .= "ActionID: meetmeunmute$boton_con_contexto\r\n";
+                $comando .= "Command: meetme unmute $conference $meetmemember\r\n\r\n";
+                send_command_to_manager( $comando, $p[ $button_server{$boton_con_contexto} ],
+                    0, $astmanproxy_servers[ $button_server{$boton_con_contexto} ] );
+            }
+            elsif ( $accion =~ /^conference/ ) {
+                log_debug( "$heading CONFERENCE extension_transfer($origin_channel)", 1 ) if DEBUG;
+
+                my $indice    = $origin_server . "^" . $origin_channel;
+                my $originate = $extension_transfer{$indice};
+                $originate =~ s/\d+\^(.*)/$1/;
+                foreach ( keys(%buttons) ) {
+                    log_debug( "$heading comparo $buttons{$_} con btn_destino $btn_destino", 1 ) if DEBUG;
+                    if ( $buttons{$_} eq $btn_destino ) {
+                        if ( $canal =~ /^_/ ) {
+                            my @canalarray = @{ $sesbot{$btn_destino} };
+                            my $canalses   = $canalarray[0];
+                            my ( $newcanal, $newses ) = separate_session_from_channel($canalses);
+                            $canal = $newcanal;
+                        }
+                        $canal =~ s/(.*)=(.*)/$1/g;
+                        log_debug( "$heading coincidencia para btn_destino $btn_destino el canal es $canal", 1 )
+                          if DEBUG;
+                        my @links = extraer_todos_los_enlaces_de_un_canal( $canal, $button_server{$datosflash} );
+
+                        my @canal_transferir = @{ $sesbot{$btn_destino} };
+
+                        my $cuantos = @links;
+                        if ( $cuantos <= 0 ) {
+                            my @extensiondialed = extracts_exten_from_active_channel($canal);
+                            $comando = "Action: Originate\r\n";
+                            $comando .= "Channel: $origin_channel\r\n";
+                            $comando .= "Exten: $extensiondialed[0]\r\n";
+                            $comando .= "Priority: 1\r\n\r\n";
+                        }
+                        else {
+
+                            log_debug( "** $canal_transferir[0] $links[0] will be conferenced together with $origin_channel ($originate)",
+                                16 )
+                              if DEBUG;
+
+                            # Try to find an empty conference
+                            my $empty_room = $first_room;
+                            for ( my $at = $first_room ; $at <= $last_room ; $at++ ) {
+                                log_debug( "room $at = " . $barge_rooms{"$at"}, 128 ) if DEBUG;
+                                if ( $barge_rooms{"$at"} == 0 ) {
+                                    $found_room = 1;
+                                    $empty_room = $at;
+                                    last;
+                                }
+                            }
+
+                            if ( $found_room == 1 ) {
+                                $comando = "Action: Redirect\r\n";
+                                $comando .= "Channel: $canal_transferir[0]\r\n";
+                                $comando .= "ExtraChannel: $links[0]\r\n";
+                                $comando .= "Exten: $empty_room\r\n";
+                                $comando .= "ActionID: 1234\r\n";
+                                $comando .= "Context: $conference_context\r\n";
+                                $comando .= "Priority: 1\r\n\r\n";
+                                $auto_conference{ $canal_transferir[0] } = $origin_channel;
+                            }
+                            else {
+                                log_debug( "$heading No hay meetme vacio!", 64 ) if DEBUG;
+                                $comando = "";
+                            }
+                        }
+                        send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                            0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+                        last;
+                    }
+                }
+            }
+            elsif ( $accion =~ /transferir/ ) {
+
+                if ( $accion =~ /^ctransferir/ ) {
+
+                    # Sets db variable to set callerid on dialplan
+                    $comando = "Action: Command\r\n";
+                    $comando .= "Command: database put clid $destino ";
+                    $comando .= "\"$clid\"\r\n\r\n";
+                    send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                        0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+                }
+
+                $canal_destino = retrieve_extension($btn_destino);
+
+                if ( $origin_channel =~ /\*/ ) {
+                    my @canalarray = @{ $sesbot{$datosflash} };
+                    my $canalses   = $canalarray[0];
+                    my ( $newcanal, $newses ) = separate_session_from_channel($canalses);
+                    $origin_channel = $newcanal;
+                }
+
+                if ( $canal_destino ne "-1" ) {
+                    if ( $canal_destino =~ /\@/ ) {
+                        @pedazos       = split( /\@/, $canal_destino );
+                        $canal_destino = $pedazos[0];
+                        $contexto      = $pedazos[1];
+                    }
+
+                    my @cuales_transferir = get_transfer_channel( $origin_channel, $datosflash );
+
+                    foreach my $valor (@cuales_transferir) {
+                        log_debug( "$heading Will try to transfer $valor to extension number $canal_destino!", 16 )
+                          if DEBUG;
+                        $comando = "Action: Redirect\r\n";
+                        $comando .= "Channel: $valor\r\n";
+                        $comando .= "Exten: $canal_destino\r\n";
+                        if ( $contexto ne "" ) {
+                            $comando .= "Context: $contexto\r\n";
+                        }
+                        $comando .= "Priority: 1\r\n\r\n";
+                        send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                            0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+
+                        if ( $calltimeout > 0 ) {
+                            $comando = "Action: AbsoluteTimeout\r\n";
+                            $comando .= "Channel: $valor\r\n";
+                            $comando .= "Timeout: $calltimeout\r\n";
+                            $comando .= "ActionID: timeout|$valor|$calltimeout\r\n";
+                            $comando .= "\r\n";
+                            send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                                , 0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+                        }
+
+                    }
+                }
+                else {
+                    log_debug( "** Untransferable destination! ($origin_channel)", 16 ) if DEBUG;
+                }
+            }
+            elsif ( $accion =~ /originate/ ) {
+
+                if ( $origin_channel =~ /\*/ ) {
+                    log_debug( "** Cannot originate from wildcard buttons ($origin_channel)", 16 ) if DEBUG;
+                    $tab = substr( $tab, 0, -1 ) if DEBUG;
+                    return;
+                }
+
+                if ( $accion =~ /^coriginate/ ) {
+                    $comando = "Action: Command\r\n";
+                    $comando .= "Command: database put clid $destino ";
+                    $comando .= "\"$clid\"\r\n\r\n";
+                    send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                        0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+                }
+
+                $extension_destino = retrieve_extension($btn_destino);
+
+                $destino = "";
+                while ( my ( $canloop, $nrobotonloop ) = each(%buttons_preserve_case) ) {
+                    if ( $nrobotonloop eq $btn_destino ) {
+                        $destino = $canloop;
+                    }
+                }
+                if ( $destino ne "" ) {
+                    $destino =~ s/(.*)=(.*)/$1/g;
+                    $destino =~ s/^\d+\^(.*)/$1/g;
+                }
+
+                if ( $destino =~ m/QUEUE\//i ) {
+                    $destino =~ s/^QUEUE\/(.*)/$1/g;
+                    $destino =~ s/(.*)&(.*)/$1/g;
+
+                    my $member = 0;
+                    while ( my ( $key, $val ) = each(%count_queue) ) {
+                        if ( $key eq "$button_server{$datosflash}^$destino" ) {
+                            foreach my $qmember (@$val) {
+                                my $canal_compara = "$button_server{$datosflash}^$origin_channel";
+                                if ( uc($qmember) eq uc($canal_compara) ) {
+                                    $member++;
+                                }
+                            }
+                        }
+                    }
+                    if ( $origin_channel !~ /^QUEUEAGENT/ ) {
+                        if ( $member > 0 ) {
+                            $comando = "Action: QueueRemove\r\n";
+                            $comando .= "Queue: $destino\r\n";
+                            $comando .= "Interface: $origin_channel\r\n";
+                            $comando .= "\r\n";
+                        }
+                        else {
+                            $comando = "Action: QueueAdd\r\n";
+                            $comando .= "Queue: $destino\r\n";
+                            $comando .= "Interface: $origin_channel\r\n";
+                            $comando .= "\r\n";
+                        }
+                    }
+                }
+                else {
+
+                    if ( $extension_destino =~ /\@/ ) {
+                        @pedazos           = split( /\@/, $extension_destino );
+                        $extension_destino = $pedazos[0];
+                        $contexto          = $pedazos[1];
+                    }
+
+                    log_debug( "$heading Originate from $origin_channel to extension $extension_destino!", 16 ) if DEBUG;
+                    my $keyext = "$origin_server^$origin_channel";
+
+                    if ( $panelcontext ne "" && $panelcontext ne "GENERAL" ) { $keyext .= "\&$panelcontext"; }
+
+                    my $dclid = $extension_transfer{$keyext};
+                    $dclid =~ s/\d+\^(.*)/$1/g;
+                    $dclid =~ s/^Local\///g;
+                    $dclid =~ s/(.*)\@(.*)/$1/g;
+
+                    $clid = $textos{"$datosflash"} . " <$dclid>";
+
+                    if ( $origin_channel =~ /^IAX2\[/ ) {
+                        $origin_channel =~ s/^IAX2\[(.*)\]/IAX2\/$1/g;
+                    }
+                    $comando = "Action: Originate\r\n";
+                    $comando .= "Channel: $origin_channel\r\n";
+                    $comando .= "Async: True\r\n";
+                    $comando .= "Callerid: $clid\r\n";
+                    $comando .= "Exten: $extension_destino\r\n";
+
+                    if ( $contexto ne "" ) {
+                        $comando .= "Context: $contexto\r\n";
+                    }
+                    $comando .= "Priority: 1\r\n";
+                    $comando .= "\r\n";
+                }
+                send_command_to_manager( $comando, $p[ $button_server{$datosflash} ],
+                    0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+            }
+            elsif ( $accion =~ /^dial/ ) {
+                if ( $servidor_dial eq "default" ) {
+                    $servidor_dial = $p[0];
+                }
+                else {
+                    $servidor_dial = $p[ $button_server{$datosflash} ];
+                }
+                my $numero_a_discar = $accion;
+                $numero_a_discar =~ s/^dial//g;
+                $comando = "Action: Originate\r\n";
+                $comando .= "Channel: $origin_channel\r\n";
+                $comando .= "Async: True\r\n";
+                $comando .= "Exten: $numero_a_discar\r\n";
+                if ( $contexto ne "" ) {
+                    $comando .= "Context: $contexto\r\n";
+                }
+                $comando .= "Priority: 1\r\n";
+                $comando .= "\r\n";
+                send_command_to_manager( $comando, $servidor_dial, 0, $astmanproxy_servers[ $button_server{$datosflash} ] );
+            }
+        }
+        else {
+            log_debug( "$heading Password mismatch -$password-$md5clave-!", 1 ) if DEBUG;
+            sends_key($socket);
+            sends_incorrect($socket);
+        }
+    }
+    else {
+        log_debug( "$heading There is no channel selected ?", 16 ) if DEBUG;
+    }
+    $tab = substr( $tab, 0, -1 ) if DEBUG;
+}
+
+sub retrieve_extension {
+    my $param         = shift;
+    my $canal         = "";
+    my $canal_destino = "";
+    my $heading       = "** RETRIEVE_EXTEN";
+    my $contexto      = "";
+
+    my $param_sin_contexto = $param;
+    $param_sin_contexto =~ s/(.*)(\@.*)/$1/g;
+    if ( defined($2) ) {
+        $contexto = $2;
+        $contexto =~ s/\@/&/g;
+    }
+
+    log_debug( "$heading param $param param_sin_con $param_sin_contexto", 32 ) if DEBUG;
+
+    if ( is_number($param_sin_contexto) ) {
+        log_debug( "$heading I guess its a button number", 32 ) if DEBUG;
+
+        # If the parameter is a number, assume button number
+        foreach ( keys(%buttons) ) {
+            if ( $buttons{$_} eq $param ) {
+                log_debug( "$heading coincide con $param", 64 ) if DEBUG;
+                $canal = $_;
+                $canal =~ s/(.*)=(.*)/$1/g;
+                $canal =~ s/(.*)&(.*)/$1/g;
+                log_debug( "$heading canal $canal contexto $contexto", 64 ) if DEBUG;
+                $canal_destino = $extension_transfer{"$canal$contexto"};
+                last;
+            }
+        }
+    }
+    else {
+        log_debug( "$heading I guess its a channel name", 32 ) if DEBUG;
+
+        # If its not a number, asume channel name (technology/name)
+        foreach ( keys(%buttons) ) {
+            my $linealog = sprintf( "%-20s %-10s", $_, $buttons{$_} );
+
+            # log_debug("$heading $linealog",64) if DEBUG;
+            if ( $_ eq $param ) {
+                log_debug( "$heading coincide con $param", 64 ) if DEBUG;
+                $canal = $_;
+                $canal =~ s/(.*)=(.*)/$1/g;
+                $canal_destino = $extension_transfer{"$canal"};
+                last;
+            }
+        }
+    }
+
+    log_debug( "$heading canal_destino =  $canal_destino", 32 ) if DEBUG;
+    $canal_destino =~ s/\d+\^(.*)/$1/g;
+    log_debug( "$heading La extension para $param es $canal_destino", 32 ) if DEBUG;
+    return $canal_destino;
+}
+
+sub request_astdb_status {
+
+    for my $key ( keys %astdbcommands ) {
+        my $nro_servidor = 0;
+        foreach my $socket (@p) {
+            if ( defined($socket) && $socket ne "" ) {
+                for ( keys %buttons_preserve_case ) {
+                    my $canal = $_;
+                    $canal =~ m/(\d+)\^([^&]*)(.*)/g;
+                    my $servidor = $1;
+                    my $canalito = $2;
+                    if ( $canalito !~ m/^_/ && $nro_servidor == $servidor && $canalito !~ m/=/ ) {
+                        my $comando = "Action: Command\r\n";
+                        $comando .= "ActionID: astdb-$key-$canalito\r\n";
+                        $comando .= "Command: database get $key $canalito\r\n\r\n";
+                        if ( defined( $autenticado{$socket} ) ) {
+                            if ( $autenticado{$socket} == 1 ) {
+                                send_command_to_manager( $comando, $socket );
+                            }
+                        }
+                    }
+                }
+            }
+            $nro_servidor++;
+        }
+    }
+}
+
+sub request_queue_status {
+    my $socket     = shift;
+    my $canalid    = shift;
+    my $member     = "";
+    my $nada       = "";
+    my $showagents = 0;
+
+    if ( defined($canalid) ) {
+        if ( $canalid eq "initialrequest" ) {
+
+            # We only ask for agents on startup
+            $showagents = 1;
+        }
+        else {
+            ( $member, $nada ) = separate_session_from_channel($canalid);
+        }
+    }
+
+    my @todos = ();
+
+    if ( $socket eq "all" ) {
+        @todos = @p;
+    }
+    else {
+        push @todos, $socket;
+    }
+
+    foreach my $socket2 (@todos) {
+        if ( defined($socket2) && $socket2 ne "" ) {
+            if ( $showagents == 1 ) {
+                send_command_to_manager( "Action: Command\r\nActionId: agents\r\nCommand: show agents\r\n\r\n", $socket2 );
+            }
+            if ( defined($member) ) {
+                my @agentes = ();
+                push @agentes, $member;
+                if ( exists( $reverse_agents{$member} ) ) {
+                    push @agentes, "Agent/" . $reverse_agents{$member};
+                }
+                foreach my $cual (@agentes) {
+                    send_command_to_manager( "Action: QueueStatus\r\nMember: $cual\r\n\r\n", $socket2 );
+
+                }
+            }
+            else {
+                send_command_to_manager( "Action: QueueStatus\r\nActionID: QueueStatus\r\n", $socket2 );
+            }
+
+            #		if($showagents==1) {
+            #           send_command_to_manager( "Action: Command\r\nActionId: agents\r\nCommand: show agents\r\n\r\n", $socket2 );
+            #		}
+        }
+    }
+}
+
+sub first_client_status {
+
+    # This functions traverses all FOP internal hashes and send the proper
+    # commands to the flash client to reflect the status of each button.
+
+    my $socket  = shift;
+    my $interno = "";
+
+    if ( $queue_hide == 1 ) {
+
+        # If queue_hide is set, hide queue positions
+        for my $key ( keys %buttons ) {
+            if ( $key =~ m/\d+\^QUEUE\/[^=]*=\d/i ) {
+                $interno = $buttons{$key};
+                send_status_to_flash( $socket, "$interno|setalpha|00", 0 );
+            }
+        }
+    }
+
+    if ( keys(%estadoboton) ) {
+        for $interno ( keys %botonled ) {
+            if ( $botonled{$interno} == 1 ) {
+                send_status_to_flash( $socket, "$interno|changelabel1|$botonlabel{$interno}", 0 );
+            }
+        }
+        for $interno ( keys %botonlabelonly ) {
+            send_status_to_flash( $socket, "$interno|setlabel|$botonlabelonly{$interno}", 0 );
+        }
+        for $interno ( keys %botonvoicemail ) {
+            if ( $botonvoicemail{$interno} >= 0 ) {
+                send_status_to_flash( $socket, "$interno|voicemail|$botonvoicemail{$interno}", 0 );
+            }
+        }
+        for $interno ( keys %botonvoicemailcount ) {
+            send_status_to_flash( $socket, "$interno|voicemailcount|$botonvoicemailcount{$interno}", 0 );
+        }
+        for $interno ( keys %botonalpha ) {
+            if ( $botonalpha{$interno} ne "" ) {
+                send_status_to_flash( $socket, "$interno|setalpha|$botonalpha{$interno}", 0 );
+            }
+        }
+        for $interno ( keys %botonqueue ) {
+            send_status_to_flash( $socket, "$interno|infoqstat|$botonqueue{$interno}", 0 );
+        }
+        for $interno ( keys %botonqueue_count ) {
+            send_status_to_flash( $socket, "$interno|infoqstat2|$botonqueue_count{$interno}", 0 );
+        }
+        if ( keys(%botonqueuemember) ) {
+            for $interno ( keys %botonqueuemember ) {
+                if ( defined( @{ $botonqueuemember{$interno} } ) ) {
+                    my %temphash = ();
+                    foreach my $val ( @{ $botonqueuemember{$interno} } ) {
+                        my @datos = split( /\|/, $val );
+                        $temphash{ $datos[0] } = $datos[1];
+
+                        #                        send_status_to_flash($socket, "$interno|info$datos[0]|$datos[1]", 0);
+                    }
+                    while ( my ( $key, $val ) = each(%temphash) ) {
+                        send_status_to_flash( $socket, "$interno|info$key|$val", 0 );
+                    }
+                }
+            }
+        }
+        if ( keys(%botonpark) ) {
+            for $interno ( keys %botonpark ) {
+                $botonpark{$interno} =~ m/(.*)\|(.*)/;
+                my $texto   = $1;
+                my $timeout = $2;
+                my $diftime = $timeout - time();
+                if ( $diftime > 0 ) {
+                    send_status_to_flash( $socket, "$interno|park|$texto($diftime)", 0 );
+                }
+            }
+        }
+        for $interno ( keys %estadoboton ) {
+
+            #if ( $estadoboton{$interno} !~ /^free/ ) {
+            if ( $estadoboton{$interno} =~ /^busy/ ) {
+                send_status_to_flash( $socket, "$interno|state|busy", 0 );
+                if ( defined( $botonlabel{$interno} ) ) {
+                    send_status_to_flash( $socket, "$interno|changelabel0|$botonlabel{$interno}", 0 );
+                }
+            }
+            elsif ( $estadoboton{$interno} =~ /ringi/ ) {
+                send_status_to_flash( $socket, "$interno|state|ringing", 0 );
+            }
+            if ( defined( $botonclid{$interno} ) ) {
+                if ( $botonclid{$interno} ne "" ) {
+                    send_status_to_flash( $socket, "$interno|settext|$botonclid{$interno}", 0 );
+                }
+            }
+
+            #}
+        }
+        if ( keys(%botonlinked) ) {
+            for $interno ( keys %botonlinked ) {
+                if ( $botonlinked{$interno} ne "" ) {
+                    send_status_to_flash( $socket, "$interno|linked|$botonlinked{$interno}", 0 );
+                }
+            }
+        }
+        if ( keys(%botonmeetme) ) {
+            for $interno ( keys %botonmeetme ) {
+                if ( $botonmeetme{$interno} ne "" ) {
+                    send_status_to_flash( $socket, "$interno|meetmeuser|$botonmeetme{$interno}", 0 );
+                }
+            }
+        }
+        if ( keys(%botontimer) ) {
+            for $interno ( keys %botontimer ) {
+                if ( $botontimer{$interno} ne "" ) {
+                    my $diftime = time() - $botontimer{$interno};
+                    my $type    = "";
+                    if ( defined( $botontimertype{$interno} ) ) {
+                        $type = "\@" . $botontimertype{$interno};
+                    }
+                    send_status_to_flash( $socket, "$interno|settimer|$diftime$type", 0 );
+                    if ( $type eq "\@UP" ) {
+                        send_status_to_flash( $socket, "$interno|state|busy", 0 );
+                    }
+                }
+            }
+        }
+        if ( keys(%botonsetlabel) ) {
+            for $interno ( keys %botonsetlabel ) {
+                if (   $botonsetlabel{$interno} ne ""
+                    && $botonsetlabel{$interno} ne "."
+                    && $botonsetlabel{$interno} ne "original"
+                    && $botonsetlabel{$interno} ne "labeloriginal" )
+                {
+                    send_status_to_flash( $socket, "$interno|setlabel|$botonsetlabel{$interno}", 0 );
+                }
+            }
+        }
+        if ( keys(%botonregistrado) ) {
+            for $interno ( keys %botonregistrado ) {
+                if ( $botonregistrado{$interno} ne "" ) {
+                    my ( $quehace, $dos ) = split( /\|/, $botonregistrado{$interno} );
+                    send_status_to_flash( $socket, "$interno|$quehace|$dos", 0 );
+                }
+            }
+        }
+    }
+}
+
+sub send_initial_status {
+    %datos = ();
+    my $nro_servidor = 0;
+    my $heading      = "** SEND INITIAL STATUS";
+    my $cual         = shift;
+    my @socket_manager;
+
+    if ( defined($cual) ) {
+        push @socket_manager, $cual;
+    }
+    else {
+        @socket_manager = @p;
+    }
+
+    log_debug( "$heading START SUB", 16 ) if DEBUG;
+
+    request_astdb_status();
+
+    foreach my $socket (@socket_manager) {
+
+        if ( defined($socket) && $socket ne "" ) {
+            my @pedazos = split( /\|/, $manager_socket{$socket} );
+            if ( $pedazos[0] eq $ip_addy{$socket} ) {
+                my $contador = 0;
+                foreach my $valor (@manager_host) {
+                    if ( $valor eq $pedazos[0] ) {
+                        $nro_servidor = $contador;
+                    }
+                    $contador++;
+                }
+            }
+
+            # If we send the channel status after the queue status, the agentlogin will be displayed as busy
+            # when they are actually waiting for a call, trying to put it at the end
+            request_queue_status( $socket, "initialrequest" );
+
+            send_command_to_manager( "Action: Status\r\n\r\n", $socket );
+
+            send_command_to_manager( "Action: ZapShowChannels\r\n\r\n", $socket );
+
+            send_command_to_manager( "Action: Command\r\nActionID: parkedcalls\r\nCommand: show parkedcalls\r\n\r\n", $socket );
+
+            #        request_queue_status( $socket, "initialrequest" );
+            # Send commands to check the mailbox status for each mailbox defined
+            while ( my ( $key, $val ) = each(%mailbox) ) {
+                my @pedacitos = split( /\^/, $key );
+                my $servidormbox = $pedacitos[0];
+                if ( "$servidormbox" eq "$nro_servidor" ) {
+                    log_debug( "$heading mailbox $ip_addy{$socket} $key $val", 32 ) if DEBUG;
+                    send_command_to_manager( "Action: MailboxStatus\r\nMailbox: $val\r\n\r\n", $socket );
+                }
+            }
+            my @all_meetme_rooms = ();
+
+            # generates an array with all meetme rooms to check on init
+            for my $valor ( keys %barge_rooms ) {
+                push( @all_meetme_rooms, $valor );
+            }
+
+            for my $key ( keys %buttons ) {
+                if ( $key =~ /^\d+\^\d+$/ ) {
+                    push( @all_meetme_rooms, $key );
+                }
+            }
+
+            my %count               = ();
+            my @unique_meetme_rooms =
+              grep { ++$count{$_} < 2 } @all_meetme_rooms;
+
+            foreach my $valor (@unique_meetme_rooms) {
+                my $servidormeetme = 0;
+                my $meetmeroom     = "";
+
+                if ( $valor =~ /\^/ ) {
+                    my @pedacitos = split( /\^/, $valor );
+                    $servidormeetme = $pedacitos[0];
+                    $meetmeroom     = $pedacitos[1];
+                }
+                else {
+
+                    # If there is no server defined (its a barge_room)
+                    # we will query all servers - quick hack FIX IT or
+                    # try to figure out a way to have barge-rooms separated
+                    # in panel_contexts (as it is now) and also asterisk
+                    # servers.
+                    $servidormeetme = $nro_servidor;
+                    $meetmeroom     = $valor;
+                }
+
+                if ( "$servidormeetme" eq "$nro_servidor" ) {
+                    send_command_to_manager( "Action: Command\r\nActionID: meetme_$meetmeroom\r\nCommand: meetme list $meetmeroom\r\n\r\n",
+                        $socket );
+                }
+            }
+        }
+    }
+    alarm(2);
+}
+
+sub process_cli_command {
+
+    # This subroutine process the output for a manager "Command"
+    # sent, as 'sip show peers'
+
+    my $texto = shift;
+    @bloque = ();
+    my @lineas     = split( "\r\n", $texto );
+    my $contador   = 0;
+    my $interno    = "";
+    my $estado     = "";
+    my $nada       = "";
+    my $conference = 0;
+    my $usernum    = 0;
+    my $canal      = "";
+    my $sesion     = "";
+    my $heading    = "** PROCESS_CLI";
+    my $server     = 0;
+
+    foreach my $valor (@lineas) {
+        if ( $valor =~ /^Server/ ) {
+            $server = $valor;
+            $server =~ s/Server: (.*)/$1/g;
+        }
+    }
+
+    if ( $texto =~ /ActionID: meetme_/ ) {
+        log_debug( "$heading process meetme", 16 ) if DEBUG;
+
+        # Its a meetme status report
+        foreach my $valor (@lineas) {
+            $valor =~ s/\s+/ /g;
+            my ( $key, $value ) = split( /: /, $valor, 2 );
+
+            if ( defined($key) ) {
+
+                if ( $key eq "ActionID" ) {
+                    $value =~ s/meetme_(\d+)$/$1/g;
+                    $conference = $value;
+                }
+                if ( $key eq "User #" ) {
+                    my @partes = split( /Channel:/, $value );
+                    $usernum = $partes[0];
+                    $usernum =~ s/(\d+)(.*)/$1/g;
+                    $usernum = $usernum * 1;
+                    $usernum =~ s/\s+//g;
+                    $canal = $partes[1];
+                    $canal =~ s/^\s+//g;
+                    $canal =~ s/(.*?)\((.*)/$1/g;
+                    my $uniqueid = find_uniqueid( $canal, $server );
+                    $bloque[$contador]{"Event"}    = "MeetmeJoin";
+                    $bloque[$contador]{"Meetme"}   = $conference;
+                    $bloque[$contador]{"Count"}    = $contador;
+                    $bloque[$contador]{"Channel"}  = $canal;
+                    $bloque[$contador]{"Usernum"}  = $usernum;
+                    $bloque[$contador]{"Fake"}     = "hola";
+                    $bloque[$contador]{"Server"}   = "$server";
+                    $bloque[$contador]{"Uniqueid"} = $uniqueid;
+                    $contador++;
+                }
+            }
+        }
+        my $cuentamenos = $contador - 1;
+        if ( $cuentamenos >= 0 ) {
+            $bloque[$cuentamenos]{"Total"} = $contador;
+        }
+    }
+    elsif ( $texto =~ "ActionID: agents" ) {
+        log_debug( "$heading process agents", 16 ) if DEBUG;
+        my $agent_number;
+        my $agent_state;
+        my $agent_name;
+
+        # Show Agents CLI command, generates fake events
+
+        foreach (@lineas) {
+            $_ =~ s/\s+/ /g;
+            /(\d+) \((.*)\) (.*) (\(.*\))/;
+            if ( defined($1) ) {
+                $agent_number                         = $1;
+                $agent_name                           = $2;
+                $agent_state                          = $3;
+                $agents_name{"$server^$agent_number"} = $agent_name;
+            }
+
+            if ( defined($3) ) {
+                if ( $agent_state =~ /available at/ ) {
+
+                    # Agent callback login
+                    $agent_state =~ s/.*'(.*)'.*/$1/g;
+                    $bloque[$contador]{"Event"}     = "Agentcallbacklogin";
+                    $bloque[$contador]{"Loginchan"} = $agent_state;
+                    $bloque[$contador]{"Agent"}     = $agent_number;
+                    $bloque[$contador]{"Server"}    = "$server";
+                    $contador++;
+                }
+
+                if ( $agent_state =~ /logged in on/ ) {
+
+                    # Agent login
+                    $agent_state =~ s/\s+/ /g;
+                    $agent_state =~ s/logged in on //g;
+                    $agent_state =~ s/([^ ]*).*/$1/g;
+
+                    $bloque[$contador]{Event}   = "Agentlogin";
+                    $bloque[$contador]{Channel} = $agent_state;
+                    $bloque[$contador]{Agent}   = $agent_number;
+                    $bloque[$contador]{Server}  = $server;
+                    $contador++;
+                }
+                if ( $agent_state =~ /not logged in/ ) {
+                    $bloque[$contador]{Event}  = "Agentlogoff";
+                    $bloque[$contador]{Agent}  = $agent_number;
+                    $bloque[$contador]{Server} = $server;
+                    $bloque[$contador]{Fake}   = 1;
+                    $contador++;
+                }
+            }
+        }
+    }
+    elsif ( $texto =~ /ActionID: astdb-/ ) {
+        log_debug( "$heading process astdb", 16 ) if DEBUG;
+        my $astdbk = "";
+        my $canalk = "";
+        my $valork = "";
+        foreach (@lineas) {
+            if (/^ActionID/) {
+                $_ =~ m/ActionID: astdb-([^-]*)-(.*)/;
+                $astdbk = $1;
+                $canalk = $2;
+            }
+            if (/^Value:/) {
+                $valork = $_;
+                $valork =~ s/Value: //g;
+            }
+        }
+        if ( $valork ne "" ) {
+            $bloque[$contador]{"Event"}   = "ASTDB";
+            $bloque[$contador]{"Channel"} = $canalk;
+            $bloque[$contador]{"Value"}   = $valork;
+            $bloque[$contador]{"Family"}  = $astdbk;
+            $contador++;
+        }
+
+    }
+    elsif ( $texto =~ /ActionID: meetmeun/ || $texto =~ /ActionID: meetmemute/ ) {
+        log_debug( "$heading process meetmemute/meetmeunmute", 16 ) if DEBUG;
+        my $quecomando = "";
+        my $quecanal   = "";
+        foreach my $valor (@lineas) {
+            if ( $valor =~ /^ActionID:/ ) {
+                $quecomando = $valor;
+                $quecomando =~ s/^ActionID: //g;
+                if ( $quecomando =~ /meetmemute/ ) {
+                    $quecanal = $quecomando;
+                    $quecanal =~ s/meetmemute//g;
+                    $quecomando = "meetmemute";
+                }
+                else {
+                    $quecanal = $quecomando;
+                    $quecanal =~ s/meetmeunmute//g;
+                    $quecomando = "meetmeunmute";
+                }
+            }
+        }
+        my $canal_a_mutear = $buttons_reverse{$quecanal};
+        my @pedazos = split /\^/, $canal_a_mutear;
+        $canal_a_mutear = $pedazos[1];
+        $canal_a_mutear =~ s/(.*)\&(.*)/$1/g;
+        $bloque[$contador]{"Event"}   = $quecomando;
+        $bloque[$contador]{"Channel"} = $canal_a_mutear . "-XXXX";
+        $bloque[$contador]{"Server"}  = "$server";
+        $contador++;
+    }
+    elsif ( $texto =~ "ActionID: iaxpeers" ) {
+        log_debug( "$heading process iaxpeers", 16 ) if DEBUG;
+        my $info    = 0;
+        my $statPos = 74;
+        foreach my $valor (@lineas) {
+            log_debug( "$heading Line iaxpeers: $valor", 32 ) if DEBUG;
+            if ( $valor =~ /^Name\/User/i ) {
+                $statPos = index( $valor, "Status" );
+                $info = 1;
+                next;
+            }
+            last if $valor =~ /^--End/i;
+            next unless $info;
+            next unless ( length($valor) > $statPos );
+            my $estado = substr( $valor, $statPos );
+            $valor =~ s/\s+/ /g;
+            my @parametros = split( " ", $valor );
+            my $interno    = $parametros[0];
+
+            if ( $interno =~ /\// ) {
+                my @partecitas = split( /\//, $interno );
+                $interno = $partecitas[0];
+            }
+            my $dirip = $parametros[1];
+
+            if ( defined($estado) && $estado ne "" ) {
+                $interno = "IAX2/" . $interno . "-XXXX";
+                log_debug( "$heading State: $estado Extension: $interno", 32 ) if DEBUG;
+                $bloque[$contador]{"Event"}   = "Regstatus";
+                $bloque[$contador]{"Channel"} = $interno;
+                $bloque[$contador]{"State"}   = $estado;
+                $bloque[$contador]{"IP"}      = $dirip;
+                $bloque[$contador]{"Server"}  = "$server";
+                $contador++;
+            }
+        }
+    }
+    elsif ( $texto =~ "ActionID: sccppeers" ) {
+        log_debug( "$heading process sccppeers", 16 ) if DEBUG;
+        my $info = 0;
+        foreach my $valor (@lineas) {
+            log_debug( "$heading Line sccppeers: $valor", 32 ) if DEBUG;
+            last if $valor =~ /^--END/i;
+            next unless ( $valor =~ /(.*?)\t+|\s+(.*?)\t+|\s+.*?O.*/ );
+            $valor =~ s/\s+/ /g;
+            my @parametros = split( " ", $valor );
+            my $status = 0;
+            if ( $parametros[1] eq "--" ) {
+                $status = 4;
+            }
+            log_debug( "$heading State: 4 Extension: $interno", 32 ) if DEBUG;
+            $bloque[$contador]{"Event"}  = "ExtensionStatus";
+            $bloque[$contador]{"Exten"}  = $parametros[0];
+            $bloque[$contador]{"Status"} = $status;
+            $bloque[$contador]{"Server"} = "$server";
+            $contador++;
+        }
+    }
+    elsif ( $texto =~ "ActionID: parkedcalls" ) {
+        log_debug( "$heading process parkedcalls", 16 ) if DEBUG;
+        my $info = 0;
+        foreach my $valor (@lineas) {
+            log_debug( "$heading Line parkedcalls: $valor", 32 ) if DEBUG;
+            if ( $valor =~ /Timeout/ ) {
+                $info = 1;
+                next;
+            }
+            last if $valor =~ /^--End/i;
+            last if $valor =~ /^\d+ parked/i;
+            next unless $info;
+            $valor =~ s/\s+/ /g;
+            my @parametros = split( " ", $valor );
+            my $timeout = $parametros[6];
+            $timeout =~ s/(\d+)s/$1/;
+
+            $bloque[$contador]{"Event"}   = "ParkedCall";
+            $bloque[$contador]{"Channel"} = $parametros[1];
+            $bloque[$contador]{"Exten"}   = $parametros[0];
+            $bloque[$contador]{"Timeout"} = $timeout;
+            $bloque[$contador]{"Server"}  = "$server";
+            $contador++;
+
+        }
+    }
+    else {
+        my $info    = 0;
+        my $statPos = 74;
+
+        log_debug( "$heading process sip peers", 16 ) if DEBUG;
+
+        # Its a sip show peers report
+        foreach my $valor (@lineas) {
+            if ( $valor =~ /^Name\/User/i ) {
+                $statPos = index( $valor, "Status" );
+                $info = 1;
+                next;
+            }
+            last if $valor =~ /^--End/i;
+            next unless $info;
+            next unless ( length($valor) > $statPos );
+            log_debug( "$heading Line: $valor", 32 ) if DEBUG;
+
+            if ( length($valor) < $statPos ) {
+                log_debug( "$heading SIP PEER line $valor does not match $statPos!", 32 ) if DEBUG;
+                next;
+            }
+
+            my $estado = substr( $valor, $statPos );
+            $valor =~ s/\s+/ /g;
+            if ( $valor eq "" ) { next; }
+            my @parametros = split( " ", $valor );
+            my $interno    = $parametros[0];
+            my $dirip      = $parametros[1];
+            $interno =~ s/(.*)\/(.*)/$1/g;
+
+            if ( defined($interno) ) {
+
+                if ( $interno =~ /(.*)\/(.*)/ ) {
+                    if ( $1 eq $2 ) {
+                        $interno = $1 . "-XXXX";
+                    }
+                    else {
+                        $interno .= "-XXXX";
+                    }
+                }
+            }
+            if ( defined($estado)
+                && $estado ne "" )    # If set, is the status of 'sip show peers'
+            {
+                $interno = "SIP/" . $interno;
+                log_debug( "$heading State: $estado Extension: $interno", 32 ) if DEBUG;
+                $bloque[$contador]{"Event"}   = "Regstatus";
+                $bloque[$contador]{"Channel"} = $interno . "-XXXX";
+                $bloque[$contador]{"State"}   = $estado;
+                $bloque[$contador]{"IP"}      = $dirip;
+                $bloque[$contador]{"Server"}  = "$server";
+                $contador++;
+            }
+        }
+    }
+}
+
+sub get_meetme_pos {
+    my $server     = shift;
+    my $meetmeroom = shift;
+    my $userpos    = shift;
+
+    my $trunk_pos = 1;
+    my $heading   = "** GET MEETME ";
+
+    # This routine gets the usernum for a meetmejoin/meetmeleave event
+    # and coverts it to a button position for meetme=1 channels.
+    # Meetme's usernum starts from one, but if there are already members
+    # in the conference, then it counts for the last members number up.
+    # (no matter if some participants left the room)
+
+    if ( exists( $meetme_pos{"$server^$meetmeroom"}{"$userpos"} ) ) {
+        log_debug( "$heading Found meetme_pos($server^$meetmeroom)($userpos)", 64 ) if DEBUG;
+        $trunk_pos = $meetme_pos{"$server^$meetmeroom"}{"$userpos"};
+    }
+    else {
+        log_debug( "$heading Not Found meetme_pos($server^$meetmeroom)($userpos)", 64 ) if DEBUG;
+        my %busy_slots = ();
+        foreach my $key1 ( sort ( keys(%meetme_pos) ) ) {
+            if ( $key1 eq "$server^$meetmeroom" ) {
+                foreach my $key2 ( sort ( keys( %{ $meetme_pos{$key1} } ) ) ) {
+                    my $indice = $meetme_pos{$key1}{$key2};
+                    $busy_slots{$indice} = 1;
+                }
+            }
+        }
+        for ( $trunk_pos = 1 ; ; $trunk_pos++ ) {
+            last if ( !exists( $busy_slots{$trunk_pos} ) );
+        }
+        $meetme_pos{"$server^$meetmeroom"}{"$userpos"} = $trunk_pos;
+    }
+    log_debug( "$heading devuelve $meetmeroom=$trunk_pos", 32 ) if DEBUG;
+    return "$meetmeroom=$trunk_pos";
+}
+
+sub reserve_next_available_agent_button {
+    my $server = shift;
+    my $canal  = shift;
+    my $queue  = shift;
+
+    my @temparray = ();
+    my $done      = 0;
+
+    if ( $queueagent_buttons != 1 ) {
+
+        # Do not waste memory or cpu cicles if we do not have queueagent buttons
+        return;
+    }
+
+    # agents_on_queue stores every agent that is member of that queue
+    # no matter if its logged in or not. We only need to add/remove items
+    # from here when queuememberadded or queuememberremoved events
+
+    if ( $canal =~ m/^CLID/ ) {
+        my $extr = $extension_transfer{"$server^$canal"};
+        $extr =~ s/\d+\^(.*)/$1/g;
+        $canal = "Local/$extr";
+    }
+
+    log_debug( "RESERVE_AGENT_BUTTON server $server, canal $canal, queue $queue", 16 );
+
+    foreach my $vvalor ( @{ $agents_on_queue{"$server^$queue"} } ) {
+        if ( $vvalor eq "$server^$canal" ) {
+            log_debug( "RESERVE_AGENT_BUTTON no thanks, we already have it", 32 );
+
+            # We already have it here, return
+            return;
+        }
+    }
+
+    foreach my $vvalor ( @{ $agents_on_queue{"$server^$queue"} } ) {
+        if ( $vvalor =~ /^!/ ) {
+
+            # If it starts with ! it is available
+            log_debug( "RESERVE_AGENT_BUTTON yes please, we have a previous reservation", 32 );
+            push @temparray, "$server^$canal";
+            $done = 1;
+            last;
+        }
+        else {
+            push @temparray, $vvalor;
+        }
+    }
+    if ( $done == 0 ) {
+
+        # if there is no empty slot, insert at the end
+        push @temparray, "$server^$canal";
+        log_debug( "RESERVE_AGENT_BUTTON yes, but you will have to wait at the end of the line", 32 );
+    }
+    @temparray = unique(@temparray);
+    @{ $agents_on_queue{"$server^$queue"} } = @temparray;
+    print_agentonqueue("en reserve");
+}
+
+sub find_uniqueid {
+
+    # returns the uniqueid of a given channel
+    my $canal = shift;
+    $canal =~ s/\s//g;
+    my $server = shift;
+    my $uniqid = "";
+    my $match  = 0;
+
+    if ( keys(%datos) ) {
+        for ( keys %datos ) {
+            $match = 0;
+            while ( my ( $key, $val ) = each( %{ $datos{$_} } ) ) {
+                if ( $key eq "Channel" && $val =~ m/\Q$canal\E/ ) {
+                    $match++;
+                }
+                if ( $key eq "Server" && $val eq $server ) {
+                    $match++;
+                }
+            }
+            if ( $match > 1 ) {
+                $uniqid = $_;
+                last;
+            }
+        }
+    }
+
+    return $uniqid;
+}
+
+sub log_debug {
+    my $texto   = shift;
+    my $nivel   = shift;
+    my $verbose = "0";
+
+    if ( !defined($nivel) ) { $nivel = 1; }
+
+    if ( !defined($texto) ) { return }
+
+    if ( $debuglevel & $nivel ) {
+        $texto =~ s/\0//g;
+        if ( $texto !~ m/^\d+\.\d+\.\d+\.\d+/ ) {
+            $verbose = $texto;
+            $verbose =~ s/^\*\* ([^\s]*).*/$1/g;
+        }
+        else {
+            my $parte = $texto;
+            $parte =~ s/(\d+\.\d+\.\d+\.\d+)\s+(.*)/$1/g;
+            $verbose = $parte;
+        }
+        if ( $debuglevel == -1 ) {
+
+            # Debug log Cache
+            $debuglevel_cache .= "$texto\n";
+            $cont_debug_cache++;
+            if ( $cont_debug_cache > 1000 ) {
+                $debuglevel_cache = "";
+                $debuglevel       = 0;
+            }
+        }
+        else {
+            if ( $debuglevel_cache ne "" ) {
+                print $debuglevel_cache. "\n";
+                $debuglevel_cache = "";
+            }
+            if ( $verbose ne $global_verbose ) {
+                print "\n";
+            }
+            $global_verbose = $verbose;
+            print "$tab$texto\n";
+        }
+    }
+}
+
+sub alarma_al_minuto {
+    my $nro_servidor = 0;
+    my $heading      = "** ALARM ";
+    manager_connection();
+
+    # %cache_hit = ();   # Clears button cache
+    foreach (@p) {
+        if ( defined($_) && $_ ne "" ) {
+            log_debug( "$heading Enviando status a " . $ip_addy{$_}, 16 ) if DEBUG;
+            my @pedazos = split( /\|/, $manager_socket{$_} );
+
+            if ( $pedazos[0] eq $ip_addy{$_} ) {
+                my $contador = 0;
+                foreach my $valor (@manager_host) {
+                    if ( $valor eq $pedazos[0] ) {
+                        $nro_servidor = $contador;
+                    }
+                    $contador++;
+                }
+            }
+
+            my $comando = "Action: Command\r\n";
+            $comando .= "Command: sip show peers\r\n\r\n";
+            send_command_to_manager( $comando, $_ );
+
+            $comando = "Action: Command\r\n";
+            $comando .= "ActionID: iaxpeers\r\n";
+            $comando .= "Command: iax2 show peers\r\n\r\n";
+            send_command_to_manager( $comando, $_ );
+
+            $comando = "Action: Command\r\n";
+            $comando .= "ActionID: sccppeers\r\n";
+            $comando .= "Command: sccp show lines\r\n\r\n";
+            send_command_to_manager( $comando, $_ );
+
+            if ( $poll_voicemail == 1 ) {
+
+                # Send commands to check the mailbox status for each mailbox defined
+                while ( my ( $key, $val ) = each(%mailbox) ) {
+                    my @pedacitos = split( /\^/, $key );
+                    my $servidormbox = $pedacitos[0];
+                    if ( "$servidormbox" eq "$nro_servidor" ) {
+                        log_debug( "$heading mailbox $ip_addy{$_} $key $val", 32 ) if DEBUG;
+                        send_command_to_manager( "Action: MailboxStatus\r\nMailbox: $val\r\n\r\n", $_ );
+                    }
+                }
+            }
+        }
+    }
+    alarm($poll_interval);
+}
+
+sub send_status_to_flash {
+    my $socket       = shift;
+    my $status       = shift;
+    my $nocrypt      = shift;
+    my $encriptado   = $status;
+    my $but_no       = 0;
+    my $heading      = "** SEND_STATUS_TO_FLASH ";
+    my $contexto     = "";
+    my $cmd          = "";
+    my $cmd_crypt    = "";
+    my $data         = "";
+    my $data_crypt   = "";
+    my $noencriptado = "";
+
+    if ( !defined($socket) ) {
+        log_debug( "$heading socket $socket not open!!!", 64 ) if DEBUG;
+    }
+
+    if ( $encriptado =~ /key\|0/ ) {
+        $but_no = '0';
+        $encriptado =~ m/(.*)\|(.*)\|(.*)/;
+        $cmd  = $2;
+        $data = $1;
+
+    }
+    else {
+        $but_no = $status;
+        $but_no =~ s/(\d+)(.*)\|(.*)/$1/g;
+        $contexto = $status;
+        $contexto =~ s/([^\|]*).*/$1/g;
+        $contexto =~ m/(.*)\@(.*)/;
+
+        if ( defined($2) ) {
+            $contexto = $2;
+        }
+        else {
+            $contexto = "";
+        }
+        $status =~ m/(.*)\|(.*)\|(.*)/;
+        $cmd  = $2;
+        $data = $3;
+
+        if ( $contexto ne "" && $cmd ne "restrict" ) {
+            $but_no .= "\@$contexto";
+        }
+
+    }
+
+    if ( $flash_contexto{$socket} ne $contexto && $but_no ne "0" ) {
+
+        # If the context does not match, exit without queueing anything
+        return;
+    }
+
+    if ( !defined( $no_encryption{"$socket"} ) ) {
+        $no_encryption{"$socket"} = 0;
+    }
+
+    $noencriptado = "<response btn=\"$but_no\" cmd=\"$cmd\" data=\"$data\"/>\0";
+    if ( !defined( $keys_socket{$socket} ) || $nocrypt == 1 || $no_encryption{$socket} == 1 ) {
+        $encriptado = "<response btn=\"$but_no\" cmd=\"$cmd\" data=\"$data\"/>\0";
+        if ( $cmd eq "key" ) {
+            $keys_socket{$socket} = $data;
+        }
+    }
+    else {
+        $cmd_crypt  = &TEAencrypt( $cmd,  $keys_socket{"$socket"} );
+        $data_crypt = &TEAencrypt( $data, $keys_socket{"$socket"} );
+        $encriptado = "<response btn=\"$but_no\" cmd=\"$cmd_crypt\" data=\"$data_crypt\">\0";
+        if ( $cmd eq "key" ) {
+            $keys_socket{$socket} = $data;
+        }
+    }
+    if ( !defined( $ip_addy{$socket} ) ) {
+        log_debug( "Skip actual_syswrite to $socket cause it does not exists!", 128 ) if DEBUG;
+    }
+    else {
+        actual_syswrite( $socket, $encriptado, "isclient", $noencriptado );
+    }
+
+}
+
+sub manager_login_md5 {
+    my $challenge = shift;
+    my $handle    = shift;
+    my @partes    = split( /\|/, $manager_socket{$handle} );
+
+    my $md5clave = MD5HexDigest( $challenge . $partes[2] );
+
+    $command = "Action: Login\r\n";
+    $command .= "Username: $partes[1]\r\n";
+    $command .= "AuthType: MD5\r\n";
+    $command .= "Key: $md5clave\r\n\r\n";
+    send_command_to_manager( $command, $handle, 1 );
+}
+
+sub send_command_to_manager {
+    my $comando            = shift;
+    my $socket             = shift;
+    my $noneedtoauth       = shift;
+    my $astmanproxy_server = shift;
+    my @todos_sockets      = ();
+
+    if ( !defined($socket) && $astmanproxy_server eq "" ) {
+        log_debug( "No socket defined nor astmanproxy", 32 ) if DEBUG;
+        return;
+    }
+
+    if ( !defined($noneedtoauth) ) {
+        $noneedtoauth = 0;
+    }
+
+    if ( defined($astmanproxy_server) ) {
+        $comando = "Server: $astmanproxy_server\r\n" . $comando;
+    }
+
+    if ( !defined($astmanproxy_server) ) {
+        $astmanproxy_server = "";
+    }
+
+    if ( !defined( $autenticado{$socket} ) && $noneedtoauth == 0 && $astmanproxy_server eq "" ) {
+        log_debug( "Cannot send command to " . $ip_addy{$socket} . " (unauthenticated or connection failed)", 1 )
+          if DEBUG;
+        return;
+    }
+
+    #    my @partes = split( /\|/, $manager_socket{$socket} );
+
+    #    $comando = "";
+
+    if ( $comando eq "" ) {
+        return;
+    }
+
+    if ( !defined($socket) ) {
+        @todos_sockets = @p;
+    }
+    else {
+        push @todos_sockets, $socket;
+    }
+
+    foreach (@todos_sockets) {
+        my $sockwrite = $_;
+        if ( !defined($sockwrite) || $sockwrite eq "" ) { next; }
+        my @lineas = split( "\r\n", $comando );
+        foreach my $linea (@lineas) {
+            push @{ $manager_queue{$sockwrite} }, "$linea\r\n";
+        }
+        $global_verbose = "separator";
+        push @{ $manager_queue{$sockwrite} }, "\r\n";
+    }
+}
+
+sub recompute_queues {
+    my $canalid = shift;
+    my @return_corto;
+    my @return_ocupado;
+    my $maxtime = 0;
+
+    my $header = "**RECOMP QUEUE";
+    log_debug( "$header canalid $canalid", 1 ) if DEBUG;
+    my $queue_to_recompute = $cola->{$canalid}{QUEUE};
+    my $position_removed   = $cola->{$canalid}{POSITION};
+
+    log_debug( "$header queue_to_recompute $queue_to_recompute", 1 ) if DEBUG;
+    log_debug( "$header position removed $position_removed",     1 ) if DEBUG;
+
+    if ( $queue_hide == 1 ) {
+        push @return_corto,
+          $cola->{$canalid}{QUEUE} . "="
+          . $cola->{$canalid}{POSITION}
+          . "|setalpha|000|"
+          . $cola->{$canalid}{QUEUE} . "-"
+          . $cola->{$canalid}{SERVER}
+          . "|$canalid";
+    }
+    push @return_corto,
+      $cola->{$canalid}{QUEUE} . "="
+      . $cola->{$canalid}{POSITION}
+      . "|corto||"
+      . $cola->{$canalid}{QUEUE} . "-"
+      . $cola->{$canalid}{SERVER}
+      . "|$canalid";
+    delete $cola->{$canalid};
+    my $save_id;
+
+    foreach my $id ( keys %{$cola} ) {
+        if ( $queue_to_recompute eq $cola->{$id}{QUEUE} ) {
+            $save_id = $id;
+            my $diftime = time() - $cola->{$id}{TIME};
+            if ( $diftime > $maxtime ) {
+                $maxtime = $diftime;
+            }
+
+            if ( $cola->{$id}{POSITION} > $position_removed ) {
+                my $clidtext = $cola->{$id}{CLIDNAME} . " " . $cola->{$id}{CLID};
+                if ( $queue_hide == 1 ) {
+                    push @return_corto,
+                      $cola->{$id}{QUEUE} . "="
+                      . $cola->{$id}{POSITION}
+                      . "|setalpha|000|"
+                      . $cola->{$id}{QUEUE} . "-"
+                      . $cola->{$id}{SERVER} . "|$id";
+                }
+                push @return_corto,
+                  $cola->{$id}{QUEUE} . "="
+                  . $cola->{$id}{POSITION}
+                  . "|corto||"
+                  . $cola->{$id}{QUEUE} . "-"
+                  . $cola->{$id}{SERVER} . "|$id";
+                $cola->{$id}{POSITION}--;
+                push @return_ocupado,
+                  $cola->{$id}{QUEUE} . "="
+                  . $cola->{$id}{POSITION}
+                  . "|settimer|$diftime|"
+                  . $cola->{$id}{QUEUE} . "-"
+                  . $cola->{$id}{SERVER} . "|$id";
+                push @return_ocupado,
+                  $cola->{$id}{QUEUE} . "="
+                  . $cola->{$id}{POSITION}
+                  . "|state|busy|"
+                  . $cola->{$id}{QUEUE} . "-"
+                  . $cola->{$id}{SERVER} . "|$id";
+                push @return_ocupado, $cola->{$id}{QUEUE} . "|state|busy|" . $cola->{$id}{QUEUE} . "-" . $cola->{$id}{SERVER} . "|$id";
+                push @return_ocupado,
+                  $cola->{$id}{QUEUE} . "|settimer|0\@STOP|" . $cola->{$id}{QUEUE} . "-" . $cola->{$id}{SERVER} . "|$id";
+                push @return_ocupado,
+                  $cola->{$id}{QUEUE} . "="
+                  . $cola->{$id}{POSITION}
+                  . "|settext|[$clidtext]|"
+                  . $cola->{$id}{QUEUE} . "-"
+                  . $cola->{$id}{SERVER} . "|$id";
+            }
+        }
+    }
+    if ( defined($save_id) ) {
+        push @return_ocupado,
+          $cola->{$save_id}{QUEUE} . "|settimer|$maxtime\@UP|" . $cola->{$save_id}{QUEUE} . "-" . $cola->{$save_id}{SERVER} . "|$save_id";
+    }
+
+    @return_ocupado = unique(@return_ocupado);
+
+    if (@return_corto) {
+        my @todos = ();
+        push @todos, @return_corto;
+        push @todos, @return_ocupado;
+        return @todos;
+    }
+
+    # TEST|corto|&waitingonqueue,0,&|TEST-0|SIP/16-ea0c
+}
+
+sub split_callerid {
+    my $clid         = shift;
+    my @return       = ();
+    my $calleridname = "";
+    my $calleridnum  = "";
+
+    if ( $clid =~ /</ ) {
+
+        #$clid =~ /"?(.*)<(.*)>/;
+        $clid =~ /"?'?([^"']*)"?'?\s+?<(.*)>/;
+        $calleridname = $1;
+        $calleridnum  = $2;
+        if ( !defined($calleridname) ) { $calleridname = ""; }
+        if ( !defined($calleridnum) )  { $calleridnum  = ""; }
+        if ( $calleridname eq $calleridnum ) {
+            $calleridname = "";
+        }
+    }
+    else {
+        $calleridnum  = $clid;
+        $calleridname = "";
+    }
+    push @return, $calleridnum;
+    push @return, $calleridname;
+
+    return @return;
+}
+
+sub is_number {
+    my $num = shift;
+    if ( !defined($num) ) { return 1; }
+    if ( $num =~ /[^0-9]/ ) {
+        return 0;
+    }
+    else {
+        return 1;
+    }
+}
+
+sub close_all {
+    foreach my $file (@all_flash_files) {
+        log_debug( "Removing $file...", 1 ) if DEBUG;
+        unlink($file);
+    }
+    foreach my $hd ( $O->handles ) {
+        my $peer_ip = $ip_addy{$hd};
+        if ( defined($peer_ip) ) {
+            log_debug( "Closing " . $peer_ip, 1 ) if DEBUG;
+        }
+
+        $O->remove($hd);
+        close($hd);
+    }
+
+    log_debug( "Exiting...", 1 ) if DEBUG;
+    exit(0);
+}
+
+sub inArray {
+    my $val = shift;
+    for my $elem (@_) {
+        if ( $val eq $elem ) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+sub encode_base64 {
+    my $res = "";
+    my $eol = "\n";
+    pos( $_[0] ) = 0;
+    while ( $_[0] =~ /(.{1,45})/gs ) {
+        $res .= substr( pack( "u", $1 ), 1 );
+        chop($res);
+    }
+    $res =~ tr|` -_|AA-Za-z0-9+/|;    # `
+    my $padding = ( 3 - length( $_[0] ) % 3 ) % 3;
+    $res =~ s/.{$padding}$/"=" x $padding/e if $padding;
+
+    return $res;
+}
+
+sub format_clid {
+
+    # Subroutine to format the caller id number
+    # The format string is in the form "(xxx) xxx-xxxx"
+    # Every x is counted as a digit, any other text is
+    # displayed as is. The digits are replaced from right
+    # to left. If there are digits left, they are discarded
+
+    my $numero       = shift;
+    my $format       = shift;
+    my @chars_number = ();
+    my @chars_format = ();
+    my @result       = ();
+    my $devuelve     = "";
+
+    if ( !is_number($numero) ) {
+        return $numero;
+    }
+
+    if ($clid_privacy) {
+        return "n/a";
+    }
+
+    @chars_number = split( //, $numero );
+    @chars_format = split( //, $format );
+
+    @chars_format = reverse @chars_format;
+
+    my $parate = 0;
+    foreach (@chars_format) {
+        if (@chars_number) {
+            if ( $_ eq "x" or $_ eq "X" ) {
+                push( @result, pop @chars_number );
+            }
+            else {
+                push( @result, $_ );
+            }
+        }
+        else {
+            if ($parate) { last; }
+
+            if ( $_ eq "x" or $_ eq "X" or $_ ne "(" ) {
+                $parate = 1;
+                next;
+            }
+            else {
+                push( @result, $_ );
+                last;
+            }
+        }
+    }
+
+    @result = reverse @result;
+    $devuelve = join( "", @result );
+    return $devuelve;
+}
+
+sub generate_random_password {
+    my $passwordsize = shift;
+    my @alphanumeric = ( 'a' .. 'z', 'A' .. 'Z', 0 .. 9 );
+    my $randpassword = join '', map $alphanumeric[ rand @alphanumeric ], 0 .. $passwordsize;
+
+    return $randpassword;
+}
+
+sub sends_incorrect {
+    my $socket = shift;
+    my $manda  = "0|incorrect|0";
+    my $T      = send_status_to_flash( $socket, $manda, 0 );
+}
+
+sub sends_correct {
+    my $socket = shift;
+    my $manda  = "0|correct|0";
+    my $T      = send_status_to_flash( $socket, $manda, 0 );
+}
+
+sub sends_version {
+    my $socket   = shift;
+    my $nocrypt  = 0;
+    my $contexto = $flash_contexto{$socket};
+    my $boton    = "0";
+    if ( $contexto ne "" ) {
+        $boton .= "\@$contexto";
+    }
+    my $version_string = "$boton|version|$FOP_VERSION";
+    if ( !$keys_socket{"$socket"} ) {
+        $nocrypt = 1;
+    }
+    send_status_to_flash( $socket, $version_string, $nocrypt );
+}
+
+sub sends_key {
+
+    # Generate random key por padding the password
+    # and write it to the client
+    my $socket  = shift;
+    my $keylen  = int( rand(22) );
+    my $nocrypt = 0;
+    $keylen += 15;
+    my $randomkey = generate_random_password($keylen);
+    my $mandakey  = "$randomkey|key|0";
+    if ( !$keys_socket{"$socket"} ) {
+        $nocrypt = 1;
+    }
+    if ( !defined( $keys_socket{$socket} ) ) {
+        $keys_socket{$socket} = $randomkey;
+    }
+    send_status_to_flash( $socket, $mandakey, $nocrypt );
+}
+
+sub unique {
+    my %seen;
+    my @return = ();
+    return grep { !$seen{$_}++ } @_;
+
+    #@return = grep { !$seen{$_}++ } @_;
+    #@return = sort ( @return );
+    #return @return;
+}
+
+sub MD5Digest {
+    my $context = &MD5Init();
+
+    # security feature: uncomment and put your own "magic string"
+    # note: MD5test.pl will not work with your magic string, of course
+    # my $magicString = '!@#$%^';
+    # &MD5Update($context, $magicString, length($magicString));
+
+    # this should be done always
+    &MD5Update( $context, $_[0], length( $_[0] ) );
+
+    return &MD5Final($context);
+}
+
+#
+# same as Digest but returns digest in a printable (hex) form
+#
+
+sub MD5HexDigest {
+    return unpack( "H*", &MD5Digest(@_) );
+}
+
+#
+# MD5 implementation is below
+#
+
+# derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
+
+# Original context structure
+# typedef struct {
+#
+#       UINT4 state[4];                                   /* state (ABCD) */
+#       UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+#       unsigned char buffer[64];                         /* input buffer */
+#
+# } MD5_CTX;
+
+# Constants for MD5Transform routine.
+
+sub S11 { 7 }
+sub S12 { 12 }
+sub S13 { 17 }
+sub S14 { 22 }
+sub S21 { 5 }
+sub S22 { 9 }
+sub S23 { 14 }
+sub S24 { 20 }
+sub S31 { 4 }
+sub S32 { 11 }
+sub S33 { 16 }
+sub S34 { 23 }
+sub S41 { 6 }
+sub S42 { 10 }
+sub S43 { 15 }
+sub S44 { 21 }
+
+# F, G, H and I are basic MD5 functions.
+
+sub F { my ( $x, $y, $z ) = @_; ( ( ($x) & ($y) ) | ( ( ~$x ) & ($z) ) ); }
+sub G { my ( $x, $y, $z ) = @_; ( ( ($x) & ($z) ) | ( ($y) & ( ~$z ) ) ); }
+sub H { my ( $x, $y, $z ) = @_; ( ($x) ^ ($y) ^ ($z) ); }
+sub I { my ( $x, $y, $z ) = @_; ( ($y) ^ ( ($x) | ( ~$z ) ) ); }
+
+# ROTATE_LEFT rotates x left n bits.
+# Note: "& ~(-1 << $n)" is not in C version
+#
+sub ROTATE_LEFT {
+    my ( $x, $n ) = @_;
+    ( $x << $n ) | ( ( $x >> ( 32 - $n ) & ~( -1 << $n ) ) );
+}
+
+# FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+# Rotation is separate from addition to prevent recomputation.
+
+sub FF {
+    my ( $a, $b, $c, $d, $x, $s, $ac ) = @_;
+
+    $a += &F( $b, $c, $d ) + $x + $ac;
+    $a = &ROTATE_LEFT( $a, $s );
+    $a += $b;
+
+    return $a;
+}
+
+sub GG {
+    my ( $a, $b, $c, $d, $x, $s, $ac ) = @_;
+
+    $a += &G( $b, $c, $d ) + $x + $ac;
+    $a = &ROTATE_LEFT( $a, $s );
+    $a += $b;
+
+    return $a;
+}
+
+sub HH {
+    my ( $a, $b, $c, $d, $x, $s, $ac ) = @_;
+    $a += &H( $b, $c, $d ) + $x + $ac;
+    $a = &ROTATE_LEFT( $a, $s );
+    $a += $b;
+
+    return $a;
+}
+
+sub II {
+    my ( $a, $b, $c, $d, $x, $s, $ac ) = @_;
+
+    $a += &I( $b, $c, $d ) + $x + $ac;
+    $a = &ROTATE_LEFT( $a, $s );
+    $a += $b;
+
+    return $a;
+}
+
+# MD5 initialization. Begins an MD5 operation, writing a new context.
+
+sub MD5Init {
+    my $context = {};
+
+    @{ $context->{count} } = 2;
+    $context->{count}[0] = $context->{count}[1] = 0;
+    $context->{buffer} = '';
+
+    # Load magic initialization constants.
+
+    @{ $context->{state} } = 4;
+    $context->{state}[0] = 0x67452301;
+    $context->{state}[1] = 0xefcdab89;
+    $context->{state}[2] = 0x98badcfe;
+    $context->{state}[3] = 0x10325476;
+
+    return $context;
+}
+
+# MD5 block update operation. Continues an MD5 message-digest
+# operation, processing another message block, and updating the context.
+
+sub MD5Update {
+    my ( $context, $input, $inputLen ) = @_;
+
+    # Compute number of bytes mod 64
+    my $index = ( ( $context->{count}[0] >> 3 ) & 0x3F );
+
+    # Update number of bits
+    if ( ( $context->{count}[0] += ( $inputLen << 3 ) ) < ( $inputLen << 3 ) ) {
+        $context->{count}[1]++;
+        $context->{count}[1] += ( $inputLen >> 29 );
+    }
+
+    my $partLen = 64 - $index;
+
+    # Transform as many times as possible.
+
+    my $i;
+    if ( $inputLen >= $partLen ) {
+
+        substr( $context->{buffer}, $index, $partLen ) = substr( $input, 0, $partLen );
+
+        &MD5Transform( \@{ $context->{state} }, $context->{buffer} );
+
+        for ( $i = $partLen ; $i + 63 < $inputLen ; $i += 64 ) {
+            &MD5Transform( $context->{state}, substr( $input, $i ) );
+        }
+
+        $index = 0;
+    }
+    else {
+        $i = 0;
+    }
+
+    # Buffer remaining input
+    substr( $context->{buffer}, $index, $inputLen - $i ) = substr( $input, $i, $inputLen - $i );
+}
+
+# MD5 finalization. Ends an MD5 message-digest operation, writing the
+# the message digest and zeroizing the context.
+
+sub MD5Final {
+    my $context = shift;
+
+    # Save number of bits
+    my $bits = &Encode( \@{ $context->{count} }, 8 );
+
+    # Pad out to 56 mod 64.
+    my ( $index, $padLen );
+    $index  = ( $context->{count}[0] >> 3 ) & 0x3f;
+    $padLen = ( $index < 56 ) ? ( 56 - $index ) : ( 120 - $index );
+
+    &MD5Update( $context, $PADDING, $padLen );
+
+    # Append length (before padding)
+    MD5Update( $context, $bits, 8 );
+
+    # Store state in digest
+    my $digest = &Encode( \@{ $context->{state} }, 16 );
+
+    # &MD5_memset ($context, 0);
+
+    return $digest;
+}
+
+# MD5 basic transformation. Transforms state based on block.
+
+sub MD5Transform {
+    my ( $state, $block ) = @_;
+
+    my ( $a, $b, $c, $d ) = @{$state};
+    my @x = 16;
+
+    &Decode( \@x, $block, 64 );
+
+    # Round 1
+    $a = &FF( $a, $b, $c, $d, $x[0],  S11, 0xd76aa478 );    # 1
+    $d = &FF( $d, $a, $b, $c, $x[1],  S12, 0xe8c7b756 );    # 2
+    $c = &FF( $c, $d, $a, $b, $x[2],  S13, 0x242070db );    # 3
+    $b = &FF( $b, $c, $d, $a, $x[3],  S14, 0xc1bdceee );    # 4
+    $a = &FF( $a, $b, $c, $d, $x[4],  S11, 0xf57c0faf );    # 5
+    $d = &FF( $d, $a, $b, $c, $x[5],  S12, 0x4787c62a );    # 6
+    $c = &FF( $c, $d, $a, $b, $x[6],  S13, 0xa8304613 );    # 7
+    $b = &FF( $b, $c, $d, $a, $x[7],  S14, 0xfd469501 );    # 8
+    $a = &FF( $a, $b, $c, $d, $x[8],  S11, 0x698098d8 );    # 9
+    $d = &FF( $d, $a, $b, $c, $x[9],  S12, 0x8b44f7af );    # 10
+    $c = &FF( $c, $d, $a, $b, $x[10], S13, 0xffff5bb1 );    # 11
+    $b = &FF( $b, $c, $d, $a, $x[11], S14, 0x895cd7be );    # 12
+    $a = &FF( $a, $b, $c, $d, $x[12], S11, 0x6b901122 );    # 13
+    $d = &FF( $d, $a, $b, $c, $x[13], S12, 0xfd987193 );    # 14
+    $c = &FF( $c, $d, $a, $b, $x[14], S13, 0xa679438e );    # 15
+    $b = &FF( $b, $c, $d, $a, $x[15], S14, 0x49b40821 );    # 16
+
+    # Round 2
+    $a = &GG( $a, $b, $c, $d, $x[1],  S21, 0xf61e2562 );    # 17
+    $d = &GG( $d, $a, $b, $c, $x[6],  S22, 0xc040b340 );    # 18
+    $c = &GG( $c, $d, $a, $b, $x[11], S23, 0x265e5a51 );    # 19
+    $b = &GG( $b, $c, $d, $a, $x[0],  S24, 0xe9b6c7aa );    # 20
+    $a = &GG( $a, $b, $c, $d, $x[5],  S21, 0xd62f105d );    # 21
+    $d = &GG( $d, $a, $b, $c, $x[10], S22, 0x2441453 );     # 22
+    $c = &GG( $c, $d, $a, $b, $x[15], S23, 0xd8a1e681 );    # 23
+    $b = &GG( $b, $c, $d, $a, $x[4],  S24, 0xe7d3fbc8 );    # 24
+    $a = &GG( $a, $b, $c, $d, $x[9],  S21, 0x21e1cde6 );    # 25
+    $d = &GG( $d, $a, $b, $c, $x[14], S22, 0xc33707d6 );    # 26
+    $c = &GG( $c, $d, $a, $b, $x[3],  S23, 0xf4d50d87 );    # 27
+    $b = &GG( $b, $c, $d, $a, $x[8],  S24, 0x455a14ed );    # 28
+    $a = &GG( $a, $b, $c, $d, $x[13], S21, 0xa9e3e905 );    # 29
+    $d = &GG( $d, $a, $b, $c, $x[2],  S22, 0xfcefa3f8 );    # 30
+    $c = &GG( $c, $d, $a, $b, $x[7],  S23, 0x676f02d9 );    # 31
+    $b = &GG( $b, $c, $d, $a, $x[12], S24, 0x8d2a4c8a );    # 32
+
+    # Round 3
+    $a = &HH( $a, $b, $c, $d, $x[5],  S31, 0xfffa3942 );    # 33
+    $d = &HH( $d, $a, $b, $c, $x[8],  S32, 0x8771f681 );    # 34
+    $c = &HH( $c, $d, $a, $b, $x[11], S33, 0x6d9d6122 );    # 35
+    $b = &HH( $b, $c, $d, $a, $x[14], S34, 0xfde5380c );    # 36
+    $a = &HH( $a, $b, $c, $d, $x[1],  S31, 0xa4beea44 );    # 37
+    $d = &HH( $d, $a, $b, $c, $x[4],  S32, 0x4bdecfa9 );    # 38
+    $c = &HH( $c, $d, $a, $b, $x[7],  S33, 0xf6bb4b60 );    # 39
+    $b = &HH( $b, $c, $d, $a, $x[10], S34, 0xbebfbc70 );    # 40
+    $a = &HH( $a, $b, $c, $d, $x[13], S31, 0x289b7ec6 );    # 41
+    $d = &HH( $d, $a, $b, $c, $x[0],  S32, 0xeaa127fa );    # 42
+    $c = &HH( $c, $d, $a, $b, $x[3],  S33, 0xd4ef3085 );    # 43
+    $b = &HH( $b, $c, $d, $a, $x[6],  S34, 0x4881d05 );     # 44
+    $a = &HH( $a, $b, $c, $d, $x[9],  S31, 0xd9d4d039 );    # 45
+    $d = &HH( $d, $a, $b, $c, $x[12], S32, 0xe6db99e5 );    # 46
+    $c = &HH( $c, $d, $a, $b, $x[15], S33, 0x1fa27cf8 );    # 47
+    $b = &HH( $b, $c, $d, $a, $x[2],  S34, 0xc4ac5665 );    # 48
+
+    # Round 4
+    $a = &II( $a, $b, $c, $d, $x[0],  S41, 0xf4292244 );    # 49
+    $d = &II( $d, $a, $b, $c, $x[7],  S42, 0x432aff97 );    # 50
+    $c = &II( $c, $d, $a, $b, $x[14], S43, 0xab9423a7 );    # 51
+    $b = &II( $b, $c, $d, $a, $x[5],  S44, 0xfc93a039 );    # 52
+    $a = &II( $a, $b, $c, $d, $x[12], S41, 0x655b59c3 );    # 53
+    $d = &II( $d, $a, $b, $c, $x[3],  S42, 0x8f0ccc92 );    # 54
+    $c = &II( $c, $d, $a, $b, $x[10], S43, 0xffeff47d );    # 55
+    $b = &II( $b, $c, $d, $a, $x[1],  S44, 0x85845dd1 );    # 56
+    $a = &II( $a, $b, $c, $d, $x[8],  S41, 0x6fa87e4f );    # 57
+    $d = &II( $d, $a, $b, $c, $x[15], S42, 0xfe2ce6e0 );    # 58
+    $c = &II( $c, $d, $a, $b, $x[6],  S43, 0xa3014314 );    # 59
+    $b = &II( $b, $c, $d, $a, $x[13], S44, 0x4e0811a1 );    # 60
+    $a = &II( $a, $b, $c, $d, $x[4],  S41, 0xf7537e82 );    # 61
+    $d = &II( $d, $a, $b, $c, $x[11], S42, 0xbd3af235 );    # 62
+    $c = &II( $c, $d, $a, $b, $x[2],  S43, 0x2ad7d2bb );    # 63
+    $b = &II( $b, $c, $d, $a, $x[9],  S44, 0xeb86d391 );    # 64
+
+    $state->[0] += $a;
+    $state->[1] += $b;
+    $state->[2] += $c;
+    $state->[3] += $d;
+
+    # Zeroize sensitive information.
+    # MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+# Encodes input (UINT4) into output (unsigned char). Assumes len is
+# a multiple of 4.
+
+sub Encode {
+    my ( $input, $len ) = @_;
+
+    my $output = '';
+    my ( $i, $j );
+    for ( $i = 0, $j = 0 ; $j < $len ; $i++, $j += 4 ) {
+        substr( $output, $j + 0, 1 ) = chr( $input->[$i] & 0xff );
+        substr( $output, $j + 1, 1 ) = chr( ( $input->[$i] >> 8 ) & 0xff );
+        substr( $output, $j + 2, 1 ) = chr( ( $input->[$i] >> 16 ) & 0xff );
+        substr( $output, $j + 3, 1 ) = chr( ( $input->[$i] >> 24 ) & 0xff );
+    }
+
+    return $output;
+}
+
+# Decodes input (unsigned char) into output (UINT4). Assumes len is
+# a multiple of 4.
+
+sub Decode {
+    my ( $output, $input, $len ) = @_;
+
+    my ( $i, $j );
+
+    for ( $i = 0, $j = 0 ; $j < $len ; $i++, $j += 4 ) {
+        $output->[$i] =
+          ( ord( substr( $input, $j + 0, 1 ) ) ) | ( ord( substr( $input, $j + 1, 1 ) ) << 8 ) |
+          ( ord( substr( $input, $j + 2, 1 ) ) << 16 ) | ( ord( substr( $input, $j + 3, 1 ) ) << 24 );
+    }
+}
+#########################################################################
+# TEA Encryption algorithm
+#
+#########################################################################
+#        This Perl module is Copyright (c) 2000, Peter J Billam         #
+#               c/o P J B Computing, www.pjb.com.au                     #
+#########################################################################
+
+sub binary2ascii {
+    return &str2ascii( &binary2str(@_) );
+}
+
+sub ascii2binary {
+    return &str2binary( &ascii2str( $_[$[] ) );
+}
+
+sub str2binary {
+    my @str      = split //, $_[$[];
+    my @intarray = ();
+    my $ii       = $[;
+    while (1) {
+        last unless @str;
+        $intarray[$ii] = ( 0xFF & ord shift @str ) << 24;
+        last unless @str;
+        $intarray[$ii] |= ( 0xFF & ord shift @str ) << 16;
+        last unless @str;
+        $intarray[$ii] |= ( 0xFF & ord shift @str ) << 8;
+        last unless @str;
+        $intarray[$ii] |= 0xFF & ord shift @str;
+        $ii++;
+    }
+    return @intarray;
+}
+
+sub binary2str {
+    my @str = ();
+    foreach my $i (@_) {
+        push @str, chr( 0xFF & ( $i >> 24 ) ), chr( 0xFF & ( $i >> 16 ) ), chr( 0xFF & ( $i >> 8 ) ), chr( 0xFF & $i );
+    }
+    return join '', @str;
+}
+
+sub ascii2str {
+    my $a = $_[$[];    # converts pseudo-base64 to string of bytes
+    $a =~ tr#A-Za-z0-9+_##cd;
+    my $ia = $[ - 1;
+    my $la = length $a;    # BUG not length, final!
+    my $ib = $[;
+    my @b  = ();
+    my $carry;
+    while (1) {            # reads 4 ascii chars and produces 3 bytes
+        $ia++;
+        last if ( $ia >= $la );
+        $b[$ib] = $a2b{ substr $a, $ia + $[, 1 } << 2;
+        $ia++;
+        last if ( $ia >= $la );
+        $carry = $a2b{ substr $a, $ia + $[, 1 };
+        $b[$ib] |= ( $carry >> 4 );
+        $ib++;
+
+        # if low 4 bits of $carry are 0 and its the last char, then break
+        $carry = 0xF & $carry;
+        last if ( $carry == 0 && $ia == ( $la - 1 ) );
+        $b[$ib] = $carry << 4;
+        $ia++;
+        last if ( $ia >= $la );
+        $carry = $a2b{ substr $a, $ia + $[, 1 };
+        $b[$ib] |= ( $carry >> 2 );
+        $ib++;
+
+        # if low 2 bits of $carry are 0 and its the last char, then break
+        $carry = 03 & $carry;
+        last if ( $carry == 0 && $ia == ( $la - 1 ) );
+        $b[$ib] = $carry << 6;
+        $ia++;
+        last if ( $ia >= $la );
+        $b[$ib] |= $a2b{ substr $a, $ia + $[, 1 };
+        $ib++;
+    }
+    return pack 'c*', @b;
+}
+
+sub str2ascii {
+    my $b  = $_[$[];      # converts string of bytes to pseudo-base64
+    my $ib = $[;
+    my $lb = length $b;
+    my @s  = ();
+    my $b1;
+    my $b2;
+    my $b3;
+    my $carry;
+
+    while (1) {           # reads 3 bytes and produces 4 ascii chars
+        if ( $ib >= $lb ) { last; }
+        $b1 = ord substr $b, $ib + $[, 1;
+        $ib++;
+        push @s, $b2a{ $b1 >> 2 };
+        $carry = 03 & $b1;
+        if ( $ib >= $lb ) { push @s, $b2a{ $carry << 4 }; last; }
+        $b2 = ord substr $b, $ib + $[, 1;
+        $ib++;
+        push @s, $b2a{ ( $b2 >> 4 ) | ( $carry << 4 ) };
+        $carry = 0xF & $b2;
+        if ( $ib >= $lb ) { push @s, $b2a{ $carry << 2 }; last; }
+        $b3 = ord substr $b, $ib + $[, 1;
+        $ib++;
+        push @s, $b2a{ ( $b3 >> 6 ) | ( $carry << 2 ) }, $b2a{ 077 & $b3 };
+        if ( !$ENV{REMOTE_ADDR} && ( ( $ib % 36 ) == 0 ) ) { push @s, "\n"; }
+    }
+    return join( '', @s );
+}
+
+sub asciidigest {    # returns 22-char ascii signature
+    return &binary2ascii( &binarydigest( $_[$[] ) );
+}
+
+sub binarydigest {
+    my $str = $_[$[];    # returns 4 32-bit-int binary signature
+                         # warning: mode of use invented by Peter Billam 1998, needs checking !
+    return '' unless $str;
+
+    # add 1 char ('0'..'15') at front to specify no of pad chars at end ...
+    my $npads = 15 - ( ( length $str ) % 16 );
+    $str = chr($npads) . $str;
+    if ($npads) { $str .= "\0" x $npads; }
+    my @str = &str2binary($str);
+    my @key = ( 0x61626364, 0x62636465, 0x63646566, 0x64656667 );
+
+    my ( $cswap, $v0, $v1, $v2, $v3 );
+    my $c0 = 0x61626364;
+    my $c1 = 0x62636465;    # CBC Initial Value. Retain !
+    my $c2 = 0x61626364;
+    my $c3 = 0x62636465;    # likewise (abcdbcde).
+    while (@str) {
+
+        # shift 2 blocks off front of str ...
+        $v0 = shift @str;
+        $v1 = shift @str;
+        $v2 = shift @str;
+        $v3 = shift @str;
+
+        # cipher them XOR'd with previous stage ...
+        ( $c0, $c1 ) = &tea_code( $v0 ^ $c0, $v1 ^ $c1, @key );
+        ( $c2, $c3 ) = &tea_code( $v2 ^ $c2, $v3 ^ $c3, @key );
+
+        # mix up the two cipher blocks with a 4-byte left rotation ...
+        $cswap = $c0;
+        $c0    = $c1;
+        $c1    = $c2;
+        $c2    = $c3;
+        $c3    = $cswap;
+    }
+    return ( $c0, $c1, $c2, $c3 );
+}
+
+sub TEAencrypt {
+    my ( $str, $key ) = @_;    # encodes with CBC (Cipher Block Chaining)
+    use integer;
+    return '' unless $str;
+    return '' unless $key;
+    @key = &binarydigest($key);
+
+    # add 1 char ('0'..'7') at front to specify no of pad chars at end ...
+    my $npads = 7 - ( ( length $str ) % 8 );
+    $str = chr( $npads | ( 0xF8 & &rand_byte ) ) . $str;
+    if ($npads) {
+        my $padding = pack 'CCCCCCC', &rand_byte, &rand_byte, &rand_byte, &rand_byte, &rand_byte, &rand_byte, &rand_byte;
+        $str = $str . substr( $padding, $[, $npads );
+    }
+    my @pblocks = &str2binary($str);
+    my $v0;
+    my $v1;
+    my $c0 = 0x61626364;
+    my $c1 = 0x62636465;    # CBC Initial Value. Retain !
+    my @cblocks;
+    while (1) {
+        last unless @pblocks;
+        $v0 = shift @pblocks;
+        $v1 = shift @pblocks;
+        ( $c0, $c1 ) = &tea_code( $v0 ^ $c0, $v1 ^ $c1, @key );
+        push @cblocks, $c0, $c1;
+    }
+    my $btmp = &binary2str(@cblocks);
+    return &str2ascii( &binary2str(@cblocks) );
+}
+
+sub TEAdecrypt {
+    my ( $acstr, $key ) = @_;    # decodes with CBC
+    use integer;
+    return '' unless $acstr;
+    return '' unless $key;
+    @key = &binarydigest($key);
+    my $v0;
+    my $v1;
+    my $c0;
+    my $c1;
+    my @pblocks = ();
+    my $de0;
+    my $de1;
+    my $lastc0  = 0x61626364;
+    my $lastc1  = 0x62636465;                          # CBC Init Val. Retain!
+    my @cblocks = &str2binary( &ascii2str($acstr) );
+
+    while (1) {
+        last unless @cblocks;
+        $c0 = shift @cblocks;
+        $c1 = shift @cblocks;
+        ( $de0, $de1 ) = &tea_decode( $c0, $c1, @key );
+        $v0 = $lastc0 ^ $de0;
+        $v1 = $lastc1 ^ $de1;
+        push @pblocks, $v0, $v1;
+        $lastc0 = $c0;
+        $lastc1 = $c1;
+    }
+    my $str = &binary2str(@pblocks);
+
+    # remove no of pad chars at end specified by 1 char ('0'..'7') at front
+    my $npads = 0x7 & ord $str;
+    substr( $str, $[, 1 ) = '';
+    if ($npads) { substr( $str, 0 - $npads ) = ''; }
+    return $str;
+}
+
+sub triple_encrypt {
+    my ( $plaintext, $long_key ) = @_;    # not yet ...
+}
+
+sub triple_decrypt {
+    my ( $cyphertext, $long_key ) = @_;    # not yet ...
+}
+
+sub tea_code {
+    my ( $v0, $v1, $k0, $k1, $k2, $k3 ) = @_;
+
+    # TEA. 64-bit cleartext block in $v0,$v1. 128-bit key in $k0..$k3.
+    # &prn("tea_code: v0=$v0 v1=$v1");
+    use integer;
+    my $sum = 0;
+    my $n   = 32;
+    while ( $n-- > 0 ) {
+        $sum += 0x9e3779b9;                                                                          # TEA magic number delta
+        $v0  += ( ( $v1 << 4 ) + $k0 ) ^ ( $v1 + $sum ) ^ ( ( 0x07FFFFFF & ( $v1 >> 5 ) ) + $k1 );
+        $v1  += ( ( $v0 << 4 ) + $k2 ) ^ ( $v0 + $sum ) ^ ( ( 0x07FFFFFF & ( $v0 >> 5 ) ) + $k3 );
+    }
+    return ( $v0, $v1 );
+}
+
+sub tea_decode {
+    my ( $v0, $v1, $k0, $k1, $k2, $k3 ) = @_;
+
+    # TEA. 64-bit cyphertext block in $v0,$v1. 128-bit key in $k0..$k3.
+    use integer;
+    my $sum = 0;
+    my $n   = 32;
+    $sum = 0x9e3779b9 << 5;    # TEA magic number delta
+    while ( $n-- > 0 ) {
+        $v1 -= ( ( $v0 << 4 ) + $k2 ) ^ ( $v0 + $sum ) ^ ( ( 0x07FFFFFF & ( $v0 >> 5 ) ) + $k3 );
+        $v0 -= ( ( $v1 << 4 ) + $k0 ) ^ ( $v1 + $sum ) ^ ( ( 0x07FFFFFF & ( $v1 >> 5 ) ) + $k1 );
+        $sum -= 0x9e3779b9;
+    }
+    return ( $v0, $v1 );
+}
+
+sub rand_byte {
+    if ( !$rand_byte_already_called ) {
+        srand( time() ^ ( $$ + ( $$ << 15 ) ) );    # could do better, but its only padding
+        $rand_byte_already_called = 1;
+    }
+    int( rand 256 );
+}
+
+#
+# End TEA
+
+sub print_agentonqueue {
+    my $valor = shift;
+    if ( keys(%agents_on_queue) ) {
+        log_debug( $valor, 1 ) if DEBUG;
+        foreach my $valor ( sort ( keys(%agents_on_queue) ) ) {
+            foreach my $vvalor ( @{ $agents_on_queue{$valor} } ) {
+                log_debug( "agents_on_queue{$valor} = $vvalor", 1 ) if DEBUG;
+            }
+        }
+    }
+}
+
+sub print_countqueue {
+    my $valor = shift;
+    if ( keys(%count_queue) ) {
+        foreach my $valor ( sort ( keys(%count_queue) ) ) {
+            foreach my $vvalor ( @{ $count_queue{$valor} } ) {
+                log_debug( "\t| count_queue{$valor} = $vvalor", 32 ) if DEBUG;
+            }
+        }
+    }
+}
+
+sub print_datos {
+    if ( $debuglevel & 1 ) {
+        my $num = shift;
+
+        if ( keys(%datos) ) {
+            print "---------------------------------------------------\n";
+            print "DATOS $num\n";
+            print "---------------------------------------------------\n";
+            for ( keys %datos ) {
+                print $_. "\n";
+                while ( my ( $key, $val ) = each( %{ $datos{$_} } ) ) {
+                    if ( defined($val) ) {
+                        print "\t$key = $val\n";
+                    }
+                }
+                print "---------------------------------------------------\n";
+            }
+        }
+        else {
+            print "NO DATOS TO DISPLAY\n";
+        }
+    }
+}
+
+sub print_cachehit {
+    if ( $debuglevel & 1 ) {
+        print "---------------------------------------------------\n";
+        print "CACHE HIT\n";
+        print "---------------------------------------------------\n";
+        if ( keys(%cache_hit) ) {
+            for ( keys %cache_hit ) {
+                print "key $_\n";
+
+                if ( defined( @{ $cache_hit{$_} } ) ) {
+                    my @final = ();
+                    foreach my $val ( @{ $cache_hit{$_} } ) {
+                        print "\tcache_hit($_) = $val\n";
+                    }
+                }
+            }
+        }
+        else {
+            print "NO CACHE HITS TO DISPLAY\n";
+        }
+        print "---------------------------------------------------\n";
+    }
+}
+
+sub print_linkbot {
+    if ( $debuglevel & 1 ) {
+        print "---------------------------------------------------\n";
+        print "LINKS BOTONES\n";
+        print "---------------------------------------------------\n";
+        if ( keys(%linkbot) ) {
+            for ( keys %linkbot ) {
+                if ( defined( @{ $linkbot{$_} } ) ) {
+                    my @final = ();
+                    foreach my $val ( @{ $linkbot{$_} } ) {
+                        print "\tlinkbot($_) = $val\n";
+                    }
+                }
+            }
+        }
+        else {
+            print "NO DATOS TO DISPLAY\n";
+        }
+        print "---------------------------------------------------\n";
+    }
+}
+
+sub print_sesbot {
+    my $quien = shift;
+
+    if ( $debuglevel & 1 ) {
+        print "---------------------------------------------------\n";
+        print "SESIONES BOTONES $quien\n";
+        print "---------------------------------------------------\n";
+        if ( keys(%sesbot) ) {
+            for ( keys %sesbot ) {
+                if ( defined( @{ $sesbot{$_} } ) ) {
+                    my @final = ();
+                    foreach my $val ( @{ $sesbot{$_} } ) {
+                        print "\tsesbot($_) = $val\n";
+                    }
+                }
+            }
+        }
+        else {
+            print "NO DATOS TO DISPLAY\n";
+        }
+        print "---------------------------------------------------\n";
+
+    }
+}
+
+sub print_instancias {
+    if ( $debuglevel & 1 ) {
+        my $num = shift;
+        print "---------------------------------------------------\n";
+        print "Instancias 2 $num\n";
+        print "---------------------------------------------------\n";
+        foreach my $caca ( sort ( keys(%instancias) ) ) {
+            print $caca. "\n";
+            foreach my $pipu ( sort ( keys( %{ $instancias{$caca} } ) ) ) {
+                print "\t$pipu = $instancias{$caca}{$pipu}\n";
+            }
+        }
+        print "---------------------------------------------------\n";
+    }
+}
+
+sub print_botones {
+    if ( $debuglevel & 1 ) {
+        my $num = shift;
+        print "---------------------------------------------------\n";
+        print "Botones $num\n";
+        print "---------------------------------------------------\n";
+        foreach ( sort ( keys(%buttons) ) ) {
+            printf( "%-20s %-10s %-10s\n", $_, $buttons{$_}, $button_server{ $buttons{$_} } );
+        }
+    }
+}
+
+sub print_cola_write {
+    my $socket = shift;
+    if ( !defined($socket) ) {
+        for ( keys %client_queue ) {
+            my $contame = 0;
+            foreach my $val ( @{ $client_queue{$_} } ) {
+                $contame++;
+                print "cola $contame $_ comando $val\n";
+            }
+        }
+    }
+    else {
+        my $contame = 0;
+        foreach my $val ( @{ $client_queue{$socket} } ) {
+            $contame++;
+            print "cola $contame $socket comando $val\n";
+        }
+    }
+}
+
+sub print_timers {
+    if ( $debuglevel & 1 ) {
+        if ( keys(%botontimer) ) {
+            for my $interno ( keys %botontimer ) {
+                print "botontimer $interno = $botontimer{$interno}, type $botontimertype{$interno}\n";
+            }
+        }
+    }
+}
+
+sub print_clients {
+    if ( $debuglevel & 1 ) {
+        my $number_of_flash_clients_connected = @flash_clients;
+
+        if ( $number_of_flash_clients_connected > 0 ) {
+            print "\nFlash clients connected: $number_of_flash_clients_connected\n";
+            print "---------------------------------------------------\n";
+
+            foreach my $C (@flash_clients) {
+                print peerinfo($C) . " $C\n";
+            }
+            print "---------------------------------------------------\n";
+        }
+        else {
+            print "No flash clients connected\n";
+        }
+    }
+}
+
+sub print_agents {
+
+    if ( $debuglevel & 1 ) {
+        if ( keys(%agent_to_channel) ) {
+            print "Agent_to_channel: \n";
+            foreach my $valor ( sort ( keys(%agent_to_channel) ) ) {
+                print "agent_to_channel{$valor} = $agent_to_channel{$valor}\n";
+            }
+        }
+        if ( keys(%reverse_agents) ) {
+            print "Reverse Agents: \n";
+            foreach my $valor ( sort ( keys(%reverse_agents) ) ) {
+                print "reverse_agents{$valor} = $reverse_agents{$valor}\n";
+            }
+        }
+        if ( keys(%channel_to_agent) ) {
+            print "Channel to Agent: \n";
+            foreach my $valor ( sort ( keys(%channel_to_agent) ) ) {
+                print "channel_to_agent{$valor} = $channel_to_agent{$valor}\n";
+            }
+        }
+        if ( keys(%agents_on_queue) ) {
+            print "Agents on queue: \n";
+            foreach my $valor ( sort ( keys(%agents_on_queue) ) ) {
+                print "agents_on_queue{$valor} = $agents_on_queue{$valor}\n";
+            }
+        }
+        if ( keys(%is_agent) ) {
+            print "is Agents: \n";
+            foreach my $valor ( sort ( keys(%is_agent) ) ) {
+                print "is_agent{$valor} = $is_agent{$valor}\n";
+            }
+        }
+        if ( keys(%count_queue) ) {
+            print "Count on queue: \n";
+            foreach my $valor ( sort ( keys(%count_queue) ) ) {
+                print "count_queue{$valor} = $count_queue{$valor}\n";
+            }
+        }
+
+    }
+}
+
+sub print_status {
+    if ( keys(%estadoboton) ) {
+        print "---------------------------------------------------\n";
+        print "ESTADO BOTONES\n";
+        print "---------------------------------------------------\n";
+        for ( keys %estadoboton ) {
+            my $separador = 0;
+            my $nroboton  = $_;
+            print "$nroboton\t $estadoboton{$nroboton}\t \n";
+        }
+        print "---------------------------------------------------\n";
+    }
+    else {
+        print "No estadoboton populated\n";
+    }
+
+    if ( keys(%botonled) ) {
+        print "----- LEDS --------\n";
+        for ( keys %botonled ) {
+            print "$_ = $botonled{$_} $botonlabel{$_}\n";
+        }
+    }
+    if ( keys(%botonvoicemail) ) {
+        print "----- VOICEMAIL --------\n";
+        for ( keys %botonvoicemail ) {
+            print "$_ = $botonvoicemail{$_}\n";
+        }
+    }
+}
+
+__END__
+
+=head1 NAME
+
+op_server.pl - Proxy server for the Asterisk Flash Operator Panel
+
+=head1 SYNOPSIS
+
+op_server.pl [options] 
+
+ Options:
+   -?, --help
+   -p, --pidfile
+   -c, --confdir
+   -l, --logdir
+   -d, --daemon  
+   -v, --version
+   -X, --debuglevel
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>
+
+Print a brief help message and exits
+
+=item B<--pidfile>
+
+Specify the pid file to use when running in daemon mode. Defaults to /var/run/op_panel.pid
+
+=item B<--confdir>
+
+Specify where to look for the configuration files. If omited, it will look for them in the same directory where op_server.pl resides
+
+=item B<--logdir>
+
+If specified, will write the log files to that directory. If not, it will output to STDOUT and STDERR
+
+=item B<--daemon>
+
+Run the server in daemon mode, detaching itself from the console
+
+=item B<--version>
+
+Display the version and exits
+
+=item B<--debuglevel>
+
+Sets the debug level for the logs. It overrides the value inside op_server.cfg
+
+=back
+
+=head1 DESCRIPTION
+
+B<This program> will read the given input file(s) and do someting useful with the contents thereof.
+
+=cut  


Property changes on: op-panel/branches/upstream/current/op_server.pl
___________________________________________________________________
Name: svn:executable
   + 

Added: op-panel/branches/upstream/current/op_style.cfg
===================================================================
--- op-panel/branches/upstream/current/op_style.cfg	2006-05-25 19:03:02 UTC (rev 1784)
+++ op-panel/branches/upstream/current/op_style.cfg	2006-05-30 19:47:29 UTC (rev 1785)
@@ -0,0 +1,78 @@
+[general]
+shake_pixels=2
+dimm_noregister_by=20
+dimm_lagged_by=60
+enable_label_background=0
+enable_crypto=0            ; set to 1 for encrypting server to client traffic
+enable_animation=1
+use_embed_fonts=1
+ledcolor_ready=0x00A000
+ledcolor_busy=0xA01020
+ledcolor_agent=0xD0d020
+label_font_size=20
+label_font_family=Verdana  ; only valid when use_embed_fonts is disabled
+label_font_color=000000
+label_shadow_color=dddddd
+label_margin_top=20
+label_margin_left=38
+label_shadow=1
+clid_font_color=00dd00
+timer_font_color=4000ff
+clid_font_size=13
+clid_font_family=Verdana   ; only valid when use_embed_fonts is disabled
+clid_margin_top=0
+clid_margin_left=25
+timer_font_size=13
+timer_font_family=Courier  ; only valid when use_embed_fonts is disabled
+timer_margin_top=48
+timer_margin_left=6
+btn_width=246
+btn_height=70
+btn_padding=4
+btn_line_width=2
+btn_line_color=0x000000
+btn_fadecolor_1=ccccff
+btn_fadecolor_2=ffffff
+btn_round_border=8
+btn_highlight_color=ff0000
+led_scale=90
+led_margin_top=34
+led_margin_left=20
+arrow_scale=70
+arrow_margin_top=10
+arrow_margin_left=15
+icon1_margin_top=43
+icon1_margin_left=-34
+icon1_scale=17
+icon2_margin_top=46
+icon2_margin_left=-29
+icon2_scale=14
+icon3_margin_top=34
+icon3_margin_left=-36
+icon3_scale=20
+icon4_margin_top=33
+icon4_margin_left=-34
+icon4_scale=16
+icon5_margin_top=32
+icon5_margin_left=-33
+icon5_scale=16
+icon6_margin_top=32
+icon6_margin_left=-33
+icon6_scale=16
+mail_margin_left=-23
+mail_margin_top=13
+mail_scale=9
+show_security_code=1
+show_clid_info=0
+show_btn_help=3
+show_btn_debug=0
+show_btn_reload=2
+show_status=4
+
+;[sip]
+; You can have different styles per panel context
+; You need to copy all the variables, they will not be
+; inherited. If you fail to include an option the flash
+; client migth hang. So, copy the complete [general] 
+; section an change the header to the panel context name.
+; Then adjust the parameters to your liking.




More information about the Pkg-voip-commits mailing list