[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= " ";
+ 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'> </span><BR>\n";
+echo "<span id='clid$a' class='clid'> </span><BR>\n";
+echo "<div class='clid' id='tick$a'> </div>";
+echo "<div id='phone$a' class='phone1' $mouseov2> </div>";
+echo "<div id='mwi$a' class='mwi' $mouseov1> </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=" ";
+ }
+ }
+
+ 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=" ";
+ }
+ 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 = " ";
+
+ 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ä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ägg på samtal:</b> genom att dubbelklicka p&aing; den röda knappen
+<BR>
+<BR>
+<li><b>Skapa samtal:</b> genom att dra en tillgänglig anknytning till en tillgänglig mottagare
+<BR>
+<BR>
+<li><b>Konferenssamtal:</b> Du kan lägga till en tredje person till en existerande konversation genom att dra en tillgänglig anknytning till ett ben av det redan kopplade samtalet.
+<BR>
+<BR>
+<li><b>Stäng av/på mikrofonen för MeetMe medlemmar:</b> bara att dubbelklicka på pilen hos en MeetMe deltagare.
+<BR>
+<BR>
+<li><b>Visa information om senaste samtalet:</b> dubbelklicka på pilen på en tillgänglig knapp
+<BR>
+<BR>
+</ul>
+Du kan också skriva extra information i Infoboxen före samtalskoppling eller skapande av samtal. Om text skrivs in i Infoboxen kommer den att användas som CID (nummerpresentation) fö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 = "®istered";
+ }
+ 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 = "®istered";
+ }
+ 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 = "¬registered";
+ $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 = "®istered";
+ $estado_final = "registrado";
+ $unico_id = "YYYY-$server";
+ if ( $canalid !~ /(.*)-XXXX$/ ) {
+ $canalid = $canalid .= "-XXXX";
+ }
+ }
+
+ if ( $state =~ /^OK/ ) {
+ $texto = "®istered";
+ $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