commit version 22.12.12447
7
includes/weathermap/.htaccess
Normal file
@ -0,0 +1,7 @@
|
||||
Deny From All
|
||||
<FilesMatch "^(editor|data-pick)\.php$">
|
||||
Allow From All
|
||||
</FilesMatch>
|
||||
<FilesMatch "(css|js|html|png)$">
|
||||
Allow From All
|
||||
</FilesMatch>
|
518
includes/weathermap/CHANGES
Normal file
@ -0,0 +1,518 @@
|
||||
This is a roll-up of all the small bugfixes for the last couple of years, especially those that stop Weathermap
|
||||
working with newer MySQL or PHP versions. There is a more substantial 1.0 release in the works, but I will backport
|
||||
any simple improvements or fixes to 0.98(abcd) releases. There are also small usability changes aimed at reducing
|
||||
repeat "error reports" in the forums.
|
||||
|
||||
IMPORTANT NOTE - you may need to reset permissions on your users after upgrading, as I've
|
||||
finally switched to the "new-style" plugin API that's been around for 5+ years. This handles
|
||||
permissions differently, unfortunately.
|
||||
|
||||
IMPORTANT NOTE 2: THIS RELEASE DOES NOT WORK WITH CACTI 1.x! You will want version 1.0+ for that.
|
||||
|
||||
0.98a
|
||||
FIXED - Works with PHP 7.x and 5.6 - removed all mysql_*() function calls, and use PDO instead
|
||||
FIXED - Blank line issue with RRDtool 1.5+
|
||||
|
||||
0.98
|
||||
FIXED - MySQL error in table-creation. MySQL 5.6 is fussier.
|
||||
FIXED - Editor 'delete link' broken
|
||||
FIXED - KILO was ignored when processing %k in special tokens
|
||||
FIXED - Various fixes for PHP deprecated or strict-mode warnings
|
||||
FIXED - Line-ending trimming in 'external script' data source
|
||||
FIXED - rounding error 'kinks' in angled VIA links
|
||||
FIXED - Config file path validation issue in editor (CVE-2013-3739)
|
||||
FIXED - Cloning a templated node in editor retains the template in the clone
|
||||
FIXED - cacti_use_ifspeed incorrect when interfaces > 20M and ifhighspeed available
|
||||
FIXED - More PHP 5.3/5.4/strict related errors (split -> explode)
|
||||
CHANGE - Finally switch to "new-style" plugin API.
|
||||
CHANGE - Editor data picker improved sort (thanks shd)
|
||||
CHANGE - (Cacti plugin only) images are written to a temporary file first, to avoid displaying half-written images
|
||||
CHANGE - Editor no longer uses editor-config.php
|
||||
ADDED - Weathermap will use anti-aliasing if your GD supports it (php-bundled GD doesn't) (thanks shd)
|
||||
ADDED - Special token formatting can handle timeticks and time_t formatting (%T and %t respectively)
|
||||
ADDED - new DATAOUTPUTFILE allows collected data to be written to a file for later use (automatically enabled in Cacti)
|
||||
ADDED - new wmdata: datasource plugin can read data from files produced by DATAOUTPUTFILE
|
||||
ADDED - IMAGEOUTPUTFILE and HTMLOUTPUTFILE are honoured in Cacti poller as a location for a second copy of those files.
|
||||
ADDED - Editor 'tidy link' function replaces Vert & Horiz, and does much nicer job
|
||||
ADDED - 'retidy' option in editor to recalculate all links previously positioned with 'tidy'.
|
||||
ADDED - KEYBGCOLOR and KEYOUTLINECOLOR both accept 'none'
|
||||
ADDED - command-line weathermap has new --no-warn option to disable warnings
|
||||
ADDED - AICONFILLCOLOR accepts 'none' for drawing giant transparent shapes.
|
||||
ADDED - Extra warning for Boost users about poller_output
|
||||
ADDED - if there are actually 0 maps in the database, the 'Weathermaps' tab gives some basic instructions.
|
||||
ADDED - Cacti data picker in editor tracks most recently used hosts (thanks Zdolny)
|
||||
ADDED - New permission in Cacti: edit maps. Maps can be edited by authorized users without needing to enable the editor in the source code.
|
||||
|
||||
0.97c had no additional changes - it's just 0.97b with some silly errors fixed, and all
|
||||
the CSS files included with the correct paths. There were also reports of problems with the
|
||||
actual zip file.
|
||||
|
||||
0.97b is a special release starting from 0.97a and backporting all the quick bugfixes from the 0.98 code.
|
||||
There are larger structural changes in 0.98 and new features, but these bugfixes were useful enough to
|
||||
warrant a new 0.97 release (especially the mysql schema change). A real 0.98 release will follow in
|
||||
due course.
|
||||
|
||||
Also late addition to 0.97b - a couple of security analysts have pointed out flaws in the editor.
|
||||
First, the ability to remotely create .php files and then cross-site-scripting vulnerabilities. Both
|
||||
are really facets of the same thing - lack of input validation. 0.97b improves this a great deal.
|
||||
|
||||
Thanks to Gerry Eisenhaur and Daniel Ricardo dos Santos respectively for their security bug reports.
|
||||
|
||||
0.97b FIXED - absolute SCALE definitions didn't support K (thanks wwwdrich)
|
||||
FIXED - memory leak in poller code. Memory usage is MUCH lower now.
|
||||
FIXED - updated mysql schema commands to use modern ENGINE instead of TYPE;
|
||||
FIXED - static datasource plugin honours KILO
|
||||
FIXED - check-gdbug.php shouldn't complain about empty ob_flush buffers anymore
|
||||
FIXED - SNMP DS should deal better with non-numeric (and blank) return values
|
||||
FIXED - NINK colours were exchanged (thanks Deathwing00!)
|
||||
FIXED - WriteConfig (i.e. editor) won't 'lose' absolute keyword from
|
||||
FIXED - fixed some function-name clashes with other plugins
|
||||
FIXED - PHP 5.3/5.4/strict related errors ("Creating default object from empty value")
|
||||
CHANGE - editor snap function improved (snap to *nearest* point) (thanks Andreas Braun)
|
||||
CHANGE - the Cacti UI will warn you about fundamental file permissions problems
|
||||
CHANGE - editor ignores attempts to rename nodes to have space in names
|
||||
CHANGE - Moved all PHP that doesn't need to be web-accessible into lib
|
||||
CHANGE - Editor won't deal with config files that don't have a .conf extension
|
||||
CHANGE - Manual updates for changes in Cacti, and improvements in styling. Security section added.
|
||||
CHANGE - General improvements in input validation and output escaping in editor
|
||||
CHANGE - 'External Script' datasource plugin is disabled by default in new installs (NOT upgrades though!)
|
||||
ADDED - Caching for cacti data fetched by dsstats and rrdtool/poller_output DS plugins
|
||||
ADDED - Ability to disable any warning with 'SET nowarn_WMxxx 1'
|
||||
ADDED - .htaccess files added for directories that don't need to be web-accessible - needs "AllowOverride Limit" or "AllowOverride All" in your Apache config.
|
||||
|
||||
0.97a FIXED - Incorrect action URL in 'map selector' combo box for Cacti users.
|
||||
FIXED - cacti_graph_id set to 0 instead of ID, by rrd/poller_output and dsstats plugins (thanks sh0x)
|
||||
FIXED - 'classic' legend drew 'hidden' colour values for things like key background colour. (thanks jmayniac)
|
||||
FIXED - PHP 5.3 deprecated code in HTML_Imagemap.class.php
|
||||
FIXED - 'Show Only First' option ignored in Cacti (thanks inko_nick)
|
||||
FIXED - Editor deals with overlapping nodes on different ZORDERS properly.
|
||||
FIXED - "property of non-object in editor.php line 466" while editing map properties (thanks to iNeo)
|
||||
FIXED - no-data option on command-line didn't work
|
||||
FIXED - Clone Node was broken in 0.97
|
||||
FIXED - Maps with per-user permissions show up multiple times in map selector
|
||||
FIXED - Removed incorrect warning about imagefilter and USEICONSCALE.
|
||||
FIXED - string escaping bug with editor and direct config changes (thanks uhtred)
|
||||
FIXED - --imageuri was ignored on command-line (thanks Marcus Stögbauer)
|
||||
FIXED - links with targets containing spaces are broken by the editor (thanks Andreas Braun)
|
||||
FIXED - deprecated jQuery function call in cacti-pick.php (thanks again Andreas Braun)
|
||||
CHANGE - Group sorting is a bit more logical and the presentation nicer.
|
||||
CHANGE - cacti-integrate.php uses getopt to take more command-line params
|
||||
CHANGE - Updated jQuery to latest version
|
||||
CHANGE - Number formatting will pick 1G over 1000M (and similar) (thanks cerbum)
|
||||
CHANGE - The editor is disabled by default - see top of editor.php (and install guide)
|
||||
ADDED - LINK WIDTH accepts decimals
|
||||
ADDED - cacti-integrate.php can generate DSStats TARGETs too
|
||||
ADDED - Simple VIA editing in editor (thanks to Zdolny)
|
||||
ADDED - SCALE can accept G,M,K,T,m,u,n suffixes (for absolute scales)
|
||||
|
||||
0.97 FIXED - RRD Aggregation regexp was failing (thanks to shd)
|
||||
FIXED - Scale numerals honour locale (thanks again, shd)
|
||||
FIXED - THold plugin check failed with Thold 0.4.1 (PA 2.x, actually)
|
||||
FIXED - Uninitialized variable in ReadData when plugin is disabled
|
||||
FIXED - Zero-length link check didn't include offsets (thanks Ryan Botoluzzi)
|
||||
FIXED - Cacti-pick should get right rra path for packagers that move the rra directory (e.g. Ubuntu, Debian *again*)
|
||||
FIXED - DS plugins that return one value and a null should work properly
|
||||
FIXED - "Strange" characters (e.g. /) in NODE and LINK names broke the imagemap.
|
||||
FIXED - Map Style settings in editor were broken after internal defaults changes
|
||||
FIXED - Imagemap no longer contains areas with no href defined
|
||||
FIXED - SPLITPOS was ignored with VIASTYLE angled (thanks to uhtred)
|
||||
FIXED - 'AICONOUTLINECOLOR none' is actually valid now (thanks to mgb & Leathon)
|
||||
FIXED - readdir() loop never stops, on some systems (thanks to jerebernard)
|
||||
FIXED - bad regexp in the MRTG DS plugin (thanks to Matt McMahon)
|
||||
FIXED - 0.96 had a new 'time' DS plugin - now documented!
|
||||
FIXED - NCFPC now only complains about missing scale lines on NODEs for the variable that is in use.
|
||||
ADDED - USEICONSCALE no longer has special dependencies - and the colours are nicer too.
|
||||
ADDED - Option of a dropdown selector to navigate between maps (in full-size view)
|
||||
ADDED - Maps can be organised into groups in Cacti plugin. These appear
|
||||
as tabs in the UI for viewing maps.
|
||||
ADDED - Extra variables can be defined per-group, so all maps in a group can have similar settings (e.g. a "24hr average" tab).
|
||||
ADDED - INCLUDE keyword to include a file of common definitions (based on work by BorisL)
|
||||
(NOTE: this can confuse the editor sometimes - see the manual page for INCLUDE)
|
||||
ADDED - Warning for maps that contain OVERLIBGRAPH but not 'HTMLSTYLE overlib'
|
||||
ADDED - Warning for use of TEMPLATE not as the first line of an object (overwrites settings otherwise)
|
||||
ADDED - SCALE will accept values below 0, and also above 100
|
||||
ADDED - USESCALE has two new options: absolute and percent, which allows you to have a SCALE of absolute values
|
||||
ADDED - New datasource plugin to support statistics from TheWitness's DSStats Cacti Plugin. This gets you daily,weekly,monthly and annual stats with no complicated rrdtool stuff.
|
||||
ADDED - New converter to take a rrdtool-based map config and make it into a DSStats-based one
|
||||
ADDED - static datasource can be used for negative values
|
||||
ADDED - SNMP datasource has configurable timeout and retry values.
|
||||
ADDED - SNMP datasource has option to give up on a failing host
|
||||
ADDED - LABELOFFSET supports percentage compass offsets and radial offsets, like NODES does.
|
||||
ADDED - Percentage compass offsets (NODES and LABELOFFSET) support > 100% offsets
|
||||
|
||||
0.96a FIXED - New z-ordering code did not work correctly on PHP4. This broke (at least) the editor. (thanks toe_cutter)
|
||||
FIXED - \n is no longer treated as a newline in TARGETs (thanks NetAdmin)
|
||||
FIXED - KILO was broken completely between 0.95b and 0.96 (thanks Jethro Binks)
|
||||
FIXED - Link comments in certain positions could cause div-by-zero errors. (thanks again Jethro)
|
||||
FIXED - USEICONSCALE didn't colorise (broken between 0.95b and 0.96 again) (thanks colejv)
|
||||
FIXED - Managed to make LABELOFFSET case-sensitive.
|
||||
|
||||
0.96 ADDED - TEMPLATE allows a node or link to copy it's settings from another, instead of from DEFAULT.
|
||||
ADDED - RRD datasource can take SET rrd_default_path to make configs a little easier to read.
|
||||
ADDED - RRD datasource can take SET rrd_default_in_ds and rrd_default_out_ds for non-Cacti users.
|
||||
ADDED - RRD datasource can get Cacti query information (in poller_output mode ONLY) - like ifAlias, ifSpeed etc
|
||||
ADDED - RRD datasource can take the ifSpeed/ifHighSpeed from the above, and use it in the map.
|
||||
ADDED - RRD datasource fills in Cacti cacti_path_rra and cacti_url with Cacti base path and URL
|
||||
ADDED - RRD datasource can take global SET rrd_options to add extra options to rrdtool command lines
|
||||
ADDED - SNMP datasource also stores the raw data from the SNMP agent in snmp_raw_in/snmp_raw_out
|
||||
ADDED - SNMP datasource allows '-' as an OID, similar to '-' targets in RRDs.
|
||||
ADDED - Control the drawing order with ZORDER.
|
||||
ADDED - New artificial icons: nink, inpie and outpie. See ICON in manual.
|
||||
ADDED - Warning for probably-incorrect BWLABELPOS where in<out
|
||||
ADDED - Warning for gaps in a SCALE
|
||||
ADDED - New global SET variables to disable some common warnings you may not care about :-)
|
||||
ADDED - Cacti management screen shows number of warnings for each map last time it ran
|
||||
ADDED - Cacti management screen also has a link to the log entries for the map in question
|
||||
ADDED - The TARGET aggregation thing can also take scale factors now: -5.5*myrrdfile.rrd
|
||||
ADDED - Cacti plugin caches thumbnail sizes, improving thumbnail view rendering
|
||||
ADDED - Cacti plugin allows adding the same map twice (more useful than it sounds)
|
||||
ADDED - Cacti plugin allows setting of map-global variables in the management UI
|
||||
ADDED - Cacti plugin allows settings of global map-global (across all maps) variables too
|
||||
ADDED - Cacti plugin adds links in 'user' pages to management screen (if you are an admin)
|
||||
ADDED - HTMLSTYLESHEET keyword allows you to specify a URL for a CSS stylesheet (CLI tool only)
|
||||
ADDED - A few extra CSS id and class attributes, to make styling the page easier.
|
||||
ADDED - New token: in/outscalecolor contains HTML colour code of node/link colours for use in NOTES
|
||||
ADDED - New NODES offset type - angle+radius
|
||||
ADDED - New NODES offset type - compass-point+percentage
|
||||
ADDED - "KEYSTYLE inverted" - to get a thermometer-style vertical legend.
|
||||
ADDED - "COMMENTSTYLE center" to make comments run along the centre of a link arrow. (and 'edge' for the usual)
|
||||
ADDED - COMMENTFONTCOLOR accepts 'contrast' as an option, for when it's over a link
|
||||
ADDED - VIASTYLE angled (or curved) - you can turn sharp corners now
|
||||
ADDED - Comment (and pos) editing in editor (based on code by Zdolny)
|
||||
ADDED - Editor Settings dialog works, and allows you to set grid-snap and some overlays
|
||||
ADDED - SCALE allows 'none' as a colour (for non-gradients). Only affects LINKs so far.
|
||||
ADDED - fping plugin allows for changing the number of pings.
|
||||
ADDED - TARGET strings can be enclosed in quotes, to allow spaces in them (mainly for external ! scripts)
|
||||
ADDED - "KEYSTYLE tags" - like classic, but uses the scale tags instead of percentages.
|
||||
ADDED - scripts in random-bits to help with automatic/assisted mapping.
|
||||
ADDED - lots more pretty pictures in the manual, so you can see what I mean.
|
||||
ADDED - IMAGEURI keyword to match --image-uri command-line option (ignored in Cacti plugin)
|
||||
ADDED - MINTIMEPOS and MAXTIMEPOS to track data source times
|
||||
CHANGE - Cacti plugin uses "processed" map title now (allows {} tokens in the title)
|
||||
CHANGE - A NODE with no POSITION is not drawn, instead of drawn at 0,0. Useful for templates.
|
||||
CHANGE - A LINK with no NODES is no longer an error. Also for templates.
|
||||
CHANGE - The link_bulge secret mode bulges each side of a link independently now
|
||||
CHANGE - whitespace is stripped from the beginning and end of each line before parsing
|
||||
CHANGE - OVERLIBWIDTH/HEIGHT are used for img tag width and height - so they must be *correct* now
|
||||
FIXED - Cacti poller_output support works more reliably/at all on Windows
|
||||
FIXED - Renaming a node in the editor correctly handles other relatively-positioned nodes and vias
|
||||
FIXED - Minor issue with CRLF in map title for Cacti Plugin
|
||||
FIXED - CLI tool set --define options incorrectly.
|
||||
FIXED - Oneway links don't draw the INCOMMENT anymore
|
||||
FIXED - negative TIMEPOS didn't hide the timestamp
|
||||
FIXED - DEFAULT SCALE covers 0-100 properly (Thanks Dan Fusselman)
|
||||
FIXED - Scaled ICON in DEFAULT didn't get overwritten properly in nodes (Thanks Fabrizio Carusi)
|
||||
FIXED - No more floating-point imagemap coords (Thanks Trond Aspelund)
|
||||
FIXED - RRDtool regional output (. vs ,) workaround
|
||||
FIXED - Cacti poller_output handles NaN more gracefully now
|
||||
FIXED - SNMP datasource should work with Windows SNMP again
|
||||
FIXED - MRTG datasource tried to stat() URLs
|
||||
FIXED - Error reporting for CLI --define was bad. --help text was out of date.
|
||||
FIXED - Editor will honour LABEL from NODE DEFAULT, if it is set.
|
||||
|
||||
0.95b FIXED - SQL schema issue that upset some mysql versions
|
||||
FIXED - Removed sometime-problem debugging code in editor
|
||||
FIXED - incorrect jquery path in cacti-picker
|
||||
FIXED - INFOURL not used without overlib
|
||||
FIXED - 'none' colours on LINKs were broken by typo.
|
||||
FIXED - NOTES, INNOTES, OUTNOTES all just flat-out borken in 0.95 and 0.95a
|
||||
FIXED - Page title can be incorrect if filehash starts with a digit.
|
||||
FIXED - Cacti plugin behaves a little better with auth disabled.
|
||||
|
||||
0.95a FIXED - problem with global map variables. Oops.
|
||||
FIXED - few deprecated function references.
|
||||
FIXED - couple of tiny docs errors.
|
||||
FIXED - bug where INFOURL without OVERLIBGRAPH would be ignored
|
||||
CHANGE - Added in a SCALE line in the DEFAULT scale for between 0 and 1. Stops a lot of warnings on low-traffic links.
|
||||
CHANGE - Tweaked node cloning in editor - clone is offset in x and y now.
|
||||
|
||||
0.95 KNOWN ISSUE - ININFOURL/OUTINFOURL, INOVERLIBGRAPH/OUTOVERLIBGRAPH are not handled well by the editor. If you edit a map that uses these,
|
||||
then the 'in' side of the link will be copied to the 'out' side. New editor will handle this better.
|
||||
|
||||
ADDED - you get a warning if you are using values outside of the defined SCALE now.
|
||||
ADDED - You can add a 'tag' to a SCALE line, to be used in ICON or LABELs later.
|
||||
ADDED - USEICONSCALE - colorize icon images (based on patches from llow)
|
||||
ADDED - screenshot mode. "SET screenshot_mode 1" at the top of the map will anonymise all labels, comments and bwlabels.
|
||||
ADDED - LABELFONTCOLOR can use a special value of 'contrast' to always contrast with the label colour.
|
||||
ADDED - Artificial Icons. Special icon 'filenames' - 'box' 'round' 'rbox' create a shaped icon without any file.
|
||||
ADDED - Map titles show up in browser title now.
|
||||
ADDED - a basic 'live view' function which generates a map on demand. Sometimes. It's not very useful.
|
||||
ADDED - LABELANGLE allows you to rotate node labels to 90,180,270 degrees. Needs truetype font.
|
||||
ADDED - improved data-source picker in editor: host filter
|
||||
ADDED - improved data-source picker in editor: option to aggregate data sources
|
||||
ADDED - Moved data-source picker changes across into the graph-picker for NODEs too.
|
||||
ADDED - SPLITPOS keyword to control position of midpoint in links
|
||||
ADDED - VIAs can be positioned relative to NODEs (like NODEs can) (thanks again to llow)
|
||||
ADDED - Weathermap has a hook in the map viewing page to allow other plugins to add code there
|
||||
ADDED - .htaccess files bundled with Weathermap to restrict direct access to configs and output
|
||||
ADDED - filenames for output are much less guessable now (may break external references to maps)
|
||||
ADDED - You can use 'DUPLEX half' on a link to make the bandwidth percentage
|
||||
calculate work for half-duplex links
|
||||
ADDED - ININFOURL/OUTINFOURL, INOVERLIBGRAPH/OUTOVERLIBGRAPH, INNOTES/OUTNOTES
|
||||
allow you to have different urls for the in and out side of links (based on idea from llow)
|
||||
ADDED - OVERLIBGRAPH (and IN/OUT versions) can take multiple URLs separated by spaces (again from idea by llow)
|
||||
ADDED - debug/warning log output contains the map name, and the debug output is marked DEBUG
|
||||
ADDED - debug log output contains the calling function, file/line number, too. Making debugging-by-mail easier.
|
||||
ADDED - fping: TARGET to do live pings of devices. See targets.html
|
||||
ADDED - a sample 'skeleton' DS plugin
|
||||
ADDED - an additional check-gdbug.php to spot bad GD installs
|
||||
ADDED - MRTG DS plugin can do a few new tricks. See TARGET and targets.html
|
||||
CHANGE - DS plugins are able to return negative results now ***breaks user-developed DS plugins***
|
||||
CHANGE - the scale: prefix for the RRD DS plugin can take negative scale factors
|
||||
CHANGE - (internal) plugins are each created as a single object now. Result: the plugin can cache results internally.
|
||||
CHANGE - (internal) broke out some of the larger classes (node, link) into separate files.
|
||||
FIXED - KEYOUTLINECOLOR is actually used now (thanks to llow once more)
|
||||
FIXED - Editor doesn't throw away WIDTH and HEIGHT with no BG image
|
||||
FIXED - Cacti Data-source and Graph picker doesn't restrict scrolling or resizing anymore
|
||||
FIXED - weathermap-cacti-rebuild.php to work on both Cacti 0.8.6 and 0.8.7
|
||||
FIXED - weathermap-cacti-rebuild.php to flat-out fail if Cacti environment is wrong.
|
||||
FIXED - SNMP DS plugin had a typo that stopped it working at all (and no-one
|
||||
noticed for almost a year :-) ). (thanks to Fratissier Christophe for pointing it out)
|
||||
FIXED - Added some better controls into SNMP DS plugin. You can correctly pull
|
||||
interface oper/admin status, for example, now.
|
||||
|
||||
0.941 FIXED - Issue with '-' DS names again.
|
||||
FIXED - Added extra code to help discourage browser caching.
|
||||
FIXED - Removed some extra chatty debugging code from poller_output.
|
||||
ADDED - Page titles are more useful in Cacti now
|
||||
|
||||
0.94 ADDED - INBWFORMAT and OUTBWFORMAT allow you to format the text for BWLABEL, same as for COMMENTs
|
||||
ADDED - New cactithold/cactimonitor data source plugin reads data from Cacti's Threshold plugin.
|
||||
(Original development for this plugin was paid for by Stellar Consulting - Thanks!)
|
||||
ADDED - New LINKSTYLE command allows you to have one-way (one arrow) links.
|
||||
ADDED - RRD DS can use Cacti's poller_output to get data without running RRDtool at all.
|
||||
(this also means it can work with the Boost plugin for large installations)
|
||||
See targets.html for more info on this one.
|
||||
ADDED - Editor - Align horizontal and Align-vertical for links. Calculates link offsets to make link vertical/horizontal.
|
||||
CHANGE - Finally a better tab image, and a red 'active' one too, for the Cacti plugin.
|
||||
FIXED - "Full Screen Maps" mode in Cacti Plugin was broken by me adding the "View Only First" mode.
|
||||
FIXED - Imagemaps for horiz/vert format legend were wrong in editor (thanks to Alex Moura for pointing this out)
|
||||
FIXED - Changes for compatibility with Cacti 0.8.7's moved config file.
|
||||
|
||||
0.93 Added - weathermap-cacti-plugin.php?action=viewmap&id=mapfilename works as well as a map number - useful for crosslinks
|
||||
FIXED - the key_hidezero secret setting hides the zero in a gradient in a classic scale too.
|
||||
CHANGE - the auth realm names for Cacti have been changed to match ReportIt and Aggregate - easier to tell who does what
|
||||
ADDED - unique code for each warning message, and a page to explain it on the website. Ugh.
|
||||
ADDED - warning in editor file-selector so you can tell if the file is read-only
|
||||
ADDED - click config filename to edit in editor from Cacti (thanks to streaker69)
|
||||
FIXED - editor-generated node names are a bit shorter (and easier to read) now.
|
||||
FIXED - keyboard focus switches nicely to the popup dialogs now.
|
||||
ADDED - cactihost: DS plugin fetches a bunch of other stats from Cacti's DB now, too (like availability and response times)
|
||||
ADDED - Picking Cacti sources from editor has a javascript "live filter" feature now (needs a little work)
|
||||
ADDED - node coordinates are directly editable in the editor now
|
||||
ADDED - File picker allows you to use an existing map as a template
|
||||
CHANGE - Editor warns about older editor-config.php format now
|
||||
ADDED - Editor now allows you to clone a node with all it's styling intact.
|
||||
ADDED - When picking coordinates (new node, move node, move timestamp etc), you can see the coordinates
|
||||
ADDED - Editor toolbar fixed to window, to make it easier to scroll around large maps
|
||||
ADDED - RRD Datasource has improved warnings for non-existent DS names
|
||||
FIXED - RRD doesn't consider DSes other than the ones you named when finding a valid line.
|
||||
CHANGE - Formatted numbers (Mega, Kilo etc) now can include milli, micro and nano (m,u,n).
|
||||
FIXED - COMMENTPOS 0 doesn't kill everything anymore
|
||||
FIXED - OVERLIB would behave incorrectly with PHP4 and relatively positioned nodes (Bernd Ziller)
|
||||
ADDED - Editor allows you to edit raw text of nodes and links
|
||||
ADDED - Editor link in management page (warnesj)
|
||||
ADDED - Docs link in management page too (streaker69)
|
||||
ADDED - Editor has a better warning for unwriteable files and directory now.
|
||||
ADDED - When you come TO the editor from Cacti, the Change File goes BACK to Cacti
|
||||
ADDED - "Show Only First" mode in Cacti UI - useful for heirarchies of maps with a parent.
|
||||
ADDED - scale: prefix for RRD datasource - multiply/divide by any value as you read an rrd datasource
|
||||
FIXED - Non-unique IDs in imagemaps, in overlib mode.
|
||||
FIXED - Better-validating HTML produced
|
||||
FIXED - angled bwlabels have the correct imagemap
|
||||
FIXED - divide-by-zero error for some (?) PHP versions in poller
|
||||
ADDED - Warning for duplicate node or link names
|
||||
|
||||
0.92 - FIXED weathermap CLI help said --random-data instead of --randomdata
|
||||
FIXED one last php short_tag in poller_common.php - thanks Bernado Diez
|
||||
FIXED a SET in DEFAULT node/link is inherited by all node/links now.
|
||||
FIXED changing defaults in the editor changes existing objects that use the default value
|
||||
FIXED unreadable files in the configs/ directory don't kill the editor file-picker anymore
|
||||
FIXED - weathermap.conf really *is* a simple map again. My test version went out with 0.9 and 0.91
|
||||
INTERNAL added a lot more memory debug points in
|
||||
INTERNAL refactored the curve/link drawing code to make some new features possible/easier
|
||||
Further tweaks and improvements to check.php (Basic GD check, memory_limit check, PEAR Getopt check, and more explanation now)
|
||||
Small improvements to the editor's font-picking, including samples of all fonts.
|
||||
Added - Editor handles VIAs in a MUCH better way when moving nodes.
|
||||
Improved clipping reporting, improved plugin loading (Niels Baggesen)
|
||||
Added - BWSTYLE lets you choose between regular and angled bwlabels
|
||||
angled bwlabels follow the angle of the link arrow, which can save space.
|
||||
Added - Editor can pick Cacti graphs for NODE's overlib/infourl (but NOT targets)
|
||||
Added - COMMENTPOS allows you to move the position of comments along the link (like BWLABELPOS)
|
||||
FIXED - strange edge case with gradient SCALE caused div-by-zero (Tiago Giorgetti)
|
||||
CHANGE - The editor doesn't *require* an editor-config.php anymore. It *will* warn you if the defaults aren't enough, however.
|
||||
|
||||
0.91 - FIXED RRD bug with '-' DS names. This was fixed in 0.9pre3, but somehow slipped through.
|
||||
FIXED KILO bug again (Steve Woodcock)
|
||||
FIXED handling of MRTG html files on remote systems
|
||||
FIXED ReadConfig doesn't complain about KEYPOS DEFAULT -1 -1 (as written by WriteConfig) anymore
|
||||
FIXED NOTES was not fully tested, and broke cactihost: targets, at least.
|
||||
FIXED BWLABELPOS wasn't handled properly by the editor/WriteConfig (it would swap the positions over)
|
||||
FIXED Documentation fixes for installation (to include check.php) and NODE TARGETs.
|
||||
NEW check.php checks for presence of possibly-missing functions in your PHP installation
|
||||
NEW 'quiet' logging setting for Cacti plugin - in LOW logging, only errors are logged.
|
||||
NEW add a - to the front of a targetspec and you can take away values instead of aggregating them (think Total-VPN=Internet, for example)
|
||||
NEW the scale line that was 'hit' for each link direction is stored in inscalekey and outscalekey
|
||||
|
||||
0.9 - Changed node rendering - now we render to a transparent mini-image and blit them on. This will be good for the editor.
|
||||
FIXED long-undetected bug in HTML_ImageMap for similarly named nodes or links (SLander)
|
||||
Added BWLABELPOS - you can specify the position of the bandwidth labels along the link
|
||||
Added OVERLIBCAPTION based on code from Jared Gillis
|
||||
Moved all ReadData code into plugins to allow for user-supplied data sources
|
||||
FIXED unreported bug where WriteConfig throws away floating point part of SCALEs
|
||||
FIXED another variation of the imagemap sorting bug from 0.81 (Erik van Cutsem)
|
||||
FIXED KILO ignored bug (found/patch by Steve Woodcock)
|
||||
FIXED unreported bug where WriteConfig throws away HTMLOUTPUTFILE and IMAGEOUTPUTFILE
|
||||
Added facility to use multiple SCALEs in a map. SCALE takes an optional name. NODEs and LINKs can have a USESCALE line.
|
||||
FIXED bugs relating to assumption that 'admin' user always exists, and that users never go away, in the Cacti mgmt tab (adrian marsh)
|
||||
Logging is tidied up a bit under Cacti's poller
|
||||
FIXED Added a warning for RRD data sources where the DS names you specify don't exist in the RRD file
|
||||
Added numeric offsets for NODES lines, like for LABELOFFSET. Move the end of a link whereever you like.
|
||||
Added a new 'static' datasource - you can hardcode values, if you ever needed to.
|
||||
Added a 'gauge:' datasource to the rrd plugin. Allows you to use values from any rrd without bit/byte-conversion.
|
||||
Added formatting tokens into most strings - you can print data on the map from various places, including stuff
|
||||
placed there by plugins.
|
||||
Added - if you specify an output filename ending in .jpg or .gif, you'll get a GIF or JPEG file.
|
||||
Added - BACKGROUND and ICON also understand JPEG, GIF and PNG, if your GD library understands them.
|
||||
Added - support for non-standard polling periods in Cacti plugin. You can choose to only update every so often, or not at all (manually).
|
||||
Added - manual 'recalculate now' button in Cacti plugin's management UI
|
||||
Added - SET command to pass hints into plugins or weathermap core, per-node, per-link or globally.
|
||||
Cleaned up config parser. Can be more fussy. More consistent though.
|
||||
Added - CLI tool takes --define to define SET-style variables
|
||||
|
||||
0.82 FIXED another variation on ReadFromRRD not detecting NaNs properly (hyland)
|
||||
FIXED SQL error which affects only some MySQL 5s (gundamx)
|
||||
FIXED some minor php errors in setup.php (cigamit)
|
||||
Changed the rrdtool period from now-400 to now-800 to avoid long-poller-cycle problems.
|
||||
Did some more /=>DIRECTORY_SEPARATOR changes - there weren't any problems, but it's a potential one.
|
||||
FIXED if you use the editor and your rrdtool is somewhere other than /usr/bin/rrdtool then you get an incorrect error about checking line 27 of the CLI tool.
|
||||
|
||||
0.81 - Added a Weathermaps link to the Cacti 'Configuration' side-menu. Removed 'Manage Maps' link in Weathermap tab. (knobdy)
|
||||
File-picker in editor no longer masks on *.conf
|
||||
FIXED sort-order bug for imagemaps (Fran Boon)
|
||||
FIXED plugin shows same map twice if you have 'Anyone + users' (Fran Boon, again)
|
||||
FIXED default bandwidth duplicated field in editor. (qjy2000_cn)
|
||||
FIXED now allow TITLEPOS 0 0 (actually, y=0 is useless, but x=0 might be useful) (knobdy)
|
||||
Editor still won't upload images, but it WILL let you pick from any PNG files in the images/
|
||||
folder, and any images already mentioned in the map configuration file for ICON and BACKGROUND
|
||||
lines. (everyone and their dog)
|
||||
Similar change for DEFINEFONT. You still have to hand-edit to define the font, but after that, the
|
||||
editor will let you pick it.
|
||||
Changed the dependency tests to NOT give a warning about particular DLL names.
|
||||
Added more dependency tests for specific functions.
|
||||
Changes some debug messages to warning, so that they are visible in the logs even without DEBUG on.
|
||||
FIXED minor (unreported) bug with sort order in Manage Maps
|
||||
Changed most Cacti Plugin code to use Cacti's (logging) SQL functions. Hopefully this will help
|
||||
with running down a couple of problems for Windows users.
|
||||
More error reporting generally.
|
||||
Fixed error when creating multiple links between nodes in the editor (fozzy)
|
||||
Docs update - More FAQs and config reference improvements/amendments.
|
||||
Added 'Cycle' mode to plugin - automatically cycle between your weathermaps.
|
||||
|
||||
0.8 - Added ability to have multiple targets for a LINK - aggregate your T1s
|
||||
Added ability to use half an RRD (use '-' as the DS name) - if you have 'in' in one RRD, and 'out' in another
|
||||
Added a tab-seperated file datasource for TARGET lines, so you can draw anything you can dump into a textfile.
|
||||
Added ability to specify which corner of a NODE each LINK-end goes to - handy for busy hub nodes
|
||||
Added support for FreeType & GD fonts
|
||||
Added VIA points - a link can go around corners, and they're nicely curved too.
|
||||
Added gradient SCALEs - specify two colours for a band to have colours interpolated.
|
||||
Added many more colour controls for map elements:
|
||||
For Links: OUTLINECOLOR r g b ( or OUTLINECOLOR none)
|
||||
For Link bandwidth labels: BWOUTLINECOLOR, BWBOXCOLOR, BWFONTCOLOR
|
||||
For Nodes: LABELBGCOLOR, LABELFONTCOLOR, LABELOUTLINECOLOR, LABELFONTSHADOWCOLOR
|
||||
For Map 'furniture': TIMECOLOR, TITLECOLOR, KEYBGCOLOR, KEYTEXTCOLOR, KEYOUTLINE
|
||||
Added Cacti plugin. View and Manage UI, plus poller integration. No editor (yet)
|
||||
Updated example config to use new 0.8 features
|
||||
Re-organised manual, and heavily re-written config reference.
|
||||
Fixed cacti-pick.php some more (all done now?)
|
||||
Added non-bandwidth bandwidth labels: BWLABELS unformatted
|
||||
Many Thanks to James Lang, Niels Baggesen and the [php-weathermap] mailing list for feedback
|
||||
during the testing of this release.
|
||||
|
||||
0.71 - Fixed database code in cacti-pick.php
|
||||
Fixed up editor to handle blank maps better.
|
||||
Fixed a problem with cached images in editor.
|
||||
|
||||
0.7 - Updated the manual and example map to reflect all these changes.
|
||||
Added config options for HTMLOUTPUTFILE and IMAGEOUTPUTFILE. The
|
||||
idea is to reduce the size of command-lines, and make the map files
|
||||
more self-contained. CLI options still take precedence.
|
||||
Includes new 'DHTML' editor for the first time. This is still very much
|
||||
in testing - backup any map configs you edit with it first!
|
||||
Fixed DrawLegend() to not go below a minimum width (it used to use the
|
||||
title length, but that can be too small now)
|
||||
Added BACKGROUNDCOLOR option: take an R G B like the SCALE lines (request
|
||||
from kbriggs)
|
||||
Ripped out some of the 'live PHP' code to make DrawMap a bit simpler.
|
||||
Added a check for PNG support in CLI command.
|
||||
Added command-line error-checking (Niels is back again)
|
||||
Added a fix for Windows line-endings. Seems that PHP uses Unix-endings even on Win32
|
||||
Added LINK DEFAULT and NODE DEFAULT - set the defaults for (nearly) any
|
||||
parameter. This also means that most node-affecting and link-affecting
|
||||
parameters are now per-node and per-link.
|
||||
Added ARROWSTYLE option - there's 'classic' and 'compact' with neater arrowheads.
|
||||
Added LABELOFFSET option to change the relative position of the LABEL when an
|
||||
ICON is also used.
|
||||
Added OVERLIBWIDTH and OVERLIBHEIGHT to allow better OverLib output (Niels B, once more)
|
||||
Switched to using 24bit images internally. This should improve the handling of
|
||||
PNG transparency in ICONs.
|
||||
Improved number and content of error messages.
|
||||
|
||||
0.6 - Renamed weathermap.php to just 'weathermap' to make it more
|
||||
obviously not a PHP page.
|
||||
Fixed up NODE name regexp (thanks Niels Baggesen)
|
||||
Added warning for non-existent NODES in LINK (thanks again Niels Baggesen)
|
||||
HTML fix for <map> in generated HTML (Niels once more)
|
||||
More HTML fixes to make us a bit more XHTML-like.
|
||||
You can have an ICON and a LABEL now. LABEL is centred over the
|
||||
NODE, for the moment. Also, there's a drop shadow effect, to make
|
||||
it easier to read the overlaid text.
|
||||
New config features: LINKFONT, NODEFONT and KEYFONT to control the
|
||||
fonts used for those things. It's a number from 1 to 5.
|
||||
Added BWLABELS NONE for no labels on links at all (request from Ueli Heuer)
|
||||
Moved responsibility for complete HTML page from the class to the CLI program - MakeHTML produces an HTML fragment now.
|
||||
Added ability to customise timestamp and legend text, by adding new text after the KEYPOS and TIMEPOS commands.
|
||||
|
||||
0.5a - Fixed totally embarrassing problems with the DS-specification code.
|
||||
As far as I can figure I never did test it. Oh dear. Thanks to
|
||||
Jethro Binks for speedy patches.
|
||||
|
||||
0.5 - Fixed asymmetric BANDWIDTH bug - thanks rpingar
|
||||
Fix to make rrdtool commandline work on Windows - also thanks to rpingar
|
||||
Added specification of RRD DS names in TARGET ( blah.rrd:ds0:ds1 - that's in then out)
|
||||
Fix for different C libraries returning something other than NaN for a NaN (thru rrd) - now we look for good data rather than bad data.
|
||||
Allow for decimals in BANDWIDTH specifications - 1.5M should work now
|
||||
Allow for decimals in SCALE specifications - mainly useful for very small values on big links
|
||||
Brought back sub-1.0 percentages, which got lost somewhere along the line
|
||||
Added in warning for >100% lines
|
||||
Added TIMEPOS option so *you* get to choose where the timestamp goes, mgb
|
||||
Fixed stupid bug in ReadRRDData - Weathermap should follow the data better now. Thanks to 'cl'
|
||||
|
||||
0.4 - Changed all internals to deal in bits/sec instead of bytes
|
||||
Moved timestamp back up to the top-right corner.
|
||||
*BREAKAGE* Changed BANDWIDTH to use bits too
|
||||
Added support for K,M,G,T suffixes on bandwidth specs
|
||||
Added KILO config file option to redefine 1K=1000 or 1K=1024 (or anything actually)
|
||||
Added --sizedebug commandline option, to help with figuring out
|
||||
what you did wrong with the new BANDWIDTH format. Shows max
|
||||
bandwidth instead of the current bandwidth on all links.
|
||||
Included something a bit more like a manual.
|
||||
*BREAKAGE* Changed BWLABELS options to be bits/percent, since they *are* bits!
|
||||
LABEL regexp relaxed to allow spaces in labels
|
||||
HTMLSTYLE, BWLABELS regexps tightened up to detect more errors
|
||||
Added new example config in docs/ directory
|
||||
Moved editor.php out of the way to random-bits
|
||||
Included a copy of auto-overlib.pl, just cos it's handy
|
||||
|
||||
0.3 - ICON config directive for NODEs added - same effect as jas0420's perl code
|
||||
Fixed WriteConfig a little - TITLEs are written.
|
||||
OVERLIBGRAPH config is written for NODES.
|
||||
Fixed bug with OVERLIBGRAPH DHTML and NODEs
|
||||
Added --image-uri option back in from the perl version
|
||||
|
||||
0.2 - NODEs with no label aren't drawn but can still be an endpoint for a LINK.
|
||||
Small bugfixes from mgb
|
||||
Included the editor.php for people to see
|
||||
Code tidyup for weathermap.php
|
||||
|
||||
0.1 - Initial pre-release version
|
340
includes/weathermap/COPYING
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
36
includes/weathermap/README.md
Normal file
@ -0,0 +1,36 @@
|
||||
## PHP Network Weathermap 0.98a
|
||||
|
||||
This is PHP Network Weathermap, version 0.98a by Howard Jones (howie@thingy.com)
|
||||
|
||||
See the docs sub-directory for full HTML documentation, FAQ and example config.
|
||||
|
||||
See CHANGES for the most recent updates, listed by version.
|
||||
|
||||
See COPYING for the license under which php-weathermap is released.
|
||||
|
||||
There is much more information, tutorials and updates available at:
|
||||
http://www.network-weathermap.com/
|
||||
|
||||
*IMPORTANT NOTE*: This version only works with Cacti 0.8.8 (not 1.x.x)
|
||||
|
||||
------
|
||||
|
||||
PHP Weathermap contains components from other software developers:
|
||||
|
||||
overlib.js is part of Overlib 4.21, copyright Erik Bosrup 1998-2004. All rights reserved.
|
||||
See http://www.bosrup.com/web/overlib/?License
|
||||
|
||||
The Bitstream Vera Open Source fonts (Vera*.ttf) are copyright Bitstream, Inc.
|
||||
See http://www.bitstream.com/font_rendering/products/dev_fonts/vera.html
|
||||
|
||||
The manual uses the Kube CSS Framework - http://imperavi.com/kube/
|
||||
and ParaType's PT Sans font: http://www.fontsquirrel.com/fonts/PT-Sans
|
||||
|
||||
jquery-latest.min.js is the jQuery javascript library - written by John Resig and collaborators.
|
||||
http://docs.jquery.com/Licensing
|
||||
|
||||
Some of the icons used in the editor, and also supplied in the images/ folder are
|
||||
from the excellent Fam Fam Fam Silk icon collection by Mark James:
|
||||
http://www.famfamfam.com/lab/icons/silk/
|
||||
These are released under the Creative Commons Attribution 2.5 License
|
||||
http://creativecommons.org/licenses/by/2.5/
|
45
includes/weathermap/check-gdbug.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
ob_start();
|
||||
|
||||
if(isset($argv))
|
||||
{
|
||||
$env = "CLI";
|
||||
}
|
||||
else
|
||||
{
|
||||
$env = "WEB";
|
||||
}
|
||||
|
||||
print wordwrap("Some version of the GD graphics library have a bug in their handling of Alpha channels. Unfortunately, Weathermap uses these to draw Nodes.");
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
|
||||
print wordwrap("This program will test if your PHP installation is using a buggy GD library.");
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
|
||||
print wordwrap("If you are, you should either use PHP's built-in (aka 'bundled') GD library, or update to GD Version 2.0.34 or newer. Weathermap REQUIRES working Alpha support.");
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
|
||||
print wordwrap("Let's see if you have the GD transparency bug...");
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
print wordwrap("If you see no more output, or a segfault, then you do, and you'll need to upgrade.");
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
print wordwrap("If you get other errors, like 'undefined function', then run check.php to\nmake sure that your PHP installation is otherwise OK.");
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
print "Here we go...";
|
||||
print ($env=='CLI'?"\n\n":"\n<p>");
|
||||
|
||||
// make sure even the affected folks can see the explanation
|
||||
ob_flush();
|
||||
flush();
|
||||
|
||||
$temp_width = 10;
|
||||
$temp_height = 10;
|
||||
|
||||
$node_im=imagecreatetruecolor($temp_width,$temp_height );
|
||||
imageSaveAlpha($node_im, TRUE);
|
||||
$nothing=imagecolorallocatealpha($node_im,128,0,0,127);
|
||||
imagefill($node_im, 0, 0, $nothing);
|
||||
imagedestroy($node_im);
|
||||
|
||||
print "...nope. We got past the risky part, so that's good.\nYour GD library looks healthy.\n";
|
||||
print ($env=='CLI'?"\n":"\n<p>");
|
282
includes/weathermap/check.php
Normal file
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
// get some basics...
|
||||
$php_version = phpversion();
|
||||
$mem_allowed = ini_get("memory_limit");
|
||||
$php_os = php_uname();
|
||||
|
||||
$mem_warning = "";
|
||||
$mem_allowed_int = return_bytes($mem_allowed);
|
||||
if(($mem_allowed_int>0) && ($mem_allowed_int < 32000000)) { $mem_warning='You should increase this value to at least 32M. '; }
|
||||
|
||||
// capture the PHP "General Info" table
|
||||
ob_start();
|
||||
phpinfo(INFO_GENERAL);
|
||||
$s = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// <tr><td class="e">System </td><td class="v">Windows NT BLINKYZERO 6.0 build 6000 </td></tr>
|
||||
// since preg_* are potentially missing, we'll have to do this without regexps.
|
||||
foreach (explode("\n",$s) as $line)
|
||||
{
|
||||
$line = str_replace('<tr><td class="e">','',$line);
|
||||
$line = str_replace('</td></tr>','',$line);
|
||||
$line = str_replace(' </td><td class="v">',' => ',$line);
|
||||
$sep_pos = strpos($line," => ");
|
||||
if($sep_pos!==FALSE)
|
||||
{
|
||||
// by here, it should be a straight "name => value"
|
||||
$name = substr($line,0,$sep_pos);
|
||||
$value = substr($line,$sep_pos+4);
|
||||
$php_general[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$ini_file = $php_general['Loaded Configuration File'];
|
||||
$extra_ini = php_ini_scanned_files();
|
||||
if($extra_ini != '')
|
||||
{ $extra_ini = "The following additional ini files were read: $extra_ini"; }
|
||||
else { $extra_ini = "There were no additional ini files, according to PHP."; }
|
||||
|
||||
$gdversion = "";
|
||||
$gdbuiltin=FALSE;
|
||||
$gdstring = "";
|
||||
if(function_exists('gd_info'))
|
||||
{
|
||||
$gdinfo = gd_info();
|
||||
$gdversion=$gdinfo['GD Version'];
|
||||
if(strpos($gdversion,"bundled") !== FALSE)
|
||||
{
|
||||
$gdbuiltin=TRUE;
|
||||
$gdstring="This PHP uses the 'bundled' GD library, which doesn't have alpha-blending bugs. That's good!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$gdstring="This PHP uses the system GD library, which MIGHT have alpha-blending bugs. Check that you have at least GD 2.0.34 installed, if you see problems with weathermap segfaulting.\n";
|
||||
$gdstring .= "You can test for this specific fault by running check-gdbug.php\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$gdstring = "The gdinfo() function is not available, which means that either the GD extension is not available, not enabled, or not installed.\n";
|
||||
}
|
||||
|
||||
if(isset($argv))
|
||||
{
|
||||
$environment = "CLI";
|
||||
print "\n----------------------------------------------------\nWeathermap Pre-Install Checker\n\n";
|
||||
print "This script checks for some common problems with your PHP and server\nenvironment that may stop Weathermap or the Editor from working.\n\n";
|
||||
print "NOTE: You should run this script as both a web page AND from the\ncommand-line, as the environment can be different in each.\n";
|
||||
print "\nThis is the PHP version that is responsible for \n* creating maps from the Cacti poller\n* the command-line weathermap tool\n\n";
|
||||
print "PHP Basics\n----------\n";
|
||||
print wordwrap("This is PHP Version $php_version running on \"$php_os\" with a memory_limit of '$mem_allowed'. $mem_warning\n");
|
||||
print "\nThe php.ini file was $ini_file\n$extra_ini\n\n";
|
||||
print "";
|
||||
print "PHP Functions\n-------------\n";
|
||||
print "Some parts of Weathermap need special support in your PHP\ninstallation to work.\n\n";
|
||||
print wordwrap($gdstring)."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$environment = "web";
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Weathermap Pre-Install Checker</title>
|
||||
<style type="text/css">
|
||||
body { font-family: 'Lucida Grande',Arial,sans-serif; font-size: 10pt; }
|
||||
p {margin-bottom: 10px; margin-top: 10px;}
|
||||
table { margin: 20px;}
|
||||
.critical { width: 400px; padding: 10px; background: #fee; border: 1px solid #f88; padding-left: 20px; background: left no-repeat url(images/exclamation.png); }
|
||||
.noncritical { width: 400px; padding: 10px; background: #ffe; border: 1px solid #fb8; }
|
||||
.ok { width: 400px; padding: 10px; background: #efe; border: 1px solid #8f8; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Weathermap Pre-install Checker</h1>
|
||||
|
||||
<p>This page checks for some common problems with your PHP and server environment that may stop Weathermap or the Editor from working.</p>
|
||||
<p>NOTE: You should run this script as a web page AND from the command-line, as the environment can be different in each.</p>
|
||||
<h2>PHP Basics</h2><p>This is the PHP version that is responsible for</p><ul>
|
||||
<li>The web-based editor</li><li>Building maps with Rebuild Now from Cacti</li></ul>
|
||||
<p>This is PHP Version <?php echo $php_version ?> running on "<?php echo $php_os ?>" with a memory_limit of '<?php echo $mem_allowed ?>'. <?php echo $mem_warning ?></p>
|
||||
<p>The php.ini file was <?php echo $ini_file ?></p>
|
||||
<p><?php echo $extra_ini ?></p>
|
||||
<h2>PHP Functions</h2>
|
||||
<p>Some parts of Weathermap need special support in your PHP installation to work.</p>
|
||||
<?php echo $gdstring; ?>
|
||||
<table>
|
||||
<?php
|
||||
}
|
||||
|
||||
$critical=0;
|
||||
$noncritical=0;
|
||||
|
||||
|
||||
|
||||
# critical, what-it-affects, what-it-is
|
||||
$functions = array('imagepng' => array(TRUE,FALSE,'all of Weathermap','part of the GD library and the "gd" PHP extension'),
|
||||
'imagecreatetruecolor' => array(TRUE,FALSE,'all of Weathermap','part of the GD library and the "gd" PHP extension'),
|
||||
'imagealphablending' => array(TRUE,FALSE,'all of Weathermap','part of the GD library and the "gd" PHP extension'),
|
||||
'imageSaveAlpha' => array(TRUE,FALSE,'all of Weathermap','part of the GD library and the "gd" PHP extension'),
|
||||
'preg_match'=> array(TRUE,FALSE,'configuration reading','provided by the "pcre" extension') ,
|
||||
'imagecreatefrompng' => array(TRUE,FALSE,'all of Weathermap','part of the GD library and the "gd" PHP extension'),
|
||||
|
||||
'imagecreatefromjpeg' => array(FALSE,FALSE,'JPEG input support for ICON and BACKGROUND','an optional part of the GD library and the "gd" PHP extension'),
|
||||
'imagecreatefromgif' => array(FALSE,FALSE,'GIF input support for ICON and BACKGROUND','an optional part of the GD library and the "gd" PHP extension'),
|
||||
'imagejpeg' => array(FALSE,FALSE,'JPEG output support','an optional part of the GD library and the "gd" PHP extension'),
|
||||
'imagegif' => array(FALSE,FALSE,'GIF output support','an optional part of the GD library and the "gd" PHP extension'),
|
||||
# 'imagefilter' => array(FALSE, FALSE, 'colorizing icons','a special function of the PHP-supplied GD library ONLY (not the external GD library'.($gdbuiltin?'':' that you are using').')'),
|
||||
'imagecopyresampled' => array(FALSE,FALSE,'Thumbnail creation in the Cacti plugin','an optional part of the GD library and the "gd" PHP extension'),
|
||||
'imagettfbbox' => array(FALSE,FALSE,'TrueType font support','an optional part of the GD library and the "gd" PHP extension'),
|
||||
'memory_get_usage' => array(FALSE,TRUE,'memory-usage debugging','not supported on all PHP versions and platforms')
|
||||
);
|
||||
|
||||
$results=array();
|
||||
|
||||
if($environment == 'CLI')
|
||||
{
|
||||
// Console_Getopt is only needed by the CLI tool.
|
||||
$included = @include_once 'Console/Getopt.php';
|
||||
|
||||
if($included != 1)
|
||||
{
|
||||
$noncritical++;
|
||||
print wordwrap("The Console_Getopt PEAR module is not available. The CLI weathermap tool will not run without it (that may not be a problem, if you only intend to use Cacti).\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
print wordwrap("The Console_Getopt PEAR module is available. That's good!\n\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach ($functions as $function=>$details)
|
||||
{
|
||||
$exists = ""; $notes="";
|
||||
if($environment=='web') print "<tr><td align=right>$function()</td>";
|
||||
|
||||
if(function_exists($function))
|
||||
{
|
||||
$exists = "YES";
|
||||
if($environment=='web') print " /></td>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exists = "NO";
|
||||
if($details[0])
|
||||
{
|
||||
$notes .= "CRITICAL. ";
|
||||
if($environment=='web') print " /><b>CRITICAL</b> ";
|
||||
$critical++;
|
||||
} else {
|
||||
if(!$details[1])
|
||||
{
|
||||
$notes .= "Non-Critical. ";
|
||||
if($environment=='web') print " /><i>non-critical</i> ";
|
||||
$noncritical++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$notes .= "Minor. ";
|
||||
if($environment=='web') print " /><i>minor</i> ";
|
||||
}
|
||||
}
|
||||
$explanation = "This is required for ".$details[2].". It is ".$details[3].".";
|
||||
$notes .= $explanation;
|
||||
|
||||
if($environment=='web') print "$explanation</td>";
|
||||
}
|
||||
if($environment=='web') print "</tr>\n";
|
||||
else
|
||||
{
|
||||
$wnotes = wordwrap($notes,50);
|
||||
$lines = explode("\n",$wnotes);
|
||||
$i=0;
|
||||
foreach ($lines as $noteline)
|
||||
{
|
||||
if($i==0)
|
||||
{
|
||||
print sprintf("%20s %5s %-52s\n",$function,$exists,$noteline);
|
||||
$i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
print sprintf("%20s %5s %-52s\n","","",$noteline);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($environment=='web') print "</table>";
|
||||
|
||||
if( ($critical + $noncritical) > 0)
|
||||
{
|
||||
if($environment=='web')
|
||||
{
|
||||
print "<p>If these functions are not found, you may need to <ul><li>check that the 'extension=' line for that extension is uncommented in your php.ini file (then restart your webserver), or<li>install the extension, if it isn't installed already</ul>On Debian/Ubuntu systems, you may also need to use the php5enmod command to enable the extension.</p>";
|
||||
}
|
||||
else
|
||||
{
|
||||
print "\nIf these functions are not found, you may need to\n * check that the 'extension=' line for that extension is uncommented in\n your php.ini file (then restart your webserver), or\n * install the extension, if it isn't installed already\n\n";
|
||||
}
|
||||
|
||||
print wordwrap("The details of how this is done will depend on your operating system, and on where you installed (or compiled) your PHP from originally. Usually, you would install an RPM, or other package on Linux systems, a port on *BSD, or a DLL on Windows. If you build PHP from source, you need to add extra options to the './configure' line. Consult your PHP documention for more information.\n");
|
||||
if($environment=='web') print "</p>";
|
||||
}
|
||||
|
||||
if($environment=="CLI") print "\n---------------------------------------------------------------------\n";
|
||||
|
||||
if($critical>0)
|
||||
{
|
||||
if($environment=='web') print "<div class=\"critical\">";
|
||||
print wordwrap("There are problems with your PHP or server environment that will stop Weathermap from working. You need to correct these issues if you wish to use Weathermap.\n");
|
||||
if($environment=='web') print "</div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
if($noncritical>0)
|
||||
{
|
||||
if($environment=='web') print "<div class=\"noncritical\">";
|
||||
print wordwrap("Some features of Weathermap will not be available to you, due to lack of support in your PHP installation. You can still proceed with Weathermap though.\n");
|
||||
if($environment=='web') print "</div>";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if($environment=='web') print "<div class=\"ok\">";
|
||||
print wordwrap("OK! Your PHP and server environment *seems* to have support for ALL of the Weathermap features. Make sure you have run this script BOTH as a web page and from the CLI to be sure, however.\n");
|
||||
if($environment=='web') print "</div>";
|
||||
|
||||
}
|
||||
}
|
||||
if($environment=='web') print "</body></html>";
|
||||
|
||||
function return_bytes($val) {
|
||||
$val = trim($val);
|
||||
if($val != '')
|
||||
{
|
||||
$last = strtolower($val{strlen($val)-1});
|
||||
switch($last) {
|
||||
// The 'G' modifier is available since PHP 5.1.0
|
||||
case 'g':
|
||||
$val *= 1024;
|
||||
case 'm':
|
||||
$val *= 1024;
|
||||
case 'k':
|
||||
$val *= 1024;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$val = 0;
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
4
includes/weathermap/configs/.htaccess
Executable file
@ -0,0 +1,4 @@
|
||||
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
|
212
includes/weathermap/configs/example.conf
Normal file
@ -0,0 +1,212 @@
|
||||
# Automatically generated by php-weathermapp v0.98a
|
||||
|
||||
FONTDEFINE 100 docs/example/VeraIt.ttf 8
|
||||
FONTDEFINE 101 docs/example/Vera.ttf 12
|
||||
FONTDEFINE 102 docs/example/Vera.ttf 9
|
||||
|
||||
BACKGROUND background.png
|
||||
WIDTH 1230
|
||||
HEIGHT 800
|
||||
HTMLSTYLE overlib
|
||||
KEYFONT 102
|
||||
TITLE Network Overview
|
||||
HTMLOUTPUTFILE maps/example.html
|
||||
IMAGEOUTPUTFILE maps/example.png
|
||||
TIMEPOS 0 0 %Y%M%d %H:%M:%S
|
||||
|
||||
KEYPOS DEFAULT 10 400 Traffic Load
|
||||
KEYTEXTCOLOR 0 0 0
|
||||
KEYOUTLINECOLOR 0 0 0
|
||||
KEYBGCOLOR 255 255 255
|
||||
BGCOLOR 255 255 255
|
||||
TITLECOLOR 0 0 0
|
||||
TIMECOLOR 0 0 0
|
||||
SCALE DEFAULT 0 0 192 192 192
|
||||
SCALE DEFAULT 0 1 255 255 255
|
||||
SCALE DEFAULT 1 10 140 0 255
|
||||
SCALE DEFAULT 10 25 32 32 255
|
||||
SCALE DEFAULT 25 40 0 192 255
|
||||
SCALE DEFAULT 40 55 0 240 0
|
||||
SCALE DEFAULT 55 70 240 240 0
|
||||
SCALE DEFAULT 70 85 255 192 0
|
||||
SCALE DEFAULT 85 100 255 0 0
|
||||
|
||||
SET key_hidezero_DEFAULT 1
|
||||
|
||||
# End of global section
|
||||
|
||||
|
||||
# TEMPLATE-only NODEs:
|
||||
NODE DEFAULT
|
||||
LABELFONT 101
|
||||
MAXVALUE 100
|
||||
|
||||
|
||||
# TEMPLATE-only LINKs:
|
||||
LINK DEFAULT
|
||||
WIDTH 4
|
||||
OVERLIBWIDTH 395
|
||||
OVERLIBHEIGHT 153
|
||||
BWFONT 100
|
||||
BWLABEL bits
|
||||
BANDWIDTH 100M
|
||||
|
||||
|
||||
# regular NODEs:
|
||||
NODE transit
|
||||
LABEL TRANSIT
|
||||
POSITION 400 180
|
||||
|
||||
NODE isp1
|
||||
LABEL ISP
|
||||
LABELBGCOLOR 255 224 224
|
||||
INFOURL http://www.isp1.com/support/lookingglass.html
|
||||
POSITION 250 100
|
||||
|
||||
NODE isp2
|
||||
LABEL ISP2
|
||||
LABELBGCOLOR 224 255 224
|
||||
INFOURL http://www.isp2.net/portal/
|
||||
POSITION 550 100
|
||||
|
||||
NODE core
|
||||
LABEL core
|
||||
INFOURL https://core.mynet.net/admin/
|
||||
POSITION 400 300
|
||||
|
||||
NODE customer1
|
||||
LABEL xy.com
|
||||
POSITION 150 370
|
||||
|
||||
NODE customer2
|
||||
LABEL ww.co.uk
|
||||
POSITION 250 450
|
||||
|
||||
NODE infra
|
||||
LABEL INFRASTRUCTURE
|
||||
ICON images/HPMini.png
|
||||
POSITION 450 450
|
||||
|
||||
NODE sync
|
||||
LABEL Sync
|
||||
POSITION 550 370
|
||||
|
||||
NODE site1
|
||||
LABEL site1
|
||||
POSITION 1141 241
|
||||
|
||||
NODE site2
|
||||
LABEL site2
|
||||
POSITION 1070 559
|
||||
|
||||
NODE node02921
|
||||
LABEL Node
|
||||
POSITION 161 222
|
||||
|
||||
NODE node02941
|
||||
LABEL Node
|
||||
POSITION 760 86
|
||||
|
||||
|
||||
# regular LINKs:
|
||||
LINK sync-core
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=256
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=256&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/sync_traffic_in_259.rrd
|
||||
NODES sync core
|
||||
|
||||
LINK sync-site1a
|
||||
WIDTH 3
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=126
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=254&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=
|
||||
TARGET data/sync_traffic_in_257.rrd
|
||||
NODES sync:N site1:W
|
||||
VIA 837 270
|
||||
BANDWIDTH 2M
|
||||
|
||||
LINK sync-site1b
|
||||
WIDTH 3
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=56
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=255&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=
|
||||
TARGET data/sync_traffic_in_258.rrd
|
||||
NODES sync:E site1:SE
|
||||
VIA 875 337
|
||||
BANDWIDTH 2M
|
||||
|
||||
LINK sync-site2a
|
||||
WIDTH 3
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=252
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=248&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/sync_traffic_in_251.rrd
|
||||
NODES sync site2
|
||||
VIA 805 447
|
||||
BANDWIDTH 1M
|
||||
|
||||
LINK sync-site2b
|
||||
WIDTH 3
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=561
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=228&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/sync_traffic_in_252.rrd
|
||||
NODES sync site2
|
||||
VIA 817 492
|
||||
BANDWIDTH 1M
|
||||
|
||||
LINK transit-isp1
|
||||
INFOURL /graphs/type=port_bits/id=558000/
|
||||
OVERLIBGRAPH /graph.php?height=100&width=512&id=558000&type=port_bits&legend=no
|
||||
TARGET ../../rrd/195.55.84.91/port-31.rrd:INOCTETS:OUTOCTETS
|
||||
NODES transit isp1
|
||||
BANDWIDTH 10M
|
||||
|
||||
LINK transit-isp2
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=265
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=433&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/trans1_traffic_in_438.rrd
|
||||
NODES transit isp2
|
||||
BANDWIDTH 34M
|
||||
|
||||
LINK core-transit
|
||||
ARROWSTYLE compact
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=122
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=347&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/trans1_traffic_in_350.rrd
|
||||
NODES transit core
|
||||
|
||||
LINK cust1-core
|
||||
INFOURL /graphs/type=port_bits/id=564237/
|
||||
OVERLIBGRAPH /graph.php?height=100&width=512&id=564237&type=port_bits&legend=no
|
||||
TARGET ../../rrd/211.87.54.1/port-130.rrd:INOCTETS:OUTOCTETS
|
||||
NODES customer1 core
|
||||
|
||||
LINK cust2-core
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=222
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=283&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/extreme_traffic_in_286.rrd
|
||||
NODES customer2 core
|
||||
|
||||
LINK infra-core
|
||||
INFOURL http://support.mynet.net/cacti/graph.php?rra_id=all&local_graph_id=228
|
||||
OVERLIBGRAPH http://support.mynet.net/cacti/graph_image.php?local_graph_id=291&rra_id=0&graph_nolegend=true&graph_height=100&graph_width=300
|
||||
TARGET data/extreme_traffic_in_294.rrd
|
||||
NODES infra core
|
||||
|
||||
LINK node02921-isp1
|
||||
NODES node02921 isp1
|
||||
|
||||
LINK node02921-customer1
|
||||
NODES node02921 customer1
|
||||
|
||||
LINK node02941-site1
|
||||
NODES node02941 site1
|
||||
|
||||
LINK node02941-isp2
|
||||
NODES node02941 isp2
|
||||
VIA 655 63
|
||||
|
||||
LINK node02941-isp2a
|
||||
NODES node02941 isp2
|
||||
VIA 659 122
|
||||
|
||||
|
||||
|
||||
# That's All Folks!
|
5
includes/weathermap/configs/index.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
header("Location:../index.php");
|
||||
|
||||
// vim:ts=4:sw=4:
|
99
includes/weathermap/configs/simple.conf
Normal file
@ -0,0 +1,99 @@
|
||||
# Automatically generated by php-weathermap v0.98a
|
||||
|
||||
FONTDEFINE 100 docs/example/Vera.ttf 10
|
||||
|
||||
WIDTH 1250
|
||||
HEIGHT 700
|
||||
HTMLSTYLE overlib
|
||||
KEYFONT 100
|
||||
TITLE Simple Map
|
||||
HTMLOUTPUTFILE maps/simple.html
|
||||
IMAGEOUTPUTFILE maps/simple.png
|
||||
TIMEPOS 1069 690 Created: %b %d %Y %H:%M:%S
|
||||
|
||||
KEYPOS DEFAULT 7 507 Traffic Load
|
||||
KEYTEXTCOLOR 0 0 0
|
||||
KEYOUTLINECOLOR 0 0 0
|
||||
KEYBGCOLOR 255 255 255
|
||||
BGCOLOR 255 255 255
|
||||
TITLECOLOR 0 0 0
|
||||
TIMECOLOR 0 0 0
|
||||
SCALE DEFAULT 0 0 192 192 192
|
||||
SCALE DEFAULT 0 1 255 255 255
|
||||
SCALE DEFAULT 1 10 140 0 255
|
||||
SCALE DEFAULT 10 25 32 32 255
|
||||
SCALE DEFAULT 25 40 0 192 255
|
||||
SCALE DEFAULT 40 55 0 240 0
|
||||
SCALE DEFAULT 55 70 240 240 0
|
||||
SCALE DEFAULT 70 85 255 192 0
|
||||
SCALE DEFAULT 85 100 255 0 0
|
||||
|
||||
SET nowarn_clipping 1
|
||||
|
||||
# End of global section
|
||||
|
||||
|
||||
# TEMPLATE-only NODEs:
|
||||
NODE DEFAULT
|
||||
LABELFONT 100
|
||||
MAXVALUE 100
|
||||
|
||||
|
||||
# TEMPLATE-only LINKs:
|
||||
LINK DEFAULT
|
||||
WIDTH 5
|
||||
ARROWSTYLE compact
|
||||
BWFONT 100
|
||||
COMMENTFONT 100
|
||||
BWLABEL bits
|
||||
BANDWIDTH 1M
|
||||
|
||||
|
||||
# regular NODEs:
|
||||
NODE node1
|
||||
LABEL Node 1
|
||||
ICON images/PAD.png
|
||||
POSITION 837 62
|
||||
|
||||
NODE node2
|
||||
LABEL Node 2
|
||||
ICON images/Cloud-Filled.png
|
||||
POSITION 258 265
|
||||
|
||||
NODE node3
|
||||
LABEL Node 3
|
||||
ICON images/tick.png
|
||||
POSITION 502 69
|
||||
|
||||
NODE node01940
|
||||
LABEL Node
|
||||
ICON images/Host.png
|
||||
POSITION 490 439
|
||||
|
||||
|
||||
# regular LINKs:
|
||||
LINK node1-node2
|
||||
INFOURL /graphs/type=port_bits/id=556216/
|
||||
OVERLIBGRAPH http://dev.observium.org/ajax/entity_popup.php?entity_type=port&entity_id=556216
|
||||
TARGET ../../rrd/bb1.nubenet.com.ar/port-1.rrd:INOCTETS:OUTOCTETS ../../rrd/103.24.244.34/port-1.rrd:INOCTETS:OUTOCTETS
|
||||
NODES node1:-40:7 node2:46:-15
|
||||
SET _tidied 1
|
||||
|
||||
LINK node2-node3
|
||||
INFOURL /graphs/type=port_bits/id=556217/
|
||||
OVERLIBGRAPH /graph.php?height=100&width=512&id=556217&type=port_bits&legend=no
|
||||
TARGET ../../rrd/103.24.244.34/port-2.rrd:INOCTETS:OUTOCTETS
|
||||
NODES node2:0:0 node3:0:0
|
||||
BANDWIDTH 2M
|
||||
SET _tidied 1
|
||||
|
||||
LINK node01940-node1
|
||||
INFOURL /graphs/type=port_bits/id=559244/
|
||||
OVERLIBGRAPH /graph.php?height=100&width=512&id=559244&type=port_bits&legend=no
|
||||
TARGET ../../rrd/bb1.nubenet.com.ar/port-2.rrd:INOCTETS:OUTOCTETS
|
||||
NODES node01940:0:0 node1:0:0
|
||||
SET _tidied 1
|
||||
|
||||
|
||||
|
||||
# That's All Folks!
|
141
includes/weathermap/editor-resources/editor.css
Normal file
@ -0,0 +1,141 @@
|
||||
/* http://colorblender.com/?preloadblend=BC00008A513EFFF2DE5E5550857C73FCFCFC */
|
||||
|
||||
#filenameholder {
|
||||
font-size: 70%;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#busy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.viamarker {
|
||||
z-index: 500;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
|
||||
/* #themap { margin-left: auto; margin-right: auto; padding: 0; width: 800px; padding-top: 10px; display: none; } */
|
||||
#existingdata {
|
||||
border: none;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 58px;
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
|
||||
#filepicker {
|
||||
width: 500px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: none;
|
||||
padding: 10px;
|
||||
background: white;
|
||||
color: black;
|
||||
border: 1px black solid;
|
||||
}
|
||||
|
||||
#filelist {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 400px;
|
||||
background: #ddd;
|
||||
border: 1px solid gray;
|
||||
border-right: 2px solid gray;
|
||||
border-bottom: 2px solid gray;
|
||||
font-size: 110%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#filelist li {
|
||||
border-bottom: 1px solid gray;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#filelist li a em {
|
||||
font-size: 90%;
|
||||
font-weight: normal;
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
#filelist li a {
|
||||
padding: 4px;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
width: 99%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#filelist li a:hover {
|
||||
color: white;
|
||||
background: #2D3E70;
|
||||
}
|
||||
|
||||
#filelist li a img {
|
||||
border: none;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#filelist li#status em {
|
||||
font-size: 90%;
|
||||
font-weight: normal;
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
|
||||
/****************************************/
|
||||
|
||||
.draggablenode {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.tb_info {
|
||||
color: #ccc;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.tb_help {
|
||||
color: black;
|
||||
border-left: white;
|
||||
}
|
||||
|
||||
ul#tblist {
|
||||
list-style-type: none;
|
||||
background-color: whitesmoke;
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul#tblist li {
|
||||
float: left;
|
||||
display: block;
|
||||
text-align: center;
|
||||
font: normal small-caps normal 12px "Lucida Grande", Lucida, Verdana, sans-serif;
|
||||
margin: 1px;
|
||||
background-color: #efefef;
|
||||
padding: 3px 2px 3px 5px;
|
||||
}
|
||||
|
||||
a.tb_button {
|
||||
padding-left: 18px;
|
||||
background: url(add.png) no-repeat left top;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* Individual icons for the toolbar*/
|
||||
a#btn_changefile {
|
||||
background: url(bullet_disk.png) no-repeat left top;
|
||||
}
|
||||
|
||||
a#btn_refresh {
|
||||
background: url(arrow_refresh.png) no-repeat left top;
|
||||
}
|
BIN
includes/weathermap/editor-resources/exclamation.png
Normal file
After Width: | Height: | Size: 701 B |
5
includes/weathermap/editor-resources/index.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
header("Location:../index.php");
|
||||
|
||||
// vim:ts=4:sw=4:
|
154
includes/weathermap/editor-resources/jquery-latest.min.js
vendored
Executable file
@ -0,0 +1,154 @@
|
||||
/*!
|
||||
* jQuery JavaScript Library v1.4.2
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* http://sizzlejs.com/
|
||||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Sat Feb 13 22:33:48 2010 -0500
|
||||
*/
|
||||
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
|
||||
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
|
||||
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
|
||||
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
|
||||
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
|
||||
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
|
||||
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
|
||||
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
|
||||
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
|
||||
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
|
||||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
|
||||
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
|
||||
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
|
||||
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
|
||||
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
|
||||
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
|
||||
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
|
||||
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
|
||||
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
|
||||
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
|
||||
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
|
||||
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
|
||||
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
|
||||
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
|
||||
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
|
||||
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
|
||||
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
|
||||
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
|
||||
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
|
||||
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
|
||||
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
|
||||
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
|
||||
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
|
||||
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
|
||||
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
|
||||
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
|
||||
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
|
||||
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
|
||||
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
|
||||
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
|
||||
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
|
||||
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
|
||||
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
|
||||
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
|
||||
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
|
||||
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
|
||||
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
|
||||
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
|
||||
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
|
||||
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
|
||||
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
|
||||
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
||||
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
|
||||
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
|
||||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
|
||||
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
|
||||
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
||||
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
|
||||
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
|
||||
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
|
||||
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
|
||||
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
|
||||
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
|
||||
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
|
||||
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
|
||||
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
|
||||
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
|
||||
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
|
||||
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
|
||||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
|
||||
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
|
||||
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
|
||||
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
|
||||
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
|
||||
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
|
||||
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
|
||||
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
|
||||
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
|
||||
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
|
||||
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
|
||||
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
|
||||
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
|
||||
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
|
||||
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
|
||||
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
|
||||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
|
||||
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
|
||||
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
|
||||
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
|
||||
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
|
||||
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
|
||||
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
|
||||
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
|
||||
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
|
||||
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
|
||||
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
|
||||
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
|
||||
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
|
||||
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
|
||||
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
|
||||
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
|
||||
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
|
||||
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
|
||||
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
|
||||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
|
||||
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
|
||||
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
|
||||
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
|
||||
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
|
||||
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
|
||||
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
|
||||
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
|
||||
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
|
||||
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
|
||||
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
|
||||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
|
||||
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
|
||||
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
|
||||
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
|
||||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
|
||||
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
|
||||
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
|
||||
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
|
||||
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
|
||||
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
|
||||
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
|
||||
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
|
||||
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
|
||||
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
|
||||
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
|
1471
includes/weathermap/editor.php
Executable file
BIN
includes/weathermap/images/Cloud-Filled.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
includes/weathermap/images/Cloud-line.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
includes/weathermap/images/Firewall.png
Normal file
After Width: | Height: | Size: 797 B |
BIN
includes/weathermap/images/HPMini.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
includes/weathermap/images/Host.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
includes/weathermap/images/PAD.png
Normal file
After Width: | Height: | Size: 905 B |
BIN
includes/weathermap/images/Router.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
includes/weathermap/images/WorkgroupSwitch.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
includes/weathermap/images/application.png
Normal file
After Width: | Height: | Size: 464 B |
BIN
includes/weathermap/images/application_side_list.png
Normal file
After Width: | Height: | Size: 510 B |
BIN
includes/weathermap/images/application_xp_terminal.png
Normal file
After Width: | Height: | Size: 507 B |
BIN
includes/weathermap/images/background1_950x625_197.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
includes/weathermap/images/blue-ball-64.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
includes/weathermap/images/blueboard1024.png
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
includes/weathermap/images/btn_recalc.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
includes/weathermap/images/bug.png
Normal file
After Width: | Height: | Size: 774 B |
BIN
includes/weathermap/images/button_editgroups.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
includes/weathermap/images/button_settings.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
includes/weathermap/images/bw_gradient_1024.png
Normal file
After Width: | Height: | Size: 114 KiB |
BIN
includes/weathermap/images/comment.png
Normal file
After Width: | Height: | Size: 413 B |
BIN
includes/weathermap/images/control_fastforward_blue.png
Normal file
After Width: | Height: | Size: 736 B |
BIN
includes/weathermap/images/control_pause_blue.png
Normal file
After Width: | Height: | Size: 721 B |
BIN
includes/weathermap/images/control_play_blue.png
Normal file
After Width: | Height: | Size: 717 B |
BIN
includes/weathermap/images/control_rewind_blue.png
Normal file
After Width: | Height: | Size: 745 B |
BIN
includes/weathermap/images/control_stop_blue.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
includes/weathermap/images/cross.png
Normal file
After Width: | Height: | Size: 655 B |
BIN
includes/weathermap/images/emoticon_smile.png
Normal file
After Width: | Height: | Size: 725 B |
BIN
includes/weathermap/images/emoticon_unhappy.png
Normal file
After Width: | Height: | Size: 723 B |
BIN
includes/weathermap/images/error.png
Normal file
After Width: | Height: | Size: 666 B |
BIN
includes/weathermap/images/exclamation.png
Normal file
After Width: | Height: | Size: 701 B |
BIN
includes/weathermap/images/filecabinet.png
Normal file
After Width: | Height: | Size: 901 B |
BIN
includes/weathermap/images/flag_blue.png
Normal file
After Width: | Height: | Size: 671 B |
BIN
includes/weathermap/images/flag_green.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
includes/weathermap/images/flag_orange.png
Normal file
After Width: | Height: | Size: 669 B |
BIN
includes/weathermap/images/flag_pink.png
Normal file
After Width: | Height: | Size: 651 B |
BIN
includes/weathermap/images/flag_purple.png
Normal file
After Width: | Height: | Size: 656 B |
BIN
includes/weathermap/images/flag_yellow.png
Normal file
After Width: | Height: | Size: 671 B |
BIN
includes/weathermap/images/green-ball-64.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
includes/weathermap/images/grey-ball-64.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
includes/weathermap/images/hollow32.png
Normal file
After Width: | Height: | Size: 201 B |
5
includes/weathermap/images/index.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
header("Location:../index.php");
|
||||
|
||||
// vim:ts=4:sw=4:
|
BIN
includes/weathermap/images/monitor.png
Normal file
After Width: | Height: | Size: 612 B |
BIN
includes/weathermap/images/page_white.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
includes/weathermap/images/pencil.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
includes/weathermap/images/red-ball-64.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
includes/weathermap/images/s_tab_weathermap.gif
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
includes/weathermap/images/s_tab_weathermap_red.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
includes/weathermap/images/tab_weathermap.gif
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
includes/weathermap/images/tab_weathermap_red.gif
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
includes/weathermap/images/tick.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
includes/weathermap/images/uk1024.png
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
includes/weathermap/images/updown_0.png
Normal file
After Width: | Height: | Size: 574 B |
BIN
includes/weathermap/images/updown_1.png
Normal file
After Width: | Height: | Size: 531 B |
BIN
includes/weathermap/images/updown_2.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
includes/weathermap/images/world.png
Normal file
After Width: | Height: | Size: 923 B |
BIN
includes/weathermap/images/world_link.png
Normal file
After Width: | Height: | Size: 957 B |
BIN
includes/weathermap/images/wrench.png
Normal file
After Width: | Height: | Size: 610 B |
BIN
includes/weathermap/images/wrench_orange.png
Normal file
After Width: | Height: | Size: 584 B |
BIN
includes/weathermap/images/yellow-ball-64.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
4
includes/weathermap/lib/.htaccess
Executable file
@ -0,0 +1,4 @@
|
||||
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
|
427
includes/weathermap/lib/HTML_ImageMap.class.php
Normal file
@ -0,0 +1,427 @@
|
||||
<?php
|
||||
// Copyright Howard Jones, 2005-2019 howie@thingy.com
|
||||
// http://wotsit.thingy.com/haj/cacti/
|
||||
// Released under the MIT License
|
||||
|
||||
// A simple port of the guts of Apache's mod_imap
|
||||
// - if you have an image control in a form, it's not really defined what happens to USEMAP
|
||||
// attributes. They are allowed in HTML 4.0 and XHTML, but some testing shows that they're
|
||||
// basically ignored. So you need to use server-side imagemaps if you want to have a form
|
||||
// where you are choosing a verb from (for example) a <SELECT> and also specifying part of
|
||||
// an image with an IMAGE control.
|
||||
//
|
||||
//
|
||||
class HTML_ImageMap_Area
|
||||
{
|
||||
var $href;
|
||||
var $name;
|
||||
var $id;
|
||||
var $alt;
|
||||
var $z;
|
||||
var $extrahtml;
|
||||
|
||||
function common_html()
|
||||
{
|
||||
$h = "";
|
||||
if($this->name != "")
|
||||
{
|
||||
// $h .= " alt=\"".$this->name."\" ";
|
||||
$h .= "id=\"".$this->name."\" ";
|
||||
}
|
||||
if($this->href != "")
|
||||
{
|
||||
$h .= "href=\"".$this->href."\" ";
|
||||
}
|
||||
else { $h .= "nohref "; }
|
||||
if($this->extrahtml != "")
|
||||
{
|
||||
$h .= $this->extrahtml." ";
|
||||
}
|
||||
return $h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HTML_ImageMap_Area_Polygon extends HTML_ImageMap_Area
|
||||
{
|
||||
var $points = array();
|
||||
var $minx,$maxx,$miny,$maxy; // bounding box
|
||||
var $npoints;
|
||||
|
||||
function asHTML()
|
||||
{
|
||||
foreach ($this->points as $point)
|
||||
{
|
||||
$flatpoints[] = $point[0];
|
||||
$flatpoints[] = $point[1];
|
||||
}
|
||||
$coordstring = join(",",$flatpoints);
|
||||
|
||||
return '<area '.$this->common_html().'shape="poly" coords="'.$coordstring.'" />';
|
||||
}
|
||||
|
||||
function asJSON()
|
||||
{
|
||||
$json = "{ \"shape\":'poly', \"npoints\":".$this->npoints.", \"name\":'".$this->name."',";
|
||||
|
||||
$xlist = '';
|
||||
$ylist = '';
|
||||
foreach ($this->points as $point)
|
||||
{
|
||||
$xlist .= $point[0].",";
|
||||
$ylist .= $point[1].",";
|
||||
}
|
||||
$xlist = rtrim($xlist,", ");
|
||||
$ylist = rtrim($ylist,", ");
|
||||
$json .= " \"x\": [ $xlist ], \"y\":[ $ylist ], \"minx\": ".$this->minx.", \"miny\": ".$this->miny.", \"maxx\":".$this->maxx.", \"maxy\":".$this->maxy."}";
|
||||
|
||||
return($json);
|
||||
}
|
||||
|
||||
function hitTest($x,$y)
|
||||
{
|
||||
$c = 0;
|
||||
// do the easy bounding-box test first.
|
||||
if( ($x < $this->minx) || ($x>$this->maxx) || ($y<$this->miny) || ($y>$this->maxy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Algotithm from from
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html#The%20C%20Code
|
||||
for ($i = 0, $j = $this->npoints-1; $i < $this->npoints; $j = $i++)
|
||||
{
|
||||
// print "Checking: $i, $j\n";
|
||||
$x1 = $this->points[$i][0];
|
||||
$y1 = $this->points[$i][1];
|
||||
$x2 = $this->points[$j][0];
|
||||
$y2 = $this->points[$j][1];
|
||||
|
||||
// print "($x,$y) vs ($x1,$y1)-($x2,$y2)\n";
|
||||
|
||||
if (((($y1<=$y) && ($y<$y2)) || (($y2<=$y) && ($y<$y1))) &&
|
||||
($x < ($x2 - $x1) * ($y - $y1) / ($y2 - $y1) + $x1))
|
||||
{
|
||||
$c = !$c;
|
||||
}
|
||||
}
|
||||
|
||||
return ($c);
|
||||
}
|
||||
|
||||
function __construct ( $name="", $href="",$coords)
|
||||
{
|
||||
$c = $coords[0];
|
||||
|
||||
$this->name = $name;
|
||||
$this->href= $href;
|
||||
$this->npoints = count($c)/2;
|
||||
|
||||
if( intval($this->npoints) != ($this->npoints))
|
||||
{
|
||||
die("Odd number of points!");
|
||||
}
|
||||
|
||||
for ($i=0; $i<count($c); $i+=2)
|
||||
{
|
||||
$x = round($c[$i]);
|
||||
$y = round($c[$i+1]);
|
||||
$point = array($x,$y);
|
||||
$xlist[] = $x; // these two are used to get the bounding box in a moment
|
||||
$ylist[] = $y;
|
||||
$this->points[] = $point;
|
||||
}
|
||||
|
||||
$this->minx = min($xlist);
|
||||
$this->maxx = max($xlist);
|
||||
$this->miny = min($ylist);
|
||||
$this->maxy = max($ylist);
|
||||
|
||||
// print $this->asHTML()."\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HTML_ImageMap_Area_Rectangle extends HTML_ImageMap_Area
|
||||
{
|
||||
var $x1,$x2,$y1,$y2;
|
||||
|
||||
function __construct ( $name="", $href="",$coords)
|
||||
{
|
||||
|
||||
$c = $coords[0];
|
||||
|
||||
$x1 = round($c[0]);
|
||||
$y1 = round($c[1]);
|
||||
$x2 = round($c[2]);
|
||||
$y2 = round($c[3]);
|
||||
|
||||
// sort the points, so that the first is the top-left
|
||||
if($x1>$x2)
|
||||
{
|
||||
$this->x1=$x2;
|
||||
$this->x2=$x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->x1=$x1;
|
||||
$this->x2=$x2;
|
||||
}
|
||||
|
||||
if($y1>$y2)
|
||||
{
|
||||
$this->y1=$y2;
|
||||
$this->y2=$y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->y1=$y1;
|
||||
$this->y2=$y2;
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->href = $href;
|
||||
}
|
||||
|
||||
function hitTest($x,$y)
|
||||
{
|
||||
return ( ($x > $this->x1) && ($x < $this->x2) && ($y > $this->y1) && ($y < $this->y2) );
|
||||
}
|
||||
|
||||
function asHTML()
|
||||
{
|
||||
$coordstring = join(",",array($this->x1,$this->y1,$this->x2,$this->y2));
|
||||
return '<area '.$this->common_html().'shape="rect" coords="'.$coordstring.'" />';
|
||||
|
||||
}
|
||||
|
||||
function asJSON()
|
||||
{
|
||||
$json = "{ \"shape\":'rect', ";
|
||||
|
||||
$json .= " \"x1\":".$this->x1.", \"y1\":".$this->y1.", \"x2\":".$this->x2.", \"y2\":".$this->y2.", \"name\":'".$this->name."'}";
|
||||
|
||||
return($json);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HTML_ImageMap_Area_Circle extends HTML_ImageMap_Area
|
||||
{
|
||||
var $centx,$centy, $edgex, $edgey;
|
||||
|
||||
function asHTML()
|
||||
{
|
||||
$coordstring = join(",",array($this->centx,$this->centy,$this->edgex,$this->edgey) );
|
||||
return '<area '.$this->common_html().'shape="circle" coords="'.$coordstring.'" />';
|
||||
}
|
||||
|
||||
function hitTest($x,$y)
|
||||
{
|
||||
$radius1 = ($this->edgey - $this->centy) * ($this->edgey - $this->centy)
|
||||
+ ($this->edgex - $this->centx) * ($this->edgex - $this->centx);
|
||||
|
||||
$radius2 = ($this->centy - $y) * ($this->centy - $y)
|
||||
+ ($this->centx - $x) * ($this->centx - $x);
|
||||
|
||||
return ($radius2 <= $radius1);
|
||||
}
|
||||
|
||||
function __construct($name="", $href="",$coords)
|
||||
{
|
||||
$c = $coords[0];
|
||||
|
||||
$this->name = $name;
|
||||
$this->href = $href;
|
||||
$this->centx = round($c[0]);
|
||||
$this->centy = round($c[1]);
|
||||
$this->edgex = round($c[2]);
|
||||
$this->edgey = round($c[3]);
|
||||
}
|
||||
}
|
||||
|
||||
class HTML_ImageMap
|
||||
{
|
||||
var $shapes;
|
||||
var $nshapes;
|
||||
var $name;
|
||||
|
||||
function __construct($name="")
|
||||
{
|
||||
$this->Reset();
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
$this->shapes = array();
|
||||
$this->nshapes = 0;
|
||||
$this->name = "";
|
||||
}
|
||||
|
||||
// add an element to the map - takes an array with the info, in a similar way to HTML_QuickForm
|
||||
function addArea($element)
|
||||
{
|
||||
if (is_object($element) && is_subclass_of($element, 'html_imagemap_area')) {
|
||||
$elementObject = &$element;
|
||||
} else {
|
||||
$args = func_get_args();
|
||||
$className = "HTML_ImageMap_Area_".$element;
|
||||
$elementObject = new $className($args[1],$args[2],array_slice($args, 3));
|
||||
}
|
||||
|
||||
$this->shapes[] =& $elementObject;
|
||||
$this->nshapes++;
|
||||
// print $this->nshapes." shapes\n";
|
||||
}
|
||||
|
||||
// do a hit-test based on the current map
|
||||
// - can be limited to only match elements whose names match the filter
|
||||
// (e.g. pick a building, in a campus map)
|
||||
function hitTest($x,$y,$namefilter="")
|
||||
{
|
||||
$preg = '/'.$namefilter.'/';
|
||||
foreach ($this->shapes as $shape)
|
||||
{
|
||||
if($shape->hitTest($x,$y))
|
||||
{
|
||||
if( ($namefilter == "") || ( preg_match($preg,$shape->name) ) )
|
||||
{
|
||||
return $shape->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// update a property on all elements in the map that match a name
|
||||
// (use it for retro-actively adding in link information to a pre-built geometry before generating HTML)
|
||||
// returns the number of elements that were matched/changed
|
||||
function setProp($which, $what, $where)
|
||||
{
|
||||
$count = 0;
|
||||
for($i=0; $i<count($this->shapes); $i++)
|
||||
{
|
||||
// this USED to be a substring match, but that broke some things
|
||||
// and wasn't actually used as one anywhere.
|
||||
if( ($where == "") || ( $this->shapes[$i]->name==$where) )
|
||||
{
|
||||
switch($which)
|
||||
{
|
||||
case 'href':
|
||||
$this->shapes[$i]->href= $what;
|
||||
break;
|
||||
case 'extrahtml':
|
||||
$this->shapes[$i]->extrahtml= $what;
|
||||
#print "IMAGEMAP: Found $where and adding $which\n";
|
||||
break;
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
// update a property on all elements in the map that match a name as a substring
|
||||
// (use it for retro-actively adding in link information to a pre-built geometry before generating HTML)
|
||||
// returns the number of elements that were matched/changed
|
||||
function setPropSub($which, $what, $where)
|
||||
{
|
||||
|
||||
$count = 0;
|
||||
for($i=0; $i<count($this->shapes); $i++)
|
||||
{
|
||||
if( ($where == "") || ( strstr($this->shapes[$i]->name,$where)!=FALSE ) )
|
||||
{
|
||||
switch($which)
|
||||
{
|
||||
case 'href':
|
||||
$this->shapes[$i]->href= $what;
|
||||
break;
|
||||
case 'extrahtml':
|
||||
$this->shapes[$i]->extrahtml= $what;
|
||||
break;
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
// Return the imagemap as an HTML client-side imagemap for inclusion in a page
|
||||
function asHTML()
|
||||
{
|
||||
$html = '<map';
|
||||
if($this->name != "")
|
||||
{
|
||||
$html .= ' name="'.$this->name.'"';
|
||||
}
|
||||
$html .=">\n";
|
||||
foreach ($this->shapes as $shape)
|
||||
{
|
||||
$html .= $shape->asHTML()."\n";
|
||||
$html .= "\n";
|
||||
}
|
||||
$html .= "</map>\n";
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
function subJSON($namefilter="",$reverseorder=false)
|
||||
{
|
||||
$json = '';
|
||||
|
||||
$preg = '/'.$namefilter.'/';
|
||||
foreach ($this->shapes as $shape)
|
||||
{
|
||||
if( ($namefilter == "") || ( preg_match($preg,$shape->name) ))
|
||||
{
|
||||
if($reverseorder)
|
||||
{
|
||||
$json = $shape->asJSON().",\n".$json;
|
||||
}
|
||||
else
|
||||
{
|
||||
$json .= $shape->asJSON().",\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$json = rtrim($json,"\n, ");
|
||||
$json .= "\n";
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
// return HTML for a subset of the map, specified by the filter string
|
||||
// (suppose you want some partof your UI to have precedence over another part
|
||||
// - the imagemap is checked from top-to-bottom in the HTML)
|
||||
// - skipnolinks -> in normal HTML output, we don't need areas for things with no href
|
||||
function subHTML($namefilter="",$reverseorder=false, $skipnolinks=false)
|
||||
{
|
||||
$html = "";
|
||||
$preg = '/'.$namefilter.'/';
|
||||
|
||||
foreach ($this->shapes as $shape)
|
||||
{
|
||||
# if( ($namefilter == "") || ( preg_match($preg,$shape->name) ))
|
||||
if( ($namefilter == "") || ( strstr($shape->name, $namefilter) !== FALSE ))
|
||||
{
|
||||
if(!$skipnolinks || $shape->href != "" || $shape->extrahtml != "" )
|
||||
{
|
||||
if($reverseorder)
|
||||
{
|
||||
$html = $shape->asHTML()."\n".$html;
|
||||
}
|
||||
else
|
||||
{
|
||||
$html .= $shape->asHTML()."\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
}
|
||||
// vim:ts=4:sw=4:
|
61
includes/weathermap/lib/WMLine.class.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A Line is simply a Vector that passes through a Point
|
||||
*/
|
||||
class WMLine
|
||||
{
|
||||
private $point;
|
||||
private $vector;
|
||||
|
||||
public function __construct($p, $v)
|
||||
{
|
||||
$this->point = $p;
|
||||
$this->vector = $v;
|
||||
}
|
||||
|
||||
public function getSlope()
|
||||
{
|
||||
return $this->vector->getSlope();
|
||||
}
|
||||
|
||||
public function getYIntercept()
|
||||
{
|
||||
$slope = $this->getSlope();
|
||||
$intercept = $this->point->y - $this->point->x * $slope;
|
||||
|
||||
return $intercept;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf("/%s-%s/", $this->point, $this->vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the point where this line and another one cross
|
||||
*
|
||||
* @param $line2 the other line
|
||||
* @return WMPoint the crossing point
|
||||
* @throws WeathermapInternalFail
|
||||
*/
|
||||
public function findCrossingPoint($line2)
|
||||
{
|
||||
$slope1 = $this->vector->getSlope();
|
||||
$slope2 = $line2->vector->getSlope();
|
||||
|
||||
if ($slope1 == $slope2) {
|
||||
// for a general case, this should probably be handled better
|
||||
// but for our use, there should never be parallel lines
|
||||
throw new WeathermapInternalFail("ParallelLinesNeverCross");
|
||||
}
|
||||
|
||||
$intercept1 = $this->getYIntercept();
|
||||
$intercept2 = $line2->getYIntercept();
|
||||
|
||||
$xCrossing = ($intercept2 - $intercept1) / ($slope1 - $slope2);
|
||||
$yCrossing = $intercept1 + $slope1*$xCrossing;
|
||||
|
||||
return new WMPoint($xCrossing, $yCrossing);
|
||||
}
|
||||
}
|
161
includes/weathermap/lib/WMPoint.class.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Utility 'class' for 2D points.
|
||||
*
|
||||
* we use enough points in various places to make it worth a small class to
|
||||
* save some variable-pairs.
|
||||
*
|
||||
*/
|
||||
class WMPoint
|
||||
{
|
||||
public $x;
|
||||
public $y;
|
||||
|
||||
public function __construct($x = 0, $y = 0)
|
||||
{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function identical($point2)
|
||||
{
|
||||
if (($this->x == $point2->x) && ($this->y == $point2->y)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function set($newX, $newY)
|
||||
{
|
||||
$this->x = $newX;
|
||||
$this->y = $newY;
|
||||
}
|
||||
|
||||
/**
|
||||
* round() - round the coordinates to their nearest integers, in place.
|
||||
*/
|
||||
public function round()
|
||||
{
|
||||
$this->x = round($this->x);
|
||||
$this->y = round($this->y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two points to within a few decimal places - good enough for graphics! (and unit tests)
|
||||
*
|
||||
* @param $point2
|
||||
* @return bool
|
||||
*/
|
||||
public function closeEnough($point2)
|
||||
{
|
||||
if ((round($this->x, 2) == round($point2->x, 2)) && (round($this->y, 2) == round($point2->y, 2))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function vectorToPoint($p2)
|
||||
{
|
||||
$v = new WMVector($p2->x - $this->x, $p2->y - $this->y);
|
||||
|
||||
return $v;
|
||||
}
|
||||
|
||||
public function lineToPoint($p2)
|
||||
{
|
||||
$vec = $this->vectorToPoint($p2);
|
||||
return new WMLine($this, $vec);
|
||||
}
|
||||
|
||||
public function distanceToLine($l)
|
||||
{
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
||||
function distanceToLineSegment($l)
|
||||
{
|
||||
// TODO: Implement this
|
||||
// Return whichever is the shortest out of:
|
||||
// Distance to point1, distance to point2, distance to line
|
||||
}
|
||||
|
||||
public function distanceToPoint($p2)
|
||||
{
|
||||
return $this->vectorToPoint($p2)->length();
|
||||
}
|
||||
|
||||
public function copy()
|
||||
{
|
||||
return new WMPoint($this->x, $this->y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WMVector $v
|
||||
* @param float $fraction
|
||||
*
|
||||
* @return $this - to allow for chaining of operations
|
||||
*/
|
||||
public function addVector($v, $fraction = 1.0)
|
||||
{
|
||||
if ($fraction == 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->x = $this->x + $fraction * $v->dx;
|
||||
$this->y = $this->y + $fraction * $v->dy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear Interpolate between two points
|
||||
*
|
||||
* @param $point2 - other point we're interpolating to
|
||||
* @param $ratio - how far (0-1) between the two
|
||||
* @return WMPoint - a new WMPoint
|
||||
*/
|
||||
public function LERPWith($point2, $ratio)
|
||||
{
|
||||
$x = $this->x + $ratio * ($point2->x - $this->x);
|
||||
$y = $this->y + $ratio * ($point2->y - $this->y);
|
||||
|
||||
$newPoint = new WMPoint($x, $y);
|
||||
|
||||
return $newPoint;
|
||||
}
|
||||
|
||||
public function asString()
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
public function asConfig()
|
||||
{
|
||||
return sprintf("%d %d", $this->x, $this->y);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf("(%s,%s)", floatval($this->x), floatval($this->y));
|
||||
}
|
||||
|
||||
public function translate($deltaX, $deltaY)
|
||||
{
|
||||
$this->x += $deltaX;
|
||||
$this->y += $deltaY;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function translatePolar($angle, $distance)
|
||||
{
|
||||
$radiansAngle = deg2rad($angle);
|
||||
|
||||
$this->x += $distance * sin($radiansAngle);
|
||||
$this->y += -$distance * cos($radiansAngle);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
121
includes/weathermap/lib/WMVector.class.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Utility class for 2D vectors.
|
||||
* Mostly used in the VIA calculations
|
||||
*/
|
||||
class WMVector
|
||||
{
|
||||
public $dx;
|
||||
public $dy;
|
||||
|
||||
public function __construct($dx = 0, $dy = 0)
|
||||
{
|
||||
$this->dx = $dx;
|
||||
$this->dy = $dy;
|
||||
}
|
||||
|
||||
public function flip()
|
||||
{
|
||||
$this->dx = - $this->dx;
|
||||
$this->dy = - $this->dy;
|
||||
}
|
||||
|
||||
public function getAngle()
|
||||
{
|
||||
return rad2deg(atan2((-$this->dy), ($this->dx)));
|
||||
}
|
||||
|
||||
public function getSlope()
|
||||
{
|
||||
if ($this->dx == 0) {
|
||||
// special case - if slope is infinite, fudge it to be REALLY BIG instead. Close enough for TV.
|
||||
wm_debug("Slope is infinite.\n");
|
||||
return 1e10;
|
||||
}
|
||||
return ($this->dy / $this->dx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $angle
|
||||
*/
|
||||
public function rotate($angle)
|
||||
{
|
||||
$points = array();
|
||||
$points[0] = $this->dx;
|
||||
$points[1] = $this->dy;
|
||||
|
||||
rotateAboutPoint($points, 0, 0, $angle);
|
||||
|
||||
$this->dx = $points[0];
|
||||
$this->dy = $points[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WMVector
|
||||
*/
|
||||
public function getNormal()
|
||||
{
|
||||
$len = $this->length();
|
||||
|
||||
if ($len==0) {
|
||||
return new WMVector(0, 0);
|
||||
}
|
||||
|
||||
return new WMVector($this->dy / $len, -$this->dx / $len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn vector into unit-vector
|
||||
*/
|
||||
public function normalise()
|
||||
{
|
||||
$len = $this->length();
|
||||
|
||||
if ($len > 0 && $len != 1) {
|
||||
$this->dx = $this->dx / $len;
|
||||
$this->dy = $this->dy / $len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the square of the vector length.
|
||||
* Save calculating a square-root if all you need to do is compare lengths
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function squaredLength()
|
||||
{
|
||||
if (($this->dx == 0) && ($this->dy == 0)) {
|
||||
return 0;
|
||||
}
|
||||
$squaredLength = ($this->dx) * ($this->dx) + ($this->dy) * ($this->dy);
|
||||
|
||||
return $squaredLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function length()
|
||||
{
|
||||
if ($this->dx==0 && $this->dy==0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (sqrt($this->squaredLength()));
|
||||
}
|
||||
|
||||
public function asString()
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf("[%f,%f]", $this->dx, $this->dy);
|
||||
}
|
||||
}
|
2198
includes/weathermap/lib/WeatherMap.functions.php
Normal file
781
includes/weathermap/lib/WeatherMap.keywords.inc.php
Normal file
@ -0,0 +1,781 @@
|
||||
<?php
|
||||
|
||||
// new version of config_keywords
|
||||
// array of contexts, contains an array of keywords, contains a (short) list of regexps as now
|
||||
// this way, we don't scan the whole table, and we call preg_match a WHOLE lot less
|
||||
// there will be more lines in the array, but we'll be checking less of them
|
||||
$WM_config_keywords2 = array (
|
||||
'GLOBAL' => array (
|
||||
'FONTDEFINE' => array(
|
||||
array('GLOBAL',"/^\s*FONTDEFINE\s+(\d+)\s+(\S+)\s+(\d+)\s*$/i",'ReadConfig_Handle_FONTDEFINE'),
|
||||
array('GLOBAL',"/^\s*FONTDEFINE\s+(\d+)\s+(\S+)\s*$/i",'ReadConfig_Handle_FONTDEFINE'),
|
||||
),
|
||||
'KEYOUTLINECOLOR' => array (
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^KEYOUTLINECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^KEYOUTLINECOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),
|
||||
),
|
||||
'KEYTEXTCOLOR' => array (array (
|
||||
'GLOBAL',
|
||||
'/^KEYTEXTCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),),
|
||||
'TITLECOLOR' => array (array (
|
||||
'GLOBAL',
|
||||
'/^TITLECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),),
|
||||
'TIMECOLOR' => array (array (
|
||||
'GLOBAL',
|
||||
'/^TIMECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),),
|
||||
'KEYBGCOLOR' => array (
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^KEYBGCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^KEYBGCOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),
|
||||
),
|
||||
'BGCOLOR' => array (array (
|
||||
'GLOBAL',
|
||||
'/^BGCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_GLOBALCOLOR'
|
||||
),),
|
||||
'SET' => array (array (
|
||||
'GLOBAL',
|
||||
'SET',
|
||||
'ReadConfig_Handle_SET'
|
||||
),),
|
||||
'HTMLSTYLESHEET' => array (array (
|
||||
'GLOBAL',
|
||||
'/^HTMLSTYLESHEET\s+(.*)\s*$/i',
|
||||
array ('htmlstylesheet' => 1)
|
||||
),),
|
||||
'HTMLOUTPUTFILE' => array (array (
|
||||
'GLOBAL',
|
||||
'/^HTMLOUTPUTFILE\s+(.*)\s*$/i',
|
||||
array ('htmloutputfile' => 1)
|
||||
),),
|
||||
'BACKGROUND' => array (array (
|
||||
'GLOBAL',
|
||||
'/^BACKGROUND\s+(.*)\s*$/i',
|
||||
array ('background' => 1)
|
||||
),),
|
||||
'IMAGEOUTPUTFILE' => array (array (
|
||||
'GLOBAL',
|
||||
'/^IMAGEOUTPUTFILE\s+(.*)\s*$/i',
|
||||
array ('imageoutputfile' => 1)
|
||||
),),
|
||||
'DATAOUTPUTFILE' => array (array (
|
||||
'GLOBAL',
|
||||
'/^DATAOUTPUTFILE\s+(.*)\s*$/i',
|
||||
array ('dataoutputfile' => 1)
|
||||
),),
|
||||
'IMAGEURI' => array (array (
|
||||
'GLOBAL',
|
||||
'/^IMAGEURI\s+(.*)\s*$/i',
|
||||
array ('imageuri' => 1)
|
||||
),),
|
||||
'TITLE' => array (array (
|
||||
'GLOBAL',
|
||||
'/^TITLE\s+(.*)\s*$/i',
|
||||
array ('title' => 1)
|
||||
),),
|
||||
'HTMLSTYLE' => array (array (
|
||||
'GLOBAL',
|
||||
'/^HTMLSTYLE\s+(static|overlib)\s*$/i',
|
||||
array ('htmlstyle' => 1)
|
||||
),),
|
||||
'KILO' => array (array (
|
||||
'GLOBAL',
|
||||
'/^KILO\s+(\d+)\s*$/i',
|
||||
array ('kilo' => 1)
|
||||
),),
|
||||
'KEYFONT' => array (array (
|
||||
'GLOBAL',
|
||||
'/^KEYFONT\s+(\d+)\s*$/i',
|
||||
array ('keyfont' => 1)
|
||||
),),
|
||||
'TITLEFONT' => array (array (
|
||||
'GLOBAL',
|
||||
'/^TITLEFONT\s+(\d+)\s*$/i',
|
||||
array ('titlefont' => 1)
|
||||
),),
|
||||
'TIMEFONT' => array (array (
|
||||
'GLOBAL',
|
||||
'/^TIMEFONT\s+(\d+)\s*$/i',
|
||||
array ('timefont' => 1)
|
||||
),),
|
||||
'WIDTH' => array (array (
|
||||
'GLOBAL',
|
||||
"/^WIDTH\s+(\d+)\s*$/i",
|
||||
array ('width' => 1)
|
||||
),),
|
||||
'HEIGHT' => array (array (
|
||||
'(GLOBAL)',
|
||||
"/^HEIGHT\s+(\d+)\s*$/i",
|
||||
array ('height' => 1)
|
||||
),),
|
||||
'TITLEPOS' => array (
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^TITLEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',
|
||||
array (
|
||||
'titlex' => 1,
|
||||
'titley' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^TITLEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',
|
||||
array (
|
||||
'titlex' => 1,
|
||||
'titley' => 2,
|
||||
'title' => 3
|
||||
)
|
||||
),
|
||||
),
|
||||
'TIMEPOS' => array (
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^TIMEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',
|
||||
array (
|
||||
'timex' => 1,
|
||||
'timey' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^TIMEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',
|
||||
array (
|
||||
'timex' => 1,
|
||||
'timey' => 2,
|
||||
'stamptext' => 3
|
||||
)
|
||||
),
|
||||
),
|
||||
'MINTIMEPOS' => array (
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^MINTIMEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',
|
||||
array (
|
||||
'mintimex' => 1,
|
||||
'mintimey' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^MINTIMEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',
|
||||
array (
|
||||
'mintimex' => 1,
|
||||
'mintimey' => 2,
|
||||
'minstamptext' => 3
|
||||
)
|
||||
),
|
||||
),
|
||||
'MAXTIMEPOS' => array (
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^MAXTIMEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',
|
||||
array (
|
||||
'maxtimex' => 1,
|
||||
'maxtimey' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'GLOBAL',
|
||||
'/^MAXTIMEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',
|
||||
array (
|
||||
'maxtimex' => 1,
|
||||
'maxtimey' => 2,
|
||||
'maxstamptext' => 3
|
||||
)
|
||||
),
|
||||
),
|
||||
), // end of global
|
||||
'NODE' => array (
|
||||
'TARGET' => array (array (
|
||||
'NODE',
|
||||
'TARGET',
|
||||
'ReadConfig_Handle_TARGET'
|
||||
),),
|
||||
'SET' => array (array (
|
||||
'NODE',
|
||||
'SET',
|
||||
'ReadConfig_Handle_SET'
|
||||
),),
|
||||
'AICONOUTLINECOLOR' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^AICONOUTLINECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^AICONOUTLINECOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'AICONFILLCOLOR' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^AICONFILLCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^AICONFILLCOLOR\s+(copy)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'LABELOUTLINECOLOR' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELOUTLINECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELOUTLINECOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'LABELBGCOLOR' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELBGCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELBGCOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'LABELFONTCOLOR' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELFONTCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELFONTCOLOR\s+(contrast)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'LABELFONTSHADOWCOLOR' => array (array (
|
||||
'NODE',
|
||||
'/^LABELFONTSHADOWCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),),
|
||||
'NOTES' => array (array (
|
||||
'NODE',
|
||||
'/^NOTES\s+(.*)\s*$/i',
|
||||
array (
|
||||
'notestext[IN]' => 1,
|
||||
'notestext[OUT]' => 1
|
||||
)
|
||||
),),
|
||||
'MAXVALUE' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^(MAXVALUE)\s+(\d+\.?\d*[KMGT]?)\s+(\d+\.?\d*[KMGT]?)\s*$/i',
|
||||
array (
|
||||
'max_bandwidth_in_cfg' => 2,
|
||||
'max_bandwidth_out_cfg' => 3
|
||||
)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^(MAXVALUE)\s+(\d+\.?\d*[KMGT]?)\s*$/i',
|
||||
array (
|
||||
'max_bandwidth_in_cfg' => 2,
|
||||
'max_bandwidth_out_cfg' => 2
|
||||
)
|
||||
),
|
||||
),
|
||||
'ORIGIN' => array(
|
||||
array('NODE',
|
||||
"/^ORIGIN\s+(C|NE|SE|NW|SW|N|S|E|W)/i",
|
||||
array("position_origin" => 1)
|
||||
)
|
||||
),
|
||||
'POSITION' => array (
|
||||
array (
|
||||
'NODE',
|
||||
"/^POSITION\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i",
|
||||
array (
|
||||
'x' => 1,
|
||||
'y' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
"/^POSITION\s+(\S+)\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i",
|
||||
array (
|
||||
'x' => 2,
|
||||
'y' => 3,
|
||||
'original_x' => 2,
|
||||
'original_y' => 3,
|
||||
'relative_to' => 1,
|
||||
'relative_resolved' => false
|
||||
)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
"/^POSITION\s+(\S+)\s+([-+]?\d+)r(\d+)\s*$/i",
|
||||
array (
|
||||
'x' => 2,
|
||||
'y' => 3,
|
||||
'original_x' => 2,
|
||||
'original_y' => 3,
|
||||
'relative_to' => 1,
|
||||
'polar' => true,
|
||||
'relative_resolved' => false
|
||||
)
|
||||
),
|
||||
),
|
||||
'INFOURL' => array (array (
|
||||
'NODE',
|
||||
'/^INFOURL\s+(.*)\s*$/i',
|
||||
array (
|
||||
'infourl[IN]' => 1,
|
||||
'infourl[OUT]' => 1
|
||||
)
|
||||
),),
|
||||
'OVERLIBCAPTION' => array (array (
|
||||
'NODE',
|
||||
'/^OVERLIBCAPTION\s+(.*)\s*$/i',
|
||||
array (
|
||||
'overlibcaption[IN]' => 1,
|
||||
'overlibcaption[OUT]' => 1
|
||||
)
|
||||
),),
|
||||
'ZORDER' => array (array (
|
||||
'NODE',
|
||||
"/^ZORDER\s+([-+]?\d+)\s*$/i",
|
||||
array ('zorder' => 1)
|
||||
),),
|
||||
'OVERLIBHEIGHT' => array (array (
|
||||
'NODE',
|
||||
"/^OVERLIBHEIGHT\s+(\d+)\s*$/i",
|
||||
array ('overlibheight' => 1)
|
||||
),),
|
||||
'OVERLIBWIDTH' => array (array (
|
||||
'NODE',
|
||||
"/^OVERLIBWIDTH\s+(\d+)\s*$/i",
|
||||
array ('overlibwidth' => 1)
|
||||
),),
|
||||
'LABELFONT' => array (array (
|
||||
'NODE',
|
||||
'/^LABELFONT\s+(\d+)\s*$/i',
|
||||
array ('labelfont' => 1)
|
||||
),),
|
||||
'LABELANGLE' => array (array (
|
||||
'NODE',
|
||||
'/^LABELANGLE\s+(0|90|180|270)\s*$/i',
|
||||
array ('labelangle' => 1)
|
||||
),),
|
||||
'ICON' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^ICON\s+(\S+)\s*$/i',
|
||||
array (
|
||||
'iconfile' => 1,
|
||||
'iconscalew' => '#0',
|
||||
'iconscaleh' => '#0'
|
||||
)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^ICON\s+(\S+)\s*$/i',
|
||||
array ('iconfile' => 1)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^ICON\s+(\d+)\s+(\d+)\s+(inpie|outpie|box|rbox|round|gauge|nink)\s*$/i',
|
||||
array (
|
||||
'iconfile' => 3,
|
||||
'iconscalew' => 1,
|
||||
'iconscaleh' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^ICON\s+(\d+)\s+(\d+)\s+(\S+)\s*$/i',
|
||||
array (
|
||||
'iconfile' => 3,
|
||||
'iconscalew' => 1,
|
||||
'iconscaleh' => 2
|
||||
)
|
||||
),
|
||||
),
|
||||
'LABEL' => array (
|
||||
array (
|
||||
'NODE',
|
||||
"/^LABEL\s*$/i",
|
||||
array ('label' => '')
|
||||
), # special case for blank labels
|
||||
array (
|
||||
'NODE',
|
||||
"/^LABEL\s+(.*)\s*$/i",
|
||||
array ('label' => 1)
|
||||
),
|
||||
),
|
||||
'LABELOFFSET' => array (
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELOFFSET\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i',
|
||||
array (
|
||||
'labeloffsetx' => 1,
|
||||
'labeloffsety' => 2
|
||||
)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELOFFSET\s+(C|NE|SE|NW|SW|N|S|E|W)\s*$/i',
|
||||
array ('labeloffset' => 1)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELOFFSET\s+((C|NE|SE|NW|SW|N|S|E|W)\d+)\s*$/i',
|
||||
array ('labeloffset' => 1)
|
||||
),
|
||||
array (
|
||||
'NODE',
|
||||
'/^LABELOFFSET\s+(-?\d+r\d+)\s*$/i',
|
||||
array ('labeloffset' => 1)
|
||||
),
|
||||
),
|
||||
'USESCALE' => array(
|
||||
array('NODE', "/^(USESCALE)\s+([A-Za-z][A-Za-z0-9_]*)(\s+(in|out))?(\s+(absolute|percent))?\s*$/i","ReadConfig_Handle_NODE_USESCALE"),
|
||||
),
|
||||
'USEICONSCALE' => array(
|
||||
array('NODE', "/^(USEICONSCALE)\s+([A-Za-z][A-Za-z0-9_]*)(\s+(in|out))?(\s+(absolute|percent))?\s*$/i","ReadConfig_Handle_NODE_USESCALE"),
|
||||
),
|
||||
'OVERLIBGRAPH' => array(
|
||||
array('NODE',"/^OVERLIBGRAPH\s+(.+)$/i","ReadConfig_Handle_OVERLIB")
|
||||
),
|
||||
|
||||
), // end of node
|
||||
'LINK' => array (
|
||||
'TARGET' => array (array (
|
||||
'LINK',
|
||||
'TARGET',
|
||||
'ReadConfig_Handle_TARGET'
|
||||
),),
|
||||
'SET' => array (array (
|
||||
'LINK',
|
||||
'SET',
|
||||
'ReadConfig_Handle_SET'
|
||||
),),
|
||||
'NODES' => array (array (
|
||||
'LINK',
|
||||
'NODES',
|
||||
'ReadConfig_Handle_NODES'
|
||||
),),
|
||||
'VIA' => array (array (
|
||||
'LINK',
|
||||
'VIA',
|
||||
'ReadConfig_Handle_VIA'
|
||||
),),
|
||||
'COMMENTFONTCOLOR' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^COMMENTFONTCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^COMMENTFONTCOLOR\s+(contrast)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'OUTLINECOLOR' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^OUTLINECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^OUTLINECOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'BWOUTLINECOLOR' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^BWOUTLINECOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^BWOUTLINECOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'BWBOXCOLOR' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^BWBOXCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^BWBOXCOLOR\s+(none)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),
|
||||
),
|
||||
'BWFONTCOLOR' => array (array (
|
||||
'LINK',
|
||||
'/^BWFONTCOLOR\s+(\d+)\s+(\d+)\s+(\d+)$/',
|
||||
'ReadConfig_Handle_COLOR'
|
||||
),),
|
||||
'NOTES' => array (array (
|
||||
'LINK',
|
||||
'/^NOTES\s+(.*)\s*$/i',
|
||||
array (
|
||||
'notestext[IN]' => 1,
|
||||
'notestext[OUT]' => 1
|
||||
)
|
||||
),),
|
||||
'MAXVALUE' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^(MAXVALUE)\s+(\d+\.?\d*[KMGT]?)\s+(\d+\.?\d*[KMGT]?)\s*$/i',
|
||||
array (
|
||||
'max_bandwidth_in_cfg' => 2,
|
||||
'max_bandwidth_out_cfg' => 3
|
||||
)
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^(MAXVALUE)\s+(\d+\.?\d*[KMGT]?)\s*$/i',
|
||||
array (
|
||||
'max_bandwidth_in_cfg' => 2,
|
||||
'max_bandwidth_out_cfg' => 2
|
||||
)
|
||||
),
|
||||
),
|
||||
'WIDTH' => array (
|
||||
array (
|
||||
'LINK',
|
||||
"/^WIDTH\s+(\d+)\s*$/i",
|
||||
array ('width' => 1)
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
"/^WIDTH\s+(\d+\.\d+)\s*$/i",
|
||||
array ('width' => 1)
|
||||
),
|
||||
),
|
||||
'SPLITPOS' => array (array (
|
||||
'LINK',
|
||||
'/^SPLITPOS\s+(\d+)\s*$/i',
|
||||
array ('splitpos' => 1)
|
||||
),),
|
||||
'BWLABELPOS' => array (array (
|
||||
'LINK',
|
||||
'/^BWLABELPOS\s+(\d+)\s(\d+)\s*$/i',
|
||||
array (
|
||||
'labeloffset_in' => 1,
|
||||
'labeloffset_out' => 2
|
||||
)
|
||||
),),
|
||||
'COMMENTPOS' => array (array (
|
||||
'LINK',
|
||||
'/^COMMENTPOS\s+(\d+)\s(\d+)\s*$/i',
|
||||
array (
|
||||
'commentoffset_in' => 1,
|
||||
'commentoffset_out' => 2
|
||||
)
|
||||
),),
|
||||
'DUPLEX' => array (array (
|
||||
'LINK',
|
||||
'/^DUPLEX\s+(full|half)\s*$/i',
|
||||
array ('duplex' => 1)
|
||||
),),
|
||||
'BWSTYLE' => array (array (
|
||||
'LINK',
|
||||
'/^BWSTYLE\s+(classic|angled)\s*$/i',
|
||||
array ('labelboxstyle' => 1)
|
||||
),),
|
||||
'LINKSTYLE' => array (array (
|
||||
'LINK',
|
||||
'/^LINKSTYLE\s+(twoway|oneway)\s*$/i',
|
||||
array ('linkstyle' => 1)
|
||||
),),
|
||||
'COMMENTSTYLE' => array (array (
|
||||
'LINK',
|
||||
'/^COMMENTSTYLE\s+(edge|center)\s*$/i',
|
||||
array ('commentstyle' => 1)
|
||||
),),
|
||||
'ARROWSTYLE' => array (array (
|
||||
'LINK',
|
||||
'/^ARROWSTYLE\s+(classic|compact)\s*$/i',
|
||||
array ('arrowstyle' => 1)
|
||||
),),
|
||||
'VIASTYLE' => array (array (
|
||||
'LINK',
|
||||
'/^VIASTYLE\s+(curved|angled)\s*$/i',
|
||||
array ('viastyle' => 1)
|
||||
),),
|
||||
'INCOMMENT' => array (array (
|
||||
'LINK',
|
||||
'/^INCOMMENT\s+(.*)\s*$/i',
|
||||
array ('comments[IN]' => 1)
|
||||
),),
|
||||
'OUTCOMMENT' => array (array (
|
||||
'LINK',
|
||||
'/^OUTCOMMENT\s+(.*)\s*$/i',
|
||||
array ('comments[OUT]' => 1)
|
||||
),),
|
||||
|
||||
'OVERLIBGRAPH' => array(
|
||||
array('LINK',"/^OVERLIBGRAPH\s+(.+)$/i","ReadConfig_Handle_OVERLIB")
|
||||
),
|
||||
'INOVERLIBGRAPH' => array(
|
||||
array('LINK',"/^INOVERLIBGRAPH\s+(.+)$/i","ReadConfig_Handle_OVERLIB")
|
||||
),
|
||||
'OUTOVERLIBGRAPH' => array(
|
||||
array('LINK',"/^OUTOVERLIBGRAPH\s+(.+)$/i","ReadConfig_Handle_OVERLIB")
|
||||
),
|
||||
|
||||
'USESCALE' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^USESCALE\s+([A-Za-z][A-Za-z0-9_]*)\s*$/i',
|
||||
array ('usescale' => 1)
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^USESCALE\s+([A-Za-z][A-Za-z0-9_]*)\s+(absolute|percent)\s*$/i',
|
||||
array (
|
||||
'usescale' => 1,
|
||||
'scaletype' => 2
|
||||
)
|
||||
),
|
||||
),
|
||||
'BWFONT' => array (array (
|
||||
'LINK',
|
||||
'/^BWFONT\s+(\d+)\s*$/i',
|
||||
array ('bwfont' => 1)
|
||||
),),
|
||||
'COMMENTFONT' => array (array (
|
||||
'LINK',
|
||||
'/^COMMENTFONT\s+(\d+)\s*$/i',
|
||||
array ('commentfont' => 1)
|
||||
),),
|
||||
'BANDWIDTH' => array (
|
||||
array (
|
||||
'LINK',
|
||||
'/^(BANDWIDTH)\s+(\d+\.?\d*[KMGT]?)\s+(\d+\.?\d*[KMGT]?)\s*$/i',
|
||||
array (
|
||||
'max_bandwidth_in_cfg' => 2,
|
||||
'max_bandwidth_out_cfg' => 3
|
||||
)
|
||||
),
|
||||
array (
|
||||
'LINK',
|
||||
'/^(BANDWIDTH)\s+(\d+\.?\d*[KMGT]?)\s*$/i',
|
||||
array (
|
||||
'max_bandwidth_in_cfg' => 2,
|
||||
'max_bandwidth_out_cfg' => 2
|
||||
)
|
||||
),
|
||||
),
|
||||
'OUTBWFORMAT' => array (array (
|
||||
'LINK',
|
||||
'/^OUTBWFORMAT\s+(.*)\s*$/i',
|
||||
array (
|
||||
'bwlabelformats[OUT]' => 1,
|
||||
'labelstyle' => '--'
|
||||
)
|
||||
),),
|
||||
'INBWFORMAT' => array (array (
|
||||
'LINK',
|
||||
'/^INBWFORMAT\s+(.*)\s*$/i',
|
||||
array (
|
||||
'bwlabelformats[IN]' => 1,
|
||||
'labelstyle' => '--'
|
||||
)
|
||||
),),
|
||||
'INNOTES' => array (array (
|
||||
'LINK',
|
||||
'/^INNOTES\s+(.*)\s*$/i',
|
||||
array ('notestext[IN]' => 1)
|
||||
),),
|
||||
'OUTNOTES' => array (array (
|
||||
'LINK',
|
||||
'/^OUTNOTES\s+(.*)\s*$/i',
|
||||
array ('notestext[OUT]' => 1)
|
||||
),),
|
||||
'INFOURL' => array (array (
|
||||
'LINK',
|
||||
'/^INFOURL\s+(.*)\s*$/i',
|
||||
array (
|
||||
'infourl[IN]' => 1,
|
||||
'infourl[OUT]' => 1
|
||||
)
|
||||
),),
|
||||
'ININFOURL' => array (array (
|
||||
'LINK',
|
||||
'/^ININFOURL\s+(.*)\s*$/i',
|
||||
array ('infourl[IN]' => 1)
|
||||
),),
|
||||
'OUTINFOURL' => array (array (
|
||||
'LINK',
|
||||
'/^OUTINFOURL\s+(.*)\s*$/i',
|
||||
array ('infourl[OUT]' => 1)
|
||||
),),
|
||||
'OVERLIBCAPTION' => array (array (
|
||||
'LINK',
|
||||
'/^OVERLIBCAPTION\s+(.*)\s*$/i',
|
||||
array (
|
||||
'overlibcaption[IN]' => 1,
|
||||
'overlibcaption[OUT]' => 1
|
||||
)
|
||||
),),
|
||||
'INOVERLIBCAPTION' => array (array (
|
||||
'LINK',
|
||||
'/^INOVERLIBCAPTION\s+(.*)\s*$/i',
|
||||
array ('overlibcaption[IN]' => 1)
|
||||
),),
|
||||
'OUTOVERLIBCAPTION' => array (array (
|
||||
'LINK',
|
||||
'/^OUTOVERLIBCAPTION\s+(.*)\s*$/i',
|
||||
array ('overlibcaption[OUT]' => 1)
|
||||
),),
|
||||
'ZORDER' => array (array (
|
||||
'LINK',
|
||||
"/^ZORDER\s+([-+]?\d+)\s*$/i",
|
||||
array ('zorder' => 1)
|
||||
),),
|
||||
'OVERLIBWIDTH' => array (array (
|
||||
'LINK',
|
||||
"/^OVERLIBWIDTH\s+(\d+)\s*$/i",
|
||||
array ('overlibwidth' => 1)
|
||||
),),
|
||||
'OVERLIBHEIGHT' => array (array (
|
||||
'LINK',
|
||||
"/^OVERLIBHEIGHT\s+(\d+)\s*$/i",
|
||||
array ('overlibheight' => 1)
|
||||
),),
|
||||
) // end of link
|
||||
);
|
||||
|
856
includes/weathermap/lib/WeatherMapLink.class.php
Normal file
@ -0,0 +1,856 @@
|
||||
<?php
|
||||
// PHP Weathermap 0.98a
|
||||
// Copyright Howard Jones, 2005-2019 howie@thingy.com
|
||||
// http://www.network-weathermap.com/
|
||||
// Released under the MIT License
|
||||
|
||||
require_once "HTML_ImageMap.class.php";
|
||||
|
||||
class WeatherMapLink extends WeatherMapItem
|
||||
{
|
||||
var $owner, $name;
|
||||
var $id;
|
||||
var $maphtml;
|
||||
var $a, $b; // the ends - references to nodes
|
||||
var $width, $arrowstyle, $linkstyle;
|
||||
var $bwfont, $labelstyle, $labelboxstyle;
|
||||
var $zorder;
|
||||
var $overliburl = array();
|
||||
var $infourl = array();
|
||||
var $notes;
|
||||
var $overlibcaption = array();
|
||||
var $overlibwidth, $overlibheight;
|
||||
var $bandwidth_in, $bandwidth_out;
|
||||
var $max_bandwidth_in, $max_bandwidth_out;
|
||||
var $max_bandwidth_in_cfg, $max_bandwidth_out_cfg;
|
||||
var $targets = array();
|
||||
var $a_offset, $b_offset;
|
||||
var $in_ds, $out_ds;
|
||||
var $colours = array();
|
||||
var $selected;
|
||||
var $inpercent, $outpercent;
|
||||
var $inherit_fieldlist;
|
||||
var $vialist = array();
|
||||
var $viastyle;
|
||||
var $usescale, $duplex;
|
||||
var $scaletype;
|
||||
var $outlinecolour;
|
||||
var $bwoutlinecolour;
|
||||
var $bwboxcolour;
|
||||
var $splitpos;
|
||||
var $commentfont;
|
||||
var $notestext = array();
|
||||
var $inscalekey,$outscalekey;
|
||||
var $inscaletag, $outscaletag;
|
||||
# var $incolour,$outcolour;
|
||||
var $commentfontcolour;
|
||||
var $commentstyle;
|
||||
var $bwfontcolour;
|
||||
# var $incomment, $outcomment;
|
||||
var $comments = array();
|
||||
var $bwlabelformats = array();
|
||||
var $curvepoints;
|
||||
var $labeloffset_in, $labeloffset_out;
|
||||
var $commentoffset_in, $commentoffset_out;
|
||||
var $template;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
|
||||
$this->inherit_fieldlist=array
|
||||
(
|
||||
'my_default' => NULL,
|
||||
'width' => 7,
|
||||
'commentfont' => 1,
|
||||
'bwfont' => 2,
|
||||
'template' => ':: DEFAULT ::',
|
||||
'splitpos'=>50,
|
||||
'labeloffset_out' => 25,
|
||||
'labeloffset_in' => 75,
|
||||
'commentoffset_out' => 5,
|
||||
'commentoffset_in' => 95,
|
||||
'commentstyle' => 'edge',
|
||||
'arrowstyle' => 'classic',
|
||||
'viastyle' => 'curved',
|
||||
'usescale' => 'DEFAULT',
|
||||
'scaletype' => 'percent',
|
||||
'targets' => array(),
|
||||
'duplex' => 'full',
|
||||
'infourl' => array('',''),
|
||||
'notes' => array(),
|
||||
'hints' => array(),
|
||||
'comments' => array('',''),
|
||||
'bwlabelformats' => array(FMT_PERC_IN,FMT_PERC_OUT),
|
||||
'overliburl' => array(array(),array()),
|
||||
'notestext' => array(IN=>'',OUT=>''),
|
||||
'labelstyle' => 'percent',
|
||||
'labelboxstyle' => 'classic',
|
||||
'linkstyle' => 'twoway',
|
||||
'overlibwidth' => 0,
|
||||
'overlibheight' => 0,
|
||||
'outlinecolour' => array(0, 0, 0),
|
||||
'bwoutlinecolour' => array(0, 0, 0),
|
||||
'bwfontcolour' => array(0, 0, 0),
|
||||
'bwboxcolour' => array(255, 255, 255),
|
||||
'commentfontcolour' => array(192,192,192),
|
||||
'inpercent'=>0, 'outpercent'=>0,
|
||||
'inscalekey'=>'', 'outscalekey'=>'',
|
||||
# 'incolour'=>-1,'outcolour'=>-1,
|
||||
'a_offset' => 'C',
|
||||
'b_offset' => 'C',
|
||||
#'incomment' => '',
|
||||
#'outcomment' => '',
|
||||
'zorder' => 300,
|
||||
'overlibcaption' => array('',''),
|
||||
'max_bandwidth_in' => 100000000,
|
||||
'max_bandwidth_out' => 100000000,
|
||||
'max_bandwidth_in_cfg' => '100M',
|
||||
'max_bandwidth_out_cfg' => '100M'
|
||||
);
|
||||
// $this->a_offset = 'C';
|
||||
// $this->b_offset = 'C';
|
||||
// $this->targets = array();
|
||||
}
|
||||
|
||||
function Reset(&$newowner)
|
||||
{
|
||||
$this->owner=$newowner;
|
||||
|
||||
$template = $this->template;
|
||||
if($template == '') $template = "DEFAULT";
|
||||
|
||||
wm_debug("Resetting $this->name with $template\n");
|
||||
|
||||
// the internal default-default gets it's values from inherit_fieldlist
|
||||
// everything else comes from a link object - the template.
|
||||
if($this->name==':: DEFAULT ::')
|
||||
{
|
||||
foreach (array_keys($this->inherit_fieldlist) as $fld) {
|
||||
$this->$fld=$this->inherit_fieldlist[$fld];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->CopyFrom($this->owner->links[$template]);
|
||||
}
|
||||
$this->template = $template;
|
||||
|
||||
// to stop the editor tanking, now that colours are decided earlier in ReadData
|
||||
$this->colours[IN] = new Colour(192,192,192);
|
||||
$this->colours[OUT] = new Colour(192,192,192);
|
||||
$this->id = $newowner->next_id++;
|
||||
}
|
||||
|
||||
function my_type() { return "LINK"; }
|
||||
|
||||
function CopyFrom(&$source)
|
||||
{
|
||||
wm_debug("Initialising LINK $this->name from $source->name\n");
|
||||
assert('is_object($source)');
|
||||
|
||||
foreach (array_keys($this->inherit_fieldlist) as $fld) {
|
||||
if($fld != 'template') $this->$fld = $source->$fld;
|
||||
}
|
||||
}
|
||||
|
||||
// image = GD image references
|
||||
// col = array of Colour objects
|
||||
// widths = array of link widths
|
||||
function DrawComments($image,$col,$widths)
|
||||
{
|
||||
$curvepoints =& $this->curvepoints;
|
||||
$last = count($curvepoints)-1;
|
||||
|
||||
$totaldistance = $curvepoints[$last][2];
|
||||
|
||||
$start[OUT] = 0;
|
||||
$commentpos[OUT] = $this->commentoffset_out;
|
||||
$commentpos[IN] = $this->commentoffset_in;
|
||||
$start[IN] = $last;
|
||||
|
||||
if($this->linkstyle=="oneway")
|
||||
{
|
||||
$dirs = array(OUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
$dirs = array(OUT,IN);
|
||||
}
|
||||
|
||||
foreach ($dirs as $dir)
|
||||
{
|
||||
|
||||
|
||||
// Time to deal with Link Comments, if any
|
||||
$comment = $this->owner->ProcessString($this->comments[$dir], $this);
|
||||
|
||||
# print "COMMENT: $comment";
|
||||
|
||||
if($this->owner->get_hint('screenshot_mode')==1) $comment=screenshotify($comment);
|
||||
|
||||
if($comment != '')
|
||||
{
|
||||
# print "\n\n----------------------------------------------------------------\nComment $dir for ".$this->name."\n";;
|
||||
|
||||
list($textlength, $textheight) = $this->owner->myimagestringsize($this->commentfont, $comment);
|
||||
|
||||
$extra_percent = $commentpos[$dir];
|
||||
|
||||
// $font = $this->commentfont;
|
||||
// nudge pushes the comment out along the link arrow a little bit
|
||||
// (otherwise there are more problems with text disappearing underneath links)
|
||||
# $nudgealong = 0; $nudgeout=0;
|
||||
$nudgealong = intval($this->get_hint("comment_nudgealong"));
|
||||
$nudgeout = intval($this->get_hint("comment_nudgeout"));
|
||||
|
||||
$extra = ($totaldistance * ($extra_percent/100));
|
||||
# $comment_index = find_distance($curvepoints,$extra);
|
||||
|
||||
list($x,$y,$comment_index,$angle) = find_distance_coords_angle($curvepoints,$extra);
|
||||
|
||||
# print "$extra_percent => $extra ($totaldistance)\n";
|
||||
#printf(" Point A is %f,%f\n",$curvepoints[$comment_index][0], $curvepoints[$comment_index][1]);
|
||||
#printf(" Point B is %f,%f\n",$curvepoints[$comment_index+1][0], $curvepoints[$comment_index+1][1]);
|
||||
#printf(" Point X is %f,%f\n",$x, $y);
|
||||
|
||||
# if( ($comment_index != 0)) print "I ";
|
||||
# if (($x != $curvepoints[$comment_index][0]) ) print "X ";
|
||||
# if (($y != $curvepoints[$comment_index][1]) ) print "Y ";
|
||||
# print "\n";
|
||||
|
||||
if( ($comment_index != 0) && (($x != $curvepoints[$comment_index][0]) || ($y != $curvepoints[$comment_index][1])) )
|
||||
{
|
||||
# print " -> Path 1\n";
|
||||
$dx = $x - $curvepoints[$comment_index][0];
|
||||
$dy = $y - $curvepoints[$comment_index][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
# print " -> Path 2\n";
|
||||
$dx = $curvepoints[$comment_index+1][0] - $x;
|
||||
$dy = $curvepoints[$comment_index+1][1] - $y;
|
||||
}
|
||||
|
||||
$centre_distance = $widths[$dir] + 4 + $nudgeout;
|
||||
if($this->commentstyle == 'center')
|
||||
{
|
||||
$centre_distance = $nudgeout - ($textheight/2);
|
||||
}
|
||||
|
||||
// find the normal to our link, so we can get outside the arrow
|
||||
|
||||
$l=sqrt(($dx * $dx) + ($dy * $dy));
|
||||
|
||||
# print "$extra => $comment_index/$last => $x,$y => $dx,$dy => $l\n";
|
||||
|
||||
$dx = $dx/$l; $dy = $dy/$l;
|
||||
$nx = $dy; $ny = -$dx;
|
||||
$flipped=FALSE;
|
||||
|
||||
// if the text will be upside-down, rotate it, flip it, and right-justify it
|
||||
// not quite as catchy as Missy's version
|
||||
if(abs($angle)>90)
|
||||
{
|
||||
# $col = $map->selected;
|
||||
$angle -= 180;
|
||||
if($angle < -180) $angle +=360;
|
||||
$edge_x = $x + $nudgealong*$dx - $nx * $centre_distance;
|
||||
$edge_y = $y + $nudgealong*$dy - $ny * $centre_distance;
|
||||
# $comment .= "@";
|
||||
$flipped = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$edge_x = $x + $nudgealong*$dx + $nx * $centre_distance;
|
||||
$edge_y = $y + $nudgealong*$dy + $ny * $centre_distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( !$flipped && ($extra + $textlength) > $totaldistance)
|
||||
{
|
||||
$edge_x -= $dx * $textlength;
|
||||
$edge_y -= $dy * $textlength;
|
||||
# $comment .= "#";
|
||||
}
|
||||
|
||||
if( $flipped && ($extra - $textlength) < 0)
|
||||
{
|
||||
$edge_x += $dx * $textlength;
|
||||
$edge_y += $dy * $textlength;
|
||||
# $comment .= "%";
|
||||
}
|
||||
|
||||
// FINALLY, draw the text!
|
||||
# imagefttext($image, $fontsize, $angle, $edge_x, $edge_y, $col, $font,$comment);
|
||||
$this->owner->myimagestring($image, $this->commentfont, $edge_x, $edge_y, $comment, $col[$dir], $angle);
|
||||
#imagearc($image,$x,$y,10,10,0, 360,$this->owner->selected);
|
||||
#imagearc($image,$edge_x,$edge_y,10,10,0, 360,$this->owner->selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Draw($im, &$map)
|
||||
{
|
||||
// Get the positions of the end-points
|
||||
$x1=$map->nodes[$this->a->name]->x;
|
||||
$y1=$map->nodes[$this->a->name]->y;
|
||||
|
||||
$x2=$map->nodes[$this->b->name]->x;
|
||||
$y2=$map->nodes[$this->b->name]->y;
|
||||
|
||||
if(is_null($x1)) { wm_warn("LINK ".$this->name." uses a NODE with no POSITION! [WMWARN35]\n"); return; }
|
||||
if(is_null($y1)) { wm_warn("LINK ".$this->name." uses a NODE with no POSITION! [WMWARN35]\n"); return; }
|
||||
if(is_null($x2)) { wm_warn("LINK ".$this->name." uses a NODE with no POSITION! [WMWARN35]\n"); return; }
|
||||
if(is_null($y2)) { wm_warn("LINK ".$this->name." uses a NODE with no POSITION! [WMWARN35]\n"); return; }
|
||||
|
||||
|
||||
if( ($this->linkstyle=='twoway') && ($this->labeloffset_in < $this->labeloffset_out) && (intval($map->get_hint("nowarn_bwlabelpos"))==0) )
|
||||
{
|
||||
wm_warn("LINK ".$this->name." probably has it's BWLABELPOSs the wrong way around [WMWARN50]\n");
|
||||
}
|
||||
|
||||
list($dx, $dy)=calc_offset($this->a_offset, $map->nodes[$this->a->name]->width, $map->nodes[$this->a->name]->height);
|
||||
$x1+=$dx;
|
||||
$y1+=$dy;
|
||||
|
||||
list($dx, $dy)=calc_offset($this->b_offset, $map->nodes[$this->b->name]->width, $map->nodes[$this->b->name]->height);
|
||||
$x2+=$dx;
|
||||
$y2+=$dy;
|
||||
|
||||
if( ($x1==$x2) && ($y1==$y2) && sizeof($this->vialist)==0)
|
||||
{
|
||||
wm_warn("Zero-length link ".$this->name." skipped. [WMWARN45]");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$outlinecol = new Colour($this->outlinecolour);
|
||||
$commentcol = new Colour($this->commentfontcolour);
|
||||
|
||||
$outline_colour = $outlinecol->gdallocate($im);
|
||||
|
||||
$xpoints = array ( );
|
||||
$ypoints = array ( );
|
||||
|
||||
$xpoints[]=$x1;
|
||||
$ypoints[]=$y1;
|
||||
|
||||
# warn("There are VIAs.\n");
|
||||
foreach ($this->vialist as $via)
|
||||
{
|
||||
# imagearc($im, $via[0],$via[1],20,20,0,360,$map->selected);
|
||||
if(isset($via[2]))
|
||||
{
|
||||
$xpoints[]=$map->nodes[$via[2]]->x + $via[0];
|
||||
$ypoints[]=$map->nodes[$via[2]]->y + $via[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$xpoints[]=$via[0];
|
||||
$ypoints[]=$via[1];
|
||||
}
|
||||
}
|
||||
|
||||
$xpoints[]=$x2;
|
||||
$ypoints[]=$y2;
|
||||
|
||||
# list($link_in_colour,$link_in_scalekey, $link_in_scaletag) = $map->NewColourFromPercent($this->inpercent,$this->usescale,$this->name);
|
||||
# list($link_out_colour,$link_out_scalekey, $link_out_scaletag) = $map->NewColourFromPercent($this->outpercent,$this->usescale,$this->name);
|
||||
|
||||
$link_in_colour = $this->colours[IN];
|
||||
$link_out_colour = $this->colours[OUT];
|
||||
|
||||
$gd_in_colour = $link_in_colour->gdallocate($im);
|
||||
$gd_out_colour = $link_out_colour->gdallocate($im);
|
||||
|
||||
// $map->links[$this->name]->inscalekey = $link_in_scalekey;
|
||||
// $map->links[$this->name]->outscalekey = $link_out_scalekey;
|
||||
|
||||
$link_width=$this->width;
|
||||
// these will replace the one above, ultimately.
|
||||
$link_in_width=$this->width;
|
||||
$link_out_width=$this->width;
|
||||
|
||||
// for bulging animations
|
||||
if ( ($map->widthmod) || ($map->get_hint('link_bulge') == 1))
|
||||
{
|
||||
// a few 0.1s and +1s to fix div-by-zero, and invisible links
|
||||
$link_width = (($link_width * $this->inpercent * 1.5 + 0.1) / 100) + 1;
|
||||
// these too
|
||||
$link_in_width = (($link_in_width * $this->inpercent * 1.5 + 0.1) / 100) + 1;
|
||||
$link_out_width = (($link_out_width * $this->outpercent * 1.5 + 0.1) / 100) + 1;
|
||||
}
|
||||
|
||||
// If there are no vias, treat this as a 2-point angled link, not curved
|
||||
if( sizeof($this->vialist)==0 || $this->viastyle=='angled') {
|
||||
// Calculate the spine points - the actual not a curve really, but we
|
||||
// need to create the array, and calculate the distance bits, otherwise
|
||||
// things like bwlabels won't know where to go.
|
||||
|
||||
$this->curvepoints = calc_straight($xpoints, $ypoints);
|
||||
|
||||
// then draw the "curve" itself
|
||||
draw_straight($im, $this->curvepoints,
|
||||
array($link_in_width,$link_out_width), $outline_colour, array($gd_in_colour, $gd_out_colour),
|
||||
$this->name, $map, $this->splitpos, ($this->linkstyle=='oneway'?TRUE:FALSE) );
|
||||
}
|
||||
elseif($this->viastyle=='curved')
|
||||
{
|
||||
// Calculate the spine points - the actual curve
|
||||
$this->curvepoints = calc_curve($xpoints, $ypoints);
|
||||
|
||||
// then draw the curve itself
|
||||
draw_curve($im, $this->curvepoints,
|
||||
array($link_in_width,$link_out_width), $outline_colour, array($gd_in_colour, $gd_out_colour),
|
||||
$this->name, $map, $this->splitpos, ($this->linkstyle=='oneway'?TRUE:FALSE) );
|
||||
}
|
||||
|
||||
|
||||
if ( !$commentcol->is_none() )
|
||||
{
|
||||
if($commentcol->is_contrast())
|
||||
{
|
||||
$commentcol_in = $link_in_colour->contrast();
|
||||
$commentcol_out = $link_out_colour->contrast();
|
||||
}
|
||||
else
|
||||
{
|
||||
$commentcol_in = $commentcol;
|
||||
$commentcol_out = $commentcol;
|
||||
}
|
||||
|
||||
$comment_colour_in = $commentcol_in->gdallocate($im);
|
||||
$comment_colour_out = $commentcol_out->gdallocate($im);
|
||||
|
||||
$this->DrawComments($im,array($comment_colour_in, $comment_colour_out),array($link_in_width*1.1,$link_out_width*1.1));
|
||||
}
|
||||
|
||||
$curvelength = $this->curvepoints[count($this->curvepoints)-1][2];
|
||||
// figure out where the labels should be, and what the angle of the curve is at that point
|
||||
list($q1_x,$q1_y,$junk,$q1_angle) = find_distance_coords_angle($this->curvepoints,($this->labeloffset_out/100)*$curvelength);
|
||||
list($q3_x,$q3_y,$junk,$q3_angle) = find_distance_coords_angle($this->curvepoints,($this->labeloffset_in/100)*$curvelength);
|
||||
|
||||
# imageline($im, $q1_x+20*cos(deg2rad($q1_angle)),$q1_y-20*sin(deg2rad($q1_angle)), $q1_x-20*cos(deg2rad($q1_angle)), $q1_y+20*sin(deg2rad($q1_angle)), $this->owner->selected );
|
||||
# imageline($im, $q3_x+20*cos(deg2rad($q3_angle)),$q3_y-20*sin(deg2rad($q3_angle)), $q3_x-20*cos(deg2rad($q3_angle)), $q3_y+20*sin(deg2rad($q3_angle)), $this->owner->selected );
|
||||
|
||||
# warn("$q1_angle $q3_angle\n");
|
||||
|
||||
if (!is_null($q1_x))
|
||||
{
|
||||
$outbound=array
|
||||
(
|
||||
$q1_x,
|
||||
$q1_y,
|
||||
0,
|
||||
0,
|
||||
$this->outpercent,
|
||||
$this->bandwidth_out,
|
||||
$q1_angle,
|
||||
OUT
|
||||
);
|
||||
|
||||
$inbound=array
|
||||
(
|
||||
$q3_x,
|
||||
$q3_y,
|
||||
0,
|
||||
0,
|
||||
$this->inpercent,
|
||||
$this->bandwidth_in,
|
||||
$q3_angle,
|
||||
IN
|
||||
);
|
||||
|
||||
if ($map->sizedebug)
|
||||
{
|
||||
$outbound[5]=$this->max_bandwidth_out;
|
||||
$inbound[5]=$this->max_bandwidth_in;
|
||||
}
|
||||
|
||||
|
||||
if($this->linkstyle=='oneway')
|
||||
{
|
||||
$tasks = array($outbound);
|
||||
}
|
||||
else
|
||||
{
|
||||
$tasks = array($inbound,$outbound);
|
||||
}
|
||||
|
||||
foreach ($tasks as $task)
|
||||
{
|
||||
$thelabel="";
|
||||
|
||||
$thelabel = $map->ProcessString($this->bwlabelformats[$task[7]],$this);
|
||||
|
||||
if ($thelabel != '')
|
||||
{
|
||||
wm_debug("Bandwidth for label is ".$task[5]."\n");
|
||||
|
||||
$padding = intval($this->get_hint('bwlabel_padding'));
|
||||
|
||||
// if screenshot_mode is enabled, wipe any letters to X and wipe any IP address to 127.0.0.1
|
||||
// hopefully that will preserve enough information to show cool stuff without leaking info
|
||||
if($map->get_hint('screenshot_mode')==1) $thelabel = screenshotify($thelabel);
|
||||
|
||||
if($this->labelboxstyle == 'angled')
|
||||
{
|
||||
$angle = $task[6];
|
||||
}
|
||||
else
|
||||
{
|
||||
$angle = 0;
|
||||
}
|
||||
|
||||
$map->DrawLabelRotated($im, $task[0], $task[1],$angle, $thelabel, $this->bwfont, $padding,
|
||||
$this->name, $this->bwfontcolour, $this->bwboxcolour, $this->bwoutlinecolour,$map, $task[7]);
|
||||
|
||||
// imagearc($im, $task[0], $task[1], 10,10,0,360,$map->selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function WriteConfig()
|
||||
{
|
||||
$output='';
|
||||
# $output .= "# ID ".$this->id." - first seen in ".$this->defined_in."\n";
|
||||
|
||||
if($this->config_override != '')
|
||||
{
|
||||
$output = $this->config_override."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
# $defdef = $this->owner->defaultlink;
|
||||
$dd = $this->owner->links[$this->template];
|
||||
|
||||
wm_debug("Writing config for LINK $this->name against $this->template\n");
|
||||
|
||||
$basic_params = array(
|
||||
array('width','WIDTH',CONFIG_TYPE_LITERAL),
|
||||
array('zorder','ZORDER',CONFIG_TYPE_LITERAL),
|
||||
array('overlibwidth','OVERLIBWIDTH',CONFIG_TYPE_LITERAL),
|
||||
array('overlibheight','OVERLIBHEIGHT',CONFIG_TYPE_LITERAL),
|
||||
array('arrowstyle','ARROWSTYLE',CONFIG_TYPE_LITERAL),
|
||||
array('viastyle','VIASTYLE',CONFIG_TYPE_LITERAL),
|
||||
array('linkstyle','LINKSTYLE',CONFIG_TYPE_LITERAL),
|
||||
array('splitpos','SPLITPOS',CONFIG_TYPE_LITERAL),
|
||||
array('duplex','DUPLEX',CONFIG_TYPE_LITERAL),
|
||||
array('commentstyle','COMMENTSTYLE',CONFIG_TYPE_LITERAL),
|
||||
array('labelboxstyle','BWSTYLE',CONFIG_TYPE_LITERAL),
|
||||
// array('usescale','USESCALE',CONFIG_TYPE_LITERAL),
|
||||
|
||||
array('bwfont','BWFONT',CONFIG_TYPE_LITERAL),
|
||||
array('commentfont','COMMENTFONT',CONFIG_TYPE_LITERAL),
|
||||
|
||||
array('bwoutlinecolour','BWOUTLINECOLOR',CONFIG_TYPE_COLOR),
|
||||
array('bwboxcolour','BWBOXCOLOR',CONFIG_TYPE_COLOR),
|
||||
array('outlinecolour','OUTLINECOLOR',CONFIG_TYPE_COLOR),
|
||||
array('commentfontcolour','COMMENTFONTCOLOR',CONFIG_TYPE_COLOR),
|
||||
array('bwfontcolour','BWFONTCOLOR',CONFIG_TYPE_COLOR)
|
||||
);
|
||||
|
||||
# TEMPLATE must come first. DEFAULT
|
||||
if($this->template != 'DEFAULT' && $this->template != ':: DEFAULT ::')
|
||||
{
|
||||
$output.="\tTEMPLATE " . $this->template . "\n";
|
||||
}
|
||||
|
||||
foreach ($basic_params as $param)
|
||||
{
|
||||
$field = $param[0];
|
||||
$keyword = $param[1];
|
||||
|
||||
# $output .= "# For $keyword: ".$this->$field." vs ".$dd->$field."\n";
|
||||
if ($this->$field != $dd->$field)
|
||||
#if (1==1)
|
||||
{
|
||||
if($param[2] == CONFIG_TYPE_COLOR) $output.="\t$keyword " . render_colour($this->$field) . "\n";
|
||||
if($param[2] == CONFIG_TYPE_LITERAL) $output.="\t$keyword " . $this->$field . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$val = $this->usescale . " " . $this->scaletype;
|
||||
$comparison = $dd->usescale . " " . $dd->scaletype;
|
||||
|
||||
if ( ($val != $comparison) ) { $output.="\tUSESCALE " . $val . "\n"; }
|
||||
|
||||
if ($this->infourl[IN] == $this->infourl[OUT]) {
|
||||
$dirs = array(IN=>""); // only use the IN value, since they're both the same, but don't prefix the output keyword
|
||||
} else {
|
||||
$dirs = array( IN=>"IN", OUT=>"OUT" );// the full monty two-keyword version
|
||||
}
|
||||
|
||||
foreach ($dirs as $dir=>$tdir) {
|
||||
if ($this->infourl[$dir] != $dd->infourl[$dir]) {
|
||||
$output .= "\t" . $tdir . "INFOURL " . $this->infourl[$dir] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->overlibcaption[IN] == $this->overlibcaption[OUT]) {
|
||||
$dirs = array(IN=>""); // only use the IN value, since they're both the same, but don't prefix the output keyword
|
||||
} else {
|
||||
$dirs = array( IN=>"IN", OUT=>"OUT" );// the full monty two-keyword version
|
||||
}
|
||||
|
||||
foreach ($dirs as $dir=>$tdir) {
|
||||
if ($this->overlibcaption[$dir] != $dd->overlibcaption[$dir]) {
|
||||
$output .= "\t".$tdir."OVERLIBCAPTION " . $this->overlibcaption[$dir] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->notestext[IN] == $this->notestext[OUT]) {
|
||||
$dirs = array(IN=>""); // only use the IN value, since they're both the same, but don't prefix the output keyword
|
||||
} else {
|
||||
$dirs = array( IN=>"IN", OUT=>"OUT" );// the full monty two-keyword version
|
||||
}
|
||||
|
||||
foreach ($dirs as $dir=>$tdir) {
|
||||
if ($this->notestext[$dir] != $dd->notestext[$dir]) {
|
||||
$output .= "\t" . $tdir . "NOTES " . $this->notestext[$dir] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->overliburl[IN]==$this->overliburl[OUT]) {
|
||||
$dirs = array(IN=>""); // only use the IN value, since they're both the same, but don't prefix the output keyword
|
||||
} else {
|
||||
$dirs = array( IN=>"IN", OUT=>"OUT" );// the full monty two-keyword version
|
||||
}
|
||||
|
||||
foreach ($dirs as $dir=>$tdir) {
|
||||
if ($this->overliburl[$dir] != $dd->overliburl[$dir]) {
|
||||
$output.="\t".$tdir."OVERLIBGRAPH " . join(" ",$this->overliburl[$dir]) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// if formats have been set, but they're just the longform of the built-in styles, set them back to the built-in styles
|
||||
if($this->labelstyle=='--' && $this->bwlabelformats[IN] == FMT_PERC_IN && $this->bwlabelformats[OUT] == FMT_PERC_OUT)
|
||||
{
|
||||
$this->labelstyle = 'percent';
|
||||
}
|
||||
if($this->labelstyle=='--' && $this->bwlabelformats[IN] == FMT_BITS_IN && $this->bwlabelformats[OUT] == FMT_BITS_OUT)
|
||||
{
|
||||
$this->labelstyle = 'bits';
|
||||
}
|
||||
if($this->labelstyle=='--' && $this->bwlabelformats[IN] == FMT_UNFORM_IN && $this->bwlabelformats[OUT] == FMT_UNFORM_OUT)
|
||||
{
|
||||
$this->labelstyle = 'unformatted';
|
||||
}
|
||||
|
||||
// if specific formats have been set, then the style will be '--'
|
||||
// if it isn't then use the named style
|
||||
if ( ($this->labelstyle != $dd->labelstyle) && ($this->labelstyle != '--') ) {
|
||||
$output .= "\tBWLABEL " . $this->labelstyle . "\n";
|
||||
}
|
||||
|
||||
// if either IN or OUT field changes, then both must be written because a regular BWLABEL can't do it
|
||||
// XXX this looks wrong
|
||||
$comparison = $dd->bwlabelformats[IN];
|
||||
$comparison2 = $dd->bwlabelformats[OUT];
|
||||
|
||||
if ( ( $this->labelstyle == '--') && ( ($this->bwlabelformats[IN] != $comparison) || ($this->bwlabelformats[OUT]!= '--')) )
|
||||
{
|
||||
$output .= "\tINBWFORMAT " . $this->bwlabelformats[IN]. "\n";
|
||||
$output .= "\tOUTBWFORMAT " . $this->bwlabelformats[OUT]. "\n";
|
||||
}
|
||||
|
||||
$comparison = $dd->labeloffset_in;
|
||||
$comparison2 = $dd->labeloffset_out;
|
||||
|
||||
if ( ($this->labeloffset_in != $comparison) || ($this->labeloffset_out != $comparison2) )
|
||||
{ $output.="\tBWLABELPOS " . $this->labeloffset_in . " " . $this->labeloffset_out . "\n"; }
|
||||
|
||||
$comparison=$dd->commentoffset_in.":".$dd->commentoffset_out;
|
||||
$mine = $this->commentoffset_in.":".$this->commentoffset_out;
|
||||
if ($mine != $comparison) { $output.="\tCOMMENTPOS " . $this->commentoffset_in." ".$this->commentoffset_out. "\n"; }
|
||||
|
||||
|
||||
$comparison=$dd->targets;
|
||||
|
||||
if ($this->targets != $comparison) {
|
||||
$output.="\tTARGET";
|
||||
|
||||
foreach ($this->targets as $target) {
|
||||
if(strpos($target[4]," ") == FALSE) {
|
||||
$output .= " " . $target[4];
|
||||
} else {
|
||||
$output .= ' "' . $target[4] . '"';
|
||||
}
|
||||
}
|
||||
$output .= "\n";
|
||||
}
|
||||
|
||||
foreach (array(IN,OUT) as $dir) {
|
||||
if ($dir==IN) {
|
||||
$tdir="IN";
|
||||
}
|
||||
if ($dir==OUT) {
|
||||
$tdir="OUT";
|
||||
}
|
||||
|
||||
$comparison=$dd->comments[$dir];
|
||||
if ($this->comments[$dir] != $comparison) {
|
||||
$output .= "\t" . $tdir . "COMMENT " . $this->comments[$dir] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->a) && isset($this->b)) {
|
||||
$output .= "\tNODES " . $this->a->name;
|
||||
|
||||
if ($this->a_offset != 'C') {
|
||||
$output .= ":" . $this->a_offset;
|
||||
}
|
||||
|
||||
$output .= " " . $this->b->name;
|
||||
|
||||
if ($this->b_offset != 'C') {
|
||||
$output .= ":" . $this->b_offset;
|
||||
}
|
||||
|
||||
$output .= "\n";
|
||||
}
|
||||
|
||||
if (count($this->vialist) > 0) {
|
||||
foreach ($this->vialist as $via) {
|
||||
if( isset($via[2])) {
|
||||
$output .= sprintf("\tVIA %s %d %d\n", $via[2],$via[0], $via[1]);
|
||||
} else {
|
||||
$output .= sprintf("\tVIA %d %d\n", $via[0], $via[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (($this->max_bandwidth_in != $dd->max_bandwidth_in)
|
||||
|| ($this->max_bandwidth_out != $dd->max_bandwidth_out)
|
||||
|| ($this->name == 'DEFAULT'))
|
||||
{
|
||||
if ($this->max_bandwidth_in == $this->max_bandwidth_out)
|
||||
{ $output.="\tBANDWIDTH " . $this->max_bandwidth_in_cfg . "\n"; }
|
||||
else { $output
|
||||
.="\tBANDWIDTH " . $this->max_bandwidth_in_cfg . " " . $this->max_bandwidth_out_cfg . "\n"; }
|
||||
}
|
||||
|
||||
foreach ($this->hints as $hintname=>$hint)
|
||||
{
|
||||
// all hints for DEFAULT node are for writing
|
||||
// only changed ones, or unique ones, otherwise
|
||||
if(
|
||||
($this->name == 'DEFAULT')
|
||||
||
|
||||
(isset($dd->hints[$hintname])
|
||||
&&
|
||||
$dd->hints[$hintname] != $hint)
|
||||
||
|
||||
(!isset($dd->hints[$hintname]))
|
||||
)
|
||||
{
|
||||
$output .= "\tSET $hintname $hint\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($output != '') {
|
||||
$output = "LINK " . $this->name . "\n".$output."\n";
|
||||
}
|
||||
}
|
||||
return($output);
|
||||
}
|
||||
|
||||
function asJS()
|
||||
{
|
||||
$js='';
|
||||
$js.="Links[" . js_escape($this->name) . "] = {";
|
||||
$js .= "\"id\":" . $this->id. ", ";
|
||||
|
||||
if (isset($this->a))
|
||||
{
|
||||
$js.="a:'" . $this->a->name . "', ";
|
||||
$js.="b:'" . $this->b->name . "', ";
|
||||
}
|
||||
|
||||
$js.="width:'" . $this->width . "', ";
|
||||
$js.="target:";
|
||||
|
||||
$tgt='';
|
||||
|
||||
foreach ($this->targets as $target) {
|
||||
if(strpos($target[4]," ") == FALSE) {
|
||||
$tgt .= $target[4] . ' ';
|
||||
} else {
|
||||
$tgt .= '"'.$target[4] . '" ';
|
||||
}
|
||||
}
|
||||
|
||||
$js.=js_escape(trim($tgt));
|
||||
$js.=",";
|
||||
|
||||
$js.="bw_in:" . js_escape($this->max_bandwidth_in_cfg) . ", ";
|
||||
$js.="bw_out:" . js_escape($this->max_bandwidth_out_cfg) . ", ";
|
||||
|
||||
$js.="name:" . js_escape($this->name) . ", ";
|
||||
$js.="overlibwidth:'" . $this->overlibheight . "', ";
|
||||
$js.="overlibheight:'" . $this->overlibwidth . "', ";
|
||||
$js.="overlibcaption:" . js_escape($this->overlibcaption[IN]) . ", ";
|
||||
|
||||
$js.="commentin:" . js_escape($this->comments[IN]) . ", ";
|
||||
$js.="commentposin:" . intval($this->commentoffset_in) . ", ";
|
||||
|
||||
$js.="commentout:" . js_escape($this->comments[OUT]) . ", ";
|
||||
$js.="commentposout:" . intval($this->commentoffset_out) . ", ";
|
||||
|
||||
$js.="infourl:" . js_escape($this->infourl[IN]) . ", ";
|
||||
$js.="overliburl:" . js_escape(join(" ",$this->overliburl[IN]));
|
||||
|
||||
$js.="};\n";
|
||||
$js .= "LinkIDs[\"L" . $this->id . "\"] = ". js_escape($this->name) . ";\n";
|
||||
return $js;
|
||||
}
|
||||
|
||||
function asJSON($complete=TRUE)
|
||||
{
|
||||
$js = '';
|
||||
$js .= "" . js_escape($this->name) . ": {";
|
||||
$js .= "\"id\":" . $this->id. ", ";
|
||||
if (isset($this->a))
|
||||
{
|
||||
$js.="\"a\":\"" . $this->a->name . "\", ";
|
||||
$js.="\"b\":\"" . $this->b->name . "\", ";
|
||||
}
|
||||
|
||||
if($complete)
|
||||
{
|
||||
$js.="\"infourl\":" . js_escape($this->infourl) . ", ";
|
||||
$js.="\"overliburl\":" . js_escape($this->overliburl). ", ";
|
||||
$js.="\"width\":\"" . $this->width . "\", ";
|
||||
$js.="\"target\":";
|
||||
|
||||
$tgt="";
|
||||
|
||||
foreach ($this->targets as $target) { $tgt.=$target[4] . " "; }
|
||||
|
||||
$js.=js_escape(trim($tgt));
|
||||
$js.=",";
|
||||
|
||||
$js.="\"bw_in\":" . js_escape($this->max_bandwidth_in_cfg) . ", ";
|
||||
$js.="\"bw_out\":" . js_escape($this->max_bandwidth_out_cfg) . ", ";
|
||||
|
||||
$js.="\"name\":" . js_escape($this->name) . ", ";
|
||||
$js.="\"overlibwidth\":\"" . $this->overlibheight . "\", ";
|
||||
$js.="\"overlibheight\":\"" . $this->overlibwidth . "\", ";
|
||||
$js.="\"overlibcaption\":" . js_escape($this->overlibcaption) . ", ";
|
||||
}
|
||||
$vias = "\"via\": [";
|
||||
foreach ($this->vialist as $via)
|
||||
$vias .= sprintf("[%d,%d,'%s'],", $via[0], $via[1],$via[2]);
|
||||
$vias .= "],";
|
||||
$vias = str_replace("],],", "]]", $vias);
|
||||
$vias = str_replace("[],", "[]", $vias);
|
||||
$js .= $vias;
|
||||
|
||||
$js.="},\n";
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
1021
includes/weathermap/lib/WeatherMapNode.class.php
Normal file
3453
includes/weathermap/lib/Weathermap.class.php
Normal file
30
includes/weathermap/lib/database.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @return null|PDO
|
||||
*/
|
||||
function weathermap_get_pdo()
|
||||
{
|
||||
// This is the Cacti standard settings
|
||||
global $database_type, $database_default, $database_hostname, $database_username, $database_password;
|
||||
global $config;
|
||||
|
||||
$cacti_version = $config["cacti_version"];
|
||||
|
||||
$host = $database_hostname;
|
||||
$dbname = $database_default;
|
||||
$user = $database_username;
|
||||
$pass = $database_password;
|
||||
|
||||
$pdo = null;
|
||||
|
||||
try {
|
||||
# MySQL with PDO_MYSQL
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
return $pdo;
|
||||
}
|
6
includes/weathermap/lib/datasources/README.txt
Normal file
@ -0,0 +1,6 @@
|
||||
Some of these datasource plugins are rather sketchy or even completely non-working.
|
||||
|
||||
In particular:
|
||||
dbsample doesn't do anything.
|
||||
snmp isn't really useful, but has some work done on it.
|
||||
external has had no real testing yet
|
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
class WeatherMapDataSource_cactihost extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
if($map->context == 'cacti')
|
||||
{
|
||||
if( function_exists('db_fetch_row') )
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_debug('ReadData CactiHost: Cacti database library not found.\n');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_debug("ReadData CactiHost: Can only run from Cacti environment.\n");
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^cactihost:(\d+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if(preg_match("/^cactihost:(\d+)$/",$targetstring,$matches))
|
||||
{
|
||||
$cacti_id = intval($matches[1]);
|
||||
|
||||
$SQL = "select * from host where id=$cacti_id";
|
||||
// 0=disabled
|
||||
// 1=down
|
||||
// 2=recovering
|
||||
// 3=up
|
||||
|
||||
$state = -1;
|
||||
$result = db_fetch_row($SQL);
|
||||
if(isset($result))
|
||||
{
|
||||
// create a note, which can be used in icon filenames or labels more nicely
|
||||
if($result['status'] == 1) { $state = 1; $statename = 'down'; }
|
||||
if($result['status'] == 2) { $state = 2; $statename = 'recovering'; }
|
||||
if($result['status'] == 3) { $state = 3; $statename = 'up'; }
|
||||
if($result['disabled']) { $state = 0; $statename = 'disabled'; }
|
||||
|
||||
$data[IN] = $state;
|
||||
$data[OUT] = $state;
|
||||
$item->add_note("state",$statename);
|
||||
$item->add_note("cacti_description",$result['description']);
|
||||
|
||||
$item->add_note("cacti_hostname",$result['hostname']);
|
||||
$item->add_note("cacti_curtime",$result['cur_time']);
|
||||
$item->add_note("cacti_avgtime",$result['avg_time']);
|
||||
$item->add_note("cacti_mintime",$result['min_time']);
|
||||
$item->add_note("cacti_maxtime",$result['max_time']);
|
||||
$item->add_note("cacti_availability",$result['availability']);
|
||||
|
||||
$item->add_note("cacti_faildate",$result['status_fail_date']);
|
||||
$item->add_note("cacti_recdate",$result['status_rec_date']);
|
||||
}
|
||||
}
|
||||
|
||||
wm_debug ("CactiHost ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
// Cacti thold/monitor DS plugin
|
||||
// Can read state of Thresholds from the THold Cacti plugin
|
||||
// and also overall host state, in the style of the Monitor plugin (it doesn't depend on that plugin to do this)
|
||||
//
|
||||
// It DOES depend on THold though, obviously!
|
||||
//
|
||||
// Possible TARGETs:
|
||||
//
|
||||
// cactithold:234
|
||||
// (internal thold id - returns 0 for OK, and 1 for breach)
|
||||
//
|
||||
// cactithold:12:444
|
||||
// (the two IDs seen in thold URLs- also returns 0 for OK, and 1 for breach)
|
||||
//
|
||||
// cactimonitor:22
|
||||
// (cacti hostid - returns host state (0-3) or 4 for failing some thresholds)
|
||||
// also sets all the same variables as cactihost: would, and a new possible 'state' name of 'tholdbreached'
|
||||
//
|
||||
// Original development for this plugin was paid for by
|
||||
// Stellar Consulting
|
||||
|
||||
class WeatherMapDataSource_cactithold extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
global $plugins;
|
||||
|
||||
if($map->context == 'cacti')
|
||||
{
|
||||
if( !function_exists('db_fetch_row') )
|
||||
{
|
||||
wm_debug("ReadData CactiTHold: Cacti database library not found. [THOLD001]\n");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
$thold_present = false;
|
||||
|
||||
if (function_exists("api_plugin_is_enabled")) {
|
||||
if (api_plugin_is_enabled('thold')) {
|
||||
$thold_present = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset($plugins) && in_array('thold',$plugins)) {
|
||||
$thold_present = true;
|
||||
}
|
||||
|
||||
if ( !$thold_present) {
|
||||
wm_debug("ReadData CactiTHold: THold plugin not enabled. [THOLD002]\n");
|
||||
}
|
||||
|
||||
$sql = "show tables";
|
||||
$result = db_fetch_assoc($sql);
|
||||
$tables = array();
|
||||
|
||||
foreach($result as $index => $arr) {
|
||||
foreach ($arr as $t) {
|
||||
$tables[] = $t;
|
||||
}
|
||||
}
|
||||
|
||||
if( !in_array('thold_data', $tables) )
|
||||
{
|
||||
wm_debug('ReadData CactiTHold: thold_data database table not found. [THOLD003]\n');
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_debug("ReadData CactiTHold: Can only run from Cacti environment. [THOLD004]\n");
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^cacti(thold|monitor):(\d+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
elseif(preg_match("/^cactithold:(\d+):(\d+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if(preg_match("/^cactithold:(\d+):(\d+)$/",$targetstring,$matches))
|
||||
{
|
||||
// Returns 0 if threshold is not breached, 1 if it is.
|
||||
// use target aggregation to build these up into a 'badness' percentage
|
||||
// takes the same two values that are visible in thold's own URLs (the actual thold ID isn't shown anywhere)
|
||||
|
||||
$rra_id = intval($matches[1]);
|
||||
$data_id = intval($matches[2]);
|
||||
|
||||
$SQL2 = "select thold_alert from thold_data where rra_id=$rra_id and data_id=$data_id and thold_enabled='on'";
|
||||
$result = db_fetch_row($SQL2);
|
||||
if(isset($result))
|
||||
{
|
||||
if($result['thold_alert'] > 0) { $data[IN]=1; }
|
||||
else { $data[IN] = 0; }
|
||||
$data[OUT] = 0;
|
||||
}
|
||||
}
|
||||
elseif(preg_match("/^cacti(thold|monitor):(\d+)$/",$targetstring,$matches))
|
||||
{
|
||||
$type = $matches[1];
|
||||
$id = intval($matches[2]);
|
||||
|
||||
if($type=='thold')
|
||||
{
|
||||
// VERY simple. Returns 0 if threshold is not breached, 1 if it is.
|
||||
// use target aggregation to build these up into a 'badness' percentage
|
||||
$SQL2 = "select thold_alert from thold_data where id=$id and thold_enabled='on'";
|
||||
$result = db_fetch_row($SQL2);
|
||||
if(isset($result))
|
||||
{
|
||||
if($result['thold_alert'] > 0) { $data[IN]=1; }
|
||||
else { $data[IN] = 0; }
|
||||
$data[OUT] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if($type=='monitor')
|
||||
{
|
||||
wm_debug("CactiTHold ReadData: Getting cacti basic state for host $id\n");
|
||||
$SQL = "select * from host where id=$id";
|
||||
|
||||
// 0=disabled
|
||||
// 1=down
|
||||
// 2=recovering
|
||||
// 3=up
|
||||
// 4=tholdbreached
|
||||
|
||||
$state = -1;
|
||||
$statename = '';
|
||||
$result = db_fetch_row($SQL);
|
||||
if(isset($result))
|
||||
{
|
||||
// create a note, which can be used in icon filenames or labels more nicely
|
||||
if($result['status'] == 1) { $state = 1; $statename = 'down'; }
|
||||
if($result['status'] == 2) { $state = 2; $statename = 'recovering'; }
|
||||
if($result['status'] == 3) { $state = 3; $statename = 'up'; }
|
||||
if($result['disabled']) { $state = 0; $statename = 'disabled'; }
|
||||
|
||||
$data[IN] = $state;
|
||||
$data[OUT] = 0;
|
||||
$item->add_note("state",$statename);
|
||||
$item->add_note("cacti_description",$result['description']);
|
||||
|
||||
$item->add_note("cacti_hostname",$result['hostname']);
|
||||
$item->add_note("cacti_curtime",$result['cur_time']);
|
||||
$item->add_note("cacti_avgtime",$result['avg_time']);
|
||||
$item->add_note("cacti_mintime",$result['min_time']);
|
||||
$item->add_note("cacti_maxtime",$result['max_time']);
|
||||
$item->add_note("cacti_availability",$result['availability']);
|
||||
|
||||
$item->add_note("cacti_faildate",$result['status_fail_date']);
|
||||
$item->add_note("cacti_recdate",$result['status_rec_date']);
|
||||
}
|
||||
wm_debug("CactiTHold ReadData: Basic state for host $id is $state/$statename\n");
|
||||
|
||||
wm_debug("CactiTHold ReadData: Checking threshold states for host $id\n");
|
||||
$numthresh = 0;
|
||||
$numfailing = 0;
|
||||
$SQL2 = "select rra_id, data_id, thold_alert from thold_data,data_local where thold_data.rra_id=data_local.id and data_local.host_id=$id and thold_enabled='on'";
|
||||
# $result = db_fetch_row($SQL2);
|
||||
$queryrows = db_fetch_assoc($SQL2);
|
||||
if( is_array($queryrows) )
|
||||
{
|
||||
foreach ($queryrows as $th) {
|
||||
$desc = $th['rra_id']."/".$th['data_id'];
|
||||
$v = $th['thold_alert'];
|
||||
$numthresh++;
|
||||
if(intval($th['thold_alert']) > 0)
|
||||
{
|
||||
wm_debug("CactiTHold ReadData: Seen threshold $desc failing ($v)for host $id\n");
|
||||
$numfailing++;
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_debug("CactiTHold ReadData: Seen threshold $desc OK ($v) for host $id\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_debug("CactiTHold ReadData: Failed to get thold info for host $id\n");
|
||||
}
|
||||
|
||||
wm_debug("CactiTHold ReadData: Checked $numthresh and found $numfailing failing\n");
|
||||
|
||||
if( ($numfailing > 0) && ($numthresh > 0) && ($state==3) )
|
||||
{
|
||||
$state = 4;
|
||||
$statename = "tholdbreached";
|
||||
$item->add_note("state",$statename);
|
||||
$item->add_note("thold_failcount",$numfailing);
|
||||
$item->add_note("thold_failpercent",($numfailing/$numthresh)*100);
|
||||
$data[IN] = $state;
|
||||
$data[OUT] = $numfailing;
|
||||
wm_debug("CactiTHold ReadData: State is $state/$statename\n");
|
||||
}
|
||||
elseif( $numthresh>0 )
|
||||
{
|
||||
$item->add_note("thold_failcount",0);
|
||||
$item->add_note("thold_failpercent",0);
|
||||
wm_debug("CactiTHold ReadData: Leaving state as $state\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wm_debug ("CactiTHold ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim:ts=4:sw=4:
|
82
includes/weathermap/lib/datasources/WeatherMapDataSource_dbsample.php
Executable file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
// Sample Pluggable datasource for PHP Weathermap 0.9
|
||||
// - read a pair of values from a database, and return it
|
||||
|
||||
// TARGET dbplug:databasename:username:pass:hostkey
|
||||
|
||||
class WeatherMapDataSource_dbsample extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
if(! function_exists("mysql_real_escape_string") ) return FALSE;
|
||||
if(! function_exists("mysql_connect") ) return FALSE;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^dbplug:([^:]+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if(preg_match("/^dbplug:([^:]+)$/",$targetstring,$matches))
|
||||
{
|
||||
$database_user = $map->get_hint('dbplug_dbuser');
|
||||
$database_pass = $map->get_hint('dbplug_dbpass');
|
||||
$database_name = $map->get_hint('dbplug_dbname');
|
||||
$database_host = $map->get_hint('dbplug_dbhost');
|
||||
|
||||
$key = mysql_real_escape_string($matches[1]);
|
||||
|
||||
$SQL = "select in,out from table where host=$key LIMIT 1";
|
||||
if(mysql_connect($database_host,$database_user,$database_pass))
|
||||
{
|
||||
if(mysql_select_db($database_name))
|
||||
{
|
||||
$result = mysql_query($SQL);
|
||||
if (!$result)
|
||||
{
|
||||
wm_warn("dbsample ReadData: Invalid query: " . mysql_error()."\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$row = mysql_fetch_assoc($result);
|
||||
$data[IN] = $row['in'];
|
||||
$data[OUT] = $row['out'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_warn("dbsample ReadData: failed to select database: ".mysql_error()."\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_warn("dbsample ReadData: failed to connect to database server: ".mysql_error()."\n");
|
||||
}
|
||||
|
||||
$data_time = now();
|
||||
}
|
||||
|
||||
|
||||
wm_debug ("RRD ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[IN]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
||||
?>
|
@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
include_once dirname(__FILE__) . "/../ds-common.php";
|
||||
include_once dirname(__FILE__) . "/../database.php";
|
||||
|
||||
class WeatherMapDataSource_dsstats extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
global $config;
|
||||
if($map->context=='cacti')
|
||||
{
|
||||
if( !function_exists('db_fetch_row') )
|
||||
{
|
||||
wm_debug("ReadData DSStats: Cacti database library not found. [DSSTATS001]\n");
|
||||
return(FALSE);
|
||||
}
|
||||
if(function_exists("api_plugin_is_enabled"))
|
||||
{
|
||||
if(! api_plugin_is_enabled('dsstats'))
|
||||
{
|
||||
wm_debug("ReadData DSStats: DSStats plugin not enabled (new-style). [DSSTATS002B]\n");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !isset($plugins) || !in_array('dsstats',$plugins))
|
||||
{
|
||||
wm_debug("ReadData DSStats: DSStats plugin not enabled (old-style). [DSSTATS002A]\n");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "show tables";
|
||||
$result = db_fetch_assoc($sql);
|
||||
$tables = array();
|
||||
|
||||
foreach($result as $index => $arr) {
|
||||
foreach ($arr as $t) {
|
||||
$tables[] = $t;
|
||||
}
|
||||
}
|
||||
|
||||
if( !in_array('data_source_stats_hourly_last', $tables) )
|
||||
{
|
||||
wm_debug('ReadData DSStats: data_source_stats_hourly_last database table not found. [DSSTATS003]\n');
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
# dsstats:<datatype>:<local_data_id>:<rrd_name_in>:<rrd_name_out>
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^dsstats:([a-z]+):(\d+):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
elseif(preg_match("/^dsstats:(\d+):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Actually read data from a data source, and return it
|
||||
// returns a 3-part array (invalue, outvalue and datavalid time_t)
|
||||
// invalue and outvalue should be -1,-1 if there is no valid data
|
||||
// data_time is intended to allow more informed graphing in the future
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$dsnames[IN] = "traffic_in";
|
||||
$dsnames[OUT] = "traffic_out";
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
|
||||
$inbw = NULL;
|
||||
$outbw = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
$table = "";
|
||||
$keyfield = "rrd_name";
|
||||
$datatype = "";
|
||||
$field = "";
|
||||
|
||||
$pdo = weathermap_get_pdo();
|
||||
|
||||
if(preg_match("/^dsstats:(\d+):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches))
|
||||
{
|
||||
$local_data_id = $matches[1];
|
||||
$dsnames[IN] = $matches[2];
|
||||
$dsnames[OUT] = $matches[3];
|
||||
|
||||
$datatype = "last";
|
||||
|
||||
if($map->get_hint("dsstats_default_type") != '') {
|
||||
$datatype = $map->get_hint("dsstats_default_type");
|
||||
wm_debug("Default datatype changed to ".$datatype.".\n");
|
||||
}
|
||||
}elseif(preg_match("/^dsstats:([a-z]+):(\d+):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches))
|
||||
{
|
||||
$dsnames[IN] = $matches[3];
|
||||
$dsnames[OUT] = $matches[4];
|
||||
$datatype = $matches[1];
|
||||
$local_data_id = $matches[2];
|
||||
}
|
||||
|
||||
if( substr($datatype,0,5) == "daily") $table = "data_source_stats_daily";
|
||||
if( substr($datatype,0,6) == "weekly") $table = "data_source_stats_weekly";
|
||||
if( substr($datatype,0,7) == "monthly") $table = "data_source_stats_monthly";
|
||||
if( substr($datatype,0,6) == "hourly") $table = "data_source_stats_hourly";
|
||||
if( substr($datatype,0,6) == "yearly") $table = "data_source_stats_yearly";
|
||||
|
||||
if( substr($datatype,-7) == "average" ) $field = "average";
|
||||
if( substr($datatype,-4) == "peak" ) $field = "peak";
|
||||
|
||||
if($datatype == "last")
|
||||
{
|
||||
$field = "calculated";
|
||||
$table = "data_source_stats_hourly_last";
|
||||
}
|
||||
|
||||
if($datatype == "wm")
|
||||
{
|
||||
$field = "last_calc";
|
||||
$table = "weathermap_data";
|
||||
$keyfield = "data_source_name";
|
||||
}
|
||||
|
||||
if($table != "" and $field != "")
|
||||
{
|
||||
// I know... but the field names and table name are variable!
|
||||
$SQL = sprintf("select %s as name, %s as result from %s where local_data_id=? and (%s=? or %s=?)",
|
||||
$keyfield, $field, $table, $keyfield, $keyfield);
|
||||
|
||||
$stmt = $pdo->prepare($SQL);
|
||||
$stmt->execute(array($local_data_id, $dsnames[IN], $dsnames[OUT]));
|
||||
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// $results = db_fetch_assoc($SQL);
|
||||
if(sizeof($results)>0)
|
||||
{
|
||||
foreach ($results as $result)
|
||||
{
|
||||
foreach ( array(IN,OUT) as $dir)
|
||||
{
|
||||
if( ($dsnames[$dir] == $result['name']) && ($result['result'] != -90909090909) && ($result['result'] !='U') )
|
||||
{
|
||||
$data[$dir] = $result['result'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($datatype=='wm' && ($data[IN] == NULL || $data[OUT] == NULL) )
|
||||
{
|
||||
wm_debug("Didn't get data for 'wm' source. Inserting new tasks.");
|
||||
// insert the required details into weathermap_data, so it will be picked up next time
|
||||
$stmt = $pdo->prepare("select data_template_data.data_source_path as path from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_rrd.local_data_id=?");
|
||||
$stmt->execute(array($local_data_id));
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
// $SQL = sprintf("select data_template_data.data_source_path as path from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_rrd.local_data_id=%d",
|
||||
// $local_data_id
|
||||
// );
|
||||
// $result = db_fetch_row($SQL);
|
||||
if(sizeof($result)>0)
|
||||
{
|
||||
$db_rrdname = $result['path'];
|
||||
wm_debug("Filename is $db_rrdname");
|
||||
foreach (array(IN,OUT) as $dir)
|
||||
{
|
||||
if($data[$dir] === NULL)
|
||||
{
|
||||
$stmt = $pdo->prepare("insert into weathermap_data (rrdfile, data_source_name, sequence, local_data_id) values (?,?,0,?)");
|
||||
$stmt->execute(array($db_rrdname, $dsnames[$dir], $local_data_id));
|
||||
// $SQLins = "insert into weathermap_data (rrdfile, data_source_name, sequence, local_data_id) values ('" .
|
||||
// mysql_real_escape_string($db_rrdname) . "','" .
|
||||
// mysql_real_escape_string($dsnames[$dir]) . "', 0," .
|
||||
// $local_data_id.")";
|
||||
// warn($SQLins);
|
||||
// db_execute($SQLins);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_warn("DSStats ReadData: Failed to find a filename for DS id $local_data_id [WMDSTATS01]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill all that other information (ifSpeed, etc)
|
||||
if ($local_data_id > 0) UpdateCactiData($item, $local_data_id);
|
||||
|
||||
wm_debug ("DSStats ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
// Run an external 'MRTG-compatible' script, and return it's values
|
||||
// TARGET !/usr/local/bin/qmailmrtg7 t /var/log/qmail
|
||||
|
||||
// MRTG Target scripts return 4 lines of text as output:
|
||||
// 'Input' value - interpreted as a byte count (so multiplied by 8)
|
||||
// 'Output' value - interpreted as a byte count (so multiplied by 8)
|
||||
// 'uptime' as a string
|
||||
// 'name of targer' as a string
|
||||
// we ignore the last two
|
||||
|
||||
// NOTE: Obviously, if you allow anyone to create maps, you are
|
||||
// allowing them to run ANY COMMAND as the user that runs
|
||||
// weathermap, by using this plugin. This might not be a
|
||||
// good thing.
|
||||
|
||||
// If you want to allow only one command, consider making
|
||||
// your own datasource plugin which only runs that one command.
|
||||
|
||||
|
||||
class WeatherMapDataSource_external extends WeatherMapDataSource {
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^!(.*)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if(preg_match("/^!(.*)$/",$targetstring,$matches))
|
||||
{
|
||||
$command = $matches[1];
|
||||
|
||||
wm_debug("ExternalScript ReadData: Running $command\n");
|
||||
// run the command here
|
||||
if( ($pipe = popen($command,"r")) === false)
|
||||
{
|
||||
wm_warn("ExternalScript ReadData: Failed to run external script. [WMEXT01]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$i=0;
|
||||
while( ($i <5) && ! feof($pipe) )
|
||||
{
|
||||
$lines[$i++] = rtrim(fgets($pipe,1024));
|
||||
}
|
||||
pclose($pipe);
|
||||
|
||||
if($i==5)
|
||||
{
|
||||
$data[IN] = floatval($lines[0]);
|
||||
$data[OUT] = floatval($lines[1]);
|
||||
|
||||
$item->add_hint("external_line1",$lines[0]);
|
||||
$item->add_hint("external_line2",$lines[1]);
|
||||
$item->add_hint("external_line3",$lines[2]);
|
||||
$item->add_hint("external_line4",$lines[3]);
|
||||
$data_time = time();
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_warn("ExternalScript ReadData: Not enough lines read from external script ($i read, 4 expected) [WMEXT02]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wm_debug ("ExternalScript ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
||||
|
||||
?>
|
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
// Pluggable datasource for PHP Weathermap 0.9
|
||||
// - return a live ping result
|
||||
|
||||
// TARGET fping:ipaddress
|
||||
// TARGET fping:hostname
|
||||
|
||||
class WeatherMapDataSource_fping extends WeatherMapDataSource {
|
||||
|
||||
var $addresscache = array();
|
||||
var $donepings = FALSE;
|
||||
var $results = array();
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
#
|
||||
# You may need to change the line below to have something like "/usr/local/bin/fping" or "/usr/bin/fping" instead.
|
||||
#
|
||||
$this->fping_cmd = "/usr/local/sbin/fping";
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// this function will get called for every datasource, even if we replied FALSE to Init.
|
||||
// (so that we can warn the user that it *would* have worked, if only the plugin could run)
|
||||
// SO... don't do anything in here that relies on the things that Init looked for, because they might not exist!
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^fping:(\S+)$/",$targetstring,$matches))
|
||||
{
|
||||
// save the address. This way, we can do ONE fping call for all the pings in the map.
|
||||
// fping does it all in parallel, so 10 hosts takes the same time as 1
|
||||
$this->addresscache[]=$matches[1];
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
#debug("-------------------------\n");
|
||||
#print_r($this->addresscache);
|
||||
#debug("-------------------------\n");
|
||||
|
||||
$ping_count = intval($map->get_hint("fping_ping_count"));
|
||||
if($ping_count==0) $ping_count = 5;
|
||||
|
||||
if(preg_match("/^fping:(\S+)$/",$targetstring,$matches))
|
||||
{
|
||||
$target = $matches[1];
|
||||
|
||||
$pattern = "/^$target\s:";
|
||||
for($i=0;$i<$ping_count;$i++) $pattern .= "\s(\S+)";
|
||||
$pattern .= "/";
|
||||
|
||||
if(is_executable($this->fping_cmd))
|
||||
{
|
||||
$command = $this->fping_cmd." -t100 -r1 -p20 -u -C $ping_count -i10 -q $target 2>&1";
|
||||
wm_debug("Running $command\n");
|
||||
$pipe=popen($command, "r");
|
||||
|
||||
$count = 0; $hitcount=0;
|
||||
if (isset($pipe))
|
||||
{
|
||||
while (!feof($pipe))
|
||||
{
|
||||
$line=fgets($pipe, 4096);
|
||||
$count++;
|
||||
wm_debug("Output: $line");
|
||||
|
||||
if(preg_match($pattern, $line, $matches))
|
||||
{
|
||||
wm_debug("Found output line for $target\n");
|
||||
$hitcount++;
|
||||
$loss = 0;
|
||||
$ave = 0;
|
||||
$total = 0;
|
||||
$cnt = 0;
|
||||
$min = 999999;
|
||||
$max = 0;
|
||||
for($i=1;$i<=$ping_count;$i++)
|
||||
{
|
||||
if($matches[$i]=='-')
|
||||
{ $loss+=(100/$ping_count); }
|
||||
else
|
||||
{
|
||||
$cnt++;
|
||||
$total += $matches[$i];
|
||||
$max = max($matches[$i],$max);
|
||||
$min = min($matches[$i],$min);
|
||||
}
|
||||
}
|
||||
if($cnt >0) $ave = $total/$cnt;
|
||||
|
||||
wm_debug("Result: $cnt $min -> $max $ave $loss\n");
|
||||
}
|
||||
}
|
||||
pclose ($pipe);
|
||||
if($count==0)
|
||||
{
|
||||
wm_warn("FPing ReadData: No lines read. Bad hostname? ($target) [WMFPING03]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if($hitcount == 0)
|
||||
{
|
||||
wm_warn("FPing ReadData: $count lines read. But nothing returned for target??? ($target) Try running with DEBUG to see output. [WMFPING02]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$data[IN] = $ave;
|
||||
$data[OUT] = $loss;
|
||||
$item->add_note("fping_min",$min);
|
||||
$item->add_note("fping_max",$max);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_warn("FPing ReadData: Can't find fping executable. Check path at line 19 of WeatherMapDataSource_fping.php [WMFPING01]\n");
|
||||
}
|
||||
}
|
||||
|
||||
wm_debug ("FPing ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
// Sample Pluggable datasource for PHP Weathermap 0.9
|
||||
// - read a pair of values from a database, and return it
|
||||
|
||||
// TARGET dbplug:databasename:username:pass:hostkey
|
||||
|
||||
class WeatherMapDataSource_mrtg extends WeatherMapDataSource {
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/\.(htm|html)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data['IN'] = NULL;
|
||||
$data['OUT'] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
$matchvalue= $item->get_hint('mrtg_value');
|
||||
$matchperiod = $item->get_hint('mrtg_period');
|
||||
$swap = intval($item->get_hint('mrtg_swap'));
|
||||
$negate = intval($item->get_hint('mrtg_negate'));
|
||||
|
||||
if($matchvalue =='') $matchvalue = "cu";
|
||||
if($matchperiod =='') $matchperiod = "d";
|
||||
|
||||
$fd=fopen($targetstring, "r");
|
||||
|
||||
if ($fd)
|
||||
{
|
||||
while (!feof($fd))
|
||||
{
|
||||
$buffer=fgets($fd, 4096);
|
||||
wm_debug("MRTG ReadData: Matching on '{$matchvalue}in $matchperiod' and '{$matchvalue}out $matchperiod'\n");
|
||||
|
||||
if (preg_match("/<\!-- {$matchvalue}in $matchperiod ([-+]?\d+\.?\d*) -->/", $buffer, $matches)) { $data['IN'] = $matches[1] * 8; }
|
||||
if (preg_match("/<\!-- {$matchvalue}out $matchperiod ([-+]?\d+\.?\d*) -->/", $buffer, $matches)) { $data['OUT'] = $matches[1] * 8; }
|
||||
}
|
||||
fclose($fd);
|
||||
# don't bother with the modified time if the target is a URL
|
||||
if(! preg_match('/^[a-z]+:\/\//',$targetstring) )
|
||||
{
|
||||
$data_time = filemtime($targetstring);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// some error code to go in here
|
||||
wm_debug ("MRTG ReadData: Couldn't open ($targetstring). \n");
|
||||
}
|
||||
|
||||
if($swap==1)
|
||||
{
|
||||
wm_debug("MRTG ReadData: Swapping IN and OUT\n");
|
||||
$t = $data['OUT'];
|
||||
$data['OUT'] = $data['IN'];
|
||||
$data['IN'] = $t;
|
||||
}
|
||||
|
||||
if($negate)
|
||||
{
|
||||
wm_debug("MRTG ReadData: Negating values\n");
|
||||
$data['OUT'] = -$data['OUT'];
|
||||
$data['IN'] = -$data['IN'];
|
||||
}
|
||||
|
||||
wm_debug ("MRTG ReadData: Returning (".($data['IN']===NULL?'NULL':$data['IN']).",".($data['OUT']===NULL?'NULL':$data['OUT']).",$data_time)\n");
|
||||
|
||||
return( array($data['IN'], $data['OUT'], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
// Observium DB Port Datasource.
|
||||
|
||||
// TARGET obs_port:device_id|hostname:ifIndex|ifAlias
|
||||
// We prefer device_id to survive hostname changes and we prefer ifIndex to survive irritating add/removals.
|
||||
// ifAlias is provided for those who prefer. Probably won't be used officially, though.
|
||||
|
||||
class WeatherMapDataSource_obsdb extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
if(! function_exists("dbFetchRow") ) return FALSE;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Return TRUE if we can handle this target string
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^obs_port:([^:]+):([^:]+)$/",$targetstring,$matches)) { return TRUE; } else { return FALSE; }
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if(preg_match("/^obs_port:([^:]+):([^:]+)$/",$targetstring,$matches))
|
||||
{
|
||||
|
||||
//r($matches);
|
||||
|
||||
// Get device from Observium DB by device_id or by hostname
|
||||
if(is_numeric($matches[1])) { $device = device_by_id_cache($matches[1]); } else { $device = device_by_name($matches[1]); }
|
||||
if(is_array($device))
|
||||
{
|
||||
if(is_numeric($matches[1]))
|
||||
{
|
||||
$port = get_port_by_ifIndex($device['device_id'], $matches[2]);
|
||||
} else {
|
||||
$port = get_port_by_ifAlias($device['device_id'], $matches[2]);
|
||||
}
|
||||
|
||||
if(is_array($port))
|
||||
{
|
||||
$data[IN] = $port['ifInOctets_rate']*8;
|
||||
$data[OUT] = $port['ifOutOctets_rate']*8;
|
||||
$data_time = $port['poll_time'];
|
||||
|
||||
$item->add_note("Errors Rate", $port['ifErrors_rate']);
|
||||
$item->add_note("PPS In Rate", $port['ifInNUcastPkts_rate'] + $port['ifInUcastPkts_rate']);
|
||||
$item->add_note("PPS Out Rate", $port['ifOutNUcastPkts_rate'] + $port['ifOutUcastPkts_rate']);
|
||||
|
||||
} else { wm_warn("ObsPortDB: Couldn't find port"); }
|
||||
} else { wm_warn("ObsPortDB: Couldn't find device"); }
|
||||
}
|
||||
|
||||
wm_debug ("ObsPortDB ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[IN]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
||||
?>
|
572
includes/weathermap/lib/datasources/WeatherMapDataSource_rrd.php
Normal file
@ -0,0 +1,572 @@
|
||||
<?php
|
||||
// RRDtool datasource plugin.
|
||||
// gauge:filename.rrd:ds_in:ds_out
|
||||
// filename.rrd:ds_in:ds_out
|
||||
// filename.rrd:ds_in:ds_out
|
||||
//
|
||||
|
||||
include_once(dirname(__FILE__) . "/../ds-common.php");
|
||||
include_once(dirname(__FILE__) . "/../database.php");
|
||||
|
||||
class WeatherMapDataSource_rrd extends WeatherMapDataSource
|
||||
{
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
global $config;
|
||||
|
||||
/*if ($map->context == 'cacti') {
|
||||
wm_debug("RRD DS: path_rra is " . $config["rra_path"] . " - your rrd pathname must be exactly this to use poller_output\n");
|
||||
// save away a couple of useful global SET variables
|
||||
$map->add_hint("cacti_path_rra", $config["rra_path"]);
|
||||
$map->add_hint("cacti_url", $config['url_path']);
|
||||
} */
|
||||
|
||||
if (file_exists($map->rrdtool)) {
|
||||
if ((function_exists('is_executable')) && (!is_executable($map->rrdtool))) {
|
||||
wm_warn("RRD DS: RRDTool exists but is not executable? [WMRRD01]\n");
|
||||
return (FALSE);
|
||||
}
|
||||
$map->rrdtool_check = "FOUND";
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
// normally, DS plugins shouldn't really pollute the logs
|
||||
// this particular one is important to most users though...
|
||||
if ($map->context == 'cli') {
|
||||
wm_warn("RRD DS: Can't find RRDTOOL. Check line 29 of the 'weathermap' script.\nRRD-based TARGETs will fail. [WMRRD02]\n");
|
||||
}
|
||||
if ($map->context == 'cacti') { // unlikely to ever occur
|
||||
wm_warn("RRD DS: Can't find RRDTOOL. Check your Cacti config. [WMRRD03]\n");
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if (preg_match("/^(.*\.rrd):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/", $targetstring, $matches)) {
|
||||
return TRUE;
|
||||
} else if (preg_match("/^(.*\.rrd)$/", $targetstring, $matches)) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function wmrrd_read_from_poller_output($rrdfile, $cf, $start, $end, $dsnames, &$data, &$map, &$data_time, &$item)
|
||||
{
|
||||
global $config;
|
||||
|
||||
wm_debug("RRD ReadData: poller_output style\n");
|
||||
|
||||
if (isset($config)) {
|
||||
$pdo = weathermap_get_pdo();
|
||||
|
||||
// take away the cacti bit, to get the appropriate path for the table
|
||||
// $db_rrdname = realpath($rrdfile);
|
||||
$path_rra = $config["rra_path"];
|
||||
$db_rrdname = $rrdfile;
|
||||
$db_rrdname = str_replace($path_rra, "<path_rra>", $db_rrdname);
|
||||
wm_debug("******************************************************************\nChecking weathermap_data\n");
|
||||
foreach (array(IN, OUT) as $dir) {
|
||||
wm_debug("RRD ReadData: poller_output - looking for $dir value\n");
|
||||
if ($dsnames[$dir] != '-') {
|
||||
wm_debug("RRD ReadData: poller_output - DS name is " . $dsnames[$dir] . "\n");
|
||||
|
||||
// $SQL = "select * from weathermap_data where rrdfile='".mysql_real_escape_string($db_rrdname)."' and data_source_name='".mysql_real_escape_string($dsnames[$dir])."'";
|
||||
|
||||
// $SQLcheck = "select data_template_data.local_data_id from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_data.data_source_path='".mysql_real_escape_string($db_rrdname)."' and data_template_rrd.data_source_name='".mysql_real_escape_string($dsnames[$dir])."'";
|
||||
// $SQLvalid = "select data_template_rrd.data_source_name from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_data.data_source_path='".mysql_real_escape_string($db_rrdname)."'";
|
||||
|
||||
$statement_check = $pdo->prepare("select data_template_data.local_data_id from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_data.data_source_path=? and data_template_rrd.data_source_name=?");
|
||||
$statement_valid = $pdo->prepare("select data_template_rrd.data_source_name from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_data.data_source_path=?");
|
||||
$statement_search = $pdo->prepare("select * from weathermap_data where rrdfile=? and data_source_name=?");
|
||||
|
||||
$statement_search->execute(array($db_rrdname, $dsnames[$dir]));
|
||||
$result = $statement_search->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$worst_time = time() - 8 * 60;
|
||||
// $result = db_fetch_row($SQL);
|
||||
|
||||
// OK, the straightforward query for data failed, let's work out why, and add the new data source if necessary
|
||||
if (!isset($result['id'])) {
|
||||
wm_debug("RRD ReadData: poller_output - Adding new weathermap_data row for $db_rrdname:" . $dsnames[$dir] . "\n");
|
||||
|
||||
$statement_check->execute(array($db_rrdname, $dsnames[$dir]));
|
||||
$result = $statement_check->fetch(PDO::FETCH_ASSOC);
|
||||
// $result = db_fetch_row($SQLcheck);
|
||||
if (!isset($result['local_data_id'])) {
|
||||
$fields = array();
|
||||
|
||||
$statement_valid->execute(array($db_rrdname));
|
||||
$results = $statement_valid->fetchAll(PDO::FETCH_ASSOC);
|
||||
// $results = db_fetch_assoc($SQLvalid);
|
||||
foreach ($results as $result) {
|
||||
$fields[] = $result['data_source_name'];
|
||||
}
|
||||
if (count($fields) > 0) {
|
||||
wm_warn("RRD ReadData: poller_output: " . $dsnames[$dir] . " is not a valid DS name for $db_rrdname - valid names are: " . join(", ", $fields) . " [WMRRD07]\n");
|
||||
} else {
|
||||
wm_warn("RRD ReadData: poller_output: $db_rrdname is not a valid RRD filename within this Cacti install. <path_rra> is $path_rra [WMRRD08]\n");
|
||||
}
|
||||
} else {
|
||||
// add the new data source (which we just checked exists) to the table.
|
||||
// Include the local_data_id as well, to make life easier in poller_output
|
||||
// (and to allow the cacti: DS plugin to use the same table, too)
|
||||
wm_debug("RRD ReadData: poller_output - Adding new weathermap_data row for data source ID " . $result['local_data_id'] . "\n");
|
||||
$statement_insert = $pdo->prepare("INSERT INTO weathermap_data (rrdfile, data_source_name, sequence, local_data_id) VALUES (?,?, 0,?)");
|
||||
$statement_insert->execute(array($db_rrdname, $dsnames[$dir], $result['local_data_id']));
|
||||
|
||||
// $SQLins = "insert into weathermap_data (rrdfile, data_source_name, sequence, local_data_id) values ('".mysql_real_escape_string($db_rrdname)."','".mysql_real_escape_string($dsnames[$dir])."', 0,".$result['local_data_id'].")";
|
||||
// db_execute($SQLins);
|
||||
}
|
||||
} else { // the data table line already exists
|
||||
wm_debug("RRD ReadData: poller_output - found weathermap_data row\n");
|
||||
// if the result is valid, then use it
|
||||
if (($result['sequence'] > 2) && ($result['last_time'] > $worst_time)) {
|
||||
$data[$dir] = $result['last_calc'];
|
||||
$data_time = $result['last_time'];
|
||||
wm_debug("RRD ReadData: poller_output - data looks valid\n");
|
||||
} else {
|
||||
$data[$dir] = 0;
|
||||
wm_debug("RRD ReadData: poller_output - data is either too old, or too new\n");
|
||||
}
|
||||
// now, we can use the local_data_id to get some other useful info
|
||||
// first, see if the weathermap_data entry *has* a local_data_id. If not, we need to update this entry.
|
||||
$ldi = 0;
|
||||
if (!isset($result['local_data_id']) || $result['local_data_id'] == 0) {
|
||||
$statement_check->execute(array($db_rrdname, $dsnames[$dir]));
|
||||
$r2 = $statement_check->fetch(PDO::FETCH_ASSOC);
|
||||
// $r2 = db_fetch_row($SQLcheck);
|
||||
if (isset($r2['local_data_id'])) {
|
||||
$ldi = $r2['local_data_id'];
|
||||
wm_debug("RRD ReadData: updated local_data_id for wmdata.id=" . $result['id'] . "to $ldi\n");
|
||||
// put that in now, so that we can skip this step next time
|
||||
$statement_update = $pdo->prepare("update weathermap_data set local_data_id=? where id=?");
|
||||
$statement_update->execute(array($r2['local_data_id'], $result['id']));
|
||||
|
||||
// db_execute("update weathermap_data set local_data_id=".$r2['local_data_id']." where id=".$result['id']);
|
||||
|
||||
}
|
||||
} else {
|
||||
$ldi = $result['local_data_id'];
|
||||
}
|
||||
|
||||
if ($ldi > 0) UpdateCactiData($item, $ldi);
|
||||
}
|
||||
} else {
|
||||
wm_debug("RRD ReadData: poller_output - DS name is '-'\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wm_warn("RRD ReadData: poller_output - Cacti environment is not right [WMRRD12]\n");
|
||||
}
|
||||
|
||||
wm_debug("RRD ReadData: poller_output - result is " . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . "\n");
|
||||
wm_debug("RRD ReadData: poller_output - ended\n");
|
||||
}
|
||||
|
||||
function wmrrd_read_from_php_rrd($rrdfile, $cf, $start, $end, $dsnames, &$data, &$map, &$data_time, &$item)
|
||||
{
|
||||
// not yet implemented - use php-rrdtool to read rrd data. Should be quicker
|
||||
if ((1 == 0) && extension_loaded('RRDTool')) // fetch the values via the RRDtool Extension
|
||||
{
|
||||
// for the php-rrdtool module, we use an array instead...
|
||||
$rrdparams = array("AVERAGE", "--start", $start, "--end", $end);
|
||||
$rrdreturn = rrd_fetch($rrdfile, $rrdparams, count($rrdparams));
|
||||
print_r($rrdreturn);
|
||||
// XXX - figure out what to do with the results here
|
||||
$now = $rrdreturn['start'];
|
||||
$n = 0;
|
||||
do {
|
||||
$now += $rrdreturn['step'];
|
||||
print "$now - ";
|
||||
for ($i = 0; $i < $rrdreturn['ds_cnt']; $i++) {
|
||||
print $rrdreturn['ds_namv'][$i] . ' = ' . $rrdreturn['data'][$n++] . " ";
|
||||
}
|
||||
print "\n";
|
||||
} while ($now <= $rrdreturn['end']);
|
||||
}
|
||||
}
|
||||
|
||||
# rrdtool graph /dev/null -f "" -s now-30d -e now DEF:in=../rra/atm-sl_traffic_in_5498.rrd:traffic_in:AVERAGE DEF:out=../rra/atm-sl_traffic_in_5498.rrd:traffic_out:AVERAGE VDEF:avg_in=in,AVERAGE VDEF:avg_out=out,AVERAGE PRINT:avg_in:%lf PRINT:avg_out:%lf
|
||||
|
||||
function wmrrd_read_from_real_rrdtool_aggregate($rrdfile, $cf, $aggregatefn, $start, $end, $dsnames, &$data, &$map, &$data_time, &$item)
|
||||
{
|
||||
|
||||
wm_debug("RRD ReadData: VDEF style, for " . $item->my_type() . " " . $item->name . "\n");
|
||||
|
||||
$extra_options = $map->get_hint("rrd_options");
|
||||
|
||||
// Assemble an array of command args.
|
||||
// In a real programming language, we'd be able to pass this directly to exec()
|
||||
// However, this will at least allow us to put quotes around args that need them
|
||||
$args = array();
|
||||
$args[] = "graph";
|
||||
$args[] = "/dev/null";
|
||||
$args[] = "-f";
|
||||
$args[] = "''";
|
||||
$args[] = "--start";
|
||||
$args[] = $start;
|
||||
$args[] = "--end";
|
||||
$args[] = $end;
|
||||
|
||||
if ($map->daemon) {
|
||||
$args[] = "--daemon";
|
||||
$args[] = $map->daemon_args;
|
||||
}
|
||||
|
||||
# assemble an appropriate RRDtool command line, skipping any '-' DS names.
|
||||
# $command = $map->rrdtool . " graph /dev/null -f '' --start $start --end $end ";
|
||||
|
||||
if ($dsnames[IN] != '-') {
|
||||
# $command .= "DEF:in=$rrdfile:".$dsnames[IN].":$cf ";
|
||||
# $command .= "VDEF:agg_in=in,$aggregatefn ";
|
||||
# $command .= "PRINT:agg_in:'IN %lf' ";
|
||||
|
||||
$args[] = "DEF:in=$rrdfile:" . $dsnames[IN] . ":$cf";
|
||||
$args[] = "VDEF:agg_in=in,$aggregatefn";
|
||||
$args[] = "PRINT:agg_in:'IN %lf'";
|
||||
}
|
||||
|
||||
if ($dsnames[OUT] != '-') {
|
||||
# $command .= "DEF:out=$rrdfile:".$dsnames[OUT].":$cf ";
|
||||
# $command .= "VDEF:agg_out=out,$aggregatefn ";
|
||||
# $command .= "PRINT:agg_out:'OUT %lf' ";
|
||||
|
||||
$args[] = "DEF:out=$rrdfile:" . $dsnames[OUT] . ":$cf";
|
||||
$args[] = "VDEF:agg_out=out,$aggregatefn";
|
||||
$args[] = "PRINT:agg_out:'OUT %lf'";
|
||||
}
|
||||
|
||||
$command = $map->rrdtool;
|
||||
foreach ($args as $arg) {
|
||||
if (strchr($arg, " ") != FALSE) {
|
||||
$command .= ' "' . $arg . '"';
|
||||
} else {
|
||||
$command .= ' ' . $arg;
|
||||
}
|
||||
}
|
||||
$command .= " " . $extra_options;
|
||||
|
||||
wm_debug("RRD ReadData: Running: $command\n");
|
||||
$pipe = popen($command, "r");
|
||||
|
||||
$lines = array();
|
||||
$count = 0;
|
||||
$linecount = 0;
|
||||
|
||||
if (isset($pipe)) {
|
||||
// fgets($pipe, 4096); // skip the blank line
|
||||
$buffer = '';
|
||||
$data_ok = FALSE;
|
||||
|
||||
while (!feof($pipe)) {
|
||||
$line = fgets($pipe, 4096);
|
||||
// there might (pre-1.5) or might not (1.5+) be a leading blank line
|
||||
// we don't want to count it if there is
|
||||
if (trim($line) != "") {
|
||||
|
||||
wm_debug("> " . $line);
|
||||
$buffer .= $line;
|
||||
$lines[] = $line;
|
||||
$linecount++;
|
||||
}
|
||||
}
|
||||
pclose($pipe);
|
||||
|
||||
if ($linecount > 1) {
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/^\'(IN|OUT)\s(\-?\d+[\.,]?\d*e?[+-]?\d*:?)\'$/i', $line, $matches)) {
|
||||
wm_debug("MATCHED: " . $matches[1] . " " . $matches[2] . "\n");
|
||||
if ($matches[1] == 'IN') $data[IN] = floatval($matches[2]);
|
||||
if ($matches[1] == 'OUT') $data[OUT] = floatval($matches[2]);
|
||||
$data_ok = TRUE;
|
||||
}
|
||||
}
|
||||
if ($data_ok) {
|
||||
if ($data[IN] === NULL) $data[IN] = 0;
|
||||
if ($data[OUT] === NULL) $data[OUT] = 0;
|
||||
}
|
||||
} else {
|
||||
wm_warn("Not enough output from RRDTool. [WMRRD09]\n");
|
||||
}
|
||||
} else {
|
||||
$error = error_get_last();
|
||||
wm_warn("RRD ReadData: failed to open pipe to RRDTool: " . $error['message'] . " [WMRRD04]\n");
|
||||
}
|
||||
wm_debug("RRD ReadDataFromRealRRDAggregate: Returning (" . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . ",$data_time)\n");
|
||||
|
||||
}
|
||||
|
||||
function wmrrd_read_from_real_rrdtool($rrdfile, $cf, $start, $end, $dsnames, &$data, &$map, &$data_time, &$item)
|
||||
{
|
||||
wm_debug("RRD ReadData: traditional style\n");
|
||||
|
||||
// we get the last 800 seconds of data - this might be 1 or 2 lines, depending on when in the
|
||||
// cacti polling cycle we get run. This ought to stop the 'some lines are grey' problem that some
|
||||
// people were seeing
|
||||
|
||||
// NEW PLAN - READ LINES (LIKE NOW), *THEN* CHECK IF REQUIRED DS NAMES EXIST (AND FAIL IF NOT),
|
||||
// *THEN* GET THE LAST LINE WHERE THOSE TWO DS ARE VALID, *THEN* DO ANY PROCESSING.
|
||||
// - this allows for early failure, and also tolerance of empty data in other parts of an rrd (like smokeping uptime)
|
||||
|
||||
$extra_options = $map->get_hint("rrd_options");
|
||||
|
||||
$values = array();
|
||||
$args = array();
|
||||
|
||||
#### $command = '"'.$map->rrdtool . '" fetch "'.$rrdfile.'" AVERAGE --start '.$start.' --end '.$end;
|
||||
#$command=$map->rrdtool . " fetch $rrdfile $cf --start $start --end $end $extra_options";
|
||||
$args[] = "fetch";
|
||||
$args[] = $rrdfile;
|
||||
$args[] = $cf;
|
||||
$args[] = "--start";
|
||||
$args[] = $start;
|
||||
$args[] = "--end";
|
||||
$args[] = $end;
|
||||
|
||||
if ($map->daemon) {
|
||||
$args[] = "--daemon";
|
||||
$args[] = $map->daemon_args;
|
||||
}
|
||||
|
||||
$command = $map->rrdtool;
|
||||
foreach ($args as $arg) {
|
||||
if (strchr($arg, " ") != FALSE) {
|
||||
$command .= ' "' . $arg . '"';
|
||||
} else {
|
||||
$command .= ' ' . $arg;
|
||||
}
|
||||
}
|
||||
$command .= " " . $extra_options;
|
||||
|
||||
wm_debug("RRD ReadData: Running: $command\n");
|
||||
$pipe = popen($command, "r");
|
||||
|
||||
$lines = array();
|
||||
$count = 0;
|
||||
$linecount = 0;
|
||||
|
||||
if (isset($pipe)) {
|
||||
$headings = fgets($pipe, 4096);
|
||||
// this replace fudges 1.2.x output to look like 1.0.x
|
||||
// then we can treat them both the same.
|
||||
$heads = preg_split("/\s+/", preg_replace("/^\s+/", "timestamp ", $headings));
|
||||
|
||||
//fgets($pipe, 4096); // skip the blank line
|
||||
$buffer = '';
|
||||
|
||||
while (!feof($pipe)) {
|
||||
$line = fgets($pipe, 4096);
|
||||
// there might (pre-1.5) or might not (1.5+) be a leading blank line
|
||||
// we don't want to count it if there is
|
||||
if (trim($line) != "") {
|
||||
wm_debug("> " . $line);
|
||||
$buffer .= $line;
|
||||
$lines[] = $line;
|
||||
$linecount++;
|
||||
}
|
||||
|
||||
}
|
||||
pclose($pipe);
|
||||
|
||||
wm_debug("RRD ReadData: Read $linecount lines from rrdtool\n");
|
||||
wm_debug("RRD ReadData: Headings are: $headings\n");
|
||||
|
||||
if ((in_array($dsnames[IN], $heads) || $dsnames[IN] == '-') && (in_array($dsnames[OUT], $heads) || $dsnames[OUT] == '-')) {
|
||||
// deal with the data, starting with the last line of output
|
||||
$rlines = array_reverse($lines);
|
||||
|
||||
foreach ($rlines as $line) {
|
||||
wm_debug("--" . $line . "\n");
|
||||
$cols = preg_split("/\s+/", $line);
|
||||
for ($i = 0, $cnt = count($cols) - 1; $i < $cnt; $i++) {
|
||||
$h = $heads[$i];
|
||||
$v = $cols[$i];
|
||||
# print "|$h|,|$v|\n";
|
||||
$values[$h] = trim($v);
|
||||
}
|
||||
|
||||
$data_ok = FALSE;
|
||||
|
||||
foreach (array(IN, OUT) as $dir) {
|
||||
$n = $dsnames[$dir];
|
||||
# print "|$n|\n";
|
||||
if (array_key_exists($n, $values)) {
|
||||
$candidate = $values[$n];
|
||||
if (preg_match('/^\-?\d+[\.,]?\d*e?[+-]?\d*:?$/i', $candidate)) {
|
||||
$data[$dir] = $candidate;
|
||||
wm_debug("$candidate is OK value for $n\n");
|
||||
$data_ok = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($data_ok) {
|
||||
// at least one of the named DS had good data
|
||||
$data_time = intval($values['timestamp']);
|
||||
|
||||
// 'fix' a -1 value to 0, so the whole thing is valid
|
||||
// (this needs a proper fix!)
|
||||
if ($data[IN] === NULL) $data[IN] = 0;
|
||||
if ($data[OUT] === NULL) $data[OUT] = 0;
|
||||
|
||||
// break out of the loop here
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// report DS name error
|
||||
$names = join(",", $heads);
|
||||
$names = str_replace("timestamp,", "", $names);
|
||||
wm_warn("RRD ReadData: At least one of your DS names (" . $dsnames[IN] . " and " . $dsnames[OUT] . ") were not found, even though there was a valid data line. Maybe they are wrong? Valid DS names in this file are: $names [WMRRD06]\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
$error = error_get_last();
|
||||
wm_warn("RRD ReadData: failed to open pipe to RRDTool: " . $error['message'] . " [WMRRD04]\n");
|
||||
}
|
||||
wm_debug("RRD ReadDataFromRealRRD: Returning (" . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . ",$data_time)\n");
|
||||
}
|
||||
|
||||
// Actually read data from a data source, and return it
|
||||
// returns a 3-part array (invalue, outvalue and datavalid time_t)
|
||||
// invalue and outvalue should be -1,-1 if there is no valid data
|
||||
// data_time is intended to allow more informed graphing in the future
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$dsnames[IN] = "traffic_in";
|
||||
$dsnames[OUT] = "traffic_out";
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$SQL[IN] = 'select null';
|
||||
$SQL[OUT] = 'select null';
|
||||
$rrdfile = $targetstring;
|
||||
|
||||
if ($map->get_hint("rrd_default_in_ds") != '') {
|
||||
$dsnames[IN] = $map->get_hint("rrd_default_in_ds");
|
||||
wm_debug("Default 'in' DS name changed to " . $dsnames[IN] . ".\n");
|
||||
}
|
||||
if ($map->get_hint("rrd_default_out_ds") != '') {
|
||||
$dsnames[OUT] = $map->get_hint("rrd_default_out_ds");
|
||||
wm_debug("Default 'out' DS name changed to " . $dsnames[OUT] . ".\n");
|
||||
}
|
||||
|
||||
$multiplier = 8; // default bytes-to-bits
|
||||
|
||||
$inbw = NULL;
|
||||
$outbw = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if (preg_match("/^(.*\.rrd):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/", $targetstring, $matches)) {
|
||||
$rrdfile = $matches[1];
|
||||
|
||||
$dsnames[IN] = $matches[2];
|
||||
$dsnames[OUT] = $matches[3];
|
||||
|
||||
wm_debug("Special DS names seen (" . $dsnames[IN] . " and " . $dsnames[OUT] . ").\n");
|
||||
}
|
||||
|
||||
if (preg_match("/^rrd:(.*)/", $rrdfile, $matches)) {
|
||||
$rrdfile = $matches[1];
|
||||
}
|
||||
|
||||
if (preg_match("/^gauge:(.*)/", $rrdfile, $matches)) {
|
||||
$rrdfile = $matches[1];
|
||||
$multiplier = 1;
|
||||
}
|
||||
|
||||
if (preg_match("/^scale:([+-]?\d*\.?\d*):(.*)/", $rrdfile, $matches)) {
|
||||
$rrdfile = $matches[2];
|
||||
$multiplier = $matches[1];
|
||||
}
|
||||
|
||||
wm_debug("SCALING result by $multiplier\n");
|
||||
|
||||
// try and make a complete path, if we've been given a clue
|
||||
// (if the path starts with a . or a / then assume the user knows what they are doing)
|
||||
if (!preg_match("/^(\/|\.)/", $rrdfile)) {
|
||||
$rrdbase = $map->get_hint('rrd_default_path');
|
||||
if ($rrdbase != '') {
|
||||
$rrdfile = $rrdbase . "/" . $rrdfile;
|
||||
}
|
||||
}
|
||||
|
||||
$cfname = $map->get_hint('rrd_cf');
|
||||
if ($cfname == '') $cfname = 'AVERAGE';
|
||||
|
||||
$period = intval($map->get_hint('rrd_period'));
|
||||
if ($period == 0) $period = 800;
|
||||
$start = $map->get_hint('rrd_start');
|
||||
if ($start == '') {
|
||||
$start = "now-$period";
|
||||
$end = "now";
|
||||
} else {
|
||||
$end = "start+" . $period;
|
||||
}
|
||||
|
||||
$use_poller_output = intval($map->get_hint('rrd_use_poller_output'));
|
||||
$nowarn_po_agg = intval($map->get_hint("nowarn_rrd_poller_output_aggregation"));
|
||||
$aggregatefunction = $map->get_hint('rrd_aggregate_function');
|
||||
|
||||
if ($aggregatefunction != '' && $use_poller_output == 1) {
|
||||
$use_poller_output = 0;
|
||||
if ($nowarn_po_agg == 0) {
|
||||
wm_warn("Can't use poller_output for rrd-aggregated data - disabling rrd_use_poller_output [WMRRD10]\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ($use_poller_output == 1) {
|
||||
wm_debug("Going to try poller_output, as requested.\n");
|
||||
WeatherMapDataSource_rrd::wmrrd_read_from_poller_output($rrdfile, "AVERAGE", $start, $end, $dsnames, $data, $map, $data_time, $item);
|
||||
}
|
||||
|
||||
// if poller_output didn't get anything, or if it couldn't/didn't run, do it the old-fashioned way
|
||||
// - this will still be the case for the first couple of runs after enabling poller_output support
|
||||
// because there won't be valid data in the weathermap_data table yet.
|
||||
if (($dsnames[IN] != '-' && $data[IN] === NULL) || ($dsnames[OUT] != '-' && $data[OUT] === NULL)) {
|
||||
if ($use_poller_output == 1) {
|
||||
wm_debug("poller_output didn't get anything useful. Kicking it old skool.\n");
|
||||
}
|
||||
if (file_exists($rrdfile)) {
|
||||
wm_debug("RRD ReadData: Target DS names are " . $dsnames[IN] . " and " . $dsnames[OUT] . "\n");
|
||||
|
||||
$values = array();
|
||||
|
||||
|
||||
if ($aggregatefunction != '') {
|
||||
WeatherMapDataSource_rrd::wmrrd_read_from_real_rrdtool_aggregate($rrdfile, $cfname, $aggregatefunction, $start, $end, $dsnames, $data, $map, $data_time, $item);
|
||||
} else {
|
||||
// do this the tried and trusted old-fashioned way
|
||||
WeatherMapDataSource_rrd::wmrrd_read_from_real_rrdtool($rrdfile, $cfname, $start, $end, $dsnames, $data, $map, $data_time, $item);
|
||||
}
|
||||
|
||||
} else {
|
||||
wm_warn("Target $rrdfile doesn't exist. Is it a file? [WMRRD06]\n");
|
||||
}
|
||||
}
|
||||
|
||||
// if the Locale says that , is the decimal point, then rrdtool
|
||||
// will honour it. However, floatval() doesn't, so let's replace
|
||||
// any , with . (there are never thousands separators, luckily)
|
||||
//
|
||||
if ($data[IN] !== NULL) {
|
||||
$data[IN] = floatval(str_replace(",", ".", $data[IN]));
|
||||
$data[IN] = $data[IN] * $multiplier;
|
||||
}
|
||||
if ($data[OUT] !== NULL) {
|
||||
$data[OUT] = floatval(str_replace(",", ".", $data[OUT]));
|
||||
$data[OUT] = $data[OUT] * $multiplier;
|
||||
}
|
||||
|
||||
wm_debug("RRD ReadData: Returning (" . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . ",$data_time)\n");
|
||||
|
||||
return (array($data[IN], $data[OUT], $data_time));
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
//
|
||||
// This is a sample 'empty' DS plugin, in case you want to make your own.
|
||||
// it's what the fping plugin looked like before I added the code in.
|
||||
//
|
||||
// Pluggable datasource for PHP Weathermap 0.9
|
||||
// - return a live ping result
|
||||
|
||||
// TARGET fping:ipaddress
|
||||
// TARGET fping:hostname
|
||||
|
||||
class WeatherMapDataSource_fping extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^ping:(\S+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
if(preg_match("/^ping:(\S+)$/",$targetstring,$matches))
|
||||
{
|
||||
}
|
||||
|
||||
debug ("FPing ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[IN]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
||||
?>
|
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
// Pluggable datasource for PHP Weathermap 0.9
|
||||
// - return a live SNMP value
|
||||
|
||||
// doesn't work well with large values like interface counters (I think this is a rounding problem)
|
||||
// - also it doesn't calculate rates. Just fetches a value.
|
||||
|
||||
// useful for absolute GAUGE-style values like DHCP Lease Counts, Wireless AP Associations, Firewall Sessions
|
||||
// which you want to use to colour a NODE
|
||||
|
||||
// You could also fetch interface states from IF-MIB with it.
|
||||
|
||||
// TARGET snmp:public:hostname:1.3.6.1.4.1.3711.1.1:1.3.6.1.4.1.3711.1.2
|
||||
// (that is, TARGET snmp:community:host:in_oid:out_oid
|
||||
|
||||
class WeatherMapDataSource_snmp extends WeatherMapDataSource {
|
||||
|
||||
function Init(&$map)
|
||||
{
|
||||
// We can keep a list of unresponsive nodes, so we can give up earlier
|
||||
$this->down_cache = array();
|
||||
|
||||
if(function_exists('snmpget')) { return(TRUE); }
|
||||
wm_debug("SNMP DS: snmpget() not found. Do you have the PHP SNMP module?\n");
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^snmp:([^:]+):([^:]+):([^:]+):([^:]+)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time = 0;
|
||||
|
||||
$timeout = 1000000;
|
||||
$retries = 2;
|
||||
$abort_count = 0;
|
||||
|
||||
$in_result = NULL;
|
||||
$out_result = NULL;
|
||||
|
||||
if($map->get_hint("snmp_timeout") != '') {
|
||||
$timeout = intval($map->get_hint("snmp_timeout"));
|
||||
wm_debug("Timeout changed to ".$timeout." microseconds.\n");
|
||||
}
|
||||
|
||||
if($map->get_hint("snmp_abort_count") != '') {
|
||||
$abort_count = intval($map->get_hint("snmp_abort_count"));
|
||||
wm_debug("Will abort after $abort_count failures for a given host.\n");
|
||||
}
|
||||
|
||||
if($map->get_hint("snmp_retries") != '') {
|
||||
$retries = intval($map->get_hint("snmp_retries"));
|
||||
wm_debug("Number of retries changed to ".$retries.".\n");
|
||||
}
|
||||
|
||||
if(preg_match("/^snmp:([^:]+):([^:]+):([^:]+):([^:]+)$/",$targetstring,$matches))
|
||||
{
|
||||
$community = $matches[1];
|
||||
$host = $matches[2];
|
||||
$in_oid = $matches[3];
|
||||
$out_oid = $matches[4];
|
||||
|
||||
if(
|
||||
($abort_count == 0)
|
||||
|| (
|
||||
( $abort_count>0 )
|
||||
&& ( !isset($this->down_cache[$host]) || intval($this->down_cache[$host]) < $abort_count )
|
||||
)
|
||||
)
|
||||
{
|
||||
if(function_exists("snmp_get_quick_print"))
|
||||
{
|
||||
$was = snmp_get_quick_print();
|
||||
snmp_set_quick_print(1);
|
||||
}
|
||||
if(function_exists("snmp_get_valueretrieval"))
|
||||
{
|
||||
$was2 = snmp_get_valueretrieval();
|
||||
}
|
||||
|
||||
if(function_exists('snmp_set_oid_output_format'))
|
||||
{
|
||||
snmp_set_oid_output_format ( SNMP_OID_OUTPUT_NUMERIC );
|
||||
}
|
||||
if(function_exists('snmp_set_valueretrieval'))
|
||||
{
|
||||
snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
|
||||
}
|
||||
|
||||
if($in_oid != '-')
|
||||
{
|
||||
$in_result = snmpget($host,$community,$in_oid,$timeout,$retries);
|
||||
if($in_result !== FALSE)
|
||||
{
|
||||
$data[IN] = floatval($in_result);
|
||||
$item->add_hint("snmp_in_raw",$in_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->down_cache[$host]++;
|
||||
}
|
||||
}
|
||||
if($out_oid != '-')
|
||||
{
|
||||
$out_result = snmpget($host,$community,$out_oid,$timeout,$retries);
|
||||
if($out_result !== FALSE)
|
||||
{
|
||||
// use floatval() here to force the output to be *some* kind of number
|
||||
// just in case the stupid formatting stuff doesn't stop net-snmp returning 'down' instead of 2
|
||||
$data[OUT] = floatval($out_result);
|
||||
$item->add_hint("snmp_out_raw",$out_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->down_cache[$host]++;
|
||||
}
|
||||
}
|
||||
|
||||
wm_debug ("SNMP ReadData: Got $in_result and $out_result\n");
|
||||
|
||||
$data_time = time();
|
||||
|
||||
if(function_exists("snmp_set_quick_print"))
|
||||
{
|
||||
snmp_set_quick_print($was);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wm_warn("SNMP for $host has reached $abort_count failures. Skipping. [WMSNMP01]");
|
||||
}
|
||||
}
|
||||
|
||||
wm_debug ("SNMP ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
// Pluggable datasource for PHP Weathermap 0.9
|
||||
// - return a static value
|
||||
|
||||
// TARGET static:10M
|
||||
// TARGET static:2M:256K
|
||||
|
||||
class WeatherMapDataSource_static extends WeatherMapDataSource {
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if( preg_match("/^static:(\-?\d+\.?\d*[KMGT]?):(\-?\d+\.?\d*[KMGT]?)$/",$targetstring,$matches) ||
|
||||
preg_match("/^static:(\-?\d+\.?\d*[KMGT]?)$/",$targetstring,$matches) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$inbw = NULL;
|
||||
$outbw = NULL;
|
||||
$data_time=0;
|
||||
|
||||
if(preg_match("/^static:(\-?\d+\.?\d*[KMGT]*):(\-?\d+\.?\d*[KMGT]*)$/",$targetstring,$matches))
|
||||
{
|
||||
$inbw = unwm_format_number($matches[1], $map->kilo);
|
||||
$outbw = unwm_format_number($matches[2], $map->kilo);
|
||||
$data_time = time();
|
||||
}
|
||||
|
||||
if(preg_match("/^static:(\-?\d+\.?\d*[KMGT]*)$/",$targetstring,$matches))
|
||||
{
|
||||
$inbw = unwm_format_number($matches[1], $map->kilo);
|
||||
$outbw = $inbw;
|
||||
$data_time = time();
|
||||
}
|
||||
wm_debug ("Static ReadData: Returning ($inbw,$outbw,$data_time)\n");
|
||||
|
||||
return ( array($inbw,$outbw,$data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
// Sample Pluggable datasource for PHP Weathermap 0.9
|
||||
// - read a pair of values from a database, and return it
|
||||
|
||||
// TARGET dbplug:databasename:username:pass:hostkey
|
||||
|
||||
class WeatherMapDataSource_tabfile extends WeatherMapDataSource {
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/\.(tsv|txt)$/",$targetstring,$matches))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// function ReadData($targetstring, $configline, $itemtype, $itemname, $map)
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time=0;
|
||||
$itemname = $item->name;
|
||||
|
||||
$matches=0;
|
||||
|
||||
$fd=fopen($targetstring, "r");
|
||||
|
||||
if ($fd)
|
||||
{
|
||||
while (!feof($fd))
|
||||
{
|
||||
$buffer=fgets($fd, 4096);
|
||||
# strip out any Windows line-endings that have gotten in here
|
||||
$buffer=str_replace("\r", "", $buffer);
|
||||
|
||||
if (preg_match("/^$itemname\t(\d+\.?\d*[KMGT]*)\t(\d+\.?\d*[KMGT]*)/", $buffer, $matches))
|
||||
{
|
||||
$data[IN]=unwm_format_number($matches[1]);
|
||||
$data[OUT]=unwm_format_number($matches[2]);
|
||||
}
|
||||
}
|
||||
$stats = stat($targetstring);
|
||||
$data_time = $stats['mtime'];
|
||||
}
|
||||
else {
|
||||
// some error code to go in here
|
||||
wm_debug ("TabText ReadData: Couldn't open ($targetstring). \n"); }
|
||||
|
||||
wm_debug ("TabText ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
class WeatherMapDataSource_time extends WeatherMapDataSource {
|
||||
|
||||
function Recognise($targetstring)
|
||||
{
|
||||
if(preg_match("/^time:(.*)$/",$targetstring,$matches))
|
||||
{
|
||||
if(preg_match("/^[234]\./",phpversion()))
|
||||
{
|
||||
wm_warn("Time DS Plugin recognised a TARGET, but needs PHP5+ to run. [WMTIME01]\n");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// function ReadData($targetstring, $configline, $itemtype, $itemname, $map)
|
||||
function ReadData($targetstring, &$map, &$item)
|
||||
{
|
||||
$data[IN] = NULL;
|
||||
$data[OUT] = NULL;
|
||||
$data_time=0;
|
||||
$itemname = $item->name;
|
||||
|
||||
$matches=0;
|
||||
|
||||
if(preg_match("/^time:(.*)$/",$targetstring,$matches))
|
||||
{
|
||||
$timezone = $matches[1];
|
||||
$timezone_l = strtolower($timezone);
|
||||
|
||||
$timezone_identifiers = DateTimeZone::listIdentifiers();
|
||||
|
||||
foreach ($timezone_identifiers as $tz)
|
||||
{
|
||||
if(strtolower($tz) == $timezone_l)
|
||||
{
|
||||
wm_debug ("Time ReadData: Timezone exists: $tz\n");
|
||||
$dateTime = new DateTime("now", new DateTimeZone($tz));
|
||||
|
||||
$item->add_note("time_time12",$dateTime->format("h:i"));
|
||||
$item->add_note("time_time12ap",$dateTime->format("h:i A"));
|
||||
$item->add_note("time_time24",$dateTime->format("H:i"));
|
||||
$item->add_note("time_timezone",$tz);
|
||||
$data[IN] = $dateTime->format("H");
|
||||
$data_time = time();
|
||||
$data[OUT] = $dateTime->format("i");
|
||||
$matches++;
|
||||
}
|
||||
}
|
||||
if($matches==0)
|
||||
{
|
||||
wm_warn ("Time ReadData: Couldn't recognize $timezone as a valid timezone name [WMTIME02]\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// some error code to go in here
|
||||
wm_warn ("Time ReadData: Couldn't recognize $targetstring \n");
|
||||
}
|
||||
|
||||
wm_debug ("Time ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n");
|
||||
|
||||
return( array($data[IN], $data[OUT], $data_time) );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:
|